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 59a75cb67e..7cf8ecbb87 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 @@ -9,3 +9,10 @@ internal fun RoomEntity.deleteOnCascade(chunkEntity: ChunkEntity) { chunkEntity.events.deleteAllFromRealm() chunkEntity.deleteFromRealm() } + +internal fun RoomEntity.addOrUpdate(chunkEntity: ChunkEntity) { + chunkEntity.events.forEachIndexed { index, eventEntity -> eventEntity.displayIndex = index } + if (!chunks.contains(chunkEntity)) { + chunks.add(chunkEntity) + } +} \ 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 49b78ca50d..2bcb91e8a5 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 @@ -13,7 +13,8 @@ internal open class EventEntity(var eventId: String = "", var sender: String? = null, var age: Long? = 0, var redacts: String? = null, - var stateIndex: Int = 0 + var stateIndex: Int = 0, + var displayIndex: Int = 0 ) : RealmObject() { companion object { 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 f0b8e5697f..430b08b69c 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.model.EventEntity +import im.vector.matrix.android.internal.database.helper.addOrUpdate 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.room.timeline.PaginationDirection 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 @@ -53,15 +52,13 @@ internal class LoadRoomMembersRequest(private val roomAPI: RoomAPI, .tryTransactionSync { realm -> // We ignore all the already known members val roomEntity = RoomEntity.where(realm, roomId).findFirst() - ?: throw IllegalStateException("You shouldn't use this method without a room") + ?: throw IllegalStateException("You shouldn't use this method without a room") val roomMembers = RoomMembers(realm, roomId).getLoaded() val eventsToInsert = response.roomMemberEvents.filter { !roomMembers.containsKey(it.stateKey) } val chunk = stateEventsChunkHandler.handle(realm, roomId, eventsToInsert) - if (!roomEntity.chunks.contains(chunk)) { - roomEntity.chunks.add(chunk) - } + roomEntity.addOrUpdate(chunk) roomEntity.areAllMembersLoaded = true } .map { response } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultTimelineHolder.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultTimelineHolder.kt index 40b3d9f9a0..21095bcd39 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultTimelineHolder.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultTimelineHolder.kt @@ -8,8 +8,10 @@ import im.vector.matrix.android.api.session.events.interceptor.EnrichedEventInte import im.vector.matrix.android.api.session.events.model.EnrichedEvent import im.vector.matrix.android.api.session.room.TimelineHolder 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.query.findLastLiveChunkFromRoom +import im.vector.matrix.android.internal.database.model.ChunkEntityFields +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.where import im.vector.matrix.android.internal.session.events.interceptor.MessageEventInterceptor private const val PAGE_SIZE = 30 @@ -28,9 +30,10 @@ internal class DefaultTimelineHolder(private val roomId: String, override fun liveTimeline(): LiveData<PagedList<EnrichedEvent>> { val realmDataSourceFactory = monarchy.createDataSourceFactory { realm -> - ChunkEntity.findLastLiveChunkFromRoom(realm, roomId = roomId) - ?.events - ?.where() + EventEntity + .where(realm, roomId = roomId) + .equalTo("${EventEntityFields.CHUNK}.${ChunkEntityFields.IS_LAST}", true) + .sort(EventEntityFields.DISPLAY_INDEX) } val domainSourceFactory = realmDataSourceFactory .map { it.asDomain() } 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 678603cb72..5ca59f71d2 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 @@ -6,6 +6,7 @@ import com.zhuinden.monarchy.Monarchy 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.deleteOnCascade import im.vector.matrix.android.internal.database.helper.merge import im.vector.matrix.android.internal.database.model.ChunkEntity @@ -90,15 +91,11 @@ internal class PaginationRequest(private val roomAPI: RoomAPI, } } - if (!roomEntity.chunks.contains(currentChunk)) { - roomEntity.chunks.add(currentChunk) - } + roomEntity.addOrUpdate(currentChunk) // TODO : there is an issue with the pagination sending unwanted room member events val stateEventsChunk = stateEventsChunkHandler.handle(realm, roomId, receivedChunk.stateEvents) - if (!roomEntity.chunks.contains(stateEventsChunk)) { - roomEntity.chunks.add(stateEventsChunk) - } + roomEntity.addOrUpdate(stateEventsChunk) } .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 e2312ffac2..7b1227115a 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 @@ -5,6 +5,7 @@ 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.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.model.ChunkEntity import im.vector.matrix.android.internal.database.model.RoomEntity import im.vector.matrix.android.internal.database.model.RoomSummaryEntity @@ -65,16 +66,12 @@ internal class RoomSyncHandler(private val monarchy: Monarchy, if (roomSync.state != null && roomSync.state.events.isNotEmpty()) { val chunkEntity = stateEventsChunkHandler.handle(realm, roomId, roomSync.state.events) - if (!roomEntity.chunks.contains(chunkEntity)) { - roomEntity.chunks.add(chunkEntity) - } + roomEntity.addOrUpdate(chunkEntity) } if (roomSync.timeline != null && roomSync.timeline.events.isNotEmpty()) { val chunkEntity = handleTimelineEvents(realm, roomId, roomSync.timeline.events, roomSync.timeline.prevToken, isLimited = roomSync.timeline.limited) - if (!roomEntity.chunks.contains(chunkEntity)) { - roomEntity.chunks.add(chunkEntity) - } + roomEntity.addOrUpdate(chunkEntity) } if (roomSync.summary != null) { @@ -96,9 +93,7 @@ internal class RoomSyncHandler(private val monarchy: Monarchy, roomEntity.membership = MyMembership.INVITED if (roomSync.inviteState != null && roomSync.inviteState.events.isNotEmpty()) { val chunkEntity = handleTimelineEvents(realm, roomId, roomSync.inviteState.events) - if (!roomEntity.chunks.contains(chunkEntity)) { - roomEntity.chunks.add(chunkEntity) - } + roomEntity.addOrUpdate(chunkEntity) } return roomEntity } @@ -112,26 +107,6 @@ internal class RoomSyncHandler(private val monarchy: Monarchy, } } - private fun handleRoomSummary(realm: Realm, - roomId: String, - roomSummary: RoomSyncSummary) { - - val roomSummaryEntity = RoomSummaryEntity.where(realm, roomId).findFirst() - ?: RoomSummaryEntity(roomId) - - if (roomSummary.heroes.isNotEmpty()) { - roomSummaryEntity.heroes.clear() - roomSummaryEntity.heroes.addAll(roomSummary.heroes) - } - if (roomSummary.invitedMembersCount != null) { - roomSummaryEntity.invitedMembersCount = roomSummary.invitedMembersCount - } - if (roomSummary.joinedMembersCount != null) { - roomSummaryEntity.joinedMembersCount = roomSummary.joinedMembersCount - } - realm.insertOrUpdate(roomSummaryEntity) - } - private fun handleTimelineEvents(realm: Realm, roomId: String, eventList: List<Event>, @@ -155,6 +130,26 @@ internal class RoomSyncHandler(private val monarchy: Monarchy, return chunkEntity } + private fun handleRoomSummary(realm: Realm, + roomId: String, + roomSummary: RoomSyncSummary) { + + val roomSummaryEntity = RoomSummaryEntity.where(realm, roomId).findFirst() + ?: RoomSummaryEntity(roomId) + + if (roomSummary.heroes.isNotEmpty()) { + roomSummaryEntity.heroes.clear() + roomSummaryEntity.heroes.addAll(roomSummary.heroes) + } + if (roomSummary.invitedMembersCount != null) { + roomSummaryEntity.invitedMembersCount = roomSummary.invitedMembersCount + } + if (roomSummary.joinedMembersCount != null) { + roomSummaryEntity.joinedMembersCount = roomSummary.joinedMembersCount + } + realm.insertOrUpdate(roomSummaryEntity) + } + private fun handleEphemeral(realm: Realm, roomId: String, ephemeral: RoomSyncEphemeral) {