Start switching from sync to room data
This commit is contained in:
parent
676d6c28a7
commit
29e81a88ac
|
@ -1,8 +1,11 @@
|
|||
import Browser exposing (application, UrlRequest(..))
|
||||
import Browser.Navigation as Nav
|
||||
import Browser.Dom exposing (Viewport, setViewportOf)
|
||||
import Scylla.Room exposing (OpenRooms, applySync)
|
||||
import Scylla.Sync exposing (..)
|
||||
import Scylla.Sync.Events exposing (toMessageEvent, getType, getSender, getUnsigned)
|
||||
import Scylla.Sync.AccountData exposing (..)
|
||||
import Scylla.ListUtils exposing (..)
|
||||
import Scylla.Messages exposing (..)
|
||||
import Scylla.Login exposing (..)
|
||||
import Scylla.Api exposing (..)
|
||||
|
@ -14,7 +17,7 @@ import Scylla.UserData exposing (..)
|
|||
import Scylla.Notification exposing (..)
|
||||
import Scylla.Storage exposing (..)
|
||||
import Scylla.Markdown exposing (..)
|
||||
import Scylla.AccountData exposing (..)
|
||||
import Scylla.Room exposing (..)
|
||||
import Url exposing (Url)
|
||||
import Url.Parser exposing (parse)
|
||||
import Url.Builder
|
||||
|
@ -55,6 +58,7 @@ init _ url key =
|
|||
, roomNames = Dict.empty
|
||||
, connected = True
|
||||
, searchText = ""
|
||||
, rooms = emptyOpenRooms
|
||||
}
|
||||
cmd = getStoreValuePort "scylla.loginInfo"
|
||||
in
|
||||
|
@ -355,6 +359,7 @@ updateSyncResponse model r notify =
|
|||
{ model | sync = newSync sr
|
||||
, sending = sending (mergeSyncResponse model.sync sr)
|
||||
, roomNames = computeRoomsDisplayNames model.userData (newSync sr)
|
||||
, rooms = applySync sr model.rooms
|
||||
}
|
||||
in
|
||||
case r of
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
module Scylla.AccountData exposing (..)
|
||||
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.Encode as Encode
|
||||
import Dict exposing (Dict)
|
||||
|
||||
type alias DirectMessages = Dict String String
|
||||
type alias DirectMessagesRaw = Dict String (List String)
|
||||
|
||||
directMessagesDecoder : Decode.Decoder DirectMessages
|
||||
directMessagesDecoder =
|
||||
Decode.dict (Decode.list Decode.string)
|
||||
|> Decode.map (invertDirectMessages)
|
||||
|
||||
invertDirectMessages : DirectMessagesRaw -> DirectMessages
|
||||
invertDirectMessages dmr =
|
||||
Dict.foldl
|
||||
(\k lv acc -> List.foldl (\v -> Dict.insert v k) acc lv)
|
||||
Dict.empty
|
||||
dmr
|
||||
|
39
src/Scylla/ListUtils.elm
Normal file
39
src/Scylla/ListUtils.elm
Normal file
|
@ -0,0 +1,39 @@
|
|||
module Scylla.ListUtils exposing (..)
|
||||
import Dict exposing (Dict)
|
||||
import Set exposing (Set)
|
||||
|
||||
groupBy : (a -> comparable) -> List a -> Dict comparable (List a)
|
||||
groupBy f xs =
|
||||
let
|
||||
update v ml = case ml of
|
||||
Just l -> Just (v::l)
|
||||
Nothing -> Just [ v ]
|
||||
in
|
||||
List.foldl (\v acc -> Dict.update (f v) (update v) acc) Dict.empty xs
|
||||
|
||||
uniqueByTailRecursive : (a -> comparable) -> List a -> Set comparable -> List a -> List a
|
||||
uniqueByTailRecursive f l s acc =
|
||||
case l of
|
||||
x::tail ->
|
||||
if Set.member (f x) s
|
||||
then uniqueByTailRecursive f tail s acc
|
||||
else uniqueByTailRecursive f tail (Set.insert (f x) s) (x::acc)
|
||||
[] -> List.reverse acc
|
||||
|
||||
uniqueBy : (a -> comparable) -> List a -> List a
|
||||
uniqueBy f l = uniqueByTailRecursive f l Set.empty []
|
||||
|
||||
findFirst : (a -> Bool) -> List a -> Maybe a
|
||||
findFirst cond l = case l of
|
||||
x::xs -> if cond x then Just x else findFirst cond xs
|
||||
[] -> Nothing
|
||||
|
||||
findLast : (a -> Bool) -> List a -> Maybe a
|
||||
findLast cond l = findFirst cond <| List.reverse l
|
||||
|
||||
findFirstBy : (a -> comparable) -> (a -> Bool) -> List a -> Maybe a
|
||||
findFirstBy sortFunction cond l = findFirst cond <| List.sortBy sortFunction l
|
||||
|
||||
findLastBy : (a -> comparable) -> (a -> Bool) -> List a -> Maybe a
|
||||
findLastBy sortFunction cond l = findLast cond <| List.sortBy sortFunction l
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
module Scylla.Model exposing (..)
|
||||
import Scylla.Api exposing (..)
|
||||
import Scylla.Sync exposing (SyncResponse, HistoryResponse, senderName, roomName, roomJoinedUsers, findFirst)
|
||||
import Scylla.Sync exposing (SyncResponse, HistoryResponse, senderName, roomName, roomJoinedUsers)
|
||||
import Scylla.ListUtils exposing (findFirst)
|
||||
import Scylla.Room exposing (OpenRooms)
|
||||
import Scylla.Sync.Rooms exposing (JoinedRoom)
|
||||
import Scylla.Sync.AccountData exposing (AccountData)
|
||||
import Scylla.AccountData exposing (directMessagesDecoder)
|
||||
import Scylla.Sync.AccountData exposing (AccountData, directMessagesDecoder)
|
||||
import Scylla.Login exposing (LoginResponse, Username, Password)
|
||||
import Scylla.UserData exposing (UserData)
|
||||
import Scylla.Route exposing (Route(..), RoomId)
|
||||
|
@ -37,6 +38,7 @@ type alias Model =
|
|||
, roomNames : Dict RoomId String
|
||||
, connected : Bool
|
||||
, searchText : String
|
||||
, rooms : OpenRooms
|
||||
}
|
||||
|
||||
type Msg =
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
port module Scylla.Notification exposing (..)
|
||||
import Scylla.Sync exposing (SyncResponse, joinedRoomsTimelineEvents)
|
||||
import Scylla.Sync.Events exposing (RoomEvent, MessageEvent, toMessageEvent)
|
||||
import Scylla.AccountData exposing (..)
|
||||
import Json.Decode as Decode exposing (string, field)
|
||||
import Dict
|
||||
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
module Scylla.Room exposing (..)
|
||||
import Scylla.Route exposing (RoomId)
|
||||
import Scylla.Sync exposing (SyncResponse)
|
||||
import Scylla.Login exposing (Username)
|
||||
import Scylla.UserData exposing (UserData)
|
||||
import Scylla.Sync.Events exposing (MessageEvent, StateEvent, toStateEvent, toMessageEvent)
|
||||
import Scylla.Sync.AccountData exposing (AccountData)
|
||||
import Scylla.Sync.AccountData exposing (AccountData, getDirectMessages)
|
||||
import Scylla.Sync.Rooms exposing (JoinedRoom, UnreadNotificationCounts, Ephemeral)
|
||||
import Json.Decode as Decode exposing (Value)
|
||||
import Json.Decode as Decode exposing (Decoder, Value, decodeValue)
|
||||
import Dict exposing (Dict)
|
||||
|
||||
type alias RoomState = Dict (String, String) Value
|
||||
|
@ -108,3 +110,19 @@ applySync sr or =
|
|||
|> Maybe.withDefault Dict.empty
|
||||
in
|
||||
Dict.foldl applyJoinedRoom or joinedRooms
|
||||
|
||||
getStateData : (String, String) -> Decoder a -> RoomData -> Maybe a
|
||||
getStateData k d rd = Dict.get k rd.roomState
|
||||
|> Maybe.andThen (Result.toMaybe << decodeValue d)
|
||||
|
||||
getRoomName : Maybe AccountData -> Dict Username UserData -> RoomId -> RoomData -> String
|
||||
getRoomName ad ud rid rd =
|
||||
let
|
||||
customName = getStateData ("m.room.name", "") Decode.string rd
|
||||
direct = Maybe.andThen getDirectMessages ad
|
||||
|> Maybe.andThen (Dict.get rid)
|
||||
in
|
||||
case (customName, direct) of
|
||||
(Just cn, _) -> cn
|
||||
(_, Just d) -> d
|
||||
_ -> rid
|
||||
|
|
|
@ -2,6 +2,7 @@ module Scylla.Sync exposing (..)
|
|||
import Scylla.Api exposing (..)
|
||||
import Scylla.Login exposing (Username)
|
||||
import Scylla.Route exposing (RoomId)
|
||||
import Scylla.ListUtils exposing (..)
|
||||
import Scylla.Sync.DecodeTools exposing (maybeDecode)
|
||||
import Scylla.Sync.Events exposing (..)
|
||||
import Scylla.Sync.Rooms exposing (..)
|
||||
|
@ -51,41 +52,6 @@ historyResponseDecoder =
|
|||
|> required "chunk" (list roomEventDecoder)
|
||||
|
||||
-- Business Logic: Helper Functions
|
||||
groupBy : (a -> comparable) -> List a -> Dict comparable (List a)
|
||||
groupBy f xs =
|
||||
let
|
||||
update v ml = case ml of
|
||||
Just l -> Just (v::l)
|
||||
Nothing -> Just [ v ]
|
||||
in
|
||||
List.foldl (\v acc -> Dict.update (f v) (update v) acc) Dict.empty xs
|
||||
|
||||
uniqueByTailRecursive : (a -> comparable) -> List a -> Set comparable -> List a -> List a
|
||||
uniqueByTailRecursive f l s acc =
|
||||
case l of
|
||||
x::tail ->
|
||||
if Set.member (f x) s
|
||||
then uniqueByTailRecursive f tail s acc
|
||||
else uniqueByTailRecursive f tail (Set.insert (f x) s) (x::acc)
|
||||
[] -> List.reverse acc
|
||||
|
||||
uniqueBy : (a -> comparable) -> List a -> List a
|
||||
uniqueBy f l = uniqueByTailRecursive f l Set.empty []
|
||||
|
||||
findFirst : (a -> Bool) -> List a -> Maybe a
|
||||
findFirst cond l = case l of
|
||||
x::xs -> if cond x then Just x else findFirst cond xs
|
||||
[] -> Nothing
|
||||
|
||||
findLast : (a -> Bool) -> List a -> Maybe a
|
||||
findLast cond l = findFirst cond <| List.reverse l
|
||||
|
||||
findFirstBy : (a -> comparable) -> (a -> Bool) -> List a -> Maybe a
|
||||
findFirstBy sortFunction cond l = findFirst cond <| List.sortBy sortFunction l
|
||||
|
||||
findLastBy : (a -> comparable) -> (a -> Bool) -> List a -> Maybe a
|
||||
findLastBy sortFunction cond l = findLast cond <| List.sortBy sortFunction l
|
||||
|
||||
findFirstEvent : ({ a | originServerTs : Int } -> Bool) -> List { a | originServerTs : Int } -> Maybe { a | originServerTs : Int }
|
||||
findFirstEvent = findFirstBy .originServerTs
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
module Scylla.Sync.AccountData exposing (..)
|
||||
import Scylla.ListUtils exposing (..)
|
||||
import Scylla.Sync.DecodeTools exposing (maybeDecode)
|
||||
import Scylla.Sync.Events exposing (Event, eventDecoder)
|
||||
import Json.Decode as Decode exposing (Decoder, list)
|
||||
import Json.Decode as Decode exposing (Decoder, list, decodeValue)
|
||||
import Dict exposing (Dict)
|
||||
|
||||
type alias AccountData =
|
||||
{ events : Maybe (List Event)
|
||||
|
@ -12,3 +14,27 @@ accountDataDecoder =
|
|||
Decode.succeed AccountData
|
||||
|> maybeDecode "events" (list eventDecoder)
|
||||
|
||||
type alias DirectMessages = Dict String String
|
||||
|
||||
directMessagesDecoder : Decode.Decoder DirectMessages
|
||||
directMessagesDecoder =
|
||||
Decode.dict (Decode.list Decode.string)
|
||||
|> Decode.map (invertDirectMessages)
|
||||
|
||||
type alias DirectMessagesRaw = Dict String (List String)
|
||||
|
||||
invertDirectMessages : DirectMessagesRaw -> DirectMessages
|
||||
invertDirectMessages dmr =
|
||||
Dict.foldl
|
||||
(\k lv acc -> List.foldl (\v -> Dict.insert v k) acc lv)
|
||||
Dict.empty
|
||||
dmr
|
||||
|
||||
getAccountData : String -> Decode.Decoder a -> AccountData -> Maybe a
|
||||
getAccountData key d ad = ad.events
|
||||
|> Maybe.andThen (findFirst ((==) key << .type_))
|
||||
|> Maybe.map .content
|
||||
|> Maybe.andThen (Result.toMaybe << decodeValue d)
|
||||
|
||||
getDirectMessages : AccountData -> Maybe DirectMessages
|
||||
getDirectMessages = getAccountData "m.direct" directMessagesDecoder
|
||||
|
|
|
@ -3,6 +3,7 @@ import Scylla.Model exposing (..)
|
|||
import Scylla.Sync exposing (..)
|
||||
import Scylla.Sync.Events exposing (..)
|
||||
import Scylla.Sync.Rooms exposing (..)
|
||||
import Scylla.Room exposing (RoomData, emptyOpenRooms, getRoomName)
|
||||
import Scylla.Route exposing (..)
|
||||
import Scylla.Fnv as Fnv
|
||||
import Scylla.Messages exposing (..)
|
||||
|
@ -10,6 +11,7 @@ import Scylla.Login exposing (Username)
|
|||
import Scylla.UserData exposing (UserData)
|
||||
import Scylla.Http exposing (fullMediaUrl)
|
||||
import Scylla.Api exposing (ApiUrl)
|
||||
import Scylla.ListUtils exposing (groupBy)
|
||||
import Html.Parser
|
||||
import Html.Parser.Util
|
||||
import Svg
|
||||
|
@ -85,11 +87,8 @@ reconnectView m = if m.connected
|
|||
roomListView : Model -> Html Msg
|
||||
roomListView m =
|
||||
let
|
||||
rooms = Maybe.withDefault (Dict.empty)
|
||||
<| Maybe.andThen .join
|
||||
<| m.sync.rooms
|
||||
groups = roomGroups
|
||||
<| Dict.toList rooms
|
||||
<| Dict.toList m.rooms
|
||||
homeserverList = div [ class "homeservers-list" ]
|
||||
<| List.map (\(k, v) -> homeserverView m k v)
|
||||
<| Dict.toList groups
|
||||
|
@ -106,22 +105,22 @@ roomListView m =
|
|||
, homeserverList
|
||||
]
|
||||
|
||||
roomGroups : List (String, JoinedRoom) -> Dict String (List (String, JoinedRoom))
|
||||
roomGroups : List (String, RoomData) -> Dict String (List (String, RoomData))
|
||||
roomGroups jrs = groupBy (homeserver << Tuple.first) jrs
|
||||
|
||||
homeserverView : Model -> String -> List (String, JoinedRoom) -> Html Msg
|
||||
homeserverView : Model -> String -> List (String, RoomData) -> Html Msg
|
||||
homeserverView m hs rs =
|
||||
let
|
||||
roomList = div [ class "rooms-list" ]
|
||||
<| List.map (\(rid, r) -> roomListElementView m rid r)
|
||||
<| List.sortBy (\(rid, r) -> roomDisplayName m.roomNames rid) rs
|
||||
<| List.sortBy (\(rid, r) -> getRoomName m.sync.accountData m.userData rid r) rs
|
||||
in
|
||||
div [ class "homeserver-wrapper" ] [ h3 [] [ text hs ], roomList ]
|
||||
|
||||
roomListElementView : Model -> RoomId -> JoinedRoom -> Html Msg
|
||||
roomListElementView m rid jr =
|
||||
roomListElementView : Model -> RoomId -> RoomData -> Html Msg
|
||||
roomListElementView m rid rd =
|
||||
let
|
||||
name = roomDisplayName m.roomNames rid
|
||||
name = getRoomName m.sync.accountData m.userData rid rd
|
||||
isVisible = m.searchText == "" || (String.contains (String.toLower m.searchText) <| String.toLower name)
|
||||
isCurrentRoom = case currentRoomId m of
|
||||
Nothing -> False
|
||||
|
@ -133,10 +132,10 @@ roomListElementView m rid jr =
|
|||
, ("hidden", not isVisible)
|
||||
]
|
||||
]
|
||||
<| roomNotificationCountView jr.unreadNotifications ++
|
||||
<| roomNotificationCountView rd.unreadNotifications ++
|
||||
[ a [ href <| roomUrl rid ] [ text name ] ]
|
||||
|
||||
roomNotificationCountView : Maybe UnreadNotificationCounts -> List (Html Msg)
|
||||
roomNotificationCountView : UnreadNotificationCounts -> List (Html Msg)
|
||||
roomNotificationCountView ns =
|
||||
let
|
||||
wrap b = span
|
||||
|
@ -145,7 +144,7 @@ roomNotificationCountView ns =
|
|||
, ("bright", b)
|
||||
]
|
||||
]
|
||||
getCount f = Maybe.withDefault 0 << Maybe.andThen f
|
||||
getCount f = Maybe.withDefault 0 << f
|
||||
in
|
||||
case (getCount .notificationCount ns, getCount .highlightCount ns) of
|
||||
(0, 0) -> []
|
||||
|
|
Loading…
Reference in New Issue
Block a user