mattgallagher92 / safe-consequences

A SAFE stack app for playing consequences, the classic pen-and-paper game
1 stars 0 forks source link

Automatically update pages #9

Open mattgallagher92 opened 3 years ago

mattgallagher92 commented 3 years ago

As a player I want some pages to update automatically So that I don't have to refresh the page to see the latest information

mattgallagher92 commented 3 years ago

Auto-update:

Maybe also:

mattgallagher92 commented 3 years ago

Change of plan

we could then remove player's button on lobby page to start responding to prompts

we could then remove player's button on completion progress page to view their story

In the end, this isn't how things have been implemented for v1.0 - when a player reloads their page they will automatically be sent to the appropriate section.

As such, the plan now is to automatically update the state of the lobby and completion progress pages, and the transitions from them.

mattgallagher92 commented 3 years ago

Useful resources

Of these the ideas from CIT's blog post look easisest to integrate with what I already have and doesn't require a change in architecture, so I'll explore that avenue first.

mattgallagher92 commented 3 years ago

I've got the websocket messages working, but am now facing an issue with serialisation/deserialisation of the message sent from server to client:

Warning:

[ELMISH DEBUGGER] Cannot generate auto encoder for Microsoft.FSharp.Core.FSharpFunc`2[Shared.NamedUser,Index.Msg]. Please pass an extra encoder.

Error:

Uncaught Error: Error at: $.Payload Expecting a string but instead got: undefined

This is my subscription:

module Channel =
    open Browser.Types
    open Browser.WebSocket

    let inline decode<'a> x = x |> unbox<string> |> Thoth.Json.Decode.Auto.unsafeFromString<'a>

    let subscription _ =
        let sub dispatch =
            /// Handles push messages from the server and relays them into Elmish messages.
            let onWebSocketMessage (msg:MessageEvent) =
                let msg = msg.data |> decode<{| Payload : string |}>
                msg.Payload
                |> decode<WebSocketServerMessage>
                |> ReceivedFromServer
                |> dispatch

            // Naive web socket connection management
            let ws = WebSocket.Create "ws://localhost:8085/channel"
            ws.onmessage <- onWebSocketMessage

        Cmd.ofSub sub

with

ReceivedFromServer of WebSocketServerMessage

and

type WebSocketServerMessage =
    | PlayerJoinedRoom of NamedUser * RoomId

The server is broadcasting messages with

let broadcastRoomJoined room =
    let wait (t : Threading.Tasks.Task) = t.Wait()
    let hub = ctx.GetService<Channels.ISocketHub>()
    Channel.broadcastMessage hub <| PlayerJoinedRoom (user, room.Id)
    |> wait

using

module Channel =
    open Thoth.Json.Net

    /// Sends a message to all connected clients.
    let broadcastMessage (hub:Channels.ISocketHub) (payload:WebSocketServerMessage) = task {
        let payload = Encode.Auto.toString(0, payload)
        do! hub.SendMessageToClients "/channel" "" payload
    }
mattgallagher92 commented 3 years ago

Same warning and error with

type PlayerJoinedRoom = { User: NamedUser; RoomId: RoomId }

type WebSocketServerMessage =
    | PlayerJoinedRoom of PlayerJoinedRoom

and associated updates elsewhere.