From e5777f6f7a57ac56863b7edbb3e14d4cdecb3510 Mon Sep 17 00:00:00 2001 From: Correl Roush Date: Wed, 20 May 2020 21:24:01 -0400 Subject: [PATCH] Handle presence events in Elm Pass state and diff events to elm, where the state can be managed accordingly. Because vote events are used to update player state, we don't want to blindly overwrite it by passing a separately synced presence list through, as it will lack vote data. Fixes #1 --- assets/js/app.js | 13 +----- assets/src/PlanningPokerAPI.elm | 8 +++- assets/src/PlanningPokerRoom.elm | 79 ++++++++++++++++++++++++++------ 3 files changed, 74 insertions(+), 26 deletions(-) diff --git a/assets/js/app.js b/assets/js/app.js index 168f1a5..9eefc6f 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -38,17 +38,8 @@ app.ports.joinRoom.subscribe(options => { let channel = socket.channel("room:" + options.room, {}) // Presence events - let presences = {} - channel.on("presence_state", state => { - console.log("presence state", state) - presences = Presence.syncState(presences, state) - app.ports.gotPresence.send(presences) - }) - channel.on("presence_diff", diff => { - console.log("presence diff", diff) - presences = Presence.syncDiff(presences, diff) - app.ports.gotPresence.send(presences) - }) + channel.on("presence_state", app.ports.gotPresenceState.send) + channel.on("presence_diff", app.ports.gotPresenceDiff.send) // Incoming room events channel.on("vote", app.ports.gotVote.send) diff --git a/assets/src/PlanningPokerAPI.elm b/assets/src/PlanningPokerAPI.elm index ce31c1b..eae7f3a 100644 --- a/assets/src/PlanningPokerAPI.elm +++ b/assets/src/PlanningPokerAPI.elm @@ -1,5 +1,6 @@ port module PlanningPokerAPI exposing - ( gotPresence + ( gotPresenceDiff + , gotPresenceState , gotReset , gotReveal , gotVote @@ -73,7 +74,10 @@ encodeAction action = wrap "reveal" (Encode.object []) -port gotPresence : (Decode.Value -> msg) -> Sub msg +port gotPresenceState : (Decode.Value -> msg) -> Sub msg + + +port gotPresenceDiff : (Decode.Value -> msg) -> Sub msg port gotVote : (Decode.Value -> msg) -> Sub msg diff --git a/assets/src/PlanningPokerRoom.elm b/assets/src/PlanningPokerRoom.elm index 93fe576..6fa401a 100644 --- a/assets/src/PlanningPokerRoom.elm +++ b/assets/src/PlanningPokerRoom.elm @@ -41,12 +41,25 @@ type Msg | Reveal | PlayerNameChanged String | JoinRoom - | GotPresence Decode.Value + | GotPresence Presence + | GotPresenceDiff Decode.Value | GotVote Decode.Value | GotReveal | GotReset +type Presence + = PresenceState (Dict String Player) + | PresenceDiff (Diff (Dict String Player)) + | PresenceError Decode.Error + + +type alias Diff a = + { joins : a + , leaves : a + } + + type alias Room = { id : String , name : String @@ -138,17 +151,30 @@ update key msg model = , API.newProfile { playerName = model.playerName } ) - GotPresence value -> - case Decode.decodeValue playersDecoder value of - Ok players -> - let - newRoom = - { room | players = players } - in - ( { model | room = newRoom }, Cmd.none ) + GotPresence (PresenceState players) -> + let + newRoom = + { room | players = players } + in + ( { model | room = newRoom }, Cmd.none ) - Err _ -> - ( model, Cmd.none ) + GotPresence (PresenceDiff { joins, leaves }) -> + let + newPlayers = + room.players + |> Dict.filter (\id _ -> not (Dict.member id leaves)) + |> Dict.union joins + + newRoom = + { room | players = newPlayers } + in + ( { model | room = newRoom }, Cmd.none ) + + GotPresence _ -> + ( model, Cmd.none ) + + GotPresenceDiff _ -> + ( model, Cmd.none ) GotVote value -> case Decode.decodeValue voteDecoder value of @@ -194,7 +220,6 @@ view dimensions model = let device = classifyDevice dimensions - |> Debug.log "device" playerName = Dict.get model.player model.room.players @@ -439,13 +464,41 @@ joinForm room playerName = subscriptions : Sub Msg subscriptions = Sub.batch - [ API.gotPresence GotPresence + [ API.gotPresenceState (decodePresenceState >> GotPresence) + , API.gotPresenceDiff (decodePresenceDiff >> GotPresence) , API.gotReset (\_ -> GotReset) , API.gotReveal (\_ -> GotReveal) , API.gotVote GotVote ] +decodePresenceState : Decode.Value -> Presence +decodePresenceState value = + case Decode.decodeValue playersDecoder value of + Ok players -> + PresenceState players + + Err error -> + PresenceError error + + +decodePresenceDiff : Decode.Value -> Presence +decodePresenceDiff value = + let + diffDecoder = + Decode.map PresenceDiff <| + Decode.map2 Diff + (Decode.field "joins" playersDecoder) + (Decode.field "leaves" playersDecoder) + in + case Decode.decodeValue diffDecoder value of + Ok diff -> + diff + + Err error -> + PresenceError error + + playersDecoder : Decode.Decoder (Dict String Player) playersDecoder = let