Compare commits
3 Commits
3e7d12b6e4
...
996da079e2
Author | SHA1 | Date | |
---|---|---|---|
996da079e2 | |||
2449a3c8c4 | |||
2505610aa2 |
|
@ -36,6 +36,7 @@ init flags url key =
|
||||||
, errors = []
|
, errors = []
|
||||||
, roomText = Dict.empty
|
, roomText = Dict.empty
|
||||||
, transactionId = 0
|
, transactionId = 0
|
||||||
|
, userData = Dict.empty
|
||||||
}
|
}
|
||||||
cmd = case flags.token of
|
cmd = case flags.token of
|
||||||
Just _ -> Cmd.none
|
Just _ -> Cmd.none
|
||||||
|
@ -58,7 +59,9 @@ update msg model = case msg of
|
||||||
TryUrl urlRequest -> updateTryUrl model urlRequest
|
TryUrl urlRequest -> updateTryUrl model urlRequest
|
||||||
ChangeRoute r -> ({ model | route = r }, Cmd.none)
|
ChangeRoute r -> ({ model | route = r }, Cmd.none)
|
||||||
ReceiveLoginResponse r -> updateLoginResponse model r
|
ReceiveLoginResponse r -> updateLoginResponse model r
|
||||||
ReceiveSyncResponse r -> updateSyncResponse model r
|
ReceiveFirstSyncResponse r -> updateSyncResponse model r False
|
||||||
|
ReceiveSyncResponse r -> updateSyncResponse model r True
|
||||||
|
ReceiveUserData s r -> (model, Cmd.none)
|
||||||
ChangeRoomText r t -> ({ model | roomText = Dict.insert r t model.roomText}, Cmd.none)
|
ChangeRoomText r t -> ({ model | roomText = Dict.insert r t model.roomText}, Cmd.none)
|
||||||
SendRoomText r -> updateSendRoomText model r
|
SendRoomText r -> updateSendRoomText model r
|
||||||
SendRoomTextResponse r -> (model, Cmd.none)
|
SendRoomTextResponse r -> (model, Cmd.none)
|
||||||
|
@ -87,8 +90,8 @@ updateLoginResponse model r = case r of
|
||||||
] )
|
] )
|
||||||
Err e -> (model, Cmd.none)
|
Err e -> (model, Cmd.none)
|
||||||
|
|
||||||
updateSyncResponse : Model -> Result Http.Error SyncResponse -> (Model, Cmd Msg)
|
updateSyncResponse : Model -> Result Http.Error SyncResponse -> Bool -> (Model, Cmd Msg)
|
||||||
updateSyncResponse model r =
|
updateSyncResponse model r notify =
|
||||||
let
|
let
|
||||||
token = Maybe.withDefault "" model.token
|
token = Maybe.withDefault "" model.token
|
||||||
nextBatch = Result.withDefault model.sync.nextBatch
|
nextBatch = Result.withDefault model.sync.nextBatch
|
||||||
|
|
|
@ -3,6 +3,7 @@ import Scylla.Model exposing (..)
|
||||||
import Scylla.Api exposing (..)
|
import Scylla.Api exposing (..)
|
||||||
import Scylla.Sync exposing (syncResponseDecoder)
|
import Scylla.Sync exposing (syncResponseDecoder)
|
||||||
import Scylla.Login exposing (loginResponseDecoder, Username, Password)
|
import Scylla.Login exposing (loginResponseDecoder, Username, Password)
|
||||||
|
import Scylla.UserData exposing (userDataDecoder, UserData)
|
||||||
import Json.Encode exposing (object, string, int)
|
import Json.Encode exposing (object, string, int)
|
||||||
import Http exposing (request, emptyBody, jsonBody, expectJson, expectWhatever)
|
import Http exposing (request, emptyBody, jsonBody, expectJson, expectWhatever)
|
||||||
|
|
||||||
|
@ -16,7 +17,7 @@ firstSync apiUrl token = request
|
||||||
, headers = authenticatedHeaders token
|
, headers = authenticatedHeaders token
|
||||||
, url = (fullUrl apiUrl) ++ "/sync"
|
, url = (fullUrl apiUrl) ++ "/sync"
|
||||||
, body = emptyBody
|
, body = emptyBody
|
||||||
, expect = expectJson ReceiveSyncResponse syncResponseDecoder
|
, expect = expectJson ReceiveFirstSyncResponse syncResponseDecoder
|
||||||
, timeout = Nothing
|
, timeout = Nothing
|
||||||
, tracker = Nothing
|
, tracker = Nothing
|
||||||
}
|
}
|
||||||
|
@ -66,3 +67,14 @@ login apiUrl username password = request
|
||||||
, timeout = Nothing
|
, timeout = Nothing
|
||||||
, tracker = Nothing
|
, tracker = Nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
userData : ApiUrl -> ApiToken -> Username -> Cmd Msg
|
||||||
|
userData apiUrl token username = request
|
||||||
|
{ method = "GET"
|
||||||
|
, headers = authenticatedHeaders token
|
||||||
|
, url = (fullUrl apiUrl) ++ "/profile/" ++ username
|
||||||
|
, body = emptyBody
|
||||||
|
, expect = expectJson (ReceiveUserData username) userDataDecoder
|
||||||
|
, timeout = Nothing
|
||||||
|
, tracker = Nothing
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ module Scylla.Model exposing (..)
|
||||||
import Scylla.Api exposing (..)
|
import Scylla.Api exposing (..)
|
||||||
import Scylla.Sync exposing (SyncResponse, JoinedRoom)
|
import Scylla.Sync exposing (SyncResponse, JoinedRoom)
|
||||||
import Scylla.Login exposing (LoginResponse, Username, Password)
|
import Scylla.Login exposing (LoginResponse, Username, Password)
|
||||||
|
import Scylla.UserData exposing (UserData)
|
||||||
import Scylla.Route exposing (Route)
|
import Scylla.Route exposing (Route)
|
||||||
import Browser.Navigation as Nav
|
import Browser.Navigation as Nav
|
||||||
import Dict exposing (Dict)
|
import Dict exposing (Dict)
|
||||||
|
@ -20,6 +21,7 @@ type alias Model =
|
||||||
, errors : List String
|
, errors : List String
|
||||||
, roomText : Dict String String
|
, roomText : Dict String String
|
||||||
, transactionId : Int
|
, transactionId : Int
|
||||||
|
, userData : Dict Username UserData
|
||||||
}
|
}
|
||||||
|
|
||||||
type Msg =
|
type Msg =
|
||||||
|
@ -32,6 +34,8 @@ type Msg =
|
||||||
| ChangeRoomText String String -- Change to a room's input text
|
| ChangeRoomText String String -- Change to a room's input text
|
||||||
| SendRoomText String -- Sends a message typed into a given room's input
|
| SendRoomText String -- Sends a message typed into a given room's input
|
||||||
| SendRoomTextResponse (Result Http.Error ()) -- A send message response finished
|
| 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
|
| ReceiveSyncResponse (Result Http.Error SyncResponse) -- HTTP, Sync has finished
|
||||||
| ReceiveLoginResponse (Result Http.Error LoginResponse) -- HTTP, Login has finished
|
| ReceiveLoginResponse (Result Http.Error LoginResponse) -- HTTP, Login has finished
|
||||||
|
| ReceiveUserData Username (Result Http.Error UserData)
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
port module Scylla.Notification exposing (..)
|
port module Scylla.Notification exposing (..)
|
||||||
import Scylla.Model exposing (..)
|
|
||||||
import Json.Decode
|
import Json.Decode
|
||||||
|
|
||||||
type alias Notification =
|
type alias Notification =
|
||||||
{ name : String
|
{ name : String
|
||||||
, text : String
|
, text : String
|
||||||
|
, room : String
|
||||||
}
|
}
|
||||||
|
|
||||||
port sendNotificationPort : Notification -> Cmd msg
|
port sendNotificationPort : Notification -> Cmd msg
|
||||||
port onNotificationClockPort : (Json.Decode.Value -> msg) -> Sub msg
|
port onNotificationClickPort : (Json.Decode.Value -> msg) -> Sub msg
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
module Scylla.Sync exposing (..)
|
module Scylla.Sync exposing (..)
|
||||||
import Scylla.Api exposing (..)
|
import Scylla.Api exposing (..)
|
||||||
|
import Scylla.Notification exposing (..)
|
||||||
|
import Scylla.Login exposing (Username)
|
||||||
import Dict exposing (Dict)
|
import Dict exposing (Dict)
|
||||||
import Json.Decode as Decode exposing (Decoder, int, string, float, list, value, dict, bool, field)
|
import Json.Decode as Decode exposing (Decoder, int, string, float, list, value, dict, bool, field)
|
||||||
import Json.Decode.Pipeline exposing (required, optional)
|
import Json.Decode.Pipeline exposing (required, optional)
|
||||||
|
@ -267,6 +269,7 @@ uniqueByRecursive f l s = case l of
|
||||||
uniqueBy : (a -> comparable) -> List a -> List a
|
uniqueBy : (a -> comparable) -> List a -> List a
|
||||||
uniqueBy f l = uniqueByRecursive f l Set.empty
|
uniqueBy f l = uniqueByRecursive f l Set.empty
|
||||||
|
|
||||||
|
-- Business Logic: Merging
|
||||||
mergeMaybe : (a -> a -> a) -> Maybe a -> Maybe a -> Maybe a
|
mergeMaybe : (a -> a -> a) -> Maybe a -> Maybe a -> Maybe a
|
||||||
mergeMaybe f l r = case (l, r) of
|
mergeMaybe f l r = case (l, r) of
|
||||||
(Just v1, Just v2) -> Just <| f v1 v2
|
(Just v1, Just v2) -> Just <| f v1 v2
|
||||||
|
@ -347,6 +350,16 @@ mergeSyncResponse l r =
|
||||||
, accountData = mergeMaybe mergeAccountData l.accountData r.accountData
|
, 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 : JoinedRoom -> Maybe String
|
||||||
roomName jr =
|
roomName jr =
|
||||||
let
|
let
|
||||||
|
@ -355,3 +368,35 @@ roomName jr =
|
||||||
name e = Result.toMaybe <| Decode.decodeValue (field "name" string) e.content
|
name e = Result.toMaybe <| Decode.decodeValue (field "name" string) e.content
|
||||||
in
|
in
|
||||||
Maybe.andThen name <| Maybe.andThen nameEvent <| Maybe.andThen .events <| state
|
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
|
||||||
|
|
||||||
|
-- Business Logic: User Extraction
|
||||||
|
roomsUsers : SyncResponse -> List Username
|
||||||
|
roomsUsers s =
|
||||||
|
let
|
||||||
|
users dict =
|
||||||
|
List.map .sender
|
||||||
|
<| (List.concatMap <| Maybe.withDefault [] << .events)
|
||||||
|
<| (List.filterMap .timeline)
|
||||||
|
<| Dict.values dict
|
||||||
|
usersFor f = Maybe.withDefault [] <| Maybe.map users <| Maybe.andThen f s.rooms
|
||||||
|
joinedUsers = usersFor .join
|
||||||
|
leftUsers = usersFor .leave
|
||||||
|
in
|
||||||
|
leftUsers ++ joinedUsers
|
||||||
|
|
14
src/Scylla/UserData.elm
Normal file
14
src/Scylla/UserData.elm
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
module Scylla.UserData exposing (..)
|
||||||
|
import Json.Decode as Decode exposing (Decoder, int, string, float, list, value, dict, bool, field)
|
||||||
|
import Json.Decode.Pipeline exposing (required, optional)
|
||||||
|
|
||||||
|
type alias UserData =
|
||||||
|
{ displayName : Maybe String
|
||||||
|
, avatarUrl : Maybe String
|
||||||
|
}
|
||||||
|
|
||||||
|
userDataDecoder : Decoder UserData
|
||||||
|
userDataDecoder =
|
||||||
|
Decode.succeed UserData
|
||||||
|
|> optional "displayname" (Decode.map Just string) Nothing
|
||||||
|
|> optional "avatar_url" (Decode.map Just string) Nothing
|
|
@ -19,15 +19,6 @@ stringColor s =
|
||||||
in
|
in
|
||||||
"hsl(" ++ hue ++ ", 82%, 71%)"
|
"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 -> List (Html Msg)
|
||||||
viewFull model =
|
viewFull model =
|
||||||
let
|
let
|
||||||
|
|
|
@ -7,6 +7,11 @@ function setupNotificationPorts(app) {
|
||||||
var options = {
|
var options = {
|
||||||
"body" : data.text
|
"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
|
||||||
|
});
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user