diff --git a/src/Main.elm b/src/Main.elm index 1551678..5f381f6 100644 --- a/src/Main.elm +++ b/src/Main.elm @@ -58,7 +58,8 @@ update msg model = case msg of TryUrl urlRequest -> updateTryUrl model urlRequest ChangeRoute r -> ({ model | route = r }, Cmd.none) ReceiveLoginResponse r -> updateLoginResponse model r - ReceiveSyncResponse r -> updateSyncResponse model r + ReceiveFirstSyncResponse r -> updateSyncResponse model r False + ReceiveSyncResponse r -> updateSyncResponse model r True ChangeRoomText r t -> ({ model | roomText = Dict.insert r t model.roomText}, Cmd.none) SendRoomText r -> updateSendRoomText model r SendRoomTextResponse r -> (model, Cmd.none) @@ -87,8 +88,8 @@ updateLoginResponse model r = case r of ] ) Err e -> (model, Cmd.none) -updateSyncResponse : Model -> Result Http.Error SyncResponse -> (Model, Cmd Msg) -updateSyncResponse model r = +updateSyncResponse : Model -> Result Http.Error SyncResponse -> Bool -> (Model, Cmd Msg) +updateSyncResponse model r notify = let token = Maybe.withDefault "" model.token nextBatch = Result.withDefault model.sync.nextBatch diff --git a/src/Scylla/Http.elm b/src/Scylla/Http.elm index 8a9402a..e242cf0 100644 --- a/src/Scylla/Http.elm +++ b/src/Scylla/Http.elm @@ -16,7 +16,7 @@ firstSync apiUrl token = request , headers = authenticatedHeaders token , url = (fullUrl apiUrl) ++ "/sync" , body = emptyBody - , expect = expectJson ReceiveSyncResponse syncResponseDecoder + , expect = expectJson ReceiveFirstSyncResponse syncResponseDecoder , timeout = Nothing , tracker = Nothing } diff --git a/src/Scylla/Model.elm b/src/Scylla/Model.elm index 431144c..bfde00e 100644 --- a/src/Scylla/Model.elm +++ b/src/Scylla/Model.elm @@ -32,6 +32,7 @@ type Msg = | ChangeRoomText String String -- Change to a room's input text | SendRoomText String -- Sends a message typed into a given room's input | SendRoomTextResponse (Result Http.Error ()) -- A send message response finished + | ReceiveFirstSyncResponse (Result Http.Error SyncResponse) -- HTTP, Sync has finished | ReceiveSyncResponse (Result Http.Error SyncResponse) -- HTTP, Sync has finished | ReceiveLoginResponse (Result Http.Error LoginResponse) -- HTTP, Login has finished diff --git a/src/Scylla/Notification.elm b/src/Scylla/Notification.elm index 295077f..d4bae8b 100644 --- a/src/Scylla/Notification.elm +++ b/src/Scylla/Notification.elm @@ -1,11 +1,11 @@ port module Scylla.Notification exposing (..) -import Scylla.Model exposing (..) import Json.Decode type alias Notification = { name : String , text : String + , room : String } port sendNotificationPort : Notification -> Cmd msg -port onNotificationClockPort : (Json.Decode.Value -> msg) -> Sub msg +port onNotificationClickPort : (Json.Decode.Value -> msg) -> Sub msg diff --git a/src/Scylla/Sync.elm b/src/Scylla/Sync.elm index 3f916fe..dc7bc07 100644 --- a/src/Scylla/Sync.elm +++ b/src/Scylla/Sync.elm @@ -1,5 +1,6 @@ module Scylla.Sync exposing (..) import Scylla.Api exposing (..) +import Scylla.Notification exposing (..) import Dict exposing (Dict) import Json.Decode as Decode exposing (Decoder, int, string, float, list, value, dict, bool, field) import Json.Decode.Pipeline exposing (required, optional) @@ -267,6 +268,7 @@ uniqueByRecursive f l s = case l of uniqueBy : (a -> comparable) -> List a -> List a uniqueBy f l = uniqueByRecursive f l Set.empty +-- Business Logic: Merging mergeMaybe : (a -> a -> a) -> Maybe a -> Maybe a -> Maybe a mergeMaybe f l r = case (l, r) of (Just v1, Just v2) -> Just <| f v1 v2 @@ -347,6 +349,16 @@ mergeSyncResponse l r = , accountData = mergeMaybe mergeAccountData l.accountData r.accountData } +-- Business Logic: Names +senderName : String -> String +senderName s = + let + colonIndex = Maybe.withDefault -1 + <| List.head + <| String.indexes ":" s + in + String.slice 1 colonIndex s + roomName : JoinedRoom -> Maybe String roomName jr = let @@ -355,3 +367,20 @@ roomName jr = name e = Result.toMaybe <| Decode.decodeValue (field "name" string) e.content in Maybe.andThen name <| Maybe.andThen nameEvent <| Maybe.andThen .events <| state + +-- Business Logic: Event Extraction +notificationEvent : SyncResponse -> Maybe (String, RoomEvent) +notificationEvent s = + let + applyPair k = List.map (\v -> (k, v)) + in + List.head + <| List.sortBy (\(k, v) -> v.originServerTs) + <| Dict.foldl (\k v a -> a ++ applyPair k v) [] + <| joinedRoomsEvents s + +joinedRoomsEvents : SyncResponse -> Dict String (List RoomEvent) +joinedRoomsEvents s = + Maybe.withDefault Dict.empty + <| Maybe.map (Dict.map (\k v -> Maybe.withDefault [] <| Maybe.andThen .events v.timeline)) + <| Maybe.andThen .join s.rooms diff --git a/src/Scylla/Views.elm b/src/Scylla/Views.elm index a723be9..c30a001 100644 --- a/src/Scylla/Views.elm +++ b/src/Scylla/Views.elm @@ -19,15 +19,6 @@ stringColor s = in "hsl(" ++ hue ++ ", 82%, 71%)" -senderName : String -> String -senderName s = - let - colonIndex = Maybe.withDefault -1 - <| List.head - <| String.indexes ":" s - in - String.slice 1 colonIndex s - viewFull : Model -> List (Html Msg) viewFull model = let diff --git a/static/js/notifications.js b/static/js/notifications.js index 20d9ab4..8bdd01f 100644 --- a/static/js/notifications.js +++ b/static/js/notifications.js @@ -7,6 +7,11 @@ function setupNotificationPorts(app) { var options = { "body" : data.text } - new Notification(data.name, options) + var n = new Notification(data.name, options) + n.onclick = function() { + app.ports.onNotificationClickPort.send({ + "room" : data.room + }); + } }) }