Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update FuncUI sample to preserve state when reloading #8

Merged
merged 1 commit into from
Aug 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

<ItemGroup>
<PackageReference Include="Avalonia.Desktop" Version="$(AvaloniaVersion)" />
<PackageReference Include="FSharp.SystemTextJson" Version="0.17.4" />
<PackageReference Include="JaggerJo.Avalonia.FuncUI" Version="$(FuncUIVersion)" />
<PackageReference Include="JaggerJo.Avalonia.FuncUI.DSL" Version="$(FuncUIVersion)" />
<PackageReference Include="JaggerJo.Avalonia.FuncUI.Elmish" Version="$(FuncUIVersion)" />
Expand Down
58 changes: 41 additions & 17 deletions Live.Avalonia.FuncUI.Sample/Program.fs
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -10,20 +12,44 @@ 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<Counter.State> 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


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"
Expand All @@ -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 =

[<EntryPoint>]
let main(args: string[]) =
AppBuilder
.Configure<App>()
.UsePlatformDetect()
.UseSkia()
.StartWithClassicDesktopLifetime(args)
[<EntryPoint>]
let main (args: string array) =
AppBuilder
.Configure<App>()
.UsePlatformDetect()
.UseSkia()
.StartWithClassicDesktopLifetime(args)