Split Sync file into sub-modules

This commit is contained in:
Danila Fedorin 2019-09-10 18:15:28 -07:00
parent ccfd2fe76b
commit 595e28853e
11 changed files with 316 additions and 248 deletions

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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 =

View 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)

View 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
View 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
View 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

View File

@ -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))