From b239eecc6bf3529c12caae70c3dec144882be76c Mon Sep 17 00:00:00 2001 From: Bram Date: Tue, 9 Jul 2024 00:08:46 +0200 Subject: [PATCH] Add toUpdate function for /sync v1 --- src/Internal/Api/Sync/V1.elm | 88 +++++++++++++++++++++++++++++- src/Internal/Config/Text.elm | 4 ++ src/Internal/Tools/DecodeExtra.elm | 36 +++++++++++- src/Internal/Tools/Json.elm | 79 ++++++++++++++++++++++++++- src/Internal/Values/Context.elm | 11 +++- src/Internal/Values/Envelope.elm | 4 ++ 6 files changed, 216 insertions(+), 6 deletions(-) diff --git a/src/Internal/Api/Sync/V1.elm b/src/Internal/Api/Sync/V1.elm index 8260d66..88f0dd0 100644 --- a/src/Internal/Api/Sync/V1.elm +++ b/src/Internal/Api/Sync/V1.elm @@ -11,10 +11,14 @@ This API module represents the /sync endpoint on Matrix spec version v1.1. -} -import FastDict exposing (Dict) +import FastDict as Dict exposing (Dict) +import Internal.Config.Log exposing (Log) import Internal.Tools.Json as Json import Internal.Tools.StrippedEvent as StrippedEvent exposing (StrippedEvent) import Internal.Tools.Timestamp as Timestamp exposing (Timestamp) +import Internal.Values.Envelope as E +import Internal.Values.Room as R +import Internal.Values.Vault as V type alias SyncResponse = @@ -807,3 +811,85 @@ coderToDeviceEvent = , coder = Json.string } ) + + +updateSyncResponse : SyncResponse -> ( E.EnvelopeUpdate V.VaultUpdate, List Log ) +updateSyncResponse response = + -- TODO: Add account data + -- TODO: Add device lists + -- Next batch + [ Just ( E.SetNextBatch response.nextBatch, [] ) + + -- TODO: Add presence + -- Rooms + , Maybe.map (updateRooms >> Tuple.mapFirst E.ContentUpdate) response.rooms + + -- TODO: Add to_device + ] + |> List.filterMap identity + |> List.unzip + |> Tuple.mapFirst E.More + |> Tuple.mapSecond List.concat + + +updateRooms : Rooms -> ( V.VaultUpdate, List Log ) +updateRooms rooms = + let + ( roomUpdate, roomLogs ) = + rooms.join + |> Maybe.withDefault Dict.empty + |> Dict.toList + |> List.map + (\( roomId, room ) -> + let + ( u, l ) = + updateJoinedRoom room + in + ( V.MapRoom roomId u, l ) + ) + |> List.unzip + |> Tuple.mapBoth V.More List.concat + in + ( V.More + -- Add rooms + [ rooms.join + |> Maybe.withDefault Dict.empty + |> Dict.keys + |> List.map V.CreateRoomIfNotExists + |> V.More + + -- Update rooms + , roomUpdate + + -- TODO: Add invited rooms + -- TODO: Add knocked rooms + -- TODO: Add left rooms + ] + , roomLogs + ) + + +updateJoinedRoom : JoinedRoom -> ( R.RoomUpdate, List Log ) +updateJoinedRoom room = + ( R.More + [ room.accountData + |> Maybe.andThen .events + |> Maybe.map + (\events -> + events + |> List.map (\e -> R.SetAccountData e.eventType e.content) + |> R.More + ) + |> R.Optional + , room.ephemeral + |> Maybe.andThen .events + |> Maybe.map R.SetEphemeral + |> R.Optional + + -- TODO: Add state + -- TODO: Add RoomSummary + -- TODO: Add timeline + -- TODO: Add unread notifications + ] + , [] + ) diff --git a/src/Internal/Config/Text.elm b/src/Internal/Config/Text.elm index c40dd9a..3550be2 100644 --- a/src/Internal/Config/Text.elm +++ b/src/Internal/Config/Text.elm @@ -277,6 +277,7 @@ fields : , baseUrl : Desc , deviceId : Desc , experimental : Desc + , nextBatch : Desc , now : Desc , password : Desc , refreshToken : Desc @@ -388,6 +389,9 @@ fields = , experimental = [ "Experimental features supported by the homeserver." ] + , nextBatch = + [ "The batch token to supply in the since param of the next /sync request." + ] , now = [ "The most recently found timestamp." ] diff --git a/src/Internal/Tools/DecodeExtra.elm b/src/Internal/Tools/DecodeExtra.elm index 6460233..b7a0ae8 100644 --- a/src/Internal/Tools/DecodeExtra.elm +++ b/src/Internal/Tools/DecodeExtra.elm @@ -1,6 +1,6 @@ module Internal.Tools.DecodeExtra exposing ( opField, opFieldWithDefault - , map9, map10, map11 + , map9, map10, map11, map12 ) {-| @@ -18,7 +18,7 @@ This module contains helper functions that help decode JSON. ## Extended map functions -@docs map9, map10, map11 +@docs map9, map10, map11, map12 -} @@ -153,3 +153,35 @@ map11 func da db dc dd de df dg dh di dj dk = (D.map2 Tuple.pair df dg) (D.map2 Tuple.pair dh di) (D.map2 Tuple.pair dj dk) + + +{-| Try 12 decoders and combine the result. +-} +map12 : + (a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> l -> value) + -> D.Decoder a + -> D.Decoder b + -> D.Decoder c + -> D.Decoder d + -> D.Decoder e + -> D.Decoder f + -> D.Decoder g + -> D.Decoder h + -> D.Decoder i + -> D.Decoder j + -> D.Decoder k + -> D.Decoder l + -> D.Decoder value +map12 func da db dc dd de df dg dh di dj dk dl = + D.map8 + (\a b c d ( e, f ) ( g, h ) ( i, j ) ( k, l ) -> + func a b c d e f g h i j k l + ) + da + db + dc + dd + (D.map2 Tuple.pair de df) + (D.map2 Tuple.pair dg dh) + (D.map2 Tuple.pair di dj) + (D.map2 Tuple.pair dk dl) diff --git a/src/Internal/Tools/Json.elm b/src/Internal/Tools/Json.elm index 3ab93b3..2be4c1d 100644 --- a/src/Internal/Tools/Json.elm +++ b/src/Internal/Tools/Json.elm @@ -5,7 +5,7 @@ module Internal.Tools.Json exposing , Docs(..), RequiredField(..), toDocs , list, listWithOne, slowDict, fastDict, fastIntDict, set, maybe , Field, field, parser - , object1, object2, object3, object4, object5, object6, object7, object8, object9, object10, object11 + , object1, object2, object3, object4, object5, object6, object7, object8, object9, object10, object11, object12 ) {-| @@ -62,7 +62,7 @@ first. Once all fields are constructed, the user can create JSON objects. -@docs object1, object2, object3, object4, object5, object6, object7, object8, object9, object10, object11 +@docs object1, object2, object3, object4, object5, object6, object7, object8, object9, object10, object11, object12 -} @@ -1175,6 +1175,81 @@ object11 { name, description, init } fa fb fc fd fe ff fg fh fi fj fk = } +{-| Define an object with 12 keys +-} +object12 : + Descriptive { init : a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> l -> object } + -> Field a object + -> Field b object + -> Field c object + -> Field d object + -> Field e object + -> Field f object + -> Field g object + -> Field h object + -> Field i object + -> Field j object + -> Field k object + -> Field l object + -> Coder object +object12 { name, description, init } fa fb fc fd fe ff fg fh fi fj fk fl = + Coder + { encoder = + objectEncoder + [ toEncodeField fa + , toEncodeField fb + , toEncodeField fc + , toEncodeField fd + , toEncodeField fe + , toEncodeField ff + , toEncodeField fg + , toEncodeField fh + , toEncodeField fi + , toEncodeField fj + , toEncodeField fk + , toEncodeField fl + ] + , decoder = + D.map12 + (\( a, la ) ( b, lb ) ( c, lc ) ( d, ld ) ( e, le ) ( f, lf ) ( g, lg ) ( h, lh ) ( i, li ) ( j, lj ) ( k, lk ) ( l, ll ) -> + ( init a b c d e f g h i j k l + , List.concat [ la, lb, lc, ld, le, lf, lg, lh, li, lj, lk, ll ] + ) + ) + (toDecoderField fa) + (toDecoderField fb) + (toDecoderField fc) + (toDecoderField fd) + (toDecoderField fe) + (toDecoderField ff) + (toDecoderField fg) + (toDecoderField fh) + (toDecoderField fi) + (toDecoderField fj) + (toDecoderField fk) + (toDecoderField fl) + , docs = + DocsObject + { name = name + , description = description + , keys = + [ toDocsField fa + , toDocsField fb + , toDocsField fc + , toDocsField fd + , toDocsField fe + , toDocsField ff + , toDocsField fg + , toDocsField fh + , toDocsField fi + , toDocsField fj + , toDocsField fk + , toDocsField fl + ] + } + } + + {-| Define a parser that converts a string into a custom Elm type. -} parser : { name : String, p : P.Parser ( a, List Log ), toString : a -> String } -> Coder a diff --git a/src/Internal/Values/Context.elm b/src/Internal/Values/Context.elm index ca6a8a1..5fc358d 100644 --- a/src/Internal/Values/Context.elm +++ b/src/Internal/Values/Context.elm @@ -95,6 +95,7 @@ type alias Context = { accessTokens : Hashdict AccessToken , baseUrl : Maybe String , deviceId : Maybe String + , nextBatch : Maybe String , now : Maybe Timestamp , password : Maybe String , refreshToken : Maybe String @@ -152,7 +153,7 @@ fromApiFormat (APIContext c) = -} coder : Json.Coder Context coder = - Json.object11 + Json.object12 { name = Text.docs.context.name , description = Text.docs.context.description , init = Context @@ -178,6 +179,13 @@ coder = , coder = Json.string } ) + (Json.field.optional.value + { fieldName = "nextBatch" + , toField = .nextBatch + , description = Text.fields.context.nextBatch + , coder = Json.string + } + ) (Json.field.optional.value { fieldName = "now" , toField = .now @@ -303,6 +311,7 @@ init sn = { accessTokens = Hashdict.empty .value , baseUrl = Nothing , deviceId = Nothing + , nextBatch = Nothing , now = Nothing , refreshToken = Nothing , password = Nothing diff --git a/src/Internal/Values/Envelope.elm b/src/Internal/Values/Envelope.elm index 7ae8ceb..c9cc126 100644 --- a/src/Internal/Values/Envelope.elm +++ b/src/Internal/Values/Envelope.elm @@ -82,6 +82,7 @@ type EnvelopeUpdate a | SetAccessToken AccessToken | SetBaseUrl String | SetDeviceId String + | SetNextBatch String | SetNow Timestamp | SetRefreshToken String | SetVersions Versions @@ -327,6 +328,9 @@ update updateContent eu ({ context } as data) = SetDeviceId d -> { data | context = { context | deviceId = Just d } } + SetNextBatch nextBatch -> + { data | context = { context | nextBatch = Just nextBatch } } + SetNow n -> { data | context = { context | now = Just n } }