diff --git a/.idea/dictionaries/ganfra.xml b/.idea/dictionaries/ganfra.xml
index 806a1048..1ca7a97a 100644
--- a/.idea/dictionaries/ganfra.xml
+++ b/.idea/dictionaries/ganfra.xml
@@ -6,6 +6,7 @@
merlins
moshi
synchronizer
+ untimelined
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/ChunkEntityHelper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/ChunkEntityHelper.kt
index 07316c10..03b4b1e8 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/ChunkEntityHelper.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/ChunkEntityHelper.kt
@@ -1,12 +1,15 @@
package im.vector.matrix.android.internal.database.helper
import im.vector.matrix.android.api.session.events.model.Event
+import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.internal.database.mapper.asDomain
import im.vector.matrix.android.internal.database.mapper.asEntity
import im.vector.matrix.android.internal.database.model.ChunkEntity
+import im.vector.matrix.android.internal.database.model.EventEntityFields
import im.vector.matrix.android.internal.database.query.fastContains
import im.vector.matrix.android.internal.database.query.find
import im.vector.matrix.android.internal.session.room.timeline.PaginationDirection
+import io.realm.Sort
internal fun ChunkEntity.merge(chunkEntity: ChunkEntity,
@@ -25,16 +28,16 @@ internal fun ChunkEntity.merge(chunkEntity: ChunkEntity,
internal fun ChunkEntity.addAll(events: List,
direction: PaginationDirection,
- updateStateIndex: Boolean = true) {
+ stateIndexOffset: Int = 0) {
events.forEach { event ->
- addOrUpdate(event, direction, updateStateIndex)
+ addOrUpdate(event, direction, stateIndexOffset)
}
}
internal fun ChunkEntity.addOrUpdate(event: Event,
direction: PaginationDirection,
- updateStateIndex: Boolean = true) {
+ stateIndexOffset: Int = 0) {
if (!isManaged) {
throw IllegalStateException("Chunk entity should be managed to use fast contains")
}
@@ -43,11 +46,16 @@ internal fun ChunkEntity.addOrUpdate(event: Event,
return
}
- if (updateStateIndex && event.isStateEvent()) {
- updateStateIndex(direction)
+ var currentStateIndex = lastStateIndex(direction, defaultValue = stateIndexOffset)
+ if (direction == PaginationDirection.FORWARDS && event.isStateEvent()) {
+ currentStateIndex += 1
+ } else if (direction == PaginationDirection.BACKWARDS && events.isNotEmpty()) {
+ val lastEventType = events.last()?.type ?: ""
+ if (EventType.isStateEvent(lastEventType)) {
+ currentStateIndex -= 1
+ }
}
- val currentStateIndex = stateIndex(direction)
if (!events.fastContains(event.eventId)) {
val eventEntity = event.asEntity()
eventEntity.stateIndex = currentStateIndex
@@ -57,4 +65,11 @@ internal fun ChunkEntity.addOrUpdate(event: Event,
val eventEntity = events.find(event.eventId)
eventEntity?.stateIndex = currentStateIndex
}
+}
+
+internal fun ChunkEntity.lastStateIndex(direction: PaginationDirection, defaultValue: Int = 0): Int {
+ return when (direction) {
+ PaginationDirection.FORWARDS -> events.where().sort(EventEntityFields.STATE_INDEX, Sort.DESCENDING).findFirst()?.stateIndex
+ PaginationDirection.BACKWARDS -> events.where().sort(EventEntityFields.STATE_INDEX, Sort.ASCENDING).findFirst()?.stateIndex
+ } ?: defaultValue
}
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/RoomEntityHelper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/RoomEntityHelper.kt
index 7cf8ecbb..0b69f2c0 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/RoomEntityHelper.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/RoomEntityHelper.kt
@@ -1,5 +1,7 @@
package im.vector.matrix.android.internal.database.helper
+import im.vector.matrix.android.api.session.events.model.Event
+import im.vector.matrix.android.internal.database.mapper.asEntity
import im.vector.matrix.android.internal.database.model.ChunkEntity
import im.vector.matrix.android.internal.database.model.RoomEntity
@@ -15,4 +17,18 @@ internal fun RoomEntity.addOrUpdate(chunkEntity: ChunkEntity) {
if (!chunks.contains(chunkEntity)) {
chunks.add(chunkEntity)
}
+}
+
+internal fun RoomEntity.addStateEvents(stateEvents: List, stateIndex: Int = Int.MIN_VALUE) {
+ if (!isManaged) {
+ throw IllegalStateException("Chunk entity should be managed to use fast contains")
+ }
+ stateEvents.forEach { event ->
+ if (event.eventId == null) {
+ return@forEach
+ }
+ val eventEntity = event.asEntity()
+ eventEntity.stateIndex = stateIndex
+ untimelinedStateEvents.add(eventEntity)
+ }
}
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/ChunkEntity.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/ChunkEntity.kt
index 64aa9e28..354720df 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/ChunkEntity.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/ChunkEntity.kt
@@ -1,6 +1,5 @@
package im.vector.matrix.android.internal.database.model
-import im.vector.matrix.android.internal.session.room.timeline.PaginationDirection
import io.realm.RealmList
import io.realm.RealmObject
import io.realm.RealmResults
@@ -8,8 +7,6 @@ import io.realm.annotations.LinkingObjects
internal open class ChunkEntity(var prevToken: String? = null,
var nextToken: String? = null,
- var prevStateIndex: Int = -1,
- var nextStateIndex: Int = 1,
var isLast: Boolean = false,
var events: RealmList = RealmList()
) : RealmObject() {
@@ -18,19 +15,4 @@ internal open class ChunkEntity(var prevToken: String? = null,
val room: RealmResults? = null
companion object
-
- fun stateIndex(direction: PaginationDirection): Int {
- return when (direction) {
- PaginationDirection.FORWARDS -> nextStateIndex
- PaginationDirection.BACKWARDS -> prevStateIndex
- }
- }
-
- fun updateStateIndex(direction: PaginationDirection) {
- when (direction) {
- PaginationDirection.FORWARDS -> nextStateIndex += 1
- PaginationDirection.BACKWARDS -> prevStateIndex -= 1
- }
- }
-
}
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/EventEntity.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/EventEntity.kt
index 2bcb91e8..96ba986a 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/EventEntity.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/EventEntity.kt
@@ -24,4 +24,7 @@ internal open class EventEntity(var eventId: String = "",
@LinkingObjects("events")
val chunk: RealmResults? = null
+ @LinkingObjects("untimelinedStateEvents")
+ val room: RealmResults? = null
+
}
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/RoomEntity.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/RoomEntity.kt
index e8df6e34..906dff0d 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/RoomEntity.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/RoomEntity.kt
@@ -8,8 +8,9 @@ import io.realm.annotations.PrimaryKey
import kotlin.properties.Delegates
internal open class RoomEntity(@PrimaryKey var roomId: String = "",
- var chunks: RealmList = RealmList(),
- var areAllMembersLoaded: Boolean = false
+ var chunks: RealmList = RealmList(),
+ var untimelinedStateEvents: RealmList = RealmList(),
+ var areAllMembersLoaded: Boolean = false
) : RealmObject() {
private var membershipStr: String = MyMembership.NONE.name
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/ChunkEntityQueries.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/ChunkEntityQueries.kt
index 5f1a7a15..e3b071a2 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/ChunkEntityQueries.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/ChunkEntityQueries.kt
@@ -1,6 +1,5 @@
package im.vector.matrix.android.internal.database.query
-import im.vector.matrix.android.internal.database.DBConstants
import im.vector.matrix.android.internal.database.model.ChunkEntity
import im.vector.matrix.android.internal.database.model.ChunkEntityFields
import im.vector.matrix.android.internal.database.model.RoomEntityFields
@@ -34,7 +33,5 @@ internal fun ChunkEntity.Companion.findLastLiveChunkFromRoom(realm: Realm, roomI
internal fun ChunkEntity.Companion.findAllIncludingEvents(realm: Realm, eventIds: List): RealmResults {
return realm.where()
.`in`(ChunkEntityFields.EVENTS.EVENT_ID, eventIds.toTypedArray())
- .notEqualTo(ChunkEntityFields.PREV_TOKEN, DBConstants.STATE_EVENTS_CHUNK_TOKEN)
- .notEqualTo(ChunkEntityFields.NEXT_TOKEN, DBConstants.STATE_EVENTS_CHUNK_TOKEN)
.findAll()
}
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/EventEntityQueries.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/EventEntityQueries.kt
index f54881a3..91a828c7 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/EventEntityQueries.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/EventEntityQueries.kt
@@ -18,7 +18,11 @@ internal fun EventEntity.Companion.where(realm: Realm, eventId: String): RealmQu
internal fun EventEntity.Companion.where(realm: Realm, roomId: String? = null, type: String? = null): RealmQuery {
val query = realm.where()
if (roomId != null) {
- query.equalTo("${EventEntityFields.CHUNK}.${ChunkEntityFields.ROOM}.${RoomEntityFields.ROOM_ID}", roomId)
+ query.beginGroup()
+ .equalTo("${EventEntityFields.CHUNK}.${ChunkEntityFields.ROOM}.${RoomEntityFields.ROOM_ID}", roomId)
+ .or()
+ .equalTo("${EventEntityFields.ROOM}.${RoomEntityFields.ROOM_ID}", roomId)
+ .endGroup()
}
if (type != null) {
query.equalTo(EventEntityFields.TYPE, type)
@@ -26,21 +30,28 @@ internal fun EventEntity.Companion.where(realm: Realm, roomId: String? = null, t
return query
}
-internal fun RealmQuery.findMostSuitableStateEvent(stateIndex: Int): EventEntity? {
- val sort: Sort = if (stateIndex < 0) {
- this.greaterThanOrEqualTo(EventEntityFields.STATE_INDEX, stateIndex)
- Sort.ASCENDING
- } else {
- this.lessThanOrEqualTo(EventEntityFields.STATE_INDEX, stateIndex)
- Sort.DESCENDING
+internal fun RealmQuery.next(from: Int? = null, strict: Boolean = true): EventEntity? {
+ if (from != null) {
+ if (strict) {
+ this.greaterThan(EventEntityFields.STATE_INDEX, from)
+ } else {
+ this.greaterThanOrEqualTo(EventEntityFields.STATE_INDEX, from)
+ }
}
return this
- .sort(EventEntityFields.STATE_INDEX, sort)
+ .sort(EventEntityFields.STATE_INDEX, Sort.ASCENDING)
.findFirst()
}
-internal fun RealmQuery.last(): EventEntity? {
+internal fun RealmQuery.last(since: Int? = null, strict: Boolean = false): EventEntity? {
+ if (since != null) {
+ if (strict) {
+ this.lessThan(EventEntityFields.STATE_INDEX, since)
+ } else {
+ this.lessThanOrEqualTo(EventEntityFields.STATE_INDEX, since)
+ }
+ }
return this
.sort(EventEntityFields.STATE_INDEX, Sort.DESCENDING)
.findFirst()
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomModule.kt
index bfd9052e..14dee22b 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomModule.kt
@@ -25,11 +25,11 @@ class RoomModule : Module {
}
scope(DefaultSession.SCOPE) {
- LoadRoomMembersRequest(get(), get(), get(), get())
+ LoadRoomMembersRequest(get(), get(), get())
}
scope(DefaultSession.SCOPE) {
- PaginationRequest(get(), get(), get(), get())
+ PaginationRequest(get(), get(), get())
}
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/members/LoadRoomMembersRequest.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/members/LoadRoomMembersRequest.kt
index 430b08b6..c3fca61d 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/members/LoadRoomMembersRequest.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/members/LoadRoomMembersRequest.kt
@@ -5,12 +5,11 @@ import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.session.room.model.Membership
import im.vector.matrix.android.api.util.Cancelable
-import im.vector.matrix.android.internal.database.helper.addOrUpdate
+import im.vector.matrix.android.internal.database.helper.addStateEvents
import im.vector.matrix.android.internal.database.model.RoomEntity
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.network.executeRequest
import im.vector.matrix.android.internal.session.room.RoomAPI
-import im.vector.matrix.android.internal.session.sync.StateEventsChunkHandler
import im.vector.matrix.android.internal.util.CancelableCoroutine
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
import im.vector.matrix.android.internal.util.tryTransactionSync
@@ -20,8 +19,7 @@ import kotlinx.coroutines.withContext
internal class LoadRoomMembersRequest(private val roomAPI: RoomAPI,
private val monarchy: Monarchy,
- private val coroutineDispatchers: MatrixCoroutineDispatchers,
- private val stateEventsChunkHandler: StateEventsChunkHandler) {
+ private val coroutineDispatchers: MatrixCoroutineDispatchers) {
fun execute(roomId: String,
streamToken: String?,
@@ -57,8 +55,7 @@ internal class LoadRoomMembersRequest(private val roomAPI: RoomAPI,
val roomMembers = RoomMembers(realm, roomId).getLoaded()
val eventsToInsert = response.roomMemberEvents.filter { !roomMembers.containsKey(it.stateKey) }
- val chunk = stateEventsChunkHandler.handle(realm, roomId, eventsToInsert)
- roomEntity.addOrUpdate(chunk)
+ roomEntity.addStateEvents(eventsToInsert)
roomEntity.areAllMembersLoaded = true
}
.map { response }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/members/RoomMemberExtractor.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/members/RoomMemberExtractor.kt
index d7c51b71..08012cb5 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/members/RoomMemberExtractor.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/members/RoomMemberExtractor.kt
@@ -2,14 +2,12 @@ package im.vector.matrix.android.internal.session.room.members
import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.room.model.RoomMember
-import im.vector.matrix.android.internal.database.DBConstants
import im.vector.matrix.android.internal.database.mapper.asDomain
-import im.vector.matrix.android.internal.database.model.ChunkEntity
import im.vector.matrix.android.internal.database.model.EventEntity
import im.vector.matrix.android.internal.database.model.EventEntityFields
-import im.vector.matrix.android.internal.database.query.find
-import im.vector.matrix.android.internal.database.query.findMostSuitableStateEvent
import im.vector.matrix.android.internal.database.query.last
+import im.vector.matrix.android.internal.database.query.next
+import im.vector.matrix.android.internal.database.query.where
import io.realm.Realm
import io.realm.RealmQuery
@@ -17,35 +15,23 @@ internal class RoomMemberExtractor(private val realm: Realm,
private val roomId: String) {
fun extractFrom(event: EventEntity): RoomMember? {
- val stateIndex = event.stateIndex
- val chunkEntity = event.chunk?.firstOrNull()
- ?: throw IllegalStateException("An event should be attached to a chunk")
-
- // First of all, try to get the most suitable state event coming from a chunk
- val roomMember = buildQuery(chunkEntity, event.sender)
- .findMostSuitableStateEvent(stateIndex = stateIndex)
- ?.asDomain()
- ?.pickContent(stateIndex)
-
- if (roomMember != null) {
- return roomMember
+ val sender = event.sender ?: return null
+ // When stateIndex is negative, we try to get the next stateEvent prevContent()
+ // If prevContent is null we fallback to the Int.MIN state events content()
+ return if (event.stateIndex <= 0) {
+ baseQuery(realm, roomId, sender).next(from = event.stateIndex)?.asDomain()?.prevContent()
+ ?: baseQuery(realm, roomId, sender).last(since = event.stateIndex)?.asDomain()?.content()
+ } else {
+ baseQuery(realm, roomId, sender).last(since = event.stateIndex)?.asDomain()?.content()
}
-
- // If the content is null, we try get the last state event coming from a state events chunk
- val stateChunkEntity = ChunkEntity.find(realm, roomId, nextToken = DBConstants.STATE_EVENTS_CHUNK_TOKEN)
- ?: return null
-
- return buildQuery(stateChunkEntity, event.sender)
- .last()
- ?.asDomain()
- ?.content()
}
- private fun buildQuery(chunk: ChunkEntity,
- sender: String?): RealmQuery {
- return chunk.events
- .where()
- .equalTo(EventEntityFields.TYPE, EventType.STATE_ROOM_MEMBER)
+ private fun baseQuery(realm: Realm,
+ roomId: String,
+ sender: String): RealmQuery {
+
+ return EventEntity
+ .where(realm, roomId = roomId, type = EventType.STATE_ROOM_MEMBER)
.equalTo(EventEntityFields.STATE_KEY, sender)
}
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/GetContextOfEventRequest.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/GetContextOfEventRequest.kt
index fcab9e82..248c616a 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/GetContextOfEventRequest.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/GetContextOfEventRequest.kt
@@ -6,6 +6,7 @@ import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.util.Cancelable
import im.vector.matrix.android.internal.database.helper.addAll
import im.vector.matrix.android.internal.database.helper.addOrUpdate
+import im.vector.matrix.android.internal.database.helper.addStateEvents
import im.vector.matrix.android.internal.database.helper.deleteOnCascade
import im.vector.matrix.android.internal.database.helper.merge
import im.vector.matrix.android.internal.database.model.ChunkEntity
@@ -15,7 +16,6 @@ import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.legacy.util.FilterUtil
import im.vector.matrix.android.internal.network.executeRequest
import im.vector.matrix.android.internal.session.room.RoomAPI
-import im.vector.matrix.android.internal.session.sync.StateEventsChunkHandler
import im.vector.matrix.android.internal.util.CancelableCoroutine
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
import im.vector.matrix.android.internal.util.tryTransactionSync
@@ -26,8 +26,7 @@ import kotlinx.coroutines.withContext
internal class GetContextOfEventRequest(private val roomAPI: RoomAPI,
private val monarchy: Monarchy,
- private val coroutineDispatchers: MatrixCoroutineDispatchers,
- private val stateEventsChunkHandler: StateEventsChunkHandler
+ private val coroutineDispatchers: MatrixCoroutineDispatchers
) {
fun execute(roomId: String,
@@ -91,9 +90,7 @@ internal class GetContextOfEventRequest(private val roomAPI: RoomAPI,
}
*/
roomEntity.addOrUpdate(currentChunk)
-
- val stateEventsChunk = stateEventsChunkHandler.handle(realm, roomId, response.stateEvents)
- roomEntity.addOrUpdate(stateEventsChunk)
+ roomEntity.addStateEvents(response.stateEvents)
}
.map { response }
}
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/GetEventRequest.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/GetEventRequest.kt
index 1a8ebc7b..28abd072 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/GetEventRequest.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/GetEventRequest.kt
@@ -6,7 +6,6 @@ import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.util.Cancelable
import im.vector.matrix.android.internal.network.executeRequest
import im.vector.matrix.android.internal.session.room.RoomAPI
-import im.vector.matrix.android.internal.session.sync.StateEventsChunkHandler
import im.vector.matrix.android.internal.util.CancelableCoroutine
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
import kotlinx.coroutines.GlobalScope
@@ -15,8 +14,7 @@ import kotlinx.coroutines.withContext
internal class GetEventRequest(private val roomAPI: RoomAPI,
private val monarchy: Monarchy,
- private val coroutineDispatchers: MatrixCoroutineDispatchers,
- private val stateEventsChunkHandler: StateEventsChunkHandler
+ private val coroutineDispatchers: MatrixCoroutineDispatchers
) {
fun execute(roomId: String,
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/PaginationRequest.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/PaginationRequest.kt
index 5ca59f71..29a3e6c9 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/PaginationRequest.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/PaginationRequest.kt
@@ -7,6 +7,7 @@ import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.util.Cancelable
import im.vector.matrix.android.internal.database.helper.addAll
import im.vector.matrix.android.internal.database.helper.addOrUpdate
+import im.vector.matrix.android.internal.database.helper.addStateEvents
import im.vector.matrix.android.internal.database.helper.deleteOnCascade
import im.vector.matrix.android.internal.database.helper.merge
import im.vector.matrix.android.internal.database.model.ChunkEntity
@@ -17,7 +18,6 @@ import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.legacy.util.FilterUtil
import im.vector.matrix.android.internal.network.executeRequest
import im.vector.matrix.android.internal.session.room.RoomAPI
-import im.vector.matrix.android.internal.session.sync.StateEventsChunkHandler
import im.vector.matrix.android.internal.util.CancelableCoroutine
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
import im.vector.matrix.android.internal.util.tryTransactionSync
@@ -28,8 +28,7 @@ import kotlinx.coroutines.withContext
internal class PaginationRequest(private val roomAPI: RoomAPI,
private val monarchy: Monarchy,
- private val coroutineDispatchers: MatrixCoroutineDispatchers,
- private val stateEventsChunkHandler: StateEventsChunkHandler
+ private val coroutineDispatchers: MatrixCoroutineDispatchers
) {
fun execute(roomId: String,
@@ -92,10 +91,8 @@ internal class PaginationRequest(private val roomAPI: RoomAPI,
}
roomEntity.addOrUpdate(currentChunk)
-
// TODO : there is an issue with the pagination sending unwanted room member events
- val stateEventsChunk = stateEventsChunkHandler.handle(realm, roomId, receivedChunk.stateEvents)
- roomEntity.addOrUpdate(stateEventsChunk)
+ roomEntity.addStateEvents(receivedChunk.stateEvents)
}
.map { receivedChunk }
}
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt
index 7b122711..adf0b9c7 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt
@@ -6,10 +6,11 @@ import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.room.model.MyMembership
import im.vector.matrix.android.internal.database.helper.addAll
import im.vector.matrix.android.internal.database.helper.addOrUpdate
+import im.vector.matrix.android.internal.database.helper.addStateEvents
+import im.vector.matrix.android.internal.database.helper.lastStateIndex
import im.vector.matrix.android.internal.database.model.ChunkEntity
import im.vector.matrix.android.internal.database.model.RoomEntity
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
-import im.vector.matrix.android.internal.database.query.findAllIncludingEvents
import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoom
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.session.room.timeline.PaginationDirection
@@ -23,7 +24,6 @@ import io.realm.kotlin.createObject
internal class RoomSyncHandler(private val monarchy: Monarchy,
- private val stateEventsChunkHandler: StateEventsChunkHandler,
private val readReceiptHandler: ReadReceiptHandler) {
sealed class HandlingStrategy {
@@ -56,7 +56,7 @@ internal class RoomSyncHandler(private val monarchy: Monarchy,
roomSync: RoomSync): RoomEntity {
val roomEntity = RoomEntity.where(realm, roomId).findFirst()
- ?: RoomEntity(roomId)
+ ?: realm.createObject(roomId)
if (roomEntity.membership == MyMembership.INVITED) {
roomEntity.chunks.deleteAllFromRealm()
@@ -64,13 +64,27 @@ internal class RoomSyncHandler(private val monarchy: Monarchy,
roomEntity.membership = MyMembership.JOINED
+ val lastChunk = ChunkEntity.findLastLiveChunkFromRoom(realm, roomId)
+ val isInitialSync = lastChunk == null
+ val lastStateIndex = lastChunk?.lastStateIndex(PaginationDirection.FORWARDS) ?: 0
+ val numberOfStateEvents = roomSync.state?.events?.size ?: 0
+ val stateIndexOffset = lastStateIndex + numberOfStateEvents
+
if (roomSync.state != null && roomSync.state.events.isNotEmpty()) {
- val chunkEntity = stateEventsChunkHandler.handle(realm, roomId, roomSync.state.events)
- roomEntity.addOrUpdate(chunkEntity)
+ val untimelinedStateIndex = if (isInitialSync) Int.MIN_VALUE else stateIndexOffset
+ roomEntity.addStateEvents(roomSync.state.events, stateIndex = untimelinedStateIndex)
}
if (roomSync.timeline != null && roomSync.timeline.events.isNotEmpty()) {
- val chunkEntity = handleTimelineEvents(realm, roomId, roomSync.timeline.events, roomSync.timeline.prevToken, isLimited = roomSync.timeline.limited)
+ val timelineStateOffset = if (isInitialSync || roomSync.timeline.limited.not()) 0 else stateIndexOffset
+ val chunkEntity = handleTimelineEvents(
+ realm,
+ roomId,
+ roomSync.timeline.events,
+ roomSync.timeline.prevToken,
+ roomSync.timeline.limited,
+ timelineStateOffset
+ )
roomEntity.addOrUpdate(chunkEntity)
}
@@ -111,22 +125,19 @@ internal class RoomSyncHandler(private val monarchy: Monarchy,
roomId: String,
eventList: List,
prevToken: String? = null,
- nextToken: String? = null,
- isLimited: Boolean = true): ChunkEntity {
+ isLimited: Boolean = true,
+ stateIndexOffset: Int = 0): ChunkEntity {
val lastChunk = ChunkEntity.findLastLiveChunkFromRoom(realm, roomId)
- val chunkEntity = if (!isLimited) {
+ val chunkEntity = if (!isLimited && lastChunk != null) {
lastChunk
} else {
- val eventIds = eventList.filter { it.eventId != null }.map { it.eventId!! }
- ChunkEntity.findAllIncludingEvents(realm, eventIds).firstOrNull()
- } ?: realm.createObject().apply { this.prevToken = prevToken }
+ realm.createObject().apply { this.prevToken = prevToken }
+ }
lastChunk?.isLast = false
chunkEntity.isLast = true
- chunkEntity.nextToken = nextToken
-
- chunkEntity.addAll(eventList, PaginationDirection.FORWARDS)
+ chunkEntity.addAll(eventList, PaginationDirection.FORWARDS, stateIndexOffset)
return chunkEntity
}
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/StateEventsChunkHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/StateEventsChunkHandler.kt
deleted file mode 100644
index 8046b74f..00000000
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/StateEventsChunkHandler.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-package im.vector.matrix.android.internal.session.sync
-
-import im.vector.matrix.android.api.session.events.model.Event
-import im.vector.matrix.android.internal.database.DBConstants
-import im.vector.matrix.android.internal.database.helper.addAll
-import im.vector.matrix.android.internal.database.model.ChunkEntity
-import im.vector.matrix.android.internal.database.query.find
-import im.vector.matrix.android.internal.session.room.timeline.PaginationDirection
-import io.realm.Realm
-import io.realm.kotlin.createObject
-
-internal class StateEventsChunkHandler {
-
- fun handle(realm: Realm, roomId: String, stateEvents: List): ChunkEntity {
- val chunkEntity = ChunkEntity.find(realm, roomId, nextToken = DBConstants.STATE_EVENTS_CHUNK_TOKEN)
- ?: realm.createObject()
- .apply {
- prevToken = DBConstants.STATE_EVENTS_CHUNK_TOKEN
- nextToken = DBConstants.STATE_EVENTS_CHUNK_TOKEN
- nextStateIndex = Int.MIN_VALUE
- prevStateIndex = Int.MIN_VALUE
- }
-
- // We always consider going forwards as data from server are the most recent
- chunkEntity.addAll(stateEvents, direction = PaginationDirection.FORWARDS, updateStateIndex = false)
- return chunkEntity
- }
-
-
-}
-
-
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncModule.kt
index 86b739e4..0ae3e618 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncModule.kt
@@ -17,16 +17,12 @@ internal class SyncModule : Module {
retrofit.create(SyncAPI::class.java)
}
- scope(DefaultSession.SCOPE) {
- StateEventsChunkHandler()
- }
-
scope(DefaultSession.SCOPE) {
ReadReceiptHandler()
}
scope(DefaultSession.SCOPE) {
- RoomSyncHandler(get(), get(), get())
+ RoomSyncHandler(get(), get())
}
scope(DefaultSession.SCOPE) {