From 06155b52ba5c2e67d4869e2e504dc8a426cecc2e Mon Sep 17 00:00:00 2001 From: Jan Dryk Date: Tue, 20 Jul 2021 21:01:49 +0200 Subject: [PATCH] update funcui sample to preserve state when reloading --- .../Live.Avalonia.FuncUI.Sample.fsproj | 1 + Live.Avalonia.FuncUI.Sample/Program.fs | 58 +++++++++++++------ 2 files changed, 42 insertions(+), 17 deletions(-) diff --git a/Live.Avalonia.FuncUI.Sample/Live.Avalonia.FuncUI.Sample.fsproj b/Live.Avalonia.FuncUI.Sample/Live.Avalonia.FuncUI.Sample.fsproj index 1df1b5d..d325ba1 100644 --- a/Live.Avalonia.FuncUI.Sample/Live.Avalonia.FuncUI.Sample.fsproj +++ b/Live.Avalonia.FuncUI.Sample/Live.Avalonia.FuncUI.Sample.fsproj @@ -18,6 +18,7 @@ + diff --git a/Live.Avalonia.FuncUI.Sample/Program.fs b/Live.Avalonia.FuncUI.Sample/Program.fs index 96fbf65..bbe27b4 100644 --- a/Live.Avalonia.FuncUI.Sample/Program.fs +++ b/Live.Avalonia.FuncUI.Sample/Program.fs @@ -1,6 +1,8 @@ -namespace Live.Avalonia.FuncUI.Sample +module Live.Avalonia.FuncUI.Sample.Program open System +open System.Text.Json +open System.Text.Json.Serialization open Elmish open Avalonia open Avalonia.Controls @@ -10,12 +12,35 @@ open Avalonia.FuncUI open Avalonia.FuncUI.Elmish open Avalonia.FuncUI.Components.Hosts - -type MainControl() as this = +let transferState<'t> oldState = + let jsonOptions = JsonSerializerOptions() + jsonOptions.Converters.Add(JsonFSharpConverter()) + + try + let json = JsonSerializer.Serialize(oldState, jsonOptions) + let state = JsonSerializer.Deserialize<'t>(json, jsonOptions) + match box state with + | null -> None + | _ -> Some state + with ex -> + Console.Write $"Error restoring state: {ex}" + None + +type MainControl(window: Window) as this = inherit HostControl() do - Elmish.Program.mkSimple (fun () -> Counter.init) Counter.update Counter.view + // Instead of just creating default init state, try to recover state from window.DataContext + let hotInit () = + match transferState window.DataContext with + | Some newState -> + Console.WriteLine $"Restored state %O{newState}" + newState + | None -> Counter.init + + Elmish.Program.mkSimple hotInit Counter.update Counter.view |> Program.withHost this + // Every time state changes, save state to window.DataContext + |> Program.withTrace (fun _ state -> window.DataContext <- state) |> Program.run @@ -23,7 +48,8 @@ type App() = inherit Application() interface ILiveView with - member __.CreateView(window: Window) = MainControl() :> obj + member _.CreateView(window: Window) = + MainControl(window) :> obj override this.Initialize() = this.Styles.Load "avares://Avalonia.Themes.Default/DefaultTheme.xaml" @@ -32,18 +58,16 @@ type App() = override this.OnFrameworkInitializationCompleted() = match this.ApplicationLifetime with | :? IClassicDesktopStyleApplicationLifetime as desktopLifetime -> - let window = new LiveViewHost(this, fun msg -> printfn "%s" msg); - window.StartWatchingSourceFilesForHotReloading(); - window.Show(); + let window = new LiveViewHost(this, fun msg -> printfn $"%s{msg}") + window.StartWatchingSourceFilesForHotReloading() + window.Show() base.OnFrameworkInitializationCompleted() | _ -> () -module Program = - - [] - let main(args: string[]) = - AppBuilder - .Configure() - .UsePlatformDetect() - .UseSkia() - .StartWithClassicDesktopLifetime(args) \ No newline at end of file +[] +let main (args: string array) = + AppBuilder + .Configure() + .UsePlatformDetect() + .UseSkia() + .StartWithClassicDesktopLifetime(args) \ No newline at end of file