Skip to content

Instantly share code, notes, and snippets.

@OnurGumus
Created July 19, 2023 16:51
Show Gist options
  • Save OnurGumus/c7c398cbba75955aa6ad45f08ccc4f28 to your computer and use it in GitHub Desktop.
Save OnurGumus/c7c398cbba75955aa6ad45f08ccc4f28 to your computer and use it in GitHub Desktop.
nile
module Fable.Elmish.Nile
open Elmish
open FSharp.Control
open FSharp.Control.Core
[<RequireQualifiedAccess>]
module Program =
/// Uses `stream` to transform a stream of messages dispatched from the view
/// and a stream of updates to a stream of messages dispatched to `update`.
/// `stream` is only called once.
let withStream (stream: IAsyncObservable<_> -> IAsyncObservable<_> -> IAsyncObservable<_>) (program: Program<_, _, _, _>) =
let (modelObserver, modelObservable) = AsyncRx.subject ()
let (messageObserver, messageObservable) = AsyncRx.subject ()
let messages = stream modelObservable messageObservable
let mutable dispatch = ignore
let msgObserver =
{ new IAsyncObserver<'msg> with
member __.OnNextAsync x = async {
dispatch x
}
member __.OnErrorAsync err = async {
()
}
member __.OnCompletedAsync () = async {
()
}
}
let mutable initState = None
let init' fn arg =
let (model, cmd) = fn arg
initState <- Some (None, model)
(model, cmd)
let update' fn msg model =
let (model, cmd) = fn msg model
modelObserver.OnNextAsync (Some msg, model) |> Async.StartImmediate
(model, cmd)
let mutable hasSubscription = 0
let mutable subscription = AsyncDisposable.Empty
let view' fn model dispatch' =
dispatch <- dispatch'
// Wait with subscribing until we have a `dispatch`, otherwise `startWith` messages would get lost
#if FABLE_COMPILER
if hasSubscription = 0 then
hasSubscription <- 1
#else
if System.Threading.Interlocked.Exchange(&hasSubscription, 1) = 0 then
#endif
async {
let! sub = messages.SubscribeAsync msgObserver
subscription <- sub
}
|> Async.Start'
initState |> Option.iter (modelObserver.OnNextAsync >> Async.StartImmediate)
initState <- None
fn model (messageObserver.OnNextAsync >> Async.StartImmediate)
program |> Program.map init' update' view' id id id
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment