Add event to get older events
parent
c32a62c242
commit
098b38170a
|
@ -7,6 +7,7 @@ import Hash
|
|||
import Internal.Api.Chain as Chain
|
||||
import Internal.Api.Credentials as Cred exposing (Credentials)
|
||||
import Internal.Api.GetEvent.Main exposing (EventInput)
|
||||
import Internal.Api.GetMessages.Main exposing (GetMessagesInput)
|
||||
import Internal.Api.Invite.Main exposing (InviteInput)
|
||||
import Internal.Api.JoinRoomById.Main exposing (JoinRoomByIdInput)
|
||||
import Internal.Api.JoinedMembers.Main exposing (JoinedMembersInput)
|
||||
|
@ -35,6 +36,13 @@ getEvent { eventId, roomId } cred =
|
|||
|> C.toTask
|
||||
|
||||
|
||||
getMessages : GetMessagesInput -> Credentials -> FutureTask
|
||||
getMessages data cred =
|
||||
C.makeVBA cred
|
||||
|> Chain.andThen (C.getMessages data)
|
||||
|> C.toTask
|
||||
|
||||
|
||||
invite : InviteInput -> Credentials -> FutureTask
|
||||
invite data cred =
|
||||
C.makeVBA cred
|
||||
|
|
|
@ -10,6 +10,7 @@ resend other events or forward them elsewhere.
|
|||
import Internal.Api.Credentials exposing (Credentials)
|
||||
import Internal.Api.GetEvent.Main as GetEvent
|
||||
import Internal.Api.GetEvent.V1.SpecObjects as GetEventSO
|
||||
import Internal.Api.GetMessages.V4.SpecObjects as GetMessagesSO
|
||||
import Internal.Api.Sync.V2.SpecObjects as SyncSO
|
||||
import Internal.Tools.Timestamp exposing (Timestamp)
|
||||
import Internal.Values.Event as Internal
|
||||
|
@ -62,6 +63,32 @@ initFromGetEvent output =
|
|||
}
|
||||
|
||||
|
||||
{-| Create an internal event type from an API endpoint event object.
|
||||
This function is placed in this file to respect file hierarchy and avoid circular imports.
|
||||
-}
|
||||
initFromGetMessages : GetMessagesSO.ClientEvent -> Internal.IEvent
|
||||
initFromGetMessages output =
|
||||
Internal.init
|
||||
{ content = output.content
|
||||
, eventId = output.eventId
|
||||
, originServerTs = output.originServerTs
|
||||
, roomId = output.roomId
|
||||
, sender = output.sender
|
||||
, stateKey = output.stateKey
|
||||
, contentType = output.contentType
|
||||
, unsigned =
|
||||
output.unsigned
|
||||
|> Maybe.map
|
||||
(\(GetMessagesSO.UnsignedData data) ->
|
||||
{ age = data.age
|
||||
, prevContent = data.prevContent
|
||||
, redactedBecause = Maybe.map initFromGetMessages data.redactedBecause
|
||||
, transactionId = data.transactionId
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
{-| Create an internal event type from an API endpoint event object.
|
||||
This function is placed in this file to respect file hierarchy and avoid circular imports.
|
||||
-}
|
||||
|
|
|
@ -7,10 +7,11 @@ import Dict
|
|||
import Internal.Api.Credentials exposing (Credentials)
|
||||
import Internal.Api.Sync.V2.SpecObjects as Sync
|
||||
import Internal.Api.Task as Api
|
||||
import Internal.Api.VaultUpdate exposing (VaultUpdate)
|
||||
import Internal.Api.VaultUpdate exposing (VaultUpdate(..))
|
||||
import Internal.Event as Event exposing (Event)
|
||||
import Internal.Tools.Exceptions as X
|
||||
import Internal.Tools.Hashdict as Hashdict
|
||||
import Internal.Tools.SpecEnums as Enums
|
||||
import Internal.Values.Event as IEvent
|
||||
import Internal.Values.Room as Internal
|
||||
import Internal.Values.StateManager as StateManager
|
||||
|
@ -118,6 +119,26 @@ withoutCredentials (Room { room }) =
|
|||
room
|
||||
|
||||
|
||||
{-| Get older events from the Matrix API.
|
||||
-}
|
||||
getOlderEvents : { limit : Maybe Int } -> Room -> Task X.Error VaultUpdate
|
||||
getOlderEvents { limit } (Room { context, room }) =
|
||||
case Internal.latestGap room of
|
||||
Nothing ->
|
||||
Task.succeed (MultipleUpdates [])
|
||||
|
||||
Just { from, to } ->
|
||||
Api.getMessages
|
||||
{ direction = Enums.ReverseChronological
|
||||
, filter = Nothing
|
||||
, from = Just to
|
||||
, limit = limit
|
||||
, roomId = Internal.roomId room
|
||||
, to = from
|
||||
}
|
||||
context
|
||||
|
||||
|
||||
{-| Get the most recent events.
|
||||
-}
|
||||
mostRecentEvents : Room -> List Event
|
||||
|
|
|
@ -59,11 +59,28 @@ getStateEvent data (IRoom room) =
|
|||
|> StateManager.getStateEvent data
|
||||
|
||||
|
||||
{-| Get the room's id.
|
||||
{-| Insert a chunk of events into a room.
|
||||
-}
|
||||
roomId : IRoom -> String
|
||||
roomId (IRoom room) =
|
||||
room.roomId
|
||||
insertEvents :
|
||||
{ events : List IEvent
|
||||
, nextBatch : String
|
||||
, prevBatch : Maybe String
|
||||
, stateDelta : Maybe StateManager
|
||||
}
|
||||
-> IRoom
|
||||
-> IRoom
|
||||
insertEvents data (IRoom ({ timeline } as room)) =
|
||||
IRoom
|
||||
{ room | timeline = Timeline.insertEvents data timeline }
|
||||
|> List.foldl addEvent
|
||||
|> (|>) data.events
|
||||
|
||||
|
||||
{-| Get the latest gap.
|
||||
-}
|
||||
latestGap : IRoom -> Maybe { from : Maybe String, to : String }
|
||||
latestGap (IRoom room) =
|
||||
Timeline.latestGap room.timeline
|
||||
|
||||
|
||||
{-| Get the most recent events.
|
||||
|
@ -71,3 +88,10 @@ roomId (IRoom room) =
|
|||
mostRecentEvents : IRoom -> List IEvent
|
||||
mostRecentEvents (IRoom room) =
|
||||
Timeline.mostRecentEvents room.timeline
|
||||
|
||||
|
||||
{-| Get the room's id.
|
||||
-}
|
||||
roomId : IRoom -> String
|
||||
roomId (IRoom room) =
|
||||
room.roomId
|
||||
|
|
|
@ -92,63 +92,119 @@ newFromEvents { events, nextBatch, prevBatch, stateDelta } =
|
|||
insertEvents :
|
||||
{ events : List IEvent
|
||||
, nextBatch : String
|
||||
, prevBatch : String
|
||||
, prevBatch : Maybe String
|
||||
, stateDelta : Maybe StateManager
|
||||
}
|
||||
-> Timeline
|
||||
-> Timeline
|
||||
insertEvents ({ events, nextBatch, prevBatch, stateDelta } as data) (Timeline t) =
|
||||
Timeline
|
||||
(if t.nextBatch == prevBatch then
|
||||
{ t
|
||||
| events = t.events ++ events
|
||||
, nextBatch = nextBatch
|
||||
}
|
||||
|
||||
else if nextBatch == t.prevBatch then
|
||||
case t.previous of
|
||||
Gap (Timeline prevT) ->
|
||||
if prevT.nextBatch == prevBatch then
|
||||
{ events = prevT.events ++ events ++ t.events
|
||||
, nextBatch = t.nextBatch
|
||||
, prevBatch = prevT.prevBatch
|
||||
, stateAtStart = prevT.stateAtStart
|
||||
, previous = prevT.previous
|
||||
}
|
||||
|
||||
else
|
||||
(case prevBatch of
|
||||
-- No prevbatch suggests the start of the timeline.
|
||||
-- This means that we must recurse until we've hit the bottom,
|
||||
-- and then mark the bottom of the timeline.
|
||||
Nothing ->
|
||||
case t.previous of
|
||||
Gap prevT ->
|
||||
{ t
|
||||
| events = events ++ t.events
|
||||
, prevBatch = prevBatch
|
||||
, stateAtStart =
|
||||
stateDelta
|
||||
|> Maybe.withDefault StateManager.empty
|
||||
| previous =
|
||||
prevT
|
||||
|> insertEvents data
|
||||
|> Gap
|
||||
}
|
||||
|
||||
_ ->
|
||||
{ t
|
||||
| events = events ++ t.events
|
||||
, prevBatch = prevBatch
|
||||
, stateAtStart =
|
||||
stateDelta
|
||||
|> Maybe.withDefault StateManager.empty
|
||||
}
|
||||
_ ->
|
||||
if nextBatch == t.prevBatch then
|
||||
{ t | previous = StartOfTimeline, events = events ++ t.events, stateAtStart = StateManager.empty }
|
||||
|
||||
else
|
||||
case t.previous of
|
||||
Gap prevT ->
|
||||
{ t
|
||||
| previous =
|
||||
prevT
|
||||
|> insertEvents data
|
||||
|> Gap
|
||||
}
|
||||
else
|
||||
{ t | previous = Gap <| newFromEvents data }
|
||||
|
||||
_ ->
|
||||
t
|
||||
-- If there is a prevbatch, it is not the start of the timeline
|
||||
-- and could be located anywhere.
|
||||
-- Starting at the front, look for a way to match it with the existing timeline.
|
||||
Just p ->
|
||||
-- Piece connects to the front of the timeline.
|
||||
if t.nextBatch == p then
|
||||
{ t
|
||||
| events = t.events ++ events
|
||||
, nextBatch = nextBatch
|
||||
}
|
||||
-- Piece connects to the back of the timeline.
|
||||
|
||||
else if nextBatch == t.prevBatch then
|
||||
case t.previous of
|
||||
Gap (Timeline prevT) ->
|
||||
-- Piece also connects to the timeline in the back,
|
||||
-- allowing the two timelines to merge.
|
||||
if prevT.nextBatch == p then
|
||||
{ events = prevT.events ++ events ++ t.events
|
||||
, nextBatch = t.nextBatch
|
||||
, prevBatch = prevT.prevBatch
|
||||
, stateAtStart = prevT.stateAtStart
|
||||
, previous = prevT.previous
|
||||
}
|
||||
|
||||
else
|
||||
{ t
|
||||
| events = events ++ t.events
|
||||
, prevBatch = p
|
||||
, stateAtStart =
|
||||
stateDelta
|
||||
|> Maybe.withDefault StateManager.empty
|
||||
}
|
||||
|
||||
Endless _ ->
|
||||
{ t
|
||||
| events = events ++ t.events
|
||||
, prevBatch = p
|
||||
, stateAtStart =
|
||||
stateDelta
|
||||
|> Maybe.withDefault StateManager.empty
|
||||
, previous = Endless p
|
||||
}
|
||||
|
||||
_ ->
|
||||
{ t
|
||||
| events = events ++ t.events
|
||||
, prevBatch = p
|
||||
, stateAtStart =
|
||||
stateDelta
|
||||
|> Maybe.withDefault StateManager.empty
|
||||
}
|
||||
-- Piece doesn't connect to this piece of the timeline.
|
||||
-- Consequently, look for previous parts of the timeline to see if it connects.
|
||||
|
||||
else
|
||||
case t.previous of
|
||||
Gap prevT ->
|
||||
{ t
|
||||
| previous =
|
||||
prevT
|
||||
|> insertEvents data
|
||||
|> Gap
|
||||
}
|
||||
|
||||
_ ->
|
||||
t
|
||||
)
|
||||
|
||||
|
||||
{-| Get the width of the latest gap. This data is usually accessed when trying to get more messages.
|
||||
-}
|
||||
latestGap : Timeline -> Maybe { from : Maybe String, to : String }
|
||||
latestGap (Timeline t) =
|
||||
case t.previous of
|
||||
StartOfTimeline ->
|
||||
Nothing
|
||||
|
||||
Endless prevBatch ->
|
||||
Just { from = Nothing, to = prevBatch }
|
||||
|
||||
Gap (Timeline pt) ->
|
||||
Just { from = Just pt.nextBatch, to = t.prevBatch }
|
||||
|
||||
|
||||
{-| Get the longest uninterrupted length of most recent events.
|
||||
-}
|
||||
localSize : Timeline -> Int
|
||||
|
|
|
@ -16,6 +16,7 @@ import Internal.Event as Event
|
|||
import Internal.Invite as Invite
|
||||
import Internal.Room as Room
|
||||
import Internal.Tools.Exceptions as X
|
||||
import Internal.Tools.SpecEnums as Enums
|
||||
import Internal.Values.Room as IRoom
|
||||
import Internal.Values.RoomInvite exposing (IRoomInvite)
|
||||
import Internal.Values.StateManager as StateManager
|
||||
|
@ -125,8 +126,62 @@ updateWith vaultUpdate ((Vault ({ cred, context } as data)) as vault) =
|
|||
vault
|
||||
|
||||
-- TODO
|
||||
GetMessages _ _ ->
|
||||
vault
|
||||
GetMessages input output ->
|
||||
let
|
||||
prevBatch : Maybe String
|
||||
prevBatch =
|
||||
case input.direction of
|
||||
Enums.Chronological ->
|
||||
Just output.start
|
||||
|
||||
Enums.ReverseChronological ->
|
||||
case output.end of
|
||||
Just end ->
|
||||
Just end
|
||||
|
||||
Nothing ->
|
||||
input.to
|
||||
|
||||
nextBatch : Maybe String
|
||||
nextBatch =
|
||||
case input.direction of
|
||||
Enums.Chronological ->
|
||||
case output.end of
|
||||
Just end ->
|
||||
Just end
|
||||
|
||||
Nothing ->
|
||||
input.to
|
||||
|
||||
Enums.ReverseChronological ->
|
||||
Just output.start
|
||||
in
|
||||
case ( getRoomById input.roomId vault, nextBatch ) of
|
||||
( Just room, Just nb ) ->
|
||||
room
|
||||
|> Room.withoutCredentials
|
||||
|> IRoom.insertEvents
|
||||
{ events =
|
||||
output.chunk
|
||||
|> List.map Event.initFromGetMessages
|
||||
|> (\x ->
|
||||
case input.direction of
|
||||
Enums.Chronological ->
|
||||
x
|
||||
|
||||
Enums.ReverseChronological ->
|
||||
List.reverse x
|
||||
)
|
||||
, prevBatch = prevBatch
|
||||
, nextBatch = nb
|
||||
, stateDelta = Just <| StateManager.fromEventList (List.map Event.initFromGetMessages output.state)
|
||||
}
|
||||
|> Internal.insertRoom
|
||||
|> (|>) cred
|
||||
|> (\v -> Vault { cred = v, context = context })
|
||||
|
||||
_ ->
|
||||
vault
|
||||
|
||||
-- TODO
|
||||
InviteSent _ _ ->
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
module Matrix.Room exposing
|
||||
( Room, roomId, mostRecentEvents
|
||||
( Room, roomId, mostRecentEvents, findOlderEvents
|
||||
, sendMessage, sendMessages, sendOneEvent, sendMultipleEvents
|
||||
)
|
||||
|
||||
|
@ -10,7 +10,7 @@ module Matrix.Room exposing
|
|||
|
||||
A room represents a channel of communication within a Matrix home server.
|
||||
|
||||
@docs Room, roomId, mostRecentEvents
|
||||
@docs Room, roomId, mostRecentEvents, findOlderEvents
|
||||
|
||||
|
||||
# Sending events
|
||||
|
@ -35,6 +35,13 @@ type alias Room =
|
|||
Internal.Room
|
||||
|
||||
|
||||
{-| If you want more events as part of the most recent events, you can run this task to get more.
|
||||
-}
|
||||
findOlderEvents : { limit : Maybe Int, room : Room } -> Task X.Error VaultUpdate
|
||||
findOlderEvents { limit, room } =
|
||||
Internal.getOlderEvents { limit = limit } room
|
||||
|
||||
|
||||
{-| Get the most recent events from this room.
|
||||
-}
|
||||
mostRecentEvents : Room -> List Event.Event
|
||||
|
|
Loading…
Reference in New Issue