Split Sync file into sub-modules
This commit is contained in:
parent
ccfd2fe76b
commit
595e28853e
|
@ -2,6 +2,7 @@ import Browser exposing (application, UrlRequest(..))
|
||||||
import Browser.Navigation as Nav
|
import Browser.Navigation as Nav
|
||||||
import Browser.Dom exposing (Viewport, setViewportOf)
|
import Browser.Dom exposing (Viewport, setViewportOf)
|
||||||
import Scylla.Sync exposing (..)
|
import Scylla.Sync exposing (..)
|
||||||
|
import Scylla.Sync.Events exposing (toMessageEvent, getType, getSender, getUnsigned)
|
||||||
import Scylla.Messages exposing (..)
|
import Scylla.Messages exposing (..)
|
||||||
import Scylla.Login exposing (..)
|
import Scylla.Login exposing (..)
|
||||||
import Scylla.Api exposing (..)
|
import Scylla.Api exposing (..)
|
||||||
|
@ -182,7 +183,7 @@ updateHistoryResponse m r hr =
|
||||||
userDataCmd h = newUsersCmd m
|
userDataCmd h = newUsersCmd m
|
||||||
<| newUsers m
|
<| newUsers m
|
||||||
<| uniqueBy identity
|
<| uniqueBy identity
|
||||||
<| List.map .sender
|
<| List.map getSender
|
||||||
<| h.chunk
|
<| h.chunk
|
||||||
in
|
in
|
||||||
case hr of
|
case hr of
|
||||||
|
@ -253,7 +254,7 @@ updateChangeRoute m r =
|
||||||
joinedRoom = case r of
|
joinedRoom = case r of
|
||||||
Room rid -> Maybe.andThen (Dict.get rid) <| Maybe.andThen .join <| m.sync.rooms
|
Room rid -> Maybe.andThen (Dict.get rid) <| Maybe.andThen .join <| m.sync.rooms
|
||||||
_ -> Nothing
|
_ -> Nothing
|
||||||
lastMessage = Maybe.andThen (findLastEvent (((==) "m.room.message") << .type_)) <| Maybe.andThen .events <| Maybe.andThen .timeline joinedRoom
|
lastMessage = Maybe.andThen (findLastEvent (((==) "m.room.message") << .type_)) <| Maybe.map (List.filterMap toMessageEvent) <| Maybe.andThen .events <| Maybe.andThen .timeline joinedRoom
|
||||||
readMarkerCmd = case (r, lastMessage) of
|
readMarkerCmd = case (r, lastMessage) of
|
||||||
(Room rid, Just re) -> setReadMarkers m.apiUrl (Maybe.withDefault "" m.token) rid re.eventId <| Just re.eventId
|
(Room rid, Just re) -> setReadMarkers m.apiUrl (Maybe.withDefault "" m.token) rid re.eventId <| Just re.eventId
|
||||||
_ -> Cmd.none
|
_ -> Cmd.none
|
||||||
|
@ -331,6 +332,7 @@ updateSyncResponse model r notify =
|
||||||
roomMessages sr = case room of
|
roomMessages sr = case room of
|
||||||
Just rid -> List.filter (((==) "m.room.message") << .type_)
|
Just rid -> List.filter (((==) "m.room.message") << .type_)
|
||||||
<| Maybe.withDefault []
|
<| Maybe.withDefault []
|
||||||
|
<| Maybe.map (List.filterMap (toMessageEvent))
|
||||||
<| Maybe.andThen .events
|
<| Maybe.andThen .events
|
||||||
<| Maybe.andThen .timeline
|
<| Maybe.andThen .timeline
|
||||||
<| Maybe.andThen (Dict.get rid)
|
<| Maybe.andThen (Dict.get rid)
|
||||||
|
@ -345,7 +347,7 @@ updateSyncResponse model r notify =
|
||||||
(Just rid, Just re) -> setReadMarkers model.apiUrl token rid re.eventId <| Just re.eventId
|
(Just rid, Just re) -> setReadMarkers model.apiUrl token rid re.eventId <| Just re.eventId
|
||||||
_ -> Cmd.none
|
_ -> Cmd.none
|
||||||
receivedEvents sr = List.map Just <| allTimelineEventIds sr
|
receivedEvents sr = List.map Just <| allTimelineEventIds sr
|
||||||
receivedTransactions sr = List.filterMap (Maybe.andThen .transactionId << .unsigned)
|
receivedTransactions sr = List.filterMap (Maybe.andThen .transactionId << getUnsigned)
|
||||||
<| allTimelineEvents sr
|
<| allTimelineEvents sr
|
||||||
sending sr = Dict.filter (\tid (rid, { body, id }) -> not <| List.member (String.fromInt tid) <| receivedTransactions sr) model.sending
|
sending sr = Dict.filter (\tid (rid, { body, id }) -> not <| List.member (String.fromInt tid) <| receivedTransactions sr) model.sending
|
||||||
newSync sr = mergeSyncResponse model.sync sr
|
newSync sr = mergeSyncResponse model.sync sr
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
module Scylla.AccountData exposing (..)
|
module Scylla.AccountData exposing (..)
|
||||||
import Scylla.Sync exposing (SyncResponse, AccountData, JoinedRoom, roomAccountData)
|
import Scylla.Sync exposing (SyncResponse, roomAccountData)
|
||||||
|
import Scylla.Sync.AccountData exposing (AccountData)
|
||||||
|
import Scylla.Sync.Rooms exposing (JoinedRoom)
|
||||||
import Json.Decode as Decode
|
import Json.Decode as Decode
|
||||||
import Json.Encode as Encode
|
import Json.Encode as Encode
|
||||||
import Dict exposing (Dict)
|
import Dict exposing (Dict)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
module Scylla.Messages exposing (..)
|
module Scylla.Messages exposing (..)
|
||||||
import Scylla.Sync exposing (RoomEvent)
|
import Scylla.Sync.Events exposing (RoomEvent, MessageEvent, toMessageEvent)
|
||||||
import Scylla.Login exposing (Username)
|
import Scylla.Login exposing (Username)
|
||||||
import Scylla.Route exposing (RoomId)
|
import Scylla.Route exposing (RoomId)
|
||||||
import Dict exposing (Dict)
|
import Dict exposing (Dict)
|
||||||
|
@ -13,7 +13,7 @@ type alias SendingMessage =
|
||||||
|
|
||||||
type Message
|
type Message
|
||||||
= Sending SendingMessage
|
= Sending SendingMessage
|
||||||
| Received RoomEvent
|
| Received MessageEvent
|
||||||
|
|
||||||
messageUsername : Username -> Message -> Username
|
messageUsername : Username -> Message -> Username
|
||||||
messageUsername u msg = case msg of
|
messageUsername u msg = case msg of
|
||||||
|
@ -38,7 +38,8 @@ mergeMessages du xs =
|
||||||
|
|
||||||
receivedMessagesRoom : List RoomEvent -> List Message
|
receivedMessagesRoom : List RoomEvent -> List Message
|
||||||
receivedMessagesRoom es = List.map Received
|
receivedMessagesRoom es = List.map Received
|
||||||
<| List.filter (\e -> e.type_ == "m.room.message") es
|
<| List.filter (\e -> e.type_ == "m.room.message")
|
||||||
|
<| List.filterMap toMessageEvent es
|
||||||
|
|
||||||
sendingMessagesRoom : RoomId -> Dict Int (RoomId, SendingMessage) -> List Message
|
sendingMessagesRoom : RoomId -> Dict Int (RoomId, SendingMessage) -> List Message
|
||||||
sendingMessagesRoom rid ms = List.map (\(tid, (_, sm)) -> Sending sm)
|
sendingMessagesRoom rid ms = List.map (\(tid, (_, sm)) -> Sending sm)
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
module Scylla.Model exposing (..)
|
module Scylla.Model exposing (..)
|
||||||
import Scylla.Api exposing (..)
|
import Scylla.Api exposing (..)
|
||||||
import Scylla.Sync exposing (SyncResponse, HistoryResponse, JoinedRoom, senderName, roomName, roomJoinedUsers, findFirst, AccountData)
|
import Scylla.Sync exposing (SyncResponse, HistoryResponse, senderName, roomName, roomJoinedUsers, findFirst)
|
||||||
|
import Scylla.Sync.Rooms exposing (JoinedRoom)
|
||||||
|
import Scylla.Sync.AccountData exposing (AccountData)
|
||||||
import Scylla.AccountData exposing (directMessagesDecoder)
|
import Scylla.AccountData exposing (directMessagesDecoder)
|
||||||
import Scylla.Login exposing (LoginResponse, Username, Password)
|
import Scylla.Login exposing (LoginResponse, Username, Password)
|
||||||
import Scylla.UserData exposing (UserData)
|
import Scylla.UserData exposing (UserData)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
port module Scylla.Notification exposing (..)
|
port module Scylla.Notification exposing (..)
|
||||||
import Scylla.Sync exposing (SyncResponse, RoomEvent, joinedRoomsTimelineEvents)
|
import Scylla.Sync exposing (SyncResponse, joinedRoomsTimelineEvents)
|
||||||
|
import Scylla.Sync.Events exposing (RoomEvent, MessageEvent, toMessageEvent)
|
||||||
import Scylla.AccountData exposing (..)
|
import Scylla.AccountData exposing (..)
|
||||||
import Json.Decode as Decode exposing (string, field)
|
import Json.Decode as Decode exposing (string, field)
|
||||||
import Dict
|
import Dict
|
||||||
|
@ -13,17 +14,18 @@ type alias Notification =
|
||||||
port sendNotificationPort : Notification -> Cmd msg
|
port sendNotificationPort : Notification -> Cmd msg
|
||||||
port onNotificationClickPort : (String -> msg) -> Sub msg
|
port onNotificationClickPort : (String -> msg) -> Sub msg
|
||||||
|
|
||||||
notificationText : RoomEvent -> String
|
notificationText : MessageEvent -> String
|
||||||
notificationText re = case (Decode.decodeValue (field "msgtype" string) re.content) of
|
notificationText re = case (Decode.decodeValue (field "msgtype" string) re.content) of
|
||||||
Ok "m.text" -> Result.withDefault "" <| (Decode.decodeValue (field "body" string) re.content)
|
Ok "m.text" -> Result.withDefault "" <| (Decode.decodeValue (field "body" string) re.content)
|
||||||
_ -> ""
|
_ -> ""
|
||||||
|
|
||||||
joinedRoomNotificationEvents : SyncResponse -> List (String, RoomEvent)
|
joinedRoomNotificationEvents : SyncResponse -> List (String, MessageEvent)
|
||||||
joinedRoomNotificationEvents s =
|
joinedRoomNotificationEvents s =
|
||||||
let
|
let
|
||||||
applyPair k = List.map (\v -> (k, v))
|
applyPair k = List.map (\v -> (k, v))
|
||||||
in
|
in
|
||||||
List.sortBy (\(k, v) -> v.originServerTs)
|
List.sortBy (\(k, v) -> v.originServerTs)
|
||||||
|
<| List.filterMap (\(k, e) -> Maybe.map (\me -> (k, me)) <| toMessageEvent e)
|
||||||
<| Dict.foldl (\k v a -> a ++ applyPair k v) []
|
<| Dict.foldl (\k v a -> a ++ applyPair k v) []
|
||||||
<| joinedRoomsTimelineEvents s
|
<| joinedRoomsTimelineEvents s
|
||||||
|
|
||||||
|
|
|
@ -2,223 +2,15 @@ module Scylla.Sync exposing (..)
|
||||||
import Scylla.Api exposing (..)
|
import Scylla.Api exposing (..)
|
||||||
import Scylla.Login exposing (Username)
|
import Scylla.Login exposing (Username)
|
||||||
import Scylla.Route exposing (RoomId)
|
import Scylla.Route exposing (RoomId)
|
||||||
|
import Scylla.Sync.DecodeTools exposing (maybeDecode)
|
||||||
|
import Scylla.Sync.Events exposing (..)
|
||||||
|
import Scylla.Sync.Rooms exposing (..)
|
||||||
|
import Scylla.Sync.AccountData exposing (..)
|
||||||
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)
|
||||||
import Set exposing (Set)
|
import Set exposing (Set)
|
||||||
|
|
||||||
-- Special Decoding
|
|
||||||
decodeJust : Decoder a -> Decoder (Maybe a)
|
|
||||||
decodeJust = Decode.map Just
|
|
||||||
|
|
||||||
maybeDecode : String -> Decoder a -> Decoder (Maybe a -> b) -> Decoder b
|
|
||||||
maybeDecode s d = optional s (decodeJust d) Nothing
|
|
||||||
|
|
||||||
-- General Events
|
|
||||||
type alias Event =
|
|
||||||
{ content : Decode.Value
|
|
||||||
, type_ : String
|
|
||||||
}
|
|
||||||
|
|
||||||
eventDecoder : Decoder Event
|
|
||||||
eventDecoder =
|
|
||||||
Decode.succeed Event
|
|
||||||
|> required "content" value
|
|
||||||
|> required "type" string
|
|
||||||
|
|
||||||
type alias EventContent = Decode.Value
|
|
||||||
|
|
||||||
eventContentDecoder : Decoder EventContent
|
|
||||||
eventContentDecoder = Decode.value
|
|
||||||
|
|
||||||
-- Unsigned Data
|
|
||||||
type alias UnsignedData =
|
|
||||||
{ age : Maybe Int
|
|
||||||
, redactedBecause : Maybe Event
|
|
||||||
, transactionId : Maybe String
|
|
||||||
}
|
|
||||||
|
|
||||||
unsignedDataDecoder : Decoder UnsignedData
|
|
||||||
unsignedDataDecoder =
|
|
||||||
Decode.succeed UnsignedData
|
|
||||||
|> maybeDecode "age" int
|
|
||||||
|> maybeDecode "redacted_because" eventDecoder
|
|
||||||
|> maybeDecode "transaction_id" string
|
|
||||||
|
|
||||||
-- State
|
|
||||||
type alias State =
|
|
||||||
{ events : Maybe (List StateEvent)
|
|
||||||
}
|
|
||||||
|
|
||||||
stateDecoder : Decoder State
|
|
||||||
stateDecoder =
|
|
||||||
Decode.succeed State
|
|
||||||
|> maybeDecode "events" (list stateEventDecoder)
|
|
||||||
|
|
||||||
type alias StateEvent =
|
|
||||||
{ content : Decode.Value
|
|
||||||
, type_ : String
|
|
||||||
, eventId : String
|
|
||||||
, sender : String
|
|
||||||
, originServerTs : Int
|
|
||||||
, unsigned : Maybe UnsignedData
|
|
||||||
, prevContent : Maybe EventContent
|
|
||||||
, stateKey : String
|
|
||||||
}
|
|
||||||
|
|
||||||
stateEventDecoder : Decoder StateEvent
|
|
||||||
stateEventDecoder =
|
|
||||||
Decode.succeed StateEvent
|
|
||||||
|> required "content" value
|
|
||||||
|> required "type" string
|
|
||||||
|> required "event_id" string
|
|
||||||
|> required "sender" string
|
|
||||||
|> required "origin_server_ts" int
|
|
||||||
|> maybeDecode "unsigned" unsignedDataDecoder
|
|
||||||
|> maybeDecode "prev_content" eventContentDecoder
|
|
||||||
|> required "state_key" string
|
|
||||||
|
|
||||||
-- Rooms
|
|
||||||
type alias Rooms =
|
|
||||||
{ join : Maybe (Dict String JoinedRoom)
|
|
||||||
, invite : Maybe (Dict String InvitedRoom)
|
|
||||||
, leave : Maybe (Dict String LeftRoom)
|
|
||||||
}
|
|
||||||
|
|
||||||
roomsDecoder : Decoder Rooms
|
|
||||||
roomsDecoder =
|
|
||||||
Decode.succeed Rooms
|
|
||||||
|> maybeDecode "join" (dict joinedRoomDecoder)
|
|
||||||
|> maybeDecode "invite" (dict invitedRoomDecoder)
|
|
||||||
|> maybeDecode "leave" (dict leftRoomDecoder)
|
|
||||||
|
|
||||||
type alias JoinedRoom =
|
|
||||||
{ state : Maybe State
|
|
||||||
, timeline : Maybe Timeline
|
|
||||||
, ephemeral : Maybe Ephemeral
|
|
||||||
, accountData : Maybe AccountData
|
|
||||||
, unreadNotifications : Maybe UnreadNotificationCounts
|
|
||||||
}
|
|
||||||
|
|
||||||
joinedRoomDecoder : Decoder JoinedRoom
|
|
||||||
joinedRoomDecoder =
|
|
||||||
Decode.succeed JoinedRoom
|
|
||||||
|> maybeDecode "state" stateDecoder
|
|
||||||
|> maybeDecode "timeline" timelineDecoder
|
|
||||||
|> maybeDecode "ephemeral" ephemeralDecoder
|
|
||||||
|> maybeDecode "account_data" accountDataDecoder
|
|
||||||
|> maybeDecode "unread_notifications" unreadNotificationCountsDecoder
|
|
||||||
|
|
||||||
|
|
||||||
-- Joined Room Data
|
|
||||||
type alias Timeline =
|
|
||||||
{ events : Maybe (List RoomEvent)
|
|
||||||
, limited : Maybe Bool
|
|
||||||
, prevBatch : Maybe String
|
|
||||||
}
|
|
||||||
|
|
||||||
timelineDecoder =
|
|
||||||
Decode.succeed Timeline
|
|
||||||
|> maybeDecode "events" (list roomEventDecoder)
|
|
||||||
|> maybeDecode "limited" bool
|
|
||||||
|> maybeDecode "prev_batch" string
|
|
||||||
|
|
||||||
type alias RoomEvent =
|
|
||||||
{ content : Decode.Value
|
|
||||||
, type_ : String
|
|
||||||
, eventId : String
|
|
||||||
, sender : String
|
|
||||||
, originServerTs : Int
|
|
||||||
, unsigned : Maybe UnsignedData
|
|
||||||
}
|
|
||||||
|
|
||||||
roomEventDecoder : Decoder RoomEvent
|
|
||||||
roomEventDecoder =
|
|
||||||
Decode.succeed RoomEvent
|
|
||||||
|> required "content" value
|
|
||||||
|> required "type" string
|
|
||||||
|> required "event_id" string
|
|
||||||
|> required "sender" string
|
|
||||||
|> required "origin_server_ts" int
|
|
||||||
|> maybeDecode "unsigned" unsignedDataDecoder
|
|
||||||
|
|
||||||
type alias Ephemeral =
|
|
||||||
{ events : Maybe (List Event)
|
|
||||||
}
|
|
||||||
|
|
||||||
ephemeralDecoder : Decoder Ephemeral
|
|
||||||
ephemeralDecoder =
|
|
||||||
Decode.succeed Ephemeral
|
|
||||||
|> maybeDecode "events" (list eventDecoder)
|
|
||||||
|
|
||||||
type alias AccountData =
|
|
||||||
{ events : Maybe (List Event)
|
|
||||||
}
|
|
||||||
|
|
||||||
accountDataDecoder : Decoder AccountData
|
|
||||||
accountDataDecoder =
|
|
||||||
Decode.succeed AccountData
|
|
||||||
|> maybeDecode "events" (list eventDecoder)
|
|
||||||
|
|
||||||
type alias UnreadNotificationCounts =
|
|
||||||
{ highlightCount : Maybe Int
|
|
||||||
, notificationCount : Maybe Int
|
|
||||||
}
|
|
||||||
|
|
||||||
unreadNotificationCountsDecoder : Decoder UnreadNotificationCounts
|
|
||||||
unreadNotificationCountsDecoder =
|
|
||||||
Decode.succeed UnreadNotificationCounts
|
|
||||||
|> maybeDecode "highlight_count" int
|
|
||||||
|> maybeDecode "notification_count" int
|
|
||||||
|
|
||||||
-- Invited Room Data
|
|
||||||
type alias InvitedRoom =
|
|
||||||
{ inviteState : Maybe InviteState
|
|
||||||
}
|
|
||||||
|
|
||||||
invitedRoomDecoder : Decoder InvitedRoom
|
|
||||||
invitedRoomDecoder =
|
|
||||||
Decode.succeed InvitedRoom
|
|
||||||
|> maybeDecode "invite_state" inviteStateDecoder
|
|
||||||
|
|
||||||
type alias InviteState =
|
|
||||||
{ events : Maybe (List StrippedState)
|
|
||||||
}
|
|
||||||
|
|
||||||
inviteStateDecoder : Decoder InviteState
|
|
||||||
inviteStateDecoder =
|
|
||||||
Decode.succeed InviteState
|
|
||||||
|> maybeDecode "events" (list strippedStateDecoder)
|
|
||||||
|
|
||||||
type alias StrippedState =
|
|
||||||
{ content : EventContent
|
|
||||||
, stateKey : String
|
|
||||||
, type_ : String
|
|
||||||
, sender : String
|
|
||||||
}
|
|
||||||
|
|
||||||
strippedStateDecoder : Decoder StrippedState
|
|
||||||
strippedStateDecoder =
|
|
||||||
Decode.succeed StrippedState
|
|
||||||
|> required "content" eventContentDecoder
|
|
||||||
|> required "state_key" string
|
|
||||||
|> required "type" string
|
|
||||||
|> required "sender" string
|
|
||||||
|
|
||||||
-- Left Room Data
|
|
||||||
type alias LeftRoom =
|
|
||||||
{ state : Maybe State
|
|
||||||
, timeline : Maybe Timeline
|
|
||||||
, accountData : Maybe AccountData
|
|
||||||
}
|
|
||||||
|
|
||||||
leftRoomDecoder : Decoder LeftRoom
|
|
||||||
leftRoomDecoder =
|
|
||||||
Decode.succeed LeftRoom
|
|
||||||
|> maybeDecode "state" stateDecoder
|
|
||||||
|> maybeDecode "timeline" timelineDecoder
|
|
||||||
|> maybeDecode "account_data" accountDataDecoder
|
|
||||||
|
|
||||||
-- General Sync Response
|
-- General Sync Response
|
||||||
type alias SyncResponse =
|
type alias SyncResponse =
|
||||||
{ nextBatch : String
|
{ nextBatch : String
|
||||||
|
@ -315,9 +107,9 @@ mergeStateEvents : List StateEvent -> List StateEvent -> List StateEvent
|
||||||
mergeStateEvents l1 l2 = uniqueBy .eventId <| l1 ++ l2
|
mergeStateEvents l1 l2 = uniqueBy .eventId <| l1 ++ l2
|
||||||
|
|
||||||
mergeRoomEvents : List RoomEvent -> List RoomEvent -> List RoomEvent
|
mergeRoomEvents : List RoomEvent -> List RoomEvent -> List RoomEvent
|
||||||
mergeRoomEvents l1 l2 = uniqueBy .eventId <| l1 ++ l2
|
mergeRoomEvents l1 l2 = uniqueBy getEventId <| l1 ++ l2
|
||||||
|
|
||||||
mergeStrippedStates : List StrippedState -> List StrippedState -> List StrippedState
|
mergeStrippedStates : List StrippedStateEvent -> List StrippedStateEvent -> List StrippedStateEvent
|
||||||
mergeStrippedStates l1 l2 = l1 ++ l2
|
mergeStrippedStates l1 l2 = l1 ++ l2
|
||||||
|
|
||||||
mergeAccountData : AccountData -> AccountData -> AccountData
|
mergeAccountData : AccountData -> AccountData -> AccountData
|
||||||
|
@ -445,17 +237,7 @@ allRoomStateEvents jr =
|
||||||
let
|
let
|
||||||
stateEvents = Maybe.withDefault [] <| Maybe.andThen .events jr.state
|
stateEvents = Maybe.withDefault [] <| Maybe.andThen .events jr.state
|
||||||
timelineEvents = Maybe.withDefault [] <| Maybe.andThen .events jr.timeline
|
timelineEvents = Maybe.withDefault [] <| Maybe.andThen .events jr.timeline
|
||||||
roomToStateEvent re =
|
allStateEvents = uniqueBy .eventId (stateEvents ++ (List.filterMap toStateEvent timelineEvents))
|
||||||
{ content = re.content
|
|
||||||
, type_ = re.type_
|
|
||||||
, eventId = re.eventId
|
|
||||||
, sender = re.sender
|
|
||||||
, originServerTs = re.originServerTs
|
|
||||||
, unsigned = re.unsigned
|
|
||||||
, prevContent = Nothing
|
|
||||||
, stateKey = ""
|
|
||||||
}
|
|
||||||
allStateEvents = uniqueBy .eventId (stateEvents ++ (List.map roomToStateEvent timelineEvents))
|
|
||||||
in
|
in
|
||||||
allStateEvents
|
allStateEvents
|
||||||
|
|
||||||
|
@ -465,7 +247,7 @@ allRoomDictTimelineEvents dict = List.concatMap (Maybe.withDefault [] << .events
|
||||||
<| Dict.values dict
|
<| Dict.values dict
|
||||||
|
|
||||||
allTimelineEventIds : SyncResponse -> List String
|
allTimelineEventIds : SyncResponse -> List String
|
||||||
allTimelineEventIds s = List.map .eventId <| allTimelineEvents s
|
allTimelineEventIds s = List.map getEventId <| allTimelineEvents s
|
||||||
|
|
||||||
allTimelineEvents : SyncResponse -> List RoomEvent
|
allTimelineEvents : SyncResponse -> List RoomEvent
|
||||||
allTimelineEvents s =
|
allTimelineEvents s =
|
||||||
|
@ -476,7 +258,7 @@ allTimelineEvents s =
|
||||||
joinedEvents = eventsFor .join
|
joinedEvents = eventsFor .join
|
||||||
leftEvents = eventsFor .leave
|
leftEvents = eventsFor .leave
|
||||||
in
|
in
|
||||||
uniqueBy .eventId <| leftEvents ++ joinedEvents
|
leftEvents ++ joinedEvents
|
||||||
|
|
||||||
joinedRoomsTimelineEvents : SyncResponse -> Dict String (List RoomEvent)
|
joinedRoomsTimelineEvents : SyncResponse -> Dict String (List RoomEvent)
|
||||||
joinedRoomsTimelineEvents s =
|
joinedRoomsTimelineEvents s =
|
||||||
|
@ -534,7 +316,7 @@ roomTypingUsers jr = Maybe.withDefault []
|
||||||
|
|
||||||
-- Business Logic: Users
|
-- Business Logic: Users
|
||||||
allUsers : SyncResponse -> List Username
|
allUsers : SyncResponse -> List Username
|
||||||
allUsers s = uniqueBy (\u -> u) <| List.map .sender <| allTimelineEvents s
|
allUsers s = uniqueBy (\u -> u) <| List.map getSender <| allTimelineEvents s
|
||||||
|
|
||||||
roomJoinedUsers : JoinedRoom -> List Username
|
roomJoinedUsers : JoinedRoom -> List Username
|
||||||
roomJoinedUsers r =
|
roomJoinedUsers r =
|
||||||
|
|
14
src/Scylla/Sync/AccountData.elm
Normal file
14
src/Scylla/Sync/AccountData.elm
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
module Scylla.Sync.AccountData exposing (..)
|
||||||
|
import Scylla.Sync.DecodeTools exposing (maybeDecode)
|
||||||
|
import Scylla.Sync.Events exposing (Event, eventDecoder)
|
||||||
|
import Json.Decode as Decode exposing (Decoder, list)
|
||||||
|
|
||||||
|
type alias AccountData =
|
||||||
|
{ events : Maybe (List Event)
|
||||||
|
}
|
||||||
|
|
||||||
|
accountDataDecoder : Decoder AccountData
|
||||||
|
accountDataDecoder =
|
||||||
|
Decode.succeed AccountData
|
||||||
|
|> maybeDecode "events" (list eventDecoder)
|
||||||
|
|
9
src/Scylla/Sync/DecodeTools.elm
Normal file
9
src/Scylla/Sync/DecodeTools.elm
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
module Scylla.Sync.DecodeTools exposing (..)
|
||||||
|
import Json.Decode as Decode exposing (Decoder)
|
||||||
|
import Json.Decode.Pipeline exposing (optional)
|
||||||
|
|
||||||
|
decodeJust : Decoder a -> Decoder (Maybe a)
|
||||||
|
decodeJust = Decode.map Just
|
||||||
|
|
||||||
|
maybeDecode : String -> Decoder a -> Decoder (Maybe a -> b) -> Decoder b
|
||||||
|
maybeDecode s d = optional s (decodeJust d) Nothing
|
143
src/Scylla/Sync/Events.elm
Normal file
143
src/Scylla/Sync/Events.elm
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
module Scylla.Sync.Events exposing (..)
|
||||||
|
import Scylla.Sync.DecodeTools exposing (maybeDecode)
|
||||||
|
import Json.Decode as Decode exposing (Decoder, int, string, value, oneOf)
|
||||||
|
import Json.Decode.Pipeline exposing (required)
|
||||||
|
|
||||||
|
type alias UnsignedData =
|
||||||
|
{ age : Maybe Int
|
||||||
|
, redactedBecause : Maybe Event
|
||||||
|
, transactionId : Maybe String
|
||||||
|
}
|
||||||
|
|
||||||
|
unsignedDataDecoder : Decoder UnsignedData
|
||||||
|
unsignedDataDecoder =
|
||||||
|
Decode.succeed UnsignedData
|
||||||
|
|> maybeDecode "age" int
|
||||||
|
|> maybeDecode "redacted_because" eventDecoder
|
||||||
|
|> maybeDecode "transaction_id" string
|
||||||
|
|
||||||
|
type alias EventContent = Decode.Value
|
||||||
|
|
||||||
|
eventContentDecoder : Decoder EventContent
|
||||||
|
eventContentDecoder = Decode.value
|
||||||
|
|
||||||
|
type alias Event =
|
||||||
|
{ content : Decode.Value
|
||||||
|
, type_ : String
|
||||||
|
}
|
||||||
|
|
||||||
|
eventDecoder : Decoder Event
|
||||||
|
eventDecoder =
|
||||||
|
Decode.succeed Event
|
||||||
|
|> required "content" value
|
||||||
|
|> required "type" string
|
||||||
|
|
||||||
|
type RoomEvent
|
||||||
|
= StateRoomEvent StateEvent
|
||||||
|
| MessageRoomEvent MessageEvent
|
||||||
|
|
||||||
|
roomEventDecoder : Decoder RoomEvent
|
||||||
|
roomEventDecoder = oneOf
|
||||||
|
[ Decode.map MessageRoomEvent messageEventDecoder
|
||||||
|
, Decode.map StateRoomEvent stateEventDecoder
|
||||||
|
]
|
||||||
|
|
||||||
|
type alias MessageEvent =
|
||||||
|
{ content : EventContent
|
||||||
|
, type_ : String
|
||||||
|
, eventId : String
|
||||||
|
, sender : String
|
||||||
|
, originServerTs : Int
|
||||||
|
, unsigned : Maybe UnsignedData
|
||||||
|
}
|
||||||
|
|
||||||
|
messageEventDecoder : Decoder MessageEvent
|
||||||
|
messageEventDecoder =
|
||||||
|
Decode.succeed MessageEvent
|
||||||
|
|> required "content" value
|
||||||
|
|> required "type" string
|
||||||
|
|> required "event_id" string
|
||||||
|
|> required "sender" string
|
||||||
|
|> required "origin_server_ts" int
|
||||||
|
|> maybeDecode "unsigned" unsignedDataDecoder
|
||||||
|
|
||||||
|
type alias StateEvent =
|
||||||
|
{ content : EventContent
|
||||||
|
, type_ : String
|
||||||
|
, eventId : String
|
||||||
|
, sender : String
|
||||||
|
, originServerTs : Int
|
||||||
|
, unsigned : Maybe UnsignedData
|
||||||
|
, prevContent : Maybe EventContent
|
||||||
|
, stateKey : String
|
||||||
|
}
|
||||||
|
|
||||||
|
stateEventDecoder : Decoder StateEvent
|
||||||
|
stateEventDecoder =
|
||||||
|
Decode.succeed StateEvent
|
||||||
|
|> required "content" value
|
||||||
|
|> required "type" string
|
||||||
|
|> required "event_id" string
|
||||||
|
|> required "sender" string
|
||||||
|
|> required "origin_server_ts" int
|
||||||
|
|> maybeDecode "unsigned" unsignedDataDecoder
|
||||||
|
|> maybeDecode "prev_content" eventContentDecoder
|
||||||
|
|> required "state_key" string
|
||||||
|
|
||||||
|
type alias StrippedStateEvent =
|
||||||
|
{ content : EventContent
|
||||||
|
, stateKey : String
|
||||||
|
, type_ : String
|
||||||
|
, sender : String
|
||||||
|
}
|
||||||
|
|
||||||
|
strippedStateEventDecoder : Decoder StrippedStateEvent
|
||||||
|
strippedStateEventDecoder =
|
||||||
|
Decode.succeed StrippedStateEvent
|
||||||
|
|> required "content" eventContentDecoder
|
||||||
|
|> required "state_key" string
|
||||||
|
|> required "type" string
|
||||||
|
|> required "sender" string
|
||||||
|
|
||||||
|
-- Operations on Room Events
|
||||||
|
getUnsigned : RoomEvent -> Maybe UnsignedData
|
||||||
|
getUnsigned re =
|
||||||
|
case re of
|
||||||
|
StateRoomEvent e -> e.unsigned
|
||||||
|
MessageRoomEvent e -> e.unsigned
|
||||||
|
|
||||||
|
getEventId : RoomEvent -> String
|
||||||
|
getEventId re =
|
||||||
|
case re of
|
||||||
|
StateRoomEvent e -> e.eventId
|
||||||
|
MessageRoomEvent e -> e.eventId
|
||||||
|
|
||||||
|
getSender : RoomEvent -> String
|
||||||
|
getSender re =
|
||||||
|
case re of
|
||||||
|
StateRoomEvent e -> e.sender
|
||||||
|
MessageRoomEvent e -> e.sender
|
||||||
|
|
||||||
|
getType : RoomEvent -> String
|
||||||
|
getType re =
|
||||||
|
case re of
|
||||||
|
StateRoomEvent e -> e.type_
|
||||||
|
MessageRoomEvent e -> e.type_
|
||||||
|
|
||||||
|
toStateEvent : RoomEvent -> Maybe StateEvent
|
||||||
|
toStateEvent re =
|
||||||
|
case re of
|
||||||
|
StateRoomEvent e -> Just e
|
||||||
|
_ -> Nothing
|
||||||
|
|
||||||
|
toMessageEvent : RoomEvent -> Maybe MessageEvent
|
||||||
|
toMessageEvent re =
|
||||||
|
case re of
|
||||||
|
MessageRoomEvent e -> Just e
|
||||||
|
_ -> Nothing
|
||||||
|
|
||||||
|
toEvent : RoomEvent -> Event
|
||||||
|
toEvent re =
|
||||||
|
case re of
|
||||||
|
StateRoomEvent e -> { content = e.content, type_ = e.type_ }
|
||||||
|
MessageRoomEvent e -> { content = e.content, type_ = e.type_ }
|
109
src/Scylla/Sync/Rooms.elm
Normal file
109
src/Scylla/Sync/Rooms.elm
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
module Scylla.Sync.Rooms exposing (..)
|
||||||
|
import Scylla.Sync.DecodeTools exposing (maybeDecode)
|
||||||
|
import Scylla.Sync.Events exposing (Event, RoomEvent, StateEvent, StrippedStateEvent, stateEventDecoder, strippedStateEventDecoder, roomEventDecoder, eventDecoder)
|
||||||
|
import Scylla.Sync.AccountData exposing (AccountData, accountDataDecoder)
|
||||||
|
import Json.Decode as Decode exposing (Decoder, int, string, dict, list, bool)
|
||||||
|
import Json.Decode.Pipeline exposing (required)
|
||||||
|
import Dict exposing (Dict)
|
||||||
|
|
||||||
|
type alias Rooms =
|
||||||
|
{ join : Maybe (Dict String JoinedRoom)
|
||||||
|
, invite : Maybe (Dict String InvitedRoom)
|
||||||
|
, leave : Maybe (Dict String LeftRoom)
|
||||||
|
}
|
||||||
|
|
||||||
|
roomsDecoder : Decoder Rooms
|
||||||
|
roomsDecoder =
|
||||||
|
Decode.succeed Rooms
|
||||||
|
|> maybeDecode "join" (dict joinedRoomDecoder)
|
||||||
|
|> maybeDecode "invite" (dict invitedRoomDecoder)
|
||||||
|
|> maybeDecode "leave" (dict leftRoomDecoder)
|
||||||
|
|
||||||
|
type alias JoinedRoom =
|
||||||
|
{ state : Maybe State
|
||||||
|
, timeline : Maybe Timeline
|
||||||
|
, ephemeral : Maybe Ephemeral
|
||||||
|
, accountData : Maybe AccountData
|
||||||
|
, unreadNotifications : Maybe UnreadNotificationCounts
|
||||||
|
}
|
||||||
|
|
||||||
|
joinedRoomDecoder : Decoder JoinedRoom
|
||||||
|
joinedRoomDecoder =
|
||||||
|
Decode.succeed JoinedRoom
|
||||||
|
|> maybeDecode "state" stateDecoder
|
||||||
|
|> maybeDecode "timeline" timelineDecoder
|
||||||
|
|> maybeDecode "ephemeral" ephemeralDecoder
|
||||||
|
|> maybeDecode "account_data" accountDataDecoder
|
||||||
|
|> maybeDecode "unread_notifications" unreadNotificationCountsDecoder
|
||||||
|
|
||||||
|
type alias InvitedRoom =
|
||||||
|
{ inviteState : Maybe InviteState
|
||||||
|
}
|
||||||
|
|
||||||
|
invitedRoomDecoder : Decoder InvitedRoom
|
||||||
|
invitedRoomDecoder =
|
||||||
|
Decode.succeed InvitedRoom
|
||||||
|
|> maybeDecode "invite_state" inviteStateDecoder
|
||||||
|
|
||||||
|
type alias LeftRoom =
|
||||||
|
{ state : Maybe State
|
||||||
|
, timeline : Maybe Timeline
|
||||||
|
, accountData : Maybe AccountData
|
||||||
|
}
|
||||||
|
|
||||||
|
leftRoomDecoder : Decoder LeftRoom
|
||||||
|
leftRoomDecoder =
|
||||||
|
Decode.succeed LeftRoom
|
||||||
|
|> maybeDecode "state" stateDecoder
|
||||||
|
|> maybeDecode "timeline" timelineDecoder
|
||||||
|
|> maybeDecode "account_data" accountDataDecoder
|
||||||
|
|
||||||
|
type alias State =
|
||||||
|
{ events : Maybe (List StateEvent)
|
||||||
|
}
|
||||||
|
|
||||||
|
stateDecoder : Decoder State
|
||||||
|
stateDecoder =
|
||||||
|
Decode.succeed State
|
||||||
|
|> maybeDecode "events" (list stateEventDecoder)
|
||||||
|
|
||||||
|
type alias InviteState =
|
||||||
|
{ events : Maybe (List StrippedStateEvent)
|
||||||
|
}
|
||||||
|
|
||||||
|
inviteStateDecoder : Decoder InviteState
|
||||||
|
inviteStateDecoder =
|
||||||
|
Decode.succeed InviteState
|
||||||
|
|> maybeDecode "events" (list strippedStateEventDecoder)
|
||||||
|
|
||||||
|
type alias Timeline =
|
||||||
|
{ events : Maybe (List RoomEvent)
|
||||||
|
, limited : Maybe Bool
|
||||||
|
, prevBatch : Maybe String
|
||||||
|
}
|
||||||
|
|
||||||
|
timelineDecoder =
|
||||||
|
Decode.succeed Timeline
|
||||||
|
|> maybeDecode "events" (list roomEventDecoder)
|
||||||
|
|> maybeDecode "limited" bool
|
||||||
|
|> maybeDecode "prev_batch" string
|
||||||
|
|
||||||
|
type alias Ephemeral =
|
||||||
|
{ events : Maybe (List Event)
|
||||||
|
}
|
||||||
|
|
||||||
|
ephemeralDecoder : Decoder Ephemeral
|
||||||
|
ephemeralDecoder =
|
||||||
|
Decode.succeed Ephemeral
|
||||||
|
|> maybeDecode "events" (list eventDecoder)
|
||||||
|
|
||||||
|
type alias UnreadNotificationCounts =
|
||||||
|
{ highlightCount : Maybe Int
|
||||||
|
, notificationCount : Maybe Int
|
||||||
|
}
|
||||||
|
|
||||||
|
unreadNotificationCountsDecoder : Decoder UnreadNotificationCounts
|
||||||
|
unreadNotificationCountsDecoder =
|
||||||
|
Decode.succeed UnreadNotificationCounts
|
||||||
|
|> maybeDecode "highlight_count" int
|
||||||
|
|> maybeDecode "notification_count" int
|
|
@ -1,6 +1,8 @@
|
||||||
module Scylla.Views exposing (..)
|
module Scylla.Views exposing (..)
|
||||||
import Scylla.Model exposing (..)
|
import Scylla.Model exposing (..)
|
||||||
import Scylla.Sync exposing (..)
|
import Scylla.Sync exposing (..)
|
||||||
|
import Scylla.Sync.Events exposing (..)
|
||||||
|
import Scylla.Sync.Rooms exposing (..)
|
||||||
import Scylla.Route exposing (..)
|
import Scylla.Route exposing (..)
|
||||||
import Scylla.Fnv as Fnv
|
import Scylla.Fnv as Fnv
|
||||||
import Scylla.Messages exposing (..)
|
import Scylla.Messages exposing (..)
|
||||||
|
@ -250,7 +252,7 @@ sendingMessageView : SendingMessage -> Html Msg
|
||||||
sendingMessageView msg = case msg.body of
|
sendingMessageView msg = case msg.body of
|
||||||
TextMessage t -> span [ class "sending"] [ text t ]
|
TextMessage t -> span [ class "sending"] [ text t ]
|
||||||
|
|
||||||
roomEventView : Dict String UserData -> ApiUrl -> RoomEvent -> Maybe (Html Msg)
|
roomEventView : Dict String UserData -> ApiUrl -> MessageEvent -> Maybe (Html Msg)
|
||||||
roomEventView ud apiUrl re =
|
roomEventView ud apiUrl re =
|
||||||
let
|
let
|
||||||
msgtype = Decode.decodeValue (Decode.field "msgtype" Decode.string) re.content
|
msgtype = Decode.decodeValue (Decode.field "msgtype" Decode.string) re.content
|
||||||
|
@ -264,13 +266,13 @@ roomEventView ud apiUrl re =
|
||||||
Ok "m.video" -> roomEventVideoView apiUrl re
|
Ok "m.video" -> roomEventVideoView apiUrl re
|
||||||
_ -> Nothing
|
_ -> Nothing
|
||||||
|
|
||||||
roomEventFormattedContent : RoomEvent -> Maybe (List (Html Msg))
|
roomEventFormattedContent : MessageEvent -> Maybe (List (Html Msg))
|
||||||
roomEventFormattedContent re = Maybe.map Html.Parser.Util.toVirtualDom
|
roomEventFormattedContent re = Maybe.map Html.Parser.Util.toVirtualDom
|
||||||
<| Maybe.andThen (Result.toMaybe << Html.Parser.run )
|
<| Maybe.andThen (Result.toMaybe << Html.Parser.run )
|
||||||
<| Result.toMaybe
|
<| Result.toMaybe
|
||||||
<| Decode.decodeValue (Decode.field "formatted_body" Decode.string) re.content
|
<| Decode.decodeValue (Decode.field "formatted_body" Decode.string) re.content
|
||||||
|
|
||||||
roomEventContent : (List (Html Msg) -> Html Msg) -> RoomEvent -> Maybe (Html Msg)
|
roomEventContent : (List (Html Msg) -> Html Msg) -> MessageEvent -> Maybe (Html Msg)
|
||||||
roomEventContent f re =
|
roomEventContent f re =
|
||||||
let
|
let
|
||||||
body = Decode.decodeValue (Decode.field "body" Decode.string) re.content
|
body = Decode.decodeValue (Decode.field "body" Decode.string) re.content
|
||||||
|
@ -280,20 +282,20 @@ roomEventContent f re =
|
||||||
Just c -> Just <| f c
|
Just c -> Just <| f c
|
||||||
Nothing -> Maybe.map (f << List.singleton << text) <| Result.toMaybe body
|
Nothing -> Maybe.map (f << List.singleton << text) <| Result.toMaybe body
|
||||||
|
|
||||||
roomEventEmoteView : Dict String UserData -> RoomEvent -> Maybe (Html Msg)
|
roomEventEmoteView : Dict String UserData -> MessageEvent -> Maybe (Html Msg)
|
||||||
roomEventEmoteView ud re =
|
roomEventEmoteView ud re =
|
||||||
let
|
let
|
||||||
emoteText = "* " ++ displayName ud re.sender ++ " "
|
emoteText = "* " ++ displayName ud re.sender ++ " "
|
||||||
in
|
in
|
||||||
roomEventContent (\cs -> span [] (text emoteText :: cs)) re
|
roomEventContent (\cs -> span [] (text emoteText :: cs)) re
|
||||||
|
|
||||||
roomEventNoticeView : RoomEvent -> Maybe (Html Msg)
|
roomEventNoticeView : MessageEvent -> Maybe (Html Msg)
|
||||||
roomEventNoticeView = roomEventContent (span [ class "message-notice" ])
|
roomEventNoticeView = roomEventContent (span [ class "message-notice" ])
|
||||||
|
|
||||||
roomEventTextView : RoomEvent -> Maybe (Html Msg)
|
roomEventTextView : MessageEvent -> Maybe (Html Msg)
|
||||||
roomEventTextView = roomEventContent (span [])
|
roomEventTextView = roomEventContent (span [])
|
||||||
|
|
||||||
roomEventImageView : ApiUrl -> RoomEvent -> Maybe (Html Msg)
|
roomEventImageView : ApiUrl -> MessageEvent -> Maybe (Html Msg)
|
||||||
roomEventImageView apiUrl re =
|
roomEventImageView apiUrl re =
|
||||||
let
|
let
|
||||||
body = Decode.decodeValue (Decode.field "url" Decode.string) re.content
|
body = Decode.decodeValue (Decode.field "url" Decode.string) re.content
|
||||||
|
@ -302,7 +304,7 @@ roomEventImageView apiUrl re =
|
||||||
<| Maybe.map (contentRepositoryDownloadUrl apiUrl)
|
<| Maybe.map (contentRepositoryDownloadUrl apiUrl)
|
||||||
<| Result.toMaybe body
|
<| Result.toMaybe body
|
||||||
|
|
||||||
roomEventFileView : ApiUrl -> RoomEvent -> Maybe (Html Msg)
|
roomEventFileView : ApiUrl -> MessageEvent -> Maybe (Html Msg)
|
||||||
roomEventFileView apiUrl re =
|
roomEventFileView apiUrl re =
|
||||||
let
|
let
|
||||||
decoder = Decode.map2 (\l r -> (l, r)) (Decode.field "url" Decode.string) (Decode.field "body" Decode.string)
|
decoder = Decode.map2 (\l r -> (l, r)) (Decode.field "url" Decode.string) (Decode.field "body" Decode.string)
|
||||||
|
@ -312,7 +314,7 @@ roomEventFileView apiUrl re =
|
||||||
<| Maybe.map (\(url, name) -> (contentRepositoryDownloadUrl apiUrl url, name))
|
<| Maybe.map (\(url, name) -> (contentRepositoryDownloadUrl apiUrl url, name))
|
||||||
<| Result.toMaybe fileData
|
<| Result.toMaybe fileData
|
||||||
|
|
||||||
roomEventVideoView : ApiUrl -> RoomEvent -> Maybe (Html Msg)
|
roomEventVideoView : ApiUrl -> MessageEvent -> Maybe (Html Msg)
|
||||||
roomEventVideoView apiUrl re =
|
roomEventVideoView apiUrl re =
|
||||||
let
|
let
|
||||||
decoder = Decode.map2 (\l r -> (l, r))
|
decoder = Decode.map2 (\l r -> (l, r))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user