Skip to content

Instantly share code, notes, and snippets.

@object
Last active October 18, 2024 09:12
Show Gist options
  • Save object/1f25eca7af9d64c1a00f7d950e4ba704 to your computer and use it in GitHub Desktop.
Save object/1f25eca7af9d64c1a00f7d950e4ba704 to your computer and use it in GitHub Desktop.
Fable workshop (2024). Step 4. Update.fs
module Update
open System
open Elmish
open Fable.SimpleHttp
open Model
open Messages
let tryParseWith (tryParseFunc: string -> bool * _) = tryParseFunc >> function
| true, v -> Some v
| false, _ -> None
let loadEvents (state : Model) =
async {
let! response =
Http.request (sprintf "http://localhost:5000/%s" state.Filename)
|> Http.method GET
|> Http.send
if response.statusCode <> 200 then failwith (sprintf "Error %d" response.statusCode)
return response.responseText
}
let delayMessage msg (delay : int) state =
let delayedMsg (dispatch : Msg -> unit) : unit =
let delayedDispatch = async {
do! Async.Sleep delay
dispatch msg
}
Async.StartImmediate delayedDispatch
state, Cmd.ofEffect delayedMsg
let init () =
Model.Empty, Cmd.none
let update msg state =
match msg with
| FilenameChanged filename ->
{ state with Filename = filename; Error = "" }, Cmd.none
| PlaybackDelayChanged delay ->
{ state with PlaybackDelay = tryParseWith System.Int32.TryParse delay |> Option.defaultValue state.PlaybackDelay }, Cmd.none
| StartPlayback ->
{ state with EventIndex = (if state.EventIndex < 0 then 0 else state.EventIndex); IsPlaying = true }, Cmd.OfAsync.either loadEvents state EventsLoaded EventsError
| PausePlayback ->
{ state with IsPlaying = false }, Cmd.none
| StopPlayback ->
{ state with EventIndex = -1; IsPlaying = false }, Cmd.none
| NextEvent ->
if state.IsPlaying then
if state.EventIndex < state.Events.Length - 1 then
{ state with EventIndex = state.EventIndex + 1 }, Cmd.ofMsg (Delayed (NextEvent, state.PlaybackDelay * 1000))
else
{ state with EventIndex = -1; IsPlaying = false }, Cmd.none
else
state, Cmd.none
| EventsLoaded events ->
{ state with Events = events.Split([|'\r'; '\n'|], StringSplitOptions.RemoveEmptyEntries) }, Cmd.ofMsg (Delayed (NextEvent, state.PlaybackDelay * 1000))
| EventsError exn ->
{ state with Error = exn.ToString() }, Cmd.none
| Delayed (msg, delay) -> delayMessage msg delay state
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment