on master help sign in
Migrate client to Fabulous 3.0: use Cmd.OfAsync APIs instead of manual asyncCmd helper
commit1f3015edd965d2cbb713e241eda8ded8c93fe144 authoriko <mail@iko.soy> dateSun 12 Apr 2026, 09:12 (6 months ago) parentc622597
4 files changed+45−41
client/App.fs+24−37 client/Buttons.fs+19−2 client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.AssemblyInfo.fs+1−1 client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.AssemblyInfoInputs.cache+1−1
client/App.fs+24−37
@@ -412,14 +412,6 @@ module App =
412412
413413 let private log msg = eprintfn $"[skrepka] {msg}"
414414
415− let private asyncCmd (op: Async<Msg>) : Cmd<Msg> =
416− Cmd.ofEffect (fun dispatch ->
417− async {
418− let! msg = op
419− dispatch msg
420− }
421− |> Async.Start)
422−
423415 let private serializeEnvelope =
424416 function
425417 | Envelope.TextMessage(id, body) ->
@@ -503,28 +495,20 @@ module App =
503495 let mapCmd cmdMsg =
504496 match cmdMsg with
505497 | CmdConnect(url, identity) ->
506− asyncCmd (
507− async {
508− try
509− let! token = authenticate url identity
510− return AuthOk token
511− with ex ->
512− return AuthErr ex.Message
513− }
514− )
498+ Cmd.OfAsync.either
499+ (fun (url, id) -> authenticate url id)
500+ (url, identity)
501+ AuthOk
502+ (fun ex -> AuthErr ex.Message)
515503
516504 | CmdSend(session, recipientHex, envelope) ->
517− Cmd.ofEffect (fun dispatch ->
518− async {
519− try
520− do! sendEnvelope session recipientHex envelope
521− with ex ->
522− dispatch (SendFailed ex.Message)
523− }
524− |> Async.Start)
505+ Cmd.OfAsync.attempt
506+ (fun (s, r, e) -> sendEnvelope s r e)
507+ (session, recipientHex, envelope)
508+ (fun ex -> SendFailed ex.Message)
525509
526510 | CmdPoll(session, cursor) ->
527− asyncCmd (
511+ Cmd.ofEffect (fun dispatch ->
528512 async {
529513 log $"poll start cursor={cursor}"
530514
@@ -597,17 +581,17 @@ module App =
597581 | Some e -> $" [{e}]"
598582 | None -> "")
599583
600− return PollResult(events, status, response.Cursor)
584+ dispatch (PollResult(events, status, response.Cursor))
601585 with
602586 | :? TimeoutException ->
603587 log "poll timeout"
604− return PollResult([], "polling...", cursor)
588+ dispatch (PollResult([], "polling...", cursor))
605589 | ex ->
606590 log $"poll error: {ex.Message}"
607591 do! Async.Sleep 3000
608− return PollResult([], $"poll error: {ex.Message}", cursor)
592+ dispatch (PollResult([], $"poll error: {ex.Message}", cursor))
609593 }
610− )
594+ |> Async.Start)
611595
612596 | CmdCopyToClipboard text ->
613597 Cmd.ofEffect (fun _ ->
@@ -615,13 +599,15 @@ module App =
615599 |> ignore)
616600
617601 | CmdLoadState ->
618− asyncCmd (
619− async {
620− match! Store.loadIdentity () with
621− | Some id -> return StateLoaded(Some id, Store.loadData (), Store.loadProfile ())
622− | None -> return StateLoaded(None, None, None)
623− }
624− )
602+ Cmd.OfAsync.perform
603+ (fun () ->
604+ async {
605+ match! Store.loadIdentity () with
606+ | Some id -> return (Some id, Store.loadData (), Store.loadProfile ())
607+ | None -> return (None, None, None)
608+ })
609+ ()
610+ StateLoaded
625611
626612 | CmdSaveIdentity identity -> Cmd.ofEffect (fun _ -> Store.saveIdentity identity |> Async.Start)
627613
@@ -669,6 +655,7 @@ module App =
669655 Label("End-to-end encrypted messaging").font(size = 16.).centerTextHorizontal ()
670656
671657
658+ button "Next" GenIdentity
672659 Button("Generate Identity", GenIdentity).centerHorizontal ()
673660 })
674661 .padding(30.)
client/Buttons.fs+19−2
@@ -7,9 +7,26 @@ open System.Text.Json
77open Fabulous
88open Fabulous.Maui
99open Microsoft.Maui.Graphics
10+open Fabulous
11+open Fabulous.Maui
12+open Microsoft.Maui
13+open Microsoft.Maui.Graphics
1014
1115open type Fabulous.Maui.View
1216
1317module Buttons =
14− let button (text: string) (msg: 'msg) : WidgetBuilder<'msg, IFabButton> =
15− (Button(text, msg).borderWidth(4).background (Constants.accentColor)).borderColor (Colors.Black)
18+ open Microsoft.Maui
19+
20+ let button (text: string) (msg: 'msg) : WidgetBuilder<'msg, _> =
21+ Component(text) {
22+ Grid() {
23+ Rectangle().margin(Thickness(8., 8., -8., -8.)).background (Colors.Black)
24+
25+ Button(text, msg)
26+ .borderWidth(4)
27+ .background(Constants.accentColor)
28+ .borderColor(Colors.Black)
29+ .textColor(Colors.White)
30+ .font (fontFamily = "UnboundedBold", size = 24.)
31+ }
32+ }
client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.AssemblyInfo.fs+1−1
@@ -10,7 +10,7 @@ open System.Reflection
1010[<assembly: System.Reflection.AssemblyCompanyAttribute("Skrepka")>]
1111[<assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")>]
1212[<assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")>]
13−[<assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0+f1f6e116e2295466bfea4623e453ffed25d32079")>]
13+[<assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0+c622597942208741d3c804aefd43a0d3c4efc092")>]
1414[<assembly: System.Reflection.AssemblyProductAttribute("Skrepka")>]
1515[<assembly: System.Reflection.AssemblyTitleAttribute("Skrepka")>]
1616[<assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")>]
client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.AssemblyInfoInputs.cache+1−1
@@ -1 +1 @@
1−e379db3bdff4a4a771cdab0914453c7ee01e98a757a35695e8595a28293a349c
1+cea69c3a0745f404bdbfe2dfe0d3d4978e6dac8ccf2ed5f2edd84f58fc06912a