From fbc4dc44f23b1d5cad5eaeb924f0fc970453ec65 Mon Sep 17 00:00:00 2001 From: James Croft Date: Tue, 15 Mar 2022 07:26:56 +0000 Subject: [PATCH 01/13] Updated docs to include RichEditToolbar links --- docs/articles/intro.md | 17 +++++++++++++++-- docs/articles/toc.yml | 2 ++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/docs/articles/intro.md b/docs/articles/intro.md index e311533..98857e5 100644 --- a/docs/articles/intro.md +++ b/docs/articles/intro.md @@ -23,13 +23,14 @@ dotnet add package MADE.UI | MADE.UI.Controls.ChipBox | [![NuGet](https://img.shields.io/nuget/v/MADE.UI.Controls.ChipBox)](https://www.nuget.org/packages/MADE.UI.Controls.ChipBox/) | | MADE.UI.Controls.DropDownList | [![NuGet](https://img.shields.io/nuget/v/MADE.UI.Controls.DropDownList)](https://www.nuget.org/packages/MADE.UI.Controls.DropDownList/) | | MADE.UI.Controls.FilePicker | [![NuGet](https://img.shields.io/nuget/v/MADE.UI.Controls.FilePicker)](https://www.nuget.org/packages/MADE.UI.Controls.FilePicker/) | +| MADE.UI.Controls.RichEditToolbar | [![NuGet](https://img.shields.io/nuget/v/MADE.UI.Controls.RichEditToolbar)](https://www.nuget.org/packages/MADE.UI.Controls.RichEditToolbar/) | | MADE.UI.Controls.Validator | [![NuGet](https://img.shields.io/nuget/v/MADE.UI.Controls.Validator)](https://www.nuget.org/packages/MADE.UI.Controls.Validator/) | | MADE.UI.Styling | [![NuGet](https://img.shields.io/nuget/v/MADE.UI.Styling)](https://www.nuget.org/packages/MADE.UI.Styling/) | | MADE.UI.ViewManagement | [![NuGet](https://img.shields.io/nuget/v/MADE.UI.ViewManagement)](https://www.nuget.org/packages/MADE.UI.ViewManagement/) | #### UI -The UI package is a base library for building out great user experiences for applications built for Windows, Android, iOS, and the web. +The UI package is a base library for building out great user experiences for applications built for Windows, Android, iOS, and the web. Taking advantage of the Uno Platform, the UI packages provide extensible features such as: @@ -67,7 +68,7 @@ The control works in a similar way to the `ComboBox` element in the Windows SDK, #### UI.Controls.FilePicker -The UI Controls FilePicker library contains a cross-platform UI element that provides a web-like `` equivalent for native applications. +The UI Controls FilePicker library contains a cross-platform UI element that provides a web-like `` equivalent for native applications. The control provides the capability to select one or multiple files of given types and show them within the UI. @@ -77,6 +78,18 @@ The control provides the capability to select one or multiple files of given typ +#### UI.Controls.RichEditToolbar + +The UI Controls RichEditToolbar library contains a cross-platform UI element that provides customizable and extensible collection of buttons that activate rich text features in an associated RichEditBox. + +Think the InkToolbar equivalent for RichEditBox controls! + + + +[Discover UI.Controls.RichEditToolbar](features/ui-controls-filepicker.md) + + + #### UI.Controls.Validator The UI Controls Validator library contains a cross-platform UI element that provides validation capabilities over any input element. diff --git a/docs/articles/toc.yml b/docs/articles/toc.yml index b74f222..2e2fb58 100644 --- a/docs/articles/toc.yml +++ b/docs/articles/toc.yml @@ -14,6 +14,8 @@ href: features/ui-controls-dropdownlist.md - name: FilePicker href: features/ui-controls-filepicker.md + - name: RichEditToolbar + href: features/ui-controls-richedittoolbar.md - name: Validator href: features/ui-controls-validator.md - name: Styling From 67f8b1986064a0b0cbf6938ae4b02976eaac7f14 Mon Sep 17 00:00:00 2001 From: James Croft Date: Tue, 15 Mar 2022 09:23:56 +0000 Subject: [PATCH 02/13] Added new UI data converters project --- MADE-Uno.sln | 73 +++++++++++++++++++ .../MADE.UI.Data.Converters.csproj | 34 +++++++++ 2 files changed, 107 insertions(+) create mode 100644 src/MADE.UI.Data.Converters/MADE.UI.Data.Converters.csproj diff --git a/MADE-Uno.sln b/MADE-Uno.sln index 9950765..3a42eb6 100644 --- a/MADE-Uno.sln +++ b/MADE-Uno.sln @@ -43,6 +43,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MADE.UI.Controls.ChipBox", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MADE.UI.Controls.RichEditToolbar", "src\MADE.UI.Controls.RichEditToolbar\MADE.UI.Controls.RichEditToolbar.csproj", "{258FB310-DC02-488C-97C7-CD1226EAAEC8}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MADE.UI.Data.Converters", "src\MADE.UI.Data.Converters\MADE.UI.Data.Converters.csproj", "{55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution samples\MADE.Samples\MADE.Samples.Shared\MADE.Samples.Shared.projitems*{04f1b32d-9056-43fc-b4c2-b8c5481bdacb}*SharedItemsImports = 4 @@ -1104,6 +1106,76 @@ Global {258FB310-DC02-488C-97C7-CD1226EAAEC8}.Release|x64.Build.0 = Release|Any CPU {258FB310-DC02-488C-97C7-CD1226EAAEC8}.Release|x86.ActiveCfg = Release|Any CPU {258FB310-DC02-488C-97C7-CD1226EAAEC8}.Release|x86.Build.0 = Release|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Ad-Hoc|ARM64.ActiveCfg = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Ad-Hoc|ARM64.Build.0 = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Ad-Hoc|x64.Build.0 = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.AppStore|ARM.ActiveCfg = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.AppStore|ARM.Build.0 = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.AppStore|ARM64.ActiveCfg = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.AppStore|ARM64.Build.0 = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.AppStore|iPhone.Build.0 = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.AppStore|x64.ActiveCfg = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.AppStore|x64.Build.0 = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.AppStore|x86.ActiveCfg = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.AppStore|x86.Build.0 = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Debug|ARM.ActiveCfg = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Debug|ARM.Build.0 = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Debug|ARM64.Build.0 = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Debug|iPhone.Build.0 = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Debug|x64.ActiveCfg = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Debug|x64.Build.0 = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Debug|x86.ActiveCfg = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Debug|x86.Build.0 = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Package|Any CPU.ActiveCfg = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Package|Any CPU.Build.0 = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Package|ARM.ActiveCfg = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Package|ARM.Build.0 = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Package|ARM64.ActiveCfg = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Package|ARM64.Build.0 = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Package|iPhone.ActiveCfg = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Package|iPhone.Build.0 = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Package|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Package|iPhoneSimulator.Build.0 = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Package|x64.ActiveCfg = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Package|x64.Build.0 = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Package|x86.ActiveCfg = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Package|x86.Build.0 = Debug|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Release|Any CPU.Build.0 = Release|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Release|ARM.ActiveCfg = Release|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Release|ARM.Build.0 = Release|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Release|ARM64.ActiveCfg = Release|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Release|ARM64.Build.0 = Release|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Release|iPhone.ActiveCfg = Release|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Release|iPhone.Build.0 = Release|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Release|x64.ActiveCfg = Release|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Release|x64.Build.0 = Release|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Release|x86.ActiveCfg = Release|Any CPU + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1126,6 +1198,7 @@ Global {442D1E25-FFD1-405D-A1FC-40CAFCAD190C} = {01380FB8-F8A7-4416-AABA-5407574B7723} {D1A16208-5A34-4CC1-B175-01B5AC99E69E} = {01380FB8-F8A7-4416-AABA-5407574B7723} {258FB310-DC02-488C-97C7-CD1226EAAEC8} = {01380FB8-F8A7-4416-AABA-5407574B7723} + {55D12223-8B53-4EC7-8CD2-05FC8A84BA7C} = {01380FB8-F8A7-4416-AABA-5407574B7723} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {3921AD86-E6C0-4436-8880-2D9EDFAD6151} diff --git a/src/MADE.UI.Data.Converters/MADE.UI.Data.Converters.csproj b/src/MADE.UI.Data.Converters/MADE.UI.Data.Converters.csproj new file mode 100644 index 0000000..276da45 --- /dev/null +++ b/src/MADE.UI.Data.Converters/MADE.UI.Data.Converters.csproj @@ -0,0 +1,34 @@ + + + + uap10.0.19041;MonoAndroid11.0;xamarinios10;netstandard2.0;xamarinmac20 + true + MADE.NET UI Data Converters + + This package includes UI components for Windows and Uno Platform applications such as: + - BooleanToStringValueConverter for converting between a boolean and a given string value. + - ByteArrayToImageSourceValueConverter for converting between a byte array and a BitmapSource for image source bindings. + - DateTimeToStringValueConverter for converting between a DateTime and string value. + + MADE UI Data Value Converter Windows Android iOS macOS Xamarin Uno MVVM + true + + + + + + + + + Designer + MSBuild:Compile + PreserveNewest + + + + + + + + + \ No newline at end of file From 5f8f23ee8aaca49df3b8af4ef2c62dbd2115de8b Mon Sep 17 00:00:00 2001 From: James Croft Date: Tue, 15 Mar 2022 09:24:20 +0000 Subject: [PATCH 03/13] Added DateTimeToStringValueConverter from MADE Data Converters library --- .../DateTimeToStringValueConverter.cs | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 src/MADE.UI.Data.Converters/DateTimeToStringValueConverter.cs diff --git a/src/MADE.UI.Data.Converters/DateTimeToStringValueConverter.cs b/src/MADE.UI.Data.Converters/DateTimeToStringValueConverter.cs new file mode 100644 index 0000000..51bdbf3 --- /dev/null +++ b/src/MADE.UI.Data.Converters/DateTimeToStringValueConverter.cs @@ -0,0 +1,98 @@ +// MADE Apps licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace MADE.UI.Data.Converters +{ + using System; + using System.Globalization; + using MADE.Data.Converters; + using Windows.UI.Xaml.Data; + + /// + /// Defines a XAML value converter for converting from to with an optional format string. + /// + public class DateTimeToStringValueConverter : IValueConverter, IValueConverter + { + /// + /// Converts the value to the type. + /// + /// + /// The value to convert. + /// + /// The target type (unused). + /// + /// The optional string format parameter used to help with conversion. + /// + /// The display language for the conversion (unused). + /// + /// The converted object. + /// + public object Convert(object value, Type targetType, object parameter, string language) + { + return value switch + { + DateTime dateTime => this.Convert(dateTime, parameter?.ToString()), + _ => value + }; + } + + /// + /// Converts the value back to the type. + /// + /// The value to convert. + /// The target type (unused). + /// The optional parameter used to help with conversion (unused). + /// The display language for the conversion (unused). + /// + /// The converted object. + /// + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + string dateTimeString = value?.ToString(); + return this.ConvertBack(dateTimeString); + } + + /// + /// Converts the value to the type. + /// + /// + /// The value to convert. + /// + /// + /// The optional parameter used to help with conversion. + /// + /// + /// The converted object. + /// + public string Convert(DateTime value, object parameter = default) + { + string format = parameter?.ToString(); + return !string.IsNullOrWhiteSpace(format) + ? value.ToString(format, CultureInfo.InvariantCulture) + : value.ToString(CultureInfo.InvariantCulture); + } + + /// + /// Converts the value back to the type. + /// + /// + /// The value to convert. + /// + /// + /// The optional parameter used to help with conversion. + /// + /// + /// The converted object. + /// + public DateTime ConvertBack(string value, object parameter = default) + { + if (string.IsNullOrWhiteSpace(value)) + { + return DateTime.MinValue; + } + + bool parsed = DateTime.TryParse(value, out DateTime dateTime); + return parsed ? dateTime : DateTime.MinValue; + } + } +} \ No newline at end of file From 0b9592e99b0100c465f15c3248b50f40364f0cb5 Mon Sep 17 00:00:00 2001 From: James Croft Date: Tue, 15 Mar 2022 09:25:10 +0000 Subject: [PATCH 04/13] Added BooleanToStringValueConverter from MADE Data Converters library --- .../BooleanToStringValueConverter.cs | 135 ++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 src/MADE.UI.Data.Converters/BooleanToStringValueConverter.cs diff --git a/src/MADE.UI.Data.Converters/BooleanToStringValueConverter.cs b/src/MADE.UI.Data.Converters/BooleanToStringValueConverter.cs new file mode 100644 index 0000000..0679be3 --- /dev/null +++ b/src/MADE.UI.Data.Converters/BooleanToStringValueConverter.cs @@ -0,0 +1,135 @@ +// MADE Apps licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace MADE.UI.Data.Converters +{ + using System; + using MADE.Data.Converters; + using MADE.Data.Converters.Exceptions; + using MADE.Data.Converters.Strings; + using Windows.UI.Xaml; + using Windows.UI.Xaml.Data; + + /// + /// Defines a XAML value converter for converting from to . + /// + public partial class BooleanToStringValueConverter : DependencyObject, IValueConverter, IValueConverter + { + /// + /// Defines the dependency property for . + /// + public static readonly DependencyProperty TrueValueProperty = + DependencyProperty.Register( + nameof(TrueValue), + typeof(string), + typeof(BooleanToStringValueConverter), + new PropertyMetadata(Resources.BooleanToStringValueConverter_TrueValue)); + + /// + /// Defines the dependency property for . + /// + public static readonly DependencyProperty FalseValueProperty = + DependencyProperty.Register( + nameof(FalseValue), + typeof(string), + typeof(BooleanToStringValueConverter), + new PropertyMetadata(Resources.BooleanToStringValueConverter_FalseValue)); + + /// + /// Gets or sets the positive/true value. + /// + public string TrueValue + { + get => (string)this.GetValue(TrueValueProperty); + set => this.SetValue(TrueValueProperty, value); + } + + /// + /// Gets or sets the negative/false value. + /// + public string FalseValue + { + get => (string)this.GetValue(FalseValueProperty); + set => this.SetValue(FalseValueProperty, value); + } + + /// + /// Converts the value to the type. + /// + /// The value to convert. + /// The target type (unused). + /// The optional parameter used to help with conversion (unused). + /// The display language for the conversion (unused). + /// The converted object. + public object Convert(object value, Type targetType, object parameter, string language) + { + return value switch + { + bool b => this.Convert(b, parameter), + _ => value + }; + } + + /// + /// Converts the value back to the type. + /// + /// The value to convert. + /// The target type (unused). + /// The optional parameter used to help with conversion (unused). + /// The display language for the conversion (unused). + /// The converted object. + /// Thrown if the value converting back to is not known by the converter. + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + return value is not string b ? value : this.ConvertBack(b, parameter); + } + + /// + /// Converts the value to the type. + /// + /// + /// The value to convert. + /// + /// + /// The optional parameter used to help with conversion. + /// + /// + /// The converted object. + /// + public string Convert(bool value, object parameter = default) + { + return value ? this.TrueValue : this.FalseValue; + } + + /// + /// Converts the value back to the type. + /// + /// + /// The value to convert. + /// + /// + /// The optional parameter used to help with conversion. + /// + /// + /// The converted object. + /// + /// Thrown if the value converting back to is not known by the converter. + public bool ConvertBack(string value, object parameter = default) + { + if (value == this.TrueValue) + { + return true; + } + + if (value == this.FalseValue) + { + return false; + } + + throw new InvalidDataConversionException( + nameof(BooleanToStringValueConverter), + value, + $"The value to convert back is not of the expected {nameof(this.TrueValue)} or {nameof(this.FalseValue)}"); + } + } +} \ No newline at end of file From 6cc041def930d265e43fdb985879dd202f4dd93a Mon Sep 17 00:00:00 2001 From: James Croft Date: Tue, 15 Mar 2022 09:25:24 +0000 Subject: [PATCH 05/13] Added ByteArrayToImageSourceValue converter --- .../ByteArrayToImageSourceValueConverter.cs | 85 +++++++++++++++++++ .../Extensions/ByteArrayExtensions.cs | 54 ++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 src/MADE.UI.Data.Converters/ByteArrayToImageSourceValueConverter.cs create mode 100644 src/MADE.UI.Data.Converters/Extensions/ByteArrayExtensions.cs diff --git a/src/MADE.UI.Data.Converters/ByteArrayToImageSourceValueConverter.cs b/src/MADE.UI.Data.Converters/ByteArrayToImageSourceValueConverter.cs new file mode 100644 index 0000000..d47cdc1 --- /dev/null +++ b/src/MADE.UI.Data.Converters/ByteArrayToImageSourceValueConverter.cs @@ -0,0 +1,85 @@ +// MADE Apps licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace MADE.UI.Data.Converters +{ + using System; + using MADE.Data.Converters; + using MADE.UI.Data.Converters.Extensions; + using Windows.UI.Xaml; + using Windows.UI.Xaml.Data; + using Windows.UI.Xaml.Media.Imaging; + + /// + /// Defines a XAML value converter for converting from a array to . + /// +#if __ANDROID__ || __WASM__ || __IOS__ || __MACOS__ || NETSTANDARD + [Foundation.Platform.PlatformNotSupported] +#endif + public class ByteArrayToImageSourceValueConverter : IValueConverter, IValueConverter + { + /// + /// Converts the value to the type. + /// + /// The value to convert. + /// The target type (unused). + /// The optional parameter used to help with conversion (unused). + /// The display language for the conversion (unused). + /// The converted object. + public object Convert(object value, Type targetType, object parameter, string language) + { +#if __ANDROID__ || __WASM__ || __IOS__ || __MACOS__ || NETSTANDARD + // This converted is not supported yet by this platform, returning original value. + return value; +#endif + + return value switch + { + byte[] bytes => this.Convert(bytes), + _ => value + }; + } + + /// + /// Converting back from to a array is not supported. + /// + /// The value to convert (unused). + /// The target type (unused). + /// The optional parameter used to help with conversion (unused). + /// The display language for the conversion (unused). + /// + /// An unset value. + /// + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + return DependencyProperty.UnsetValue; + } + + /// + /// Converts the value to the type. + /// + /// The value to convert. + /// + /// The optional parameter used to help with conversion. + /// + /// + /// The converted object. + /// + public BitmapSource Convert(byte[] value, object parameter = null) + { + return value.ToBitmapSource(); + } + + /// + /// Converting back from to a array is not supported. + /// + /// + /// The converted object. + /// + public byte[] ConvertBack(BitmapSource value, object parameter = null) + { + // Not supported. + return null; + } + } +} diff --git a/src/MADE.UI.Data.Converters/Extensions/ByteArrayExtensions.cs b/src/MADE.UI.Data.Converters/Extensions/ByteArrayExtensions.cs new file mode 100644 index 0000000..596d3cd --- /dev/null +++ b/src/MADE.UI.Data.Converters/Extensions/ByteArrayExtensions.cs @@ -0,0 +1,54 @@ +// MADE Apps licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace MADE.UI.Data.Converters.Extensions +{ + using System; + using Windows.Storage.Streams; + using Windows.UI.Xaml.Media.Imaging; + + /// + /// Defines a collection of extensions for array instances. + /// + public static class ByteArrayExtensions + { + /// + /// Converts an array of bytes representing an image into a . + /// + /// + /// The image bytes. + /// + /// + /// Returns a of the specified bytes. + /// +#if __ANDROID__ || __WASM__ || __IOS__ || __MACOS__ || NETSTANDARD + [Foundation.Platform.PlatformNotSupported] +#endif + public static BitmapSource ToBitmapSource(this byte[] imageBytes) + { +#if __ANDROID__ || __WASM__ || __IOS__ || __MACOS__ || NETSTANDARD + throw new Foundation.Platform.PlatformNotSupportedException($"{nameof(ToBitmapSource)} is not supported yet by this platform."); +#endif + + using var raStream = new InMemoryRandomAccessStream(); + using (var writer = new DataWriter(raStream)) + { + // Write the bytes to the stream + writer.WriteBytes(imageBytes); + + // Store the bytes to the MemoryStream + writer.StoreAsync().GetAwaiter().GetResult(); + + // Detach from the Memory stream so we don't close it + writer.DetachStream(); + } + + raStream.Seek(0); + + BitmapSource bitMapSource = new BitmapImage(); + bitMapSource.SetSource(raStream); + + return bitMapSource; + } + } +} From 38e13b8a516c79f3c682e60751e8868b62fb0803 Mon Sep 17 00:00:00 2001 From: James Croft Date: Tue, 15 Mar 2022 20:12:33 +0000 Subject: [PATCH 06/13] Added empty string format value converter for displaying a pre-defined empty string value when the provided value is null or empty --- .../EmptyStringFormatValueConverter.cs | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 src/MADE.UI.Data.Converters/EmptyStringFormatValueConverter.cs diff --git a/src/MADE.UI.Data.Converters/EmptyStringFormatValueConverter.cs b/src/MADE.UI.Data.Converters/EmptyStringFormatValueConverter.cs new file mode 100644 index 0000000..c3b81cb --- /dev/null +++ b/src/MADE.UI.Data.Converters/EmptyStringFormatValueConverter.cs @@ -0,0 +1,98 @@ +// MADE Apps licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace MADE.UI.Data.Converters +{ + using System; + using MADE.Data.Converters; + using Windows.UI.Xaml; + using Windows.UI.Xaml.Data; + + /// + /// Defines a XAML value converter for converting an empty to a set value, or returning the non-empty value string. + /// + public partial class EmptyStringFormatValueConverter : + DependencyObject, + IValueConverter, + IValueConverter + { + /// + /// Defines the dependency property for . + /// + public static readonly DependencyProperty EmptyStringValueProperty = + DependencyProperty.Register( + nameof(EmptyStringValue), + typeof(string), + typeof(EmptyStringFormatValueConverter), + new PropertyMetadata("No value provided")); + + /// + /// Gets or sets the value to show when the value is empty. + /// + public string EmptyStringValue + { + get => (string)this.GetValue(EmptyStringValueProperty); + set => this.SetValue(EmptyStringValueProperty, value); + } + + /// + /// Converts the value to the if empty; otherwise, the value is returned. + /// + /// The value to convert. + /// The target type (unused). + /// The optional parameter used to help with conversion (unused). + /// The display language for the conversion (unused). + /// The converted object. + public object Convert(object value, Type targetType, object parameter, string language) + { + return this.Convert(value?.ToString(), parameter); + } + + /// + /// Converts the value back to the value. + /// + /// The value to convert. + /// The target type (unused). + /// The optional parameter used to help with conversion (unused). + /// The display language for the conversion (unused). + /// The object. + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + return this.ConvertBack(value?.ToString(), parameter); + } + + /// + /// Converts the value to the if empty; otherwise, the value is returned. + /// + /// + /// The value to convert. + /// + /// + /// The optional parameter used to help with conversion. + /// + /// + /// The converted object. + /// + public string Convert(string value, object parameter = default) + { + return string.IsNullOrWhiteSpace(value) ? this.EmptyStringValue : value; + } + + /// + /// Converts the value back to the value. + /// + /// + /// The value to convert. + /// + /// + /// The optional parameter used to help with conversion. + /// + /// + /// The converted object. + /// + public string ConvertBack(string value, object parameter = default) + { + return value == this.EmptyStringValue ? string.Empty : value; + } + } +} \ No newline at end of file From 6cfca18bbbfa871f4d51b8b5a51ffc991be433ab Mon Sep 17 00:00:00 2001 From: James Croft Date: Wed, 16 Mar 2022 13:32:50 +0000 Subject: [PATCH 07/13] Added byte array to image source support for Uno Platform --- .../ByteArrayToImageSourceValueConverter.cs | 8 -------- .../Extensions/ByteArrayExtensions.cs | 17 ++++++++--------- .../MADE.UI.Data.Converters.csproj | 9 ++++----- 3 files changed, 12 insertions(+), 22 deletions(-) diff --git a/src/MADE.UI.Data.Converters/ByteArrayToImageSourceValueConverter.cs b/src/MADE.UI.Data.Converters/ByteArrayToImageSourceValueConverter.cs index d47cdc1..b346d12 100644 --- a/src/MADE.UI.Data.Converters/ByteArrayToImageSourceValueConverter.cs +++ b/src/MADE.UI.Data.Converters/ByteArrayToImageSourceValueConverter.cs @@ -13,9 +13,6 @@ namespace MADE.UI.Data.Converters /// /// Defines a XAML value converter for converting from a array to . /// -#if __ANDROID__ || __WASM__ || __IOS__ || __MACOS__ || NETSTANDARD - [Foundation.Platform.PlatformNotSupported] -#endif public class ByteArrayToImageSourceValueConverter : IValueConverter, IValueConverter { /// @@ -28,11 +25,6 @@ public class ByteArrayToImageSourceValueConverter : IValueConverter, IValueConve /// The converted object. public object Convert(object value, Type targetType, object parameter, string language) { -#if __ANDROID__ || __WASM__ || __IOS__ || __MACOS__ || NETSTANDARD - // This converted is not supported yet by this platform, returning original value. - return value; -#endif - return value switch { byte[] bytes => this.Convert(bytes), diff --git a/src/MADE.UI.Data.Converters/Extensions/ByteArrayExtensions.cs b/src/MADE.UI.Data.Converters/Extensions/ByteArrayExtensions.cs index 596d3cd..984a38a 100644 --- a/src/MADE.UI.Data.Converters/Extensions/ByteArrayExtensions.cs +++ b/src/MADE.UI.Data.Converters/Extensions/ByteArrayExtensions.cs @@ -4,6 +4,7 @@ namespace MADE.UI.Data.Converters.Extensions { using System; + using System.IO; using Windows.Storage.Streams; using Windows.UI.Xaml.Media.Imaging; @@ -21,15 +22,11 @@ public static class ByteArrayExtensions /// /// Returns a of the specified bytes. /// -#if __ANDROID__ || __WASM__ || __IOS__ || __MACOS__ || NETSTANDARD - [Foundation.Platform.PlatformNotSupported] -#endif public static BitmapSource ToBitmapSource(this byte[] imageBytes) { -#if __ANDROID__ || __WASM__ || __IOS__ || __MACOS__ || NETSTANDARD - throw new Foundation.Platform.PlatformNotSupportedException($"{nameof(ToBitmapSource)} is not supported yet by this platform."); -#endif + BitmapSource bitmapSource = new BitmapImage(); +#if WINDOWS_UWP using var raStream = new InMemoryRandomAccessStream(); using (var writer = new DataWriter(raStream)) { @@ -45,10 +42,12 @@ public static BitmapSource ToBitmapSource(this byte[] imageBytes) raStream.Seek(0); - BitmapSource bitMapSource = new BitmapImage(); - bitMapSource.SetSource(raStream); + bitmapSource.SetSource(raStream); +#else + bitmapSource.SetSource(new MemoryStream(imageBytes) { Position = 0 }); +#endif - return bitMapSource; + return bitmapSource; } } } diff --git a/src/MADE.UI.Data.Converters/MADE.UI.Data.Converters.csproj b/src/MADE.UI.Data.Converters/MADE.UI.Data.Converters.csproj index 276da45..bc674cd 100644 --- a/src/MADE.UI.Data.Converters/MADE.UI.Data.Converters.csproj +++ b/src/MADE.UI.Data.Converters/MADE.UI.Data.Converters.csproj @@ -18,6 +18,10 @@ + + + + Designer @@ -26,9 +30,4 @@ - - - - - \ No newline at end of file From 55a54d03da128e33a4ffeb64ae01df9161e2bd3c Mon Sep 17 00:00:00 2001 From: James Croft Date: Wed, 16 Mar 2022 13:34:19 +0000 Subject: [PATCH 08/13] Added value converter samples --- assets/SampleIcons.afdesign | Bin 18388 -> 31584 bytes .../MADE.Samples/MADE.Samples.Shared/App.xaml | 5 +- .../Home/ViewModels/MainPageViewModel.cs | 36 +++++-- .../BooleanToStringValueConverterXaml.txt | 11 ++ ...teArrayToImageSourceValueConverterXaml.txt | 8 ++ .../ValueConverters/ValueConverters.png | Bin 0 -> 7719 bytes .../Samples/Pages/ValueConvertersPage.xaml | 97 ++++++++++++++++++ .../Samples/Pages/ValueConvertersPage.xaml.cs | 21 ++++ .../ValueConvertersPageViewModel.cs | 53 ++++++++++ .../MADE.Samples.Shared.projitems | 20 ++++ 10 files changed, 240 insertions(+), 11 deletions(-) create mode 100644 samples/MADE.Samples/MADE.Samples.Shared/Features/Samples/Assets/ValueConverters/BooleanToStringValueConverterXaml.txt create mode 100644 samples/MADE.Samples/MADE.Samples.Shared/Features/Samples/Assets/ValueConverters/ByteArrayToImageSourceValueConverterXaml.txt create mode 100644 samples/MADE.Samples/MADE.Samples.Shared/Features/Samples/Assets/ValueConverters/ValueConverters.png create mode 100644 samples/MADE.Samples/MADE.Samples.Shared/Features/Samples/Pages/ValueConvertersPage.xaml create mode 100644 samples/MADE.Samples/MADE.Samples.Shared/Features/Samples/Pages/ValueConvertersPage.xaml.cs create mode 100644 samples/MADE.Samples/MADE.Samples.Shared/Features/Samples/ViewModels/ValueConvertersPageViewModel.cs diff --git a/assets/SampleIcons.afdesign b/assets/SampleIcons.afdesign index be606b858717e50fd3ae9b2c1642f1ccf2c0db87..dafcf750f29c14ba07cc34a0121b0e4178413098 100644 GIT binary patch literal 31584 zcmeFYRZv~Q(kQ&yxVuAecXxLuxVw9BLVyjyEx5Z&AUFgK4ncxLAh?qd+-2RJbH4B8 zulnEaxEi=79fQl3<2npoo<*7-dxZ-Mx9BkVf9og|U_61*Ays4RcbM5~GKuI35WH1|y|J$Gz7uNmdOlTV7s5 zY2>D`zn!O*axGMLu$aW>!}j=wW;HS*}akol1hLKOVpz=A{ z!63LMRWaCBvBq2}_9$EUhv9VmXPwX*WuHWQlrV}Doq|n+j6MAdopYN0&sq^XH6T(g z54=$?**fR|Ul4-eWaQ4cWLh9c?rb3x|K1Lin*HQg~8WSUQ1m zy~)?P0cqZ-Ds5RQyz*eW_remI5!8KGlMlGshCYe4E3wpIg^q_XG&gY!bX1tf;w*ECX&0cFXU)LJ;7Olz zdV=%F(vaTDe5BdE?LH}(0*{$ZrMVjNaPVd``eq;5pzXoP4MznDC0lm|Bemb${FV{omi+W z(Oe*jb-LYdRHbuJy$D6+A%OQ9u|^<(IC1t9NYpAH=%mNi;2{X{| z#|X*QOzV7lPAy>|ypPq!(7PuNdw_){xDPfcmQLZ&?2shV_Ar2l4;@C=DmzaaT8u#P zYAsN&%}OlpIGB$rIDAN;ihb7fM(ca0Q!I@a{a)FO{RommtJramRp{9;pnVoB~n~Gbhqc zRCMtlZ1FpSD{HSchAr<|BwzGFX+0 zH7ogaE6RmSjvgW`-v{sbQ}^LkD+k#M6)8ioV1<=NEBE8zDR8F;+bH`4(>T%fVWn5};^1rJ$yG4>zrmBI1flts zRB_A3|A&Set;!Tt*)wKczWkv-nB6u4G>AM)^=1Aj_C;?up$wKGY(_R%yfFoUM*#Dq z!rsPI*Xl|okh_|0s(-|MV|lK~c#)})`b<1fx{j@rsUyT z^h{TtK(PbU0Fe@shJvq4t1K70dpuEn@;t_uYOYMDOCeZdlcU`LuMvZRR0Fq#2%@Iy7tO?uqOUZs#cdUY9pYK2?`aPybM4YI; zuW9kbsOoRwrw|k|O-`9Y?{*p;tNjR#*un2$_*9T#EQ=6h7uXAdh%T)Nj?O~sqr1!s zHDm^ajY6Rf!@~GY;RkjnC#DA+34sX-Tq++d325shjzL$cOvE#H=GS;tlB-#^SsB3>ni%R6U6IEKkVgxmo$9kNV+b#Z%o&}0JG zE`YB~CD~?7F7##dgl0;BYhK4s^dageSE$^3Ys?XMoo) zFg;j1we;m~mE1HzHSuuo`p>}YCO^~fq02s?T?qCQkl*AWf>rcQo36wui)7+LCbaqz z_ewEX2tLC+K=^GE-Cu~pqxT(Q$K`?58nQfZt1#r@KmaHud2|BhD(vtvG7;^WINY|$2->X)n zM*du%Qe|b{V~f8<3P3Y+SNzn^Lb?Z7pU1GgoMC^|HW_;|Pc8iloP9rDcs|R^U3~6a z783ZFzQb71BTMOZ;^zC(*L5%wF&IV7n5eUJv@i56gxrvzi~ilvPmk9%3v)x4Fw?w5 z*TaKk4VS^6POVoGD6Dy<*}=r*Sx<0;k0A@UbJBnuFFzUC<0fwt=~mL+U3J&b9&-V9 zvezFMcBcM*UrceX8QvFI%4g2nc;^IedkjY;5Nb?50$h(kl)vNOh(WWkTp_BufoI`a zjl5}=N9Wf3F=N*+t0CkoR=;B-M0*p` zY$MtQ5S9X?dE9r(@whYa3)$ag{dk8#Z_Xny-j03cjvXKmyJWfY#qKnH2B4L}02trc`)uN|~ z%#CRBCX-lxVXVpcSy|*^l|t(1^w&k zln9)h=3-d82wLju^$KGWSMR~8uTkHgHu;2BF~*)mmYRD33Ar!s7_oR99#W;0SqFHs zqq-&%DU(NpVcE|*mdwu!IHqr_bkR_DE_v?;_5socf$4NrTH&9nc!P~c{H$5>m#^}M zoTq^C%s15!^bLHUHW|7H01CO$_dD6=?ZY-gWk3k4fCx|s|Kj&vCQuQ;l<|6Z)Q9--c&HfQ zYA{eId_3znX%!4F9hQD|zOZUQBP{TF=bBZ9B&WGsc=4+4XlHN%@U<8=F7#_g_QcU)moM1_5_x8-e*x-3`o_<|Fj=>GYY#adJ6t z@~%yO+ylBZ00qzP>duU=$+XJl>$FGB6TtRD9u^j6@pl^kkpkAsuW_!hH2SXa=JDvY zePZ}MAOZi9(IdiNk=otpLS5FsNt3`pQ+nusiP0@9huB z35hpO4Cbb9drp1#5W46?CnI%bxYlD0R0=^2-8~s9&X__PW$t>&GU9hrA9V$yR(`Sb z_bijK|Lxwfy7;3Y+lom-Uy?n6cYrcz_@?rW<7FRc2XXAT)y zcII=~gAi3B+1DInI$Z^&td5!se`{^UBDuYg}nK^tYCj~ zr{cHq-1m+q(9fv5&%E>M8K8eW(|2(N`h2YO2+q#*Ka2q8VXv+Js^5yr0SN@mDj?2G zNZ=2|MLh3mb0h?Rm8i`YS>`o7Z+E;H2QRHOBF<03zi(7{_a0E1saxrZ0D1@#mvB!6 zev4TGq$3~K90Qs+nq8NOM|a$>Hk)Id%a5m=tUC<9d{Vy-{*o|z2Pn({q(NTlknT-q z>y<-5ZpQW3NMphMGk{g*NN|;-t%W{(hNpdPtN~Sl98iL{Vo+3Y!9@LR}aTpf5euE=Zq+3~LcYvY9c2?_=M0B;;4v7d zhGAHFfFR+K$%jQ(gWz?ns+3jm$|IRCWzroULTO^3mHA2w4I-`RfBYFQs+CsCRoDqhFq7`dv$}<1a8*`8ueWIal6HEa zq(ux^6$F=#$e7I?j>zax)J7tW9SzbBPokNmcsthcP8Rg129?XoKqmUvBKf&Yj`CaV z@~}#eNs55PBZV5ehjfeg!NrUzU-4#{#D5))7YnbcKT0gfFpCazr`Omprw13G=mgoE z$OcnISM=t+wL$UG@}Z1CK~I_!{qw;iz%r%*o|PtT%N~&rU!w}EwcfJk@!MyuAO~hT z34DJo3H$&YCEoNCY43R|M6y-uZ{SHCWHiE@A-I^G=9-#?7`sK})>!jw?V2;*nmvXB z>2n$l#)Zy|(i9>^2#lEKBeF*K?oXf4Z|bOW9^(R%lKLO{@;-zTVwKVijyn|XIS7(Y zhv2Hqdz8Eygu&3CRM3KpU=@pS-=?F;4eMlOJQ!;nJtQzG1v95l7FIz8Lvd+hOo2WD zkweg)hg#%rO&Eid?BW7L$=ByO586Jmf=Z1^CgfO}0G@#EQ`$(gApczK&wnKnc6mr_cmfOU7wAt?l7cz1_~IS zDei{4SOH+i+t;wWZp1u!dKHo#>4uqkPI1#C84s80YP5$^Af0Vp$GzV37O)Dyf0 zTz{1e`-dF<`uwuVd<{(3iNIQ!Hnz1fas!31B|14-r;)pWaX}ubYS+s8sg0VaV6Mg# zgBmVhA+MSlF?;(*(>A5GJ;g@~B$hZoRYCH#>GDMzxz{Iy&79n036#@RUX1(%FKG&k zS@ChML?AOrU@K)nXavTqaLd7|N<-!2V~5Ev_V(4xn%kopVv6;gUM*5L1MjIR2i4Ox zqmX;RE2342(GVsyl(u-=BpHWBQC4{g4VQ^4YzPUOa5+mRLFW&%iJF))`diyIZbT=! zlc}KR#Ux!^D9+71m5Ny@B)4J|7U$IfaagJ$|pJ_(}lACE?HQ z?z@Vo2iz(0wR6Z`>D{d7OkGG*d#4Qy>s#N3J%zt6`dZVRy19_;0evU2aGV0C`_RRE># zwxzkj_6%^dKU1Ih(R-2TO?sO!DE`#;wi^&w5jfC({PgkE(7n9$iwez)`^w)6mV9}F zQOjC^oUDbDy5W=!Wo`az7s$_Z;3TefJEWF_;I1#AW%X(2S0oRMCBRM$ z@3?vh3qFSsOb;sq$Vqd5^1@%e9s2*OD8*Kbrfg>x&^#7vGF_4m6?xJXs$4TPUhMEp6M2hUJF2ytn913{F;Q4XK0ad(j=(OC? zuG_Zqh-4l@16kC%&NZ^dn#Yd`RX8u|nzVfvs@3B7rW!0K;oxEq7*ZJmZpzCIOKKzx zJWp5-70qH88dKWI1SG-aFs6--sZa5_r2gY`n|J(uWJcVI{aP^EqC4SqFeHNh0uua4 zuu?l&LUu|~TiXa|LCvy}8B{~}V4D;(MUJveFlzt|ZVt&1Z8eB`2p!YLq%mBni4wjU z0hu*u9hW|hixzx0Nf3oO_Ar$Dy6*cE9G9K|(Gf2quT> zJH&Ld0)q9BKmipAu5VT-1_N*(4Z=`pNVenvwN*=LOkP(AmFeeM8!%thg&RikcnM4{ zi_&Bg7*28!6ke)uq}h3|;dbaVZ+#hV(`` zrvUYqEJ}rcZUupkgVh}@y(+be0Zvgrh`u|QzKA>vu9Pr~{*4DR2xXEeD0M82G5i^C zmRrpdZgv)T@O_{_A36QC>6^eq&M! zPo^hY(4Jg4|7rfmaix2Ta0_HGcGUV(@ROD*+GJKgwjO7|J(8GY2CZuU8X5QA={lJw z(j>$qG3R=7Lrn{Ql7v?L8@Smf9P9x>V$^$dKcja<)W?#tk|nltL`_U#tzvv>SHjsv zvgnqyX_gJcYeDP%cWa~Z?mz8Wq-7*j%Mef%%f=zpIZST86=(GDsy&h zg`-*D&j`FkRlDaj{dXf}gQK56Hw>V#ZXJEIgHeg~2LuCX_EdyK+1x(%3b7{-&hPMZ z_EVhOqcXwBw2o>KzYA~(ck4F|P zD-4GzFo}h%_4&hf$E^N1CA8mU%Z1FWQ1OfMm*7wr~&?AgG2Sfk@{z|wRQhL;}~6FdquIBh$K z6<3OSkiLe*r5;26e(&+#Huu_@QPl8bOI%?4g_f}QLN2qm449Qzvpu7zYykD^R^AaW z?yTg-?hWV8e}mL0G_9t3+;QFzol2I#lFjt*Z*{zc>>|;U&Oq#Cv4a{lWH%@ENutuT zn70)X?MughWdlOo->iciyEMPJ`f_=M=DRYi&8{y1f|2LN`;(Wfs8G%7Zx`%IAIpq* zi%C5A1^DtV&}u#>&^+}R@cZ1BNg%w;Q}AuP`2b*(1wv+=0v(IdDmy73<9FXi`aFcF z6ai;gEvsfmNBo@xiPsqnhiGD%u70*2LO5~{#b*gV87PI1q6?5W)~5! z;{4oF0h59E8yu4<81uz^R3mPM{IQl($bdX&s@Q$Nfb7w3oEwrb@Yo>6ig&9Nf*-jr zgu?Y{9fLqT)Kn4x)GT~n05fEl>G}R0m*^E^j9b?wSDKe2l-xT>_p*WUK?Wz!A_vAtV|2>_a(MgWm1+q;l2 z!d>oUz3byrR4;c{;==8Fe{GIJh_ekypPt?6UMLhupSmSC&W2YzUN)74mqx_5a~DU> zf%eXf#Ee%`WYUkrFYPcn5k8J90!(pH*VnE-Wxb9*9LHy01IC}tXEX6pUl4)}%MOhn zQy%G;np1)Y!yLH+<5M99_oWliq@ z={(Rkw={A6wxvILgXx(TkU(v2$PmcY&$te@=gWfH1LtV$FYX42KcoT7AD*o%ZIQzpQ`fWFeE{g&!@e;2{S>*rx=%7b`2d(# zHYdn(x{eM2SpZiZTWsyXCjA$+4FLG?jwfxBz>N^~qIiEM`RQQH3XpRlead>pz0g~G zinK-Xp;q96d%F6UXe9GK?Mt{0)hsi0{ewHWTzeWMb9QEc(fR65{Q@AM%==1SOwiPR zeF&+N_w`cS*lf)6e%Y*eEu;zB%;S6AEKl73+}^N8(kA!5-C%{TZeY^p%MtMQ=QR3D zh)AGyv6<2R`ux!F8+tvx@slrMxW!wO zpt>A)kSbf!+a;o0$8DN7j$x$O3Vc!dl`!hNh^e7rWn(%%g^Hp5y?|rH4Ho7I_zXbl z2AI!Z-7j8Czg@j=D4YKCHIlpFFrZ)(oxC7H*Y}ER*ug9tT^xw|{$?)Qr+yp2_0JY_ zMFQNnZI>KnIyQF5XF7-Mp(5}3|u*Lj=t(vmS2Lc_)SlCzP2{`M~=GMANkT-@4QI76F$=y;m)r` z#pmJ9Y9oNrg1Ztnpz&?cX+&x2N2yr&MvHV{Zo`U7Yhpkbij2Nu0k3VKT>%e6O5tDr z%JspcADK9~;gb5hQyjev^d;KHhAaz7#}-@(Z70T7Q8+%%+ujD*E!Zes z%>PCZxjVg&=gL(wnOP_noS?#^?Zk=uGM4d)MQ|KNu60ZbmalwGWSjm=}eFr+_Nw_tS&(xbkvS1zLOWW&OnL7Z6-* zydH<@?%?5g3^e~pU>!X<{2|_vOD2J0Uud>ThIerqQ<{>vTjT0aCZMO}u91ciD|- zb;ErKV$s!O?>6ve1DJin{CF3FbS8m+)`x!sdRCpSi$1;j1ukV}d3N2AeRX@HP+04%9QRoRxLkjCR=iCH%;KPh zM!b>P5a<=;J|bE&P)v|uTrqppw_MPgb?o#h5xLq>m_Yu7pgy1K=34fFVmD>mTh$dK zQ4IjXtc8n!PseuuhL41)YM#d@R?^}`qOwM#`c6sHqzBtftcf?8OgWZfpd5(%4Q}_m zQIH@;dgv`JtQHm=1Pkh`LIpwqS%Zp3C~dQrVMZGF;M3E6?09e{YR&`SCDIY+&S>~I zDAmM^hJ_-u!y6bN?DI|%vM;Ary7NlZ>5kZhS7GB7z9Yh(ky#;cn(__Mg5g(mAUYp> zPKNvIPNZb0Ei6MW>T%}Mgt&L#vsf6X3t?iA9m#zE$`kv{KsEQLs}x?MKUokBpBd*e z!z0nd#>+0&6al>tsd4f|?R^>*nAlqbl{m37&M)HZ;{_bWJ`U!`L5b=PQK59C0<05B z%vRTL%HtMBq#b2?`^)p8QdHYWbxI8<_`ZdsT6u6an|NA(V3~Jr-x|PZ8Xo_ysOUGicuO+vM_B*!E(nWCvwNF+;rQS90r3a&5w zeZ6ydz=9i{?5^)DrW2;S)E#~WBG2zV(W?C7N%OI6 zyIt`WX=e1s(7y(0-?pN-T8M~(A&#(WB0qb!o90jiM+DH*;E^!L zea4flFO;JYSAsFE%9Q}l9f?LPoR2vR{6z7c;^o<>yt4$H>TAnDBaN5svL-cSgL()b z2}=EbPk5+d+8)ecQ2vzcWi4Lh8+=D^yM(@6y%4IT{*h@X3aNeL+f#9i-Fk4_aj|CX zWJz~0j9ye=00yS^OC-m1(@e`3z>Gw3bph{HNcYV zfLfg-gJnn$g_YAS+tsurye5*S1MhZbH3vpNK_8`&@G=#TT9>*?*;coVRi1p_K! z(OX`s3{%p+FLwip^W7+eP62Q_k(H821g2(FX*vY!@W1Ivb)kkyHo3Q$&J(ow~-0NIC&O+p;sFbNX;=@@MNXC-8Vw1VA=!XY4@zLRUf%NQ5 z1E(g>H*(p^Qx2x6$@gJzF?lL7POb#mXs@ipBJ&811aGET+IHm#EtGBIR_d$KS*xq= z)ZLd^iB8QqvK7uA_nAFk_Imz`W&D&Qt_S%rEB%stFz?hM{A#QWqHl|t7Ub$7)4>QF zYwQ`K|8as)-9DypS%S=(&E(%XM49Ch08eu{N;^G zt)rR=V6?jL68ad5o{5(ro^6m|N0ey1p9p_#=hrqG3M~bTo=gj=k?lh#8>Sr_5J|s{NY@19GsvKq7_m8yXraT;PdOW z_;DL-vW^0Oa&gmP_e!0-ezekzw#_wv>CmNRx*^PK&G=4t#;*VuMI2NX4D6vJ{b)3A zymnnaAunrrJL>MO;}#@G{7H{UetORJHMl&(ec3;54$dmr+Nh}fd;*OIKXj#kAUDp1 zo@;0vyuic_JU7by@_B>BOzC1q?ce8ZsWL9bw*d1|SxIDG8>3EucY@Aryj%At9Ev|2 zm~zT-Sb3qca-+AGKWassbAmU_x3sSu0;%)xIS}fJiq8;}xBPRLo%Gefu8~GCBvL-S z?;KR>-IEBG4P+pI$GeAdkdSD$ASOCj;*W&NzUvv)kAxv7v0<@VQaETR+3w-#(?1MP-|$X_A;eGL8Mzar#_G>^>d2{iyz|b zZG}^6?k3-@HhB{N5_4VtLD3Mnd2wNpG`!ZPZIQ;)Jq_TB)T7*`MouEUv@wrMx%*QK zVWxd6p&<7_N~LIjaTJ^ zm1r5acKQ-n*$UFOFzL6BQZmq|d^`>fVZI;cKXTlt2(AR452XGbkZ>20O|jg$Hrb1` z5W}UwWD-4_HAlc-+h8B`y5r($qgj=bKYx9{-20bOkUCfpZ#G?UFN%CJB%28k$lQ!}1D=RF{VYDsX#I`I;qY?V5;6zNU$* z(V`c9Kxp2m)nx;;Gf9xQ37@uCw!-!wk=z%LEHFfKWxk2(Z=@f@EvRnqgi_CVk(bmyU=$t{0-?A zkp#`ePrnDR&ikWJ!r$-9cm?;I!GL5~H>Y#2&=2BvO)|K}eVad8?2vCA5syvhOsE^R zCXy(SxBp?K*|BhtaFMI|@y1W6=x+C~gptl?lj@i>h)!$KD_3wohb_M9J9C%a<45Bq zv*AOsue~RmAV*FTpD#JB)s(H9r(*>e3Lm@;dDi9?EI13-Ko%87DihYRY7hv37wJ&#L-dL_d9RRp^n=P8DyFb>R z5^tsGZF$GBc>NR7k$R~Jrn^}LEK}4my8)%6{yahM4YhdpJHBU_%-?VG4F_t;EVNql zr+&2#GM}$1BqYw`soO}Bh{MH<=ZUARwguk}V&@{vfd|Lk-pu`i`_cgRW1-eA8$jVv z7Q4`y4x*=5fp{ko)T?3N@1&GC)>XelF%<2OV5%mlcs%62XUm(oI8h3GbK4^x2bZ+D zoymTKI>hsp<9Ip9g|2(Ms-_6%xf9_dYaiQnHO8sKEP}`syk>}0XoojLhEP8`1=d>( z|5~WilA)yNshVHmr{O;;eN096@KM#saO$?#NjMO=_Wa%RW-oMI? zXz_&%tuaqM%>rT@L3Cz&Hb*;)`)6l&wS(WTn1~aSuf4celY7|;C$xjP z^Ho|rn#8^kl8`^0A*WgHCQZ`flR@6?q@0Q?efcdl6Y)99fU17_|ilYiSVYZLP8pheiDO9`gbjWK(}ec z-ByFBEXqnP(aazU&13sMru7gnxYR@JZaXF6lYuHi&4^{vT5_7|ylgBhjOiy*z6ws> zU#}|^IeFvxpab%wCWE;!oLR)E))($3*I|vCjW&8eW7<8}Zvl zE~=21@bj7Zi@ly8rlRhyD@tnbXUpHLC`2zx-bcNo@wh$=hM`CPv4wx?2_5p8xLv^c zjWalQd7hLB__yrUexxg+2$Z~M>BnZpw=SeMBTC}96~7Rr`}=9;1>vL{mJ4n*=8Fpx zDDf&6lx-07y96E^?b3}RJ;(#e&pO~!Uv>CvXP7hajw8>Knqe`9wZF=lc9l_8=<2ii z&EdVjE2og^|FUILX8HlQ9_)da1Y!H7{T4?e<2v9pG_5^V?9=+aG40>Q8tVYt+AQ6@ zc{y-ESw>eCwhH+i>^PS(ACB!^c!`)E@)8&i#n!acd~=U~EJ`k+{((R06(>|dP5CLZ zQ%etY>1WsCN|0+BR4O(TkKZ`nfKBR;I6n4YZs- zCcvq%Eaw%#3%_qa?ofKGb97|f71)aTLi_bi)|)rHhYS{HnyYdbL5aQ0+g6`Ojl+I) zlghiZ0MI}qufq#f_x}_A*Khs*&#xWkf9gp=Aq)uopQPgdwqC8;*bD>o~Yt{cCxz0s@i$Pswj+941CnT>%}11O=Lh zuB0fd1?>qMh0#SqfP(CKeHti0_E0qR0)a4w{(Ug%EEuF95G6=SR!YY|@6Y>BW zhWoRtUr%c_nk)T5>9WdJw9c(I#!ac}b4r!=?<)cyr}Bgz?(7carn8j_ZQk1n@2)7( z{#XDn3dDZQ2jC#MpaW1mj6>)Qm75-`9zt_P6 z3%)a;q6H5$q>N}B&V0&|W_rFK?}mOvLWubnVk>bdH0W>=Mwb%h=$+&vY3LJ)KvMQF zzL|k7U5r_i^9JImqhVeOBNF4miRw!FND$1x2f91jA2E$Tu~6e5Q7x4 zP}mz5aH77)arAV!P5D&1EuKEw1lOk4n>rQVruQ+mn&46d6FPm3e|3>;T?;`kk1U3f ztWKceUI5RdVViPh2Z)n=3c=PG8r}WL>n6sH-TEfC;n*bBpBsjF&hfQp|2LGk!WE-b zt)-8jU2CniX!l1n*YE0?wD;}``!t)?;UM*5CDS2!9@$B?juL_9kNVD?k90D$B*Hk38y=98EL{g!X1xBK$7{#RrpKUcP^l-=$94*yIwp7>WR5@sgA>TUpqx)HYGv zPGbCyb6;JamYnKqcGo3bL>egjiTt;RdYvT=o#i6Lx#TGB7&ol=(#v!q!wbC#He`v7GoJ zk9)x~D|?wb&QOV|Attg0U7zK=3~}xd+R~$6SNVx0rA$$@C5{X|*JPuT>VQ&@9v__| zle%8an2hEhU*q&gm`=E&1q3WEa;l0DXRRk`;Y{+}_jdf*FXNWAA`h7C)M2g$S*g}( zZ>C*Dv48k{@uLqq7NKO7Ip=>21gDWW3d0sH+)>%s9OWsU#?iM*!b{tq+a(a|}S&&f(tsN<@S zidU2Of3Cf}uo>hPUTZ#qn&Ph&Kf25tWp<@H7q;669e??56omUt4!J}H#>wUw4Wbpo zNL67ybgiF&JC%88CL}C!v8R(aT~U_%vfzh(a|izo_1z?^l;Z7O>~)Q&rlJ%2(yzOXQwWHfj6q4rEJ(js2U_p=htkRHqa@wC3PSjRa%g!E{W zxrz_GFt&{dV3%WHg;5QD%3bLFCCJ4;FZi>>pE*LQ&iD1CcW0c)`cu3%cd8wIGmp*v zTTmqoZPz+~dGDuxgQ9~iWcOI*o+np+UK}sc?7HOoc2G;qaWMSu#9;S3kHCG0GlXdB zL`r3oC1}TAO_xf%G8u;3e0=EPg2hE8vJ`LhNnQ2E&AR|C-5iTUU|7W+F{geZ1IpA+ zNYN<6#vI$O_g1p?xNna-xQ?;habajd^@lTEi&F0dGOZesdbI;HMe;G;P_Ed8SyDfq^-nE^Ma(rAe=_?J&jWo@|?6XmmB_pi0vNS0PPsN8uR5yU2MovOl5 z7zeTE#Nxuy*3+sq6ld#y zCUX|1?V@;c$sJb@vNK{TaZWaWH}pqgQ)MeBk-N#-1km4eGDzissILW#SopaAaoR*q zSTEgH#P9$%{>st%h#=Cdz^&jNtJJM0R~x zFCPt+vIt}6XbR8%zGYl%f?NbYC*7QI47$H%zL}t4f7rhx)Vo~k*?bxZVU-e>NrDHt zVppF}DQb#*TyK57N}y9j*-``Bov7bfo!Q+Tm;0R+d=^>UyKZjgC;24sY(z=#VMSY@ zF2kKkccUCI=d+Fjd2?<5zvIr(5(|@R(5L>~j@-BL5&=y9mKibIoO*V3J@?O@YDW3V z;BP>-a6$RxPHn5y$WVU;N;GL!_0HmRsx)!c_+P@cn0J*NU!K->kb8Gi*8K1YLKx0u-7~P zQC)nK<#)Q44Q}e)kZhY{f~!2TVF9HKx&s|DpA~fXZxZ0X5gEn`Hd8i#ZIAlBQ0!M~ zyy(2Rs5!x~Gk7x1t9{x)Y4*MtBQxljgD@`Oi<7=3Pwm|hT&e+gb_`Pqa?`@hU-JYK zQ?RC!WEc^0O0ump4(!fUkk!+G_9DCC$xP&!sP{?88IB+*uJ{sl(bKTgjeMq0#MV0c zTTEz70v+_{PW6~@e!hgF1&n{f69Q*|tT>jmoh1gAX?WjlQdyhm9WR7keTEiRJB?NK6dI zo0o_wI-3$b2dHtg0#PLrfu|uYm!m0sfico@Vkcux?A6Uw7 z(f&!EsQX|A^SU%G_JiWT3p>I-=Me(MmslJaU>MvwQ@22j=1hu@a1{z%S!K&E5*I?`{X7mfzo)2gO)Y-MJ zT7Jt7-6eEItk7?FZa$gEzGw7V8#E<;!%^+S6Jnr6xAu1s(2zwA&Bzs0+&Xcm_Ra}% zEx8o9yc5mOauB6&TaYO1KvcpCpDQ)1ljctCyw_X)8Cmyxv6G$P5(oP8BZrW;J48$7 z-?Nw{M&?hLt^3)U7}5?e6PT_%wQw ze#s0mJ}T_iRCb-~eQwcoVuW!IJ%0lS^K$bt`^#n|Eos}{h2?d82v>W4_mf7BH#<%0 z-_3R}(PT=JPqRH6TLSFup_4^#Bm*m7@e61Xz5r`|7; zV5>0}}kH4@MdrY5UeihOjBH8O95uU6d34 znTW1n9&NJG@%#IGCg;<4cH*+KOd#y!MXUi&U0r=WeSLS4!w*Q7Yf+Urk`P%O+Jorv zq3%P0XIDH0G<9@rZ4^yd+Q8=NP%RosD27Qb;w`P?iAhOw6L#;TTW>#QJ#bMA%gYjj zqQ|&-I5@99a~)hYu^z^iIOyx@x`$vTL8OvRl3)4nKPJK0cpPaUgm|sLepxvGC$3@M zZ5ou$-hbsf_!M)52l?86R0so!cEYaCdKjI2j^H}z`^>&Xe(YisHp z@XY<+LQ)sREb9YeXV+|7LuuKw{ea%A!+>73C$K2eRWXLZdjXNRyl>Y0sqMI*1Yx2j z!J6#*#a=$GpO>X!eO)U6i)~6-GWadX`A?;+cYHRG5^a}C zdmJ6j5=*_A_-Y=u;BjALR>#pMVOqdn?HVt}{pMX$h#y!PBux%guTW1v{l)LS*8hlV zF8v9_%*PAud0l~Q^leUsn)M{IU2sY?#&-W1DHsdg4*5;{(yMNUZ7OJkG1jVl`L}D` zJWe%L2OhJ8A?x0!dQ-!E)!=r;sd=_ka#wC5$_)xb$!^MpHxG4YM<#|h>tB`#g8tUS zF_=qx;J%0ur)kOjBhMh&w`sIW+=G*&F-K^R`e$xK?~w$DC!=B*RZ{i{AS@rVA=~<} zaOr{%ziv$SRG|NyTHRDFSV@zoI51l#5_N0P!+yZu66Vw6sJj>G>wdd%dQ##4fJbc( z>S$hr+RYsQh&af=+1h%N7s7?sKD&YS7QFRoNAT6z?p49%hpMDx(wg+WM9^{lzF#K? z`}0zvQBQ~G5btM!YGfOSAJcHrNYeO>cm*b3DlW|epr)PpReFeiSa%eJv};|y{8soM z$`G-M?c6YYpD=HbK)#%T9t%XNm5!a#vV|gte+3VJB`Ltkb+h(QIQw*U9t!&$tsi|> zPAYJfx8i0YyV_vG!h;jP+d;)F6iKEel=3GH^BbBNok4}9t^VVP>rv5g*wqa;Yan!N zy2)oPJULw1>pSX8-!IF?%&}H0`G3GgDU{~mBgLeUFbnDhOYqK!v=TwL!UQZ_bcZH9 zgBW%TRR^NQTiJ|aeGp448_F#3e1F`jATf>8xBUtKA z;|yDD=@pksdQi8ZApukvq=P=6eO1D2L2zBKO}_*~P$UVzp+HDV-wUN`1*SnY(Z8jv z6JgPA3`$Lm)cDwPE2~cpk?XRF~b&}`aR2!t8z9sG?PN9 zDnxT-rkjudS<1%KRu9MT&exP|Ah(qt+>j0eeZU1L^8BCn-Ycr9?};Bh0i*~>0*Ley z5D-v6dT*gCNUu_*H<3;#5l}-Hl-^N#N9i4eDjsSXyAD1FzG|Go`+r?i>rY2yTDsrxro^?HX>(f#9s6rz9C z+72>M6T=}yz&Ftxr!{`R$0mzNh0pzpAa4c*U&rG$T0@UEP4#`uifMWadm#_xf#*Mr ztR(!{l6ipA@iH8-+7y(#G_)tXl+eguG#PNU98GFk+O{}je8ZP7Uxv-e9d$^CAS?7? z+$ancqy!jdu%C0uTpK=*M*k=)FK4VbeXXx`@t=d$H%m2Yn!n&3s+Uc$r*I_5B@}XR z==MuRGY+3?(W*`$_M14O%n@{7>nD-hDf;tTpd-y%?Kr~uBN@8WhR<;ss5jr|`nwP8 zl++=n_QQ6m4lmJ*BK-oZLAg}nkyq=uT>*0ak_i_Rql3}UpAoDB!oquFXy*zZLR1(j z=+(NIY01rLl7gScE{n@r-6;|UN(p<--Qt8BG0qQ6-FVWan3%Cc#MWe|MZOXp3A%_^ z#P1G?JMZ*=NZ||F6oJqHS03g}V5k^qx1v>To7wbh+Ho&>OOOvy#2Fxn;C7DOj%$($ z25ugyTwh$=a4zsnGdzKi*t)wt1wNM@o~hRL1m{1wWUT-XOwOQ!>49In3z)i0ej%BF&&m5{#1aI{}fxhxk6kh1~K`OQQk2~o5B+Ng)wH_bOcB)xz>y$)11cu6qEYX{{9Y_u+Ji1ltzQ94@Le1Uodk7@v57KTO> zJ%1@G77Qv!E|$1nKqj;J5C8BvwMZB0(z)yT#mOlvXW^&e5ZQ+lpBB%|3A+<)05ahs zZt<6Qym=BR6$5?>*(_+rr z5^3b6<0l6D;W%N(uqLLDY_K=iY+o9P(CFSS^Drlz`#i)4x>jiU^5<98fp-x39{|_) zAR&Of0ZS6@fA113nXsbZw3bJWxwbFUfAQm_1`MK4))?#`w9m)Srjf!Jq@PgxaOFN^ z@)r=#I`N0Gzhy1hZ;*6}C6{x?*Qmu20}UlYA`WKL+3D$l81u7lHXV4bQ>SApWh~V` zGFc132g7JbG~O!cit?rJ4oWz2UojQYbTpWotl&pC|G1Xcrr%zv`I;G|ivIVo_b!=Y zjPX)#I8b0Ek)vHL^SEF%ks>rH7wxM|+Ira)Du5!5;-vj&&n<@iYw9a2^9`L`M)WcI zHYoWSpB}%B`^UA{mAtT-Rg+Jz6i_tfnv=M4eB1F7lYj16KkpGd*p6O>KdUG&XYzZT z*0zuziW*RTGR?5Dp6d)%#J?QU9r{xL6mhWMhg@jSY$+0QfL-M{qjp6AT@fl9n`8~!)TQ~0R-nh8Mz zAo}wvVvdF}zTY>Q3mYdqCbIWI(sbf->Cl1nCnfere7ykq_QlaQgk39oUC%B!Gu?{F z_MD^1r-mJ3N96Ko*jtoU-9RBzPW1BglW($9zXG{$CrIcKDFW7#%{r7z6)-ImcJwGv zngo^?;y?BzgeR;VBWP7?s4*)*aX{PSw*0&B02R`0DQuX9(Nw$7)~nG}5tzA+ERAko z&69yl-HgeEIyqh>mqZ-#-YJYU`b!+b-kV-Q!8WVJf;&^g=G#M$%U6nz?xrO#{h8|A z*Z%dp8eK^+Uc@N&3{+22|FC;id}V`E`iUUGJckp<5yM*U!o8%iRu*PvL1!c-muD0x zO?W%4F1JEP(7$n0|M#{JRF<~F(KgiF^Jug^T>^u9#^8NtpN8;Lg4bh5@Asz6x5&d& z(A5y$kJR~$s;ANUYUUqi-5t#QUuKL!(m4y=nOHYf-^X8mbVmv)ZxRebXuqEudJyER zA`+n(`*kY*Cb#AVx};6`uJPlUu6skf&%k?ULN8@$CN$s7kz)dVd1dAXK|+jME?Za~ z`RB&_S1-C#yQ3itg$2?V5N}B5K8QYEHVpAUo+(qHPD(_qhA9XZ`NtCjV&8sA=EfDS zGr*MYB~DHb&laz(5)9xW8$<;cP=6*P(Q81WUs?$f0>PD z?K!k0YY+S3rH5E7+dQ?VqoccQsop$=EDf+{|3>F&-Vo#duwws~#ZCWy==cq7*^tib zr6&A;7S@j&v~i6@Cy%m2DAr+$VwqQRM<7JgFY|2IZV}I%csh_;L~B5nSD?M>98ubf zXG|PX4Nzr?sPVnUG>$0OcTJlN_P=;zxHEz}_QI*>Cr$_z@4?d$s|&5w;YO*yZ*N~j zZhWzTGJf8V`ZAn2Fs94Qs32i0(Uws4l3g*Zf@zLzsiLCj7eBxTX}*?Es2D3&_TPEq zax4~oXkb6gETW);7!bAup!+4~w@3!CRso|ON!XJ#Fm!sSSNKMw3wi5D97P(YS%v#$ zl@Nl|nElrt=blI;{Fypp(Py*+^T&75+QPyjOwk~k;vw|}*+gxk`pUnPwJ&we-p_{9 zNB-KGWYKM)9tG}K2mILGz7_kdteIjt6bKm4^U!zY0wV_JotVOAj5D+Cnmy1DAXMbb z>5{}?L2cEW_+Qy=#;LzU%u*L@rNfsuW6{MEqM`R=3h~{;V=#|-GbAi&2)=9ecm|)2 zJ>gN+^JN`3B(@nGPyD`XEuJ8r=bY=|9bBq}F{QZQdKS(zh0~HYF?KkJ^`GsSeVim6 z!fv&QvT#Q?lo%N4rp7&iXOoGV+_~ zLl6@U*8c@#v~K!|DqQ+SnBuIf?mX+TVf$t_@*QuCu8Fbn8XMFwU0?({QRXagDqM2- zdu?`l`16|y?%BT#{tb6}t~FPy9I2@r%bV|ZZ02nGwVggf$Wsf>KqxMx4K{4Sh^Uq< z%q`x}%m&_k;+;AizRBwvz-1p^Rj19MA zJXEjpc{9+Tm+mgA+a$>tD-nRqnX7$7LL0C*-i9HoNSmuh`r*_%^ut!49Wnjey?r{M z*|2BAsY{4r)I`t<@96>R!aq*K@4@q4Lc^?S`x+>HOOI|2c!SV^!wol z0kW%LI!rV0FHd;yg%Y-lWjjX<)}xU;n#L_`({UY z)q-c&EY81;>R2AGV*lhMUGvyz{$tl*f_P%%=)<^?b|EJZk#8>eD*6X=+OIFusGvO5 zmWnN=8r#Mu#$jE}jpsf3U}e<5w0FC2XbEKYl}awASg)cMvs=~eLV86}Qi3epv@4JU z?G4cr+#`wozk2~_V@IVV+$}(hsTas%$X1gi&KLXpp|glODV8HDAjhYRFXn27omEsD zqp;!h=UT$aEs*?jUoqU=8IFC$Xzw&Y$rC*7rTye-d=1r(+^gU!<(5Yp-V#TBA!Fbq z?&BIGqXzvBEIGb2um!Hvnan;jzT{Onnfngh8!a5}<}o~c2c}Bzxo?dgG$$=s*gTMC zGBv;}P0w+~6wdZ|;x#F(6KxhYmW{gtI*z>dgFC3^afiLchuq>y=}O%`JGH4p0_P*kp$(| zc&^(J{NzQkk=zR7QqnO#x^7+-!n=m-txG*+N!?e!6!5cw{aM0luPfD3Z|oTHUZhoH z@4foE^qM^YBsEdur!!}+*qTF->2O^Y`oIu(`HE#idcVY>$#)HJAs#F>eo;xGcIk!O zwiX=P{k5^N@rzsMb}F!?v=dEK7W$_nknEs*RNhNd0nm8Lp$G*e?^{w&WTJnlz0T@+ zkp&gVSNKIWo?wlm0negF!KJLYy<6IbyZS3ifRsZL_9tdARfifq2p$A4P`g%ER+kSS z&rB6-QImQSniB5_6WuMl7S>Umq;o-~-gy~%QCLc?c#Q}~^}JgfpC@~2t1ozX}?g3m_k+9pBvR&i^KA$!)5A13Gm7PLk6FIP+7lQB9j6<$fQXZ)L1X@ z;Vgil6~4=eB=UdHNN*Mx>P0H#In2tUkns9W*?;VtP0)K$&_(~zi=p1$-mXbMIrq>& zrLK41+I|Pjo*GR>u9QbzZa!4btGqJ019tF5!#;Yjb#f4Sj|O3Xq=D>2f4T`En@I91 z&JrPSy|iPJ`n!md_C$|!)ZC3&!U+89lpe% zG&*oQ)GT!da-NCK9F|o;!JwDh)I@%og zwtfB&$QSSDLcA?@G1qzU;Ml5Wrg}4Y-Sw>&jut$_3UhUorX5x_kBy83HIwK2)2;9O z$nu&D!}Wu2llWNQ)^>IeujtWM zfr-sGsiQIw2F6_RqGXYj&pSbyua+q!)Ic(5JJNH1-nw3ZX{i3MfJh!s;Y6f;{?XYF zE`Sm){Qxm$>X!D7xAnSW+Vjal3`n@WCT1eKX3p-o6tfZtVi7hN=A`E%UQI!S39&CK zB539o{t)qAop7oYGxRA%e}hEG=RW<2uAL83dwBW%;74J{`wu7H?l*G(S5+&Tq+&0O zLazZ2YFSdoABRjbh{1o4D;Kz8LPn^J1V!B@2__zv&W5Y8$Qhlu6y--_-D|2P1K-*SgEm0x=pbA`cC<$~vwh_8oXc zA@B9=i|beR7jyaclAD!d2>y&G>e1gvA}RW=W1vZ>C7{th)wh(7K?FoJKEK>#46o;g zr){)e=9iZr>NFb2h4j+3VF9GtE(61apL?9CRgaPtlDkH zvneh8gc^3cKRqHt8@LNl?r)otoDN(VBc3cG@mYnuR{TTHz%Mqr#hX~r4R}wwiqMhlI{B7=nwZ5JaB2T$&T~dmJd;it>${s&xw=6h7r@=(#?*0@YRX zxO>R$C6H)tZ8*GZKMYnT2=b#Z{h#+idmmzdG_+RV+Li4xnepqG#~E9^DR%h)avWZ9 zK^Yn0S_pMWTme3#4~RnR1Fxb>Rj-&IL8kbZBK?+kW9-6A@B~^o$W;sgllkg$*V_*# zWD{2UKv!huRswksa7B&#kAmSgnB2%{Y7v=pxb!JKqolYv;kM?pMfyDv$FS#UR@Lxn z>^$j(89O2S?ZP`CD-=_B17*!nqF4%aI+6d?Mj5!bsTR za1J62)!9W4y?ruQ&^Pllp5b#oSWb_`klc|9!grBgII+dVY!GqwAkPo;=8~Il}6(_Mxx=p$*+6K|h0ha6lYRC6L;pLrYazDjrVH$Xe zW}m3)gBNLlmvK zT$ez{a!8}xwU=kxo82JkNk2d_Q3n+=meG73#*PNDj3UuD-9rvCQh3DI=doIGr1xMy zRe(J7@`hTj5+Xf4T{5}&j{z8&GEST#lknqc-rI%TB3?5TRJO-JZJ3nN_)R`BR}hR` zuoJvCkMwqP{wkDEESy8n_HKZYOfDJWOWggQ^gbL)168N3R2|<64^+KvYWc7J8=1b0 z1}U1TnT&mQ@CY1J1o8eqE=^X6{&Tz9pW8pgMdNE5blUK*uO~ zFigzAP~HF!GM&AD@Yjg zpPomhcF8l&=HfL4A~p(+AC?vtSxa9#0FcOiIAP`}9~XuxbN(;}g}n;P*!U_{l5%J2 zDxMu?64P*36*-mkpPbP6ocI3WJY0P@fIEKUIPe= zS=-S)W1OH@O9jsJ_@UL;ETg*;p^CSt*3V}WPea{S!|5+pkQOjN5_STQ+R60Uay2rt zC?|HQiZA2^OPK>CH%TOzm`qK-&-7hZb^Od zTRVfn4O*A56@Y+t2lZ^ZmxV1*B2V_`p5{h)!c?&*YkrUJeDI$BHO3yZp<%FBO{f(3m!N)=S$;~ znd`Xb6uqvwUsJGH$=F>5?e&0R+U`thfUU%b1oz{};Mv*C@A7mK_qr}H_Tra)BGDaB zxeLFf>KtvqZKbRH4bQXk+v>V3=B-{jkN{03F=9Xgo6`OY6v2vQLNb>Nm*zA1n8I)s zgy0S7sVeFaAC?^wBcqEYRXt0y$B!Sg9zI7Prp@0J|Iu^9y+Qawx?RqH9!xOlMGtzw zT7GvdJ=NnXV&w+aF)57Vt@nLShF^K(^w&T)C;nHO;ODjTFKEV$8)pIEdbM6lD3qOp zR{^fRRa zI6u~ux%irBw|88IcI5F}?J|e}jP5pfto|NJ)W&1d4sa*GcfxQx#(G~!=nb3B3bqqh zBwfX`L|iiEU8+J;(78N?ALuBJHeBnd&>Xi)&_G{pG$>59wJ87y@fb`;-MNsb8 zj9(S<|JupTcU@j4yh9Acx0H zxHE|{^I2QE;EHwPF%39VAnH)wS?v4Tfvjtt|ML4T+YSTR>>Wxz2O{@mE?qUfeV#}$ zyvX;{j|xJiiURPwpzUx5jDa)?)?w466JroPhUl}sjFoe*jo#s`6}u5o!` zTOqRkm+yZ&_Sa^eqpi9sI{hQc>F)5e*F+h&DeY=id?7*F;%-`#3SijXi zz$3p*9L5fqx;>;-{nr$8-i|=%y8BF=8f8b1(qK+J!VVjuNvxI^y`HwFz#zD&Kg3vs&yU9>z ze5B|@Ewwy#j|JScC-mO2OM|%&=%(1*kI(MFSc1_bEVoUFuSIu08=c}Hssc*YGOuzd zYVJ4-l~;^+z!46+!cP;925xwHU_o~IQ2(`VSNW&;JY$@7r^S!QuCH1r-h4IRFpIp7 zTF;G8;EFK9{?38!*g`9RBGvE+L_a-P^r&q(@q4iWm(G>f3sMV_``7%0%i}KFqTI$7e zw;&Z%7O)kZIBxyV_)`p+P+Mjov(Y-#m{rfFKO8G(QZ6*Fo5$vTlAFBDvQ55 z9pC~Q-~zv1yD(=6Gtb5+g7=-MfA_o_+K5D?5#fsQJZZYnRTLXC!aT zH^~GLgkySUPjGYpx=h}}pUFh+DCJ`D;-6RBu4tJWI!*;SU}(N@h6M3p=jt z?ZdlskPzzy|KDHDn>(i8jOC;aaoDgbLKb$KJkn>O7C zAzz9{NAoIm*{vweKIB-p-uID<0=+RU-oe4)_fTtf4*K4mvJS9~jPVW;d;KK(ZoCtj zs+scl;eQIxZG!F|TWA-|@c&LYYGxt|W<`<&ZiAd{GP-gZq8f2X21^3#G02;M5efyF67v)4&~JB0czGqoyL>{Nb8{O zTVM|V>T*|$=FE#tQ4xPIp@J`6A_1{7leV^YnuAT+eCgyP@Oc;&q0hDbsJK5%_nH_Q zB57}ikn)ZzybFb@l~92^M3Jzge8LLTu&jdVjr8w0e~%B!2s*^-J819x;@OaqQK%7Z zU!nh{Yt2<+d*guQVwmC=NBMpf`%_kGq8n7rt;UpNQdlsZF@J|?_KXW+1JLUPr%VJ# zzj6VF5I+nXt_IS~4+l3K4iZZis(J#IRaFfEO&MAqRAA#pS-};3qyo}M==JSFUbth} z6Cs+~TM8Bk1T)G4zWV}gxxW~0HFHo@UQRbuZ#i*#>8dar>!n{biH5?!LJQ^ceUUCz z1PySHq8hTeG1VHrQ=<}oH%z1n2s2T{e_aG&SApGyHo{o-{av_(>gvm*OEn{-CXk>6 z%P>VcM->-pV0(qDHh9{>=d%|s6}w2YsbZ`NC0j>CAmDfvSitMMD?3mS9#=zYV}?jY zJOP_?vVCU2BF{$lP(?YPavoY^ywe(|4zgAH7WJLCss)C`QDE6Qu|J);TN~j^a50vF zOD9`aTDTZfCI!jc1&&-85D2?NY#l^ea7%eG#|I}nHou50NjoWxylR_sweW3Q@XW=^ z0X1N260<6X2sLeEW>djobAj}MwLG3V@B*3L0V5-$MI^2=g)ssoRwf%^Fk02R-eHg; z+m0939zOR%JKs?JIEAIbm^n6jGY?Hp8cyT<4+vO`US7?BHFzKp!5vm($Z!k9qSnMD z4MqUP1J*_wJB6QujWg*jwbNkKW=8o+=NRRXJ#zKA;%OQmKc1-uQ*juE1jrU%)6F>P z;w+@F$Rk68K+sWVMUq&=$?tL3#OA^NebypzrK^{je*p#U?;30*RwD=G{l1g$NWyZ| zx=hDwB}nh1zVtj(w5{qpJ`T*~`qJ?G_itNqVm?21Fz468rGr&z>3IOaFm8yC`PhS$Ir^)^#6qL|8X5t1erO_?MYNnQX3wViP5(Af;FK}f9Dp@+>GP`a z8za;h0g-?eNh{i<007K%HXx1C*Gk^%Gl6|aZ3095U;#@aYUc?4j7BjY*HZfjWQOfSH z3Z3q8bs~}h3Z6LO8XnDWv`Gm^os5S;TDX8K7Bnm_%t@RKoImSdq=Y~&62d9Fzb@xB z`7SOZw?XTZgP#(0FWrc_c5w~%(9TVrh!WO^5X}OCF|0+Nlu4^>`)Xzir}R>IG|C0y zm@dSkE(%izot7PZZq(u*YbHB<@sm-5Z*bAajB&?ed{>9eW<0;t7;qkDgw3`Z^h_?~ zb>Y(c=3Lj$IsdLMg>3orQyUVYWJ|6=k6or`ZNqH&1du}ZpGp2NyDVieaC>gLV#nvHHeQK(rzKv$a}C>LAa$_Mu<+wf-| z2q#?Lhx~v$t8&pL>E-xwoGJ?eP@Dnvkfz(yBE7Vl8UAORbMC$u!(_;6se97KV&>7R zBWQnB4&a5!{;8{UhfSKea;WWy#LT>saZ@kZ_5lmF?xkE53aUIF7`%P(u?A<(Ksosm}mH4`y#07G{?*E*O!+{ zccnI_S>k#jW(CK2*2N`O7Y=iOvB8UsmZ-1Ed#%qy|B|mCopp#lJOje4$_(j}xlWvb zF`PHIBE%iJEzxn*XEl#7BnBmgG=T^?Tr;ubx4t}0OZHhhQ7bx48LG?iWHh8!dXm^0 zP4bD6J%LD~=C*ir5u>`x1X6BhZaPiHBUz6#!X?&3S+h zNr)9GDg9p)OEQj-za4pAP4gCKF64R)SDH!^E4AP>xtCj)Rz23=z>lrewCgFYJ_3I* zNMJW*$opf?#^>oqtEC^)>Wrd?w)iCrqom?Lspt?s_!6ib2K&z2@Dj+RJa$OmXyMV6 zwG1}wHTER(qA66u{Bp7L zBpABFl>`XNIk8fe+HBa+E<;+%1s8}*r@9EBhj0&2a`!)^rHyYNuY=xb98dBY1^K!L z5GwGcd<|h9n28e>j2XNG%OC)ZaAh0Hq(7^Dw%*B(rJY`c4I#T~lvNQ9J%Hjzb#QPn zj`TCBP-aosp$)bnvm|^Dd9pZ0qfF|O=?K>5RP{d2x{F(ACRZ}q7bD)2$;xdtZDb>V zcs5~oWx+Vrem#Ai;p&to-AL#>P*$89GW0P?=v2Qs_)ImkA|@YQNqeK5q>f~n>Oc2B z=h{G5$ZIa#|DESrn4wq{G~#ISrs_|_24*h+1F^l5C|1lMrKk#5`z&Dbak`uXXPoB< z-f6AF&U<0AH*>6gMvU`&uMN*-!6T!)F}*icdwS&&B)%t1Lr{UXS}pfkJNr764B%IUNAO9ma|FkLLf&o#JOhG* z13bS3c#TONZ7mSERjDvhu(jw2E`M++>1xS2vktYa^zz@2?_GJ!CiGS{fGAxwA`P)a zrM6Skznt>UlLk|3!^l0?M%!&!Q4t^`7aAC_*yk1YHgC(R&U;adIvN49QN3ZC_2U-e zc|K|{rngMq>Y!O<`~2)Ec7%$RmMUkaiTsre@UrZ0HNBGi-Ts0=dEQHk?z`7KmFkF= z58ipQV}!1(N9Njc`wUWPRbgwiZQJwXrvUjdQ?9hJIp;%P+J_SHWhUxPlCP;0^#CT1 z8f~VYrCk2roH5G)+Yx+k&_xhwGnH%yU7+db{$<3I-#3jyR3bY65{{M?lJyC<9zftJ^s%6k3Zk(2tE+>`d-#|FrMz2Y2E;z&ctLB?m)~XDVcDu?^T`Q z+7d(07VVq<5?cANdR5rn{BBLQ97;`bozSSVr&-LISI9v7$suCmhigIx(~4h9edEn? zD!QDPLZo7d&w!#Y^c1*$YoBLhHL_0(->W8LiL70Be50Xb9xMG+C}lSRMHK_*_br;4 z8E{FE8QomSH#O`de)`@GAJH@BN6{T8+-yftUGb|Tsc%YT!tt-0N%CoxAkS2j!rk7k zj=7Otf>G>1U>Y~(-jzqN23{i*{k9u&ZfQKUPLq+#ND#N5G_#s*L^KE4*gv5CUjdYfwOFe|Gv10ORfw?6zjx2Qk0>IJpIKG zOYQ`33GC10l2O?O0P+`C_X3<4ZO6j|pJk6ZLvc3<0Zfm#4BL@Pcckcyl6QAf_BlSZ z9JM77BzrP>YhRZfHAvcdFCttR?gvA_cWj@=l(|wq()^s0dH?XVkM}gT#(1UXaXilO zQ}^KVs>8mKqQTQ5#glR>@{mX8%oq8`icsuI!I+v(&9O_@h9a7x~ZINo7=@Jf@& z$o^@oURtz)0rzA@eTC?HWMSGh$(lv_eQ=N^EEa-#8N>HT5=WWDHbpr$FGA$B8~T_gq#@tS}ZkJ>l@O0Z0?|# z2-H=$y59>oL)8Pl9lwn(w$lxi6#uQxHG5(3u@!P5@TB~^zG|>3B{!oO1t1z1{9H{8%;eAd}oXs;iM$A|RE39{d*|2D6liNaN&}7}c5o zuoTw9_*l{-;NbH24O6dcxc!gTft8Ypi?$6J&XYT|043A4+KgMR&COdADGw6`Oo&)~ zx5f&MVcD7YpKZS2x)GBRAV1=D&x^Qi_J+OudNAqtXAl=s-IB-_iF0Q%fL=*}Sd;n- zg4ve4KJe$?FYEm&J{TXt$FT#WW2OcbfA4i2=u;-9W?L`rXN~?L+^+NEtwA{x2?OJ` zdO$_T0|jLJ#zdc=*J+Cu>Gcn>J=PyQSLY@8|E)GZ@INa^z1cT=DBfB2TIPBOKcoVf zTmD&V%K;U=a`zR}zrL9o=~&6T@m&6^akZDoP4wvC`@TQ`)Gkn+{>kQN6*z9F9M{br zIQ=P_=e#fU-;!mdbMWuOmxy4TOoHKz&Ug?k!iB~RPDl&wPK6V_7C z10^W``RnTXofhOc&XLIAIgeH;OS$zcjGk1QN$_N?IBx8}Eqg4_bX(9WX7~$P;RN}2XOacySK}Kmbsh~v*4eaHqSc_Fkreg1=o-meE>KJ;ge$lu7~Ssl zmWqi>dc6IM2Eypq(ds?Ah>L! zEg)v+XQbVSr>BpI5&>Gk-$(y00Bdbeh*{%(!_(L?_w z&Pl!qb5+oiP(8&W#w4=E*(BzV`;bS(5O)5ZTv!lLN|F|W&iy5<$Y{)flEOaqYOC3d z-R#6)UMQPLNTJ@1m0Wi}B1{#R^;F>N3Me$;n~PYJEfxj!jkB*tvH_Kpi<312&QGqJ5+p4A*##JXL2 z0A3JN5>tZobt*G}N67R#Z+FxK6*ZDH$YF=N*obeXu%o;2dfw$XL zSOuDQ*3?^&E1yDepU(O^tcn#z$lGaX`K1FpVHg`KLjpwx!1=orFi&s!H?`XHMcFIu z%kvbUq^qDcI9NUUYU1BJX~`q}=~)K;h;4sYW^W6#VI0`CbF5^w%;|rL=z0Y~sl|d5 z!~V3IlrgTx&h?Aer-D`An+sE`XOr<}m*&ZblfK5 zp^qWam4ly~p99&HlKmk->NMeE*LH7sNABs&;*c?$z_Cn@)v=4hz)@)TW47ARNgNlW zzAho43mMnAlU*&H2>xVL>X~nlNV<+-2w8X8bfd9Elb93+nn5q2Uvr%gW0MFF_BiWP zsGSEDtUJX_`;W)#kW$?WJzlrPoXxh)etma4oM+^KaQmNQ=4Oph>ES>R1tzbX0bo>( z>FMvD$~WDCEW9`n`uD}@UKmyfcBC(6Y?G|8KvP#P;#m zGR{_|hx)1&Oz#_5V&eTZw&neYn%G)?kLZ|s1{~P_+-Jdhvvm^?^QfWM8OTr-^ut8H zJ+b$lKav8%5rg!ffqOB7Q_5b~A=KDUl1ASb;S!QEfK~qB&3){z=7PHS-$%6`F%S|VH?n6oLB9NaM z0O@L?Nc|ZDV3aVOc$`*Ag(zM!+1u@r!;%6sEsE_2FiRDaz&H1O77JMxM$w_%$s zT7&zt*A-5u+XB)FYbn_ER0R|(VYIO90i!M-d+UUr;#C60n4V=W5}EKq z!ahK8z^vP5@;kmmcZ->y6V4}Mtj7a~^KpQH3|>eLBC7xY!~atT1!+1Lh zt?%U#qevB5P^?C=Xf%3#oQycMGZuKF{(~M4hoAnE1ZMFNt`Fbn*uRZ|mv;exrm7C2 JTG=Mz{{W7BA#nfz literal 18388 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 diff --git a/samples/MADE.Samples/MADE.Samples.Shared/App.xaml b/samples/MADE.Samples/MADE.Samples.Shared/App.xaml index a6d3413..477ca71 100644 --- a/samples/MADE.Samples/MADE.Samples.Shared/App.xaml +++ b/samples/MADE.Samples/MADE.Samples.Shared/App.xaml @@ -1,7 +1,10 @@ - + + + diff --git a/samples/MADE.Samples/MADE.Samples.Shared/Features/Home/ViewModels/MainPageViewModel.cs b/samples/MADE.Samples/MADE.Samples.Shared/Features/Home/ViewModels/MainPageViewModel.cs index 076b69f..99276b0 100644 --- a/samples/MADE.Samples/MADE.Samples.Shared/Features/Home/ViewModels/MainPageViewModel.cs +++ b/samples/MADE.Samples/MADE.Samples.Shared/Features/Home/ViewModels/MainPageViewModel.cs @@ -25,6 +25,8 @@ public MainPageViewModel(INavigationService navigationService, IMessenger messen public ICollection SampleGroups { get; } = GetSampleGroups(); + public ICollection Samples => SampleGroups.SelectMany(x => x.Samples).ToList(); + private static ICollection GetSampleGroups() { var controls = new SampleGroup @@ -48,13 +50,18 @@ private static ICollection GetSampleGroups() "InputValidator", typeof(InputValidatorPage), "/Features/Samples/Assets/InputValidator/InputValidator.png"), - new Sample( - "RichEditToolbar", - typeof(RichEditToolbarPage), - "/Features/Samples/Assets/RichEditToolbar/RichEditToolbar.png") } }; +#if WINDOWS_UWP + AddPlatformSpecificSample( + controls, + new Sample( + "RichEditToolbar", + typeof(RichEditToolbarPage), + "/Features/Samples/Assets/RichEditToolbar/RichEditToolbar.png")); +#endif + var helpers = new SampleGroup { Name = "Helpers", @@ -63,26 +70,35 @@ private static ICollection GetSampleGroups() new Sample( "AppDialog", typeof(AppDialogPage), - "/Features/Samples/Assets/AppDialog/AppDialog.png") + "/Features/Samples/Assets/AppDialog/AppDialog.png"), + new Sample( + "Value Converters", + typeof(ValueConvertersPage), + "/Features/Samples/Assets/ValueConverters/ValueConverters.png") } }; if (PlatformApiHelper.IsTypeSupported(typeof(WindowManager))) { - helpers.Samples.InsertAtPotentialIndex( + AddPlatformSpecificSample( + helpers, new Sample( "WindowManager", typeof(WindowManagerPage), - "/Features/Samples/Assets/WindowManager/WindowManager.png"), - (item, compare) => compare.Name.IsLessThanOrEqualTo(item.Name)); + "/Features/Samples/Assets/WindowManager/WindowManager.png")); } - var list = new List { controls, helpers }; + var list = new List {controls, helpers}; return list; } - public ICollection Samples => SampleGroups.SelectMany(x => x.Samples).ToList(); + private static void AddPlatformSpecificSample(SampleGroup sampleGroup, Sample sample) + { + sampleGroup.Samples.InsertAtPotentialIndex( + sample, + (item, compare) => compare.Name.IsLessThanOrEqualTo(item.Name)); + } private void NavigateToSample(Sample sample) { diff --git a/samples/MADE.Samples/MADE.Samples.Shared/Features/Samples/Assets/ValueConverters/BooleanToStringValueConverterXaml.txt b/samples/MADE.Samples/MADE.Samples.Shared/Features/Samples/Assets/ValueConverters/BooleanToStringValueConverterXaml.txt new file mode 100644 index 0000000..bb03979 --- /dev/null +++ b/samples/MADE.Samples/MADE.Samples.Shared/Features/Samples/Assets/ValueConverters/BooleanToStringValueConverterXaml.txt @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/samples/MADE.Samples/MADE.Samples.Shared/Features/Samples/Assets/ValueConverters/ByteArrayToImageSourceValueConverterXaml.txt b/samples/MADE.Samples/MADE.Samples.Shared/Features/Samples/Assets/ValueConverters/ByteArrayToImageSourceValueConverterXaml.txt new file mode 100644 index 0000000..970eb58 --- /dev/null +++ b/samples/MADE.Samples/MADE.Samples.Shared/Features/Samples/Assets/ValueConverters/ByteArrayToImageSourceValueConverterXaml.txt @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/samples/MADE.Samples/MADE.Samples.Shared/Features/Samples/Assets/ValueConverters/ValueConverters.png b/samples/MADE.Samples/MADE.Samples.Shared/Features/Samples/Assets/ValueConverters/ValueConverters.png new file mode 100644 index 0000000000000000000000000000000000000000..3e7cb18cf01b9e5b1c7c37e88fc00eda9e5242e7 GIT binary patch literal 7719 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 literal 0 HcmV?d00001 diff --git a/samples/MADE.Samples/MADE.Samples.Shared/Features/Samples/Pages/ValueConvertersPage.xaml b/samples/MADE.Samples/MADE.Samples.Shared/Features/Samples/Pages/ValueConvertersPage.xaml new file mode 100644 index 0000000..9492333 --- /dev/null +++ b/samples/MADE.Samples/MADE.Samples.Shared/Features/Samples/Pages/ValueConvertersPage.xaml @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + +