From f14b7b22cd954cf2978f4968e53e5ae51ee77247 Mon Sep 17 00:00:00 2001 From: dim-37 Date: Sun, 31 Jan 2021 01:44:27 +0200 Subject: [PATCH 01/40] Implemented basic navigation --- .../Elmish.Uno.Mobile.fsproj | 2 + src/Elmish.Uno.Mobile/Navigation.fs | 40 +++++++++++++++++ src/Elmish.Uno.Uwp/Elmish.Uno.Uwp.csproj | 1 + src/Elmish.Uno.Uwp/NavigationService.cs | 44 +++++++++++++++++++ src/Elmish.Uno/Elmish.Uno.fsproj | 1 + src/Elmish.Uno/Navigation.fs | 21 +++++++++ 6 files changed, 109 insertions(+) create mode 100644 src/Elmish.Uno.Mobile/Navigation.fs create mode 100644 src/Elmish.Uno.Uwp/NavigationService.cs create mode 100644 src/Elmish.Uno/Navigation.fs diff --git a/src/Elmish.Uno.Mobile/Elmish.Uno.Mobile.fsproj b/src/Elmish.Uno.Mobile/Elmish.Uno.Mobile.fsproj index a9df8797..b11d88e3 100644 --- a/src/Elmish.Uno.Mobile/Elmish.Uno.Mobile.fsproj +++ b/src/Elmish.Uno.Mobile/Elmish.Uno.Mobile.fsproj @@ -11,9 +11,11 @@ + + diff --git a/src/Elmish.Uno.Mobile/Navigation.fs b/src/Elmish.Uno.Mobile/Navigation.fs new file mode 100644 index 00000000..1ec0555f --- /dev/null +++ b/src/Elmish.Uno.Mobile/Navigation.fs @@ -0,0 +1,40 @@ +namespace Elmish.Uno.Navigation + +open System +open System.Collections.Generic +open FSharp.Collections.Immutable +open Windows.UI.Xaml.Controls + +type public NavigationService (frame : Frame, pageMap : IReadOnlyDictionary) = + + new (frame, pageMap : KeyValuePair seq) = + let pageMap' = pageMap + |> Seq.fold + (fun (b : HashMap.Builder) p -> b.Add (p.Key, p.Value); b) + (HashMap.Empty.ToBuilder()) + NavigationService (frame, pageMap'.ToImmutable()) + + interface INavigationService with + member this.BackStackDepth = frame.BackStackDepth + member this.CacheSize = frame.CacheSize + member this.CanGoBack = frame.CanGoBack + member this.CanGoForward = frame.CanGoForward + + + member this.GetNavigationState (): string = + frame.GetNavigationState () + + member this.SetNavigationState(navigationState: string): unit = + frame.SetNavigationState (navigationState) + + member this.GoBack (): unit = + frame.GoBack () + + member this.GoForward (): unit = + frame.GoForward () + + member this.Navigate (name: string, navigationParams: INavigationParameters): bool = + frame.Navigate (pageMap.[name], navigationParams) + + member this.Navigate (name: string): bool = + frame.Navigate (pageMap.[name], null) diff --git a/src/Elmish.Uno.Uwp/Elmish.Uno.Uwp.csproj b/src/Elmish.Uno.Uwp/Elmish.Uno.Uwp.csproj index cd5cde91..17fec381 100644 --- a/src/Elmish.Uno.Uwp/Elmish.Uno.Uwp.csproj +++ b/src/Elmish.Uno.Uwp/Elmish.Uno.Uwp.csproj @@ -134,6 +134,7 @@ PackageReference + diff --git a/src/Elmish.Uno.Uwp/NavigationService.cs b/src/Elmish.Uno.Uwp/NavigationService.cs new file mode 100644 index 00000000..f75787eb --- /dev/null +++ b/src/Elmish.Uno.Uwp/NavigationService.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using Windows.UI.Xaml.Controls; + +namespace Elmish.Uno.Navigation +{ + public class NavigationService : INavigationService + { + private readonly Frame frame; + private readonly IReadOnlyDictionary pageMap; + + public NavigationService(Frame frame, IReadOnlyDictionary pageMap) + { + this.frame = frame; + this.pageMap = pageMap; + } + + public NavigationService(Frame frame, IEnumerable> pageMap) + { + this.frame = frame; + this.pageMap = pageMap.Aggregate( + ImmutableDictionary.Empty.ToBuilder(), + (builder, kvp) => { builder.Add(kvp.Key, kvp.Value); return builder; }) + .ToImmutable(); + } + + public int CacheSize => frame.CacheSize; + + public int BackStackDepth => frame.BackStackDepth; + + public bool CanGoBack => frame.CanGoBack; + + public bool CanGoForward => frame.CanGoForward; + + public string GetNavigationState() => frame.GetNavigationState(); + public void SetNavigationState(string navigationState) => frame.SetNavigationState(navigationState); + public void GoBack() => frame.GoBack(); + public void GoForward() => frame.GoForward(); + public bool Navigate(string name) => frame.Navigate(pageMap[name], null); + public bool Navigate(string name, IReadOnlyDictionary navigationParams) => frame.Navigate(pageMap[name], navigationParams); + } +} diff --git a/src/Elmish.Uno/Elmish.Uno.fsproj b/src/Elmish.Uno/Elmish.Uno.fsproj index 489df10a..f0836c03 100644 --- a/src/Elmish.Uno/Elmish.Uno.fsproj +++ b/src/Elmish.Uno/Elmish.Uno.fsproj @@ -47,6 +47,7 @@ + diff --git a/src/Elmish.Uno/Navigation.fs b/src/Elmish.Uno/Navigation.fs new file mode 100644 index 00000000..e2ae6a61 --- /dev/null +++ b/src/Elmish.Uno/Navigation.fs @@ -0,0 +1,21 @@ +namespace Elmish.Uno.Navigation + +open System +open System.Collections.Generic + +type public NavigationParameter = KeyValuePair +type public INavigationParameters = IReadOnlyDictionary + +type public INavigationService = + abstract Navigate : name : string -> bool + abstract Navigate : name : string * navigationParams : INavigationParameters -> bool + + abstract GoBack : unit -> unit + abstract GoForward : unit -> unit + abstract GetNavigationState : unit -> string + abstract SetNavigationState : navigationState : string -> unit + + abstract CacheSize : int + abstract BackStackDepth : int + abstract CanGoBack : bool + abstract CanGoForward : bool From c2a3c9242f7d5a42ab74493a20fac3c2941ed524 Mon Sep 17 00:00:00 2001 From: Andrii Chebukin Date: Sun, 21 Feb 2021 22:26:33 +0200 Subject: [PATCH 02/40] Implemented passing initial parameter --- src/Elmish.Uno.Mobile/ViewModelModule.fs | 5 ++++- src/Elmish.Uno.Uwp/ViewModel.cs | 15 ++++++++++++++- src/Elmish.Uno/Program.fs | 4 ++-- src/Samples/Samples.Shared/MainPage.xaml | 18 +++++++++++++----- src/Samples/Samples.Shared/MainPage.xaml.cs | 13 +++++++++++++ .../Samples.Shared/NewWindow/Window2Page.xaml | 5 ----- src/Samples/Samples.Shared/NewWindowPage.xaml | 5 ----- src/Samples/Samples.Shared/OneWaySeqPage.xaml | 1 + src/Samples/Samples.Shared/Shell.xaml | 5 ++--- .../Samples.Shared/SingleCounterPage.xaml | 1 + .../Samples.Shared/SingleCounterPage.xaml.cs | 13 +++++++++++-- src/Samples/Samples.Shared/SubModel/Clock.xaml | 5 ----- .../Samples.Shared/SubModelOptPage.xaml | 13 ++++--------- .../SubModelSelectedItemPage.xaml | 11 +++++++---- src/Samples/Samples/SingleCounter.fs | 2 +- src/Samples/Samples/SubModelSeq.fs | 2 +- 16 files changed, 74 insertions(+), 44 deletions(-) diff --git a/src/Elmish.Uno.Mobile/ViewModelModule.fs b/src/Elmish.Uno.Mobile/ViewModelModule.fs index e1ffc014..885723ff 100644 --- a/src/Elmish.Uno.Mobile/ViewModelModule.fs +++ b/src/Elmish.Uno.Mobile/ViewModelModule.fs @@ -41,9 +41,12 @@ type ViewModel() = |> Program.withSyncDispatch uiDispatch |> programRun - static member StartLoop (config, element, programRun : Action list>>, program) = + static member StartLoop (config, element, programRun : Action list>>, program) = startLoop config element (FuncConvert.FromAction programRun) program + static member StartLoop (config, element, programRun : Action<'arg, Program<'arg, 'model, 'msg, Binding<'model, 'msg> list>>, program, arg) = + startLoop config element (FuncConvert.FromAction programRun arg) program + static member DesignInstance (model: 'model, bindings: Binding<'model, 'msg> list) = ViewModel<_,_> (model, ignore, bindings, ElmConfig.Default, "main") |> box diff --git a/src/Elmish.Uno.Uwp/ViewModel.cs b/src/Elmish.Uno.Uwp/ViewModel.cs index 6bbdf3cf..6fc21bc6 100644 --- a/src/Elmish.Uno.Uwp/ViewModel.cs +++ b/src/Elmish.Uno.Uwp/ViewModel.cs @@ -115,7 +115,7 @@ public static object DesignInstance(TModel model, Program(ElmConfig config, FrameworkElement element, Action>>> programRun, Program>> program) + public static void StartLoop(ElmConfig config, FrameworkElement element, Action>>> programRun, Program>> program) { FSharpRef>> lastModel = new FSharpRef>>(null); FSharpFunc, FSharpFunc> syncDispatch = @@ -127,6 +127,19 @@ public static void StartLoop(ElmConfig config, FrameworkElement ProgramModule.withSetState(setSate, program))); } + public static void StartLoop(ElmConfig config, FrameworkElement element, Action>>> programRun, Program>> program, T arg) + { + FSharpRef>> lastModel = new FSharpRef>>(null); + FSharpFunc, FSharpFunc> syncDispatch = + FuncConvert.FromAction(MakeSyncDispatch(element)); + var setSate = FuncConvert.FromAction(MakeSetState(config, element, program, lastModel)); + + programRun.Invoke(arg, + ProgramModule.withSyncDispatch(syncDispatch, + ProgramModule.withSetState(setSate, program))); + } + + private static Action> MakeSetState(ElmConfig config, FrameworkElement element, Program>> program, FSharpRef>> lastModel) { void SetState(TModel model, FSharpFunc dispatch) diff --git a/src/Elmish.Uno/Program.fs b/src/Elmish.Uno/Program.fs index e7fa040d..54f3609b 100644 --- a/src/Elmish.Uno/Program.fs +++ b/src/Elmish.Uno/Program.fs @@ -7,7 +7,7 @@ open Elmish /// Same as mkSimple, but with a signature adapted for Elmish.Uno. let mkSimpleUno - (init: unit -> 'model) + (init: 'arg -> 'model) (update: 'msg -> 'model -> 'model) (bindings: Binding<'model, 'msg> list) = Program.mkSimple init update (fun _ _ -> bindings) @@ -15,7 +15,7 @@ let mkSimpleUno /// Same as mkProgram, but with a signature adapted for Elmish.Uno. let mkProgramUno - (init: unit -> 'model * Cmd<'msg>) + (init: 'arg -> 'model * Cmd<'msg>) (update: 'msg -> 'model -> 'model * Cmd<'msg>) (bindings: Binding<'model, 'msg> list) = Program.mkProgram init update (fun _ _ -> bindings) diff --git a/src/Samples/Samples.Shared/MainPage.xaml b/src/Samples/Samples.Shared/MainPage.xaml index 058d84c3..8ae066c4 100644 --- a/src/Samples/Samples.Shared/MainPage.xaml +++ b/src/Samples/Samples.Shared/MainPage.xaml @@ -7,11 +7,18 @@ xmlns:ie="using:Microsoft.Xaml.Interactions.Core" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:samples="using:Elmish.Uno.Samples" + xmlns:utoolkit="using:Uno.UI.Toolkit" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" + NavigationCacheMode="Enabled" mc:Ignorable="d"> - - + + + diff --git a/src/Samples/Samples.Shared/ValidationPage.xaml b/src/Samples/Samples.Shared/ValidationPage.xaml index db4d2eb7..8e748fed 100644 --- a/src/Samples/Samples.Shared/ValidationPage.xaml +++ b/src/Samples/Samples.Shared/ValidationPage.xaml @@ -2,6 +2,7 @@ x:Class="Elmish.Uno.Samples.Validation.ValidationPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:ctrl="using:Elmish.Uno.Samples.Controls" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:samples="using:Elmish.Uno.Samples" @@ -12,7 +13,8 @@ Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" mc:Ignorable="d xamarin"> - + --> + + + + + - + PropertyName="Value" + ErrorContentStyle="{StaticResource TextBoxErrorStyle}" + ErrorItemTemplate="{StaticResource ErrorItemTemplate}"> + + - + PropertyName="Password" + ErrorContentStyle="{StaticResource TextBoxErrorStyle}" + ErrorItemTemplate="{StaticResource ErrorItemTemplate}"> + + +