From 36b1a1471aa788dd973cff699e0322a92df353bf Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 13 Jan 2021 14:23:02 +0100 Subject: [PATCH 1/2] Fix Dendrite sync response support --- .../room/timeline/EventContextResponse.kt | 12 ++++++++---- .../session/room/timeline/PaginationResponse.kt | 4 ++-- .../session/room/timeline/TokenChunkEvent.kt | 4 ++-- .../room/timeline/TokenChunkEventPersistor.kt | 16 ++++++++-------- .../session/room/uploads/GetUploadsTask.kt | 2 +- 5 files changed, 21 insertions(+), 17 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/EventContextResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/EventContextResponse.kt index bce03354d7..d76ba35280 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/EventContextResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/EventContextResponse.kt @@ -24,13 +24,17 @@ import org.matrix.android.sdk.api.session.events.model.Event data class EventContextResponse( @Json(name = "event") val event: Event, @Json(name = "start") override val start: String? = null, - @Json(name = "events_before") val eventsBefore: List = emptyList(), - @Json(name = "events_after") val eventsAfter: List = emptyList(), + @Json(name = "events_before") val eventsBefore: List? = emptyList(), + @Json(name = "events_after") val eventsAfter: List? = emptyList(), @Json(name = "end") override val end: String? = null, - @Json(name = "state") override val stateEvents: List = emptyList() + @Json(name = "state") override val stateEvents: List? = emptyList() ) : TokenChunkEvent { override val events: List by lazy { - eventsAfter.reversed() + listOf(event) + eventsBefore + mutableListOf().apply { + eventsAfter?.let { addAll(it.reversed()) } + add(event) + eventsBefore?.let { addAll(it) } + } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/PaginationResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/PaginationResponse.kt index ed384d3b3c..ff0c7fbbde 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/PaginationResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/PaginationResponse.kt @@ -24,6 +24,6 @@ import org.matrix.android.sdk.api.session.events.model.Event internal data class PaginationResponse( @Json(name = "start") override val start: String? = null, @Json(name = "end") override val end: String? = null, - @Json(name = "chunk") override val events: List = emptyList(), - @Json(name = "state") override val stateEvents: List = emptyList() + @Json(name = "chunk") override val events: List? = emptyList(), + @Json(name = "state") override val stateEvents: List? = emptyList() ) : TokenChunkEvent diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEvent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEvent.kt index 08b20f1701..50cc50beb2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEvent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEvent.kt @@ -21,8 +21,8 @@ import org.matrix.android.sdk.api.session.events.model.Event internal interface TokenChunkEvent { val start: String? val end: String? - val events: List - val stateEvents: List + val events: List? + val stateEvents: List? fun hasMore() = start != end } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistor.kt index 2a532c6bf5..fb636a9314 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistor.kt @@ -124,7 +124,7 @@ internal class TokenChunkEventPersistor @Inject constructor(@SessionDatabase pri direction: PaginationDirection): Result { monarchy .awaitTransaction { realm -> - Timber.v("Start persisting ${receivedChunk.events.size} events in $roomId towards $direction") + Timber.v("Start persisting ${receivedChunk.events?.size} events in $roomId towards $direction") val nextToken: String? val prevToken: String? @@ -149,13 +149,13 @@ internal class TokenChunkEventPersistor @Inject constructor(@SessionDatabase pri } ?: ChunkEntity.create(realm, prevToken, nextToken) - if (receivedChunk.events.isEmpty() && !receivedChunk.hasMore()) { + if (receivedChunk.events.isNullOrEmpty() && !receivedChunk.hasMore()) { handleReachEnd(realm, roomId, direction, currentChunk) } else { handlePagination(realm, roomId, direction, receivedChunk, currentChunk) } } - return if (receivedChunk.events.isEmpty()) { + return if (receivedChunk.events.isNullOrEmpty()) { if (receivedChunk.start != receivedChunk.end) { Result.SHOULD_FETCH_MORE } else { @@ -189,14 +189,14 @@ internal class TokenChunkEventPersistor @Inject constructor(@SessionDatabase pri receivedChunk: TokenChunkEvent, currentChunk: ChunkEntity ) { - Timber.v("Add ${receivedChunk.events.size} events in chunk(${currentChunk.nextToken} | ${currentChunk.prevToken}") + Timber.v("Add ${receivedChunk.events?.size} events in chunk(${currentChunk.nextToken} | ${currentChunk.prevToken}") val roomMemberContentsByUser = HashMap() val eventList = receivedChunk.events val stateEvents = receivedChunk.stateEvents val now = System.currentTimeMillis() - for (stateEvent in stateEvents) { + stateEvents?.forEach { stateEvent -> val ageLocalTs = stateEvent.unsignedData?.age?.let { now - it } val stateEventEntity = stateEvent.toEntity(roomId, SendState.SYNCED, ageLocalTs).copyToRealmOrIgnore(realm, EventInsertType.PAGINATION) currentChunk.addStateEvent(roomId, stateEventEntity, direction) @@ -204,10 +204,10 @@ internal class TokenChunkEventPersistor @Inject constructor(@SessionDatabase pri roomMemberContentsByUser[stateEvent.stateKey] = stateEvent.content.toModel() } } - val eventIds = ArrayList(eventList.size) - for (event in eventList) { + val eventIds = ArrayList(eventList?.size ?: 0) + eventList?.forEach { event -> if (event.eventId == null || event.senderId == null) { - continue + return@forEach } val ageLocalTs = event.unsignedData?.age?.let { now - it } eventIds.add(event.eventId) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/uploads/GetUploadsTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/uploads/GetUploadsTask.kt index 0c0e6a8ed0..9d66474a73 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/uploads/GetUploadsTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/uploads/GetUploadsTask.kt @@ -95,7 +95,7 @@ internal class DefaultGetUploadsTask @Inject constructor( nextToken = chunk.end ?: "", hasMore = chunk.hasMore() ) - events = chunk.events + events = chunk.events ?: emptyList() } var uploadEvents = listOf() From 5a0d62db6f28c58110e0774a53fcadf2bd9e0810 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 25 Jan 2021 12:42:39 +0100 Subject: [PATCH 2/2] Cleanup (PR review) Also add some doc and add missing `internal` keyword --- .../room/timeline/EventContextResponse.kt | 32 +++++++++++++------ .../room/timeline/PaginationResponse.kt | 26 +++++++++++++-- .../session/room/timeline/TokenChunkEvent.kt | 2 +- .../room/timeline/TokenChunkEventPersistor.kt | 14 ++++---- .../session/room/uploads/GetUploadsTask.kt | 6 ++-- 5 files changed, 57 insertions(+), 23 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/EventContextResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/EventContextResponse.kt index d76ba35280..654cf0fb74 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/EventContextResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/EventContextResponse.kt @@ -21,20 +21,34 @@ import com.squareup.moshi.JsonClass import org.matrix.android.sdk.api.session.events.model.Event @JsonClass(generateAdapter = true) -data class EventContextResponse( +internal data class EventContextResponse( + /** + * Details of the requested event. + */ @Json(name = "event") val event: Event, + /** + * A token that can be used to paginate backwards with. + */ @Json(name = "start") override val start: String? = null, - @Json(name = "events_before") val eventsBefore: List? = emptyList(), - @Json(name = "events_after") val eventsAfter: List? = emptyList(), + /** + * A list of room events that happened just before the requested event, in reverse-chronological order. + */ + @Json(name = "events_before") val eventsBefore: List? = null, + /** + * A list of room events that happened just after the requested event, in chronological order. + */ + @Json(name = "events_after") val eventsAfter: List? = null, + /** + * A token that can be used to paginate forwards with. + */ @Json(name = "end") override val end: String? = null, - @Json(name = "state") override val stateEvents: List? = emptyList() + /** + * The state of the room at the last event returned. + */ + @Json(name = "state") override val stateEvents: List? = null ) : TokenChunkEvent { override val events: List by lazy { - mutableListOf().apply { - eventsAfter?.let { addAll(it.reversed()) } - add(event) - eventsBefore?.let { addAll(it) } - } + eventsAfter.orEmpty().reversed() + event + eventsBefore.orEmpty() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/PaginationResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/PaginationResponse.kt index ff0c7fbbde..2f61b1cce8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/PaginationResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/PaginationResponse.kt @@ -22,8 +22,28 @@ import org.matrix.android.sdk.api.session.events.model.Event @JsonClass(generateAdapter = true) internal data class PaginationResponse( + /** + * The token the pagination starts from. If dir=b this will be the token supplied in from. + */ @Json(name = "start") override val start: String? = null, + /** + * The token the pagination ends at. If dir=b this token should be used again to request even earlier events. + */ @Json(name = "end") override val end: String? = null, - @Json(name = "chunk") override val events: List? = emptyList(), - @Json(name = "state") override val stateEvents: List? = emptyList() -) : TokenChunkEvent + /** + * A list of room events. The order depends on the dir parameter. For dir=b events will be in + * reverse-chronological order, for dir=f in chronological order, so that events start at the from point. + */ + @Json(name = "chunk") val chunk: List? = null, + /** + * A list of state events relevant to showing the chunk. For example, if lazy_load_members is enabled + * in the filter then this may contain the membership events for the senders of events in the chunk. + * + * Unless include_redundant_members is true, the server may remove membership events which would have + * already been sent to the client in prior calls to this endpoint, assuming the membership of those members has not changed. + */ + @Json(name = "state") override val stateEvents: List? = null +) : TokenChunkEvent { + override val events: List + get() = chunk.orEmpty() +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEvent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEvent.kt index 50cc50beb2..465b0faac8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEvent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEvent.kt @@ -21,7 +21,7 @@ import org.matrix.android.sdk.api.session.events.model.Event internal interface TokenChunkEvent { val start: String? val end: String? - val events: List? + val events: List val stateEvents: List? fun hasMore() = start != end diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistor.kt index fb636a9314..1a497b8835 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistor.kt @@ -124,7 +124,7 @@ internal class TokenChunkEventPersistor @Inject constructor(@SessionDatabase pri direction: PaginationDirection): Result { monarchy .awaitTransaction { realm -> - Timber.v("Start persisting ${receivedChunk.events?.size} events in $roomId towards $direction") + Timber.v("Start persisting ${receivedChunk.events.size} events in $roomId towards $direction") val nextToken: String? val prevToken: String? @@ -149,14 +149,14 @@ internal class TokenChunkEventPersistor @Inject constructor(@SessionDatabase pri } ?: ChunkEntity.create(realm, prevToken, nextToken) - if (receivedChunk.events.isNullOrEmpty() && !receivedChunk.hasMore()) { + if (receivedChunk.events.isEmpty() && !receivedChunk.hasMore()) { handleReachEnd(realm, roomId, direction, currentChunk) } else { handlePagination(realm, roomId, direction, receivedChunk, currentChunk) } } - return if (receivedChunk.events.isNullOrEmpty()) { - if (receivedChunk.start != receivedChunk.end) { + return if (receivedChunk.events.isEmpty()) { + if (receivedChunk.hasMore()) { Result.SHOULD_FETCH_MORE } else { Result.REACHED_END @@ -189,7 +189,7 @@ internal class TokenChunkEventPersistor @Inject constructor(@SessionDatabase pri receivedChunk: TokenChunkEvent, currentChunk: ChunkEntity ) { - Timber.v("Add ${receivedChunk.events?.size} events in chunk(${currentChunk.nextToken} | ${currentChunk.prevToken}") + Timber.v("Add ${receivedChunk.events.size} events in chunk(${currentChunk.nextToken} | ${currentChunk.prevToken}") val roomMemberContentsByUser = HashMap() val eventList = receivedChunk.events val stateEvents = receivedChunk.stateEvents @@ -204,8 +204,8 @@ internal class TokenChunkEventPersistor @Inject constructor(@SessionDatabase pri roomMemberContentsByUser[stateEvent.stateKey] = stateEvent.content.toModel() } } - val eventIds = ArrayList(eventList?.size ?: 0) - eventList?.forEach { event -> + val eventIds = ArrayList(eventList.size) + eventList.forEach { event -> if (event.eventId == null || event.senderId == null) { return@forEach } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/uploads/GetUploadsTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/uploads/GetUploadsTask.kt index 9d66474a73..b3e4a5aa05 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/uploads/GetUploadsTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/uploads/GetUploadsTask.kt @@ -56,8 +56,8 @@ internal class DefaultGetUploadsTask @Inject constructor( private val roomAPI: RoomAPI, private val tokenStore: SyncTokenStore, @SessionDatabase private val monarchy: Monarchy, - private val globalErrorReceiver: GlobalErrorReceiver) - : GetUploadsTask { + private val globalErrorReceiver: GlobalErrorReceiver +) : GetUploadsTask { override suspend fun execute(params: GetUploadsTask.Params): GetUploadsResult { val result: GetUploadsResult @@ -95,7 +95,7 @@ internal class DefaultGetUploadsTask @Inject constructor( nextToken = chunk.end ?: "", hasMore = chunk.hasMore() ) - events = chunk.events ?: emptyList() + events = chunk.events } var uploadEvents = listOf()