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 f8ccc5f9ad..b74fcdcf7e 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 @@ -18,6 +18,7 @@ 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.api.session.room.send.SendState import im.vector.matrix.android.internal.database.mapper.asDomain import im.vector.matrix.android.internal.database.mapper.toEntity import im.vector.matrix.android.internal.database.model.ChunkEntity @@ -112,11 +113,16 @@ internal fun ChunkEntity.add(roomId: String, } } - val eventEntity = TimelineEventEntity().apply { - this.root = event.toEntity(roomId) - this.eventId = event.eventId ?: "" - this.roomId = roomId - this.annotations = EventAnnotationsSummaryEntity.where(realm, eventId).findFirst() + val eventEntity = TimelineEventEntity().also { + it.root = event.toEntity(roomId).apply { + this.stateIndex = currentStateIndex + this.isUnlinked = isUnlinked + this.displayIndex = currentDisplayIndex + this.sendState = SendState.SYNCED + } + it.eventId = event.eventId ?: "" + it.roomId = roomId + it.annotations = EventAnnotationsSummaryEntity.where(realm, it.eventId).findFirst() } val position = if (direction == PaginationDirection.FORWARDS) 0 else this.timelineEvents.size timelineEvents.add(position, eventEntity) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/TimelineEventEntityQueries.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/TimelineEventEntityQueries.kt index 28b2bc018e..5367603c95 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/TimelineEventEntityQueries.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/TimelineEventEntityQueries.kt @@ -37,6 +37,24 @@ internal fun TimelineEventEntity.Companion.where(realm: Realm, eventIds: List().`in`(TimelineEventEntityFields.EVENT_ID, eventIds.toTypedArray()) } +internal fun TimelineEventEntity.Companion.where(realm: Realm, + roomId: String? = null, + type: String? = null, + linkFilterMode: EventEntity.LinkFilterMode = LINKED_ONLY): RealmQuery { + val query = realm.where() + if (roomId != null) { + query.equalTo(TimelineEventEntityFields.ROOM_ID, roomId) + } + if (type != null) { + query.equalTo(TimelineEventEntityFields.ROOT.TYPE, type) + } + return when (linkFilterMode) { + LINKED_ONLY -> query.equalTo(TimelineEventEntityFields.ROOT.IS_UNLINKED, false) + UNLINKED_ONLY -> query.equalTo(TimelineEventEntityFields.ROOT.IS_UNLINKED, true) + BOTH -> query + } +} + internal fun TimelineEventEntity.Companion.latestEvent(realm: Realm, roomId: String, @@ -51,9 +69,9 @@ internal fun TimelineEventEntity.Companion.latestEvent(realm: Realm, } val query = eventList?.where() if (includedTypes.isNotEmpty()) { - query?.`in`(EventEntityFields.TYPE, includedTypes.toTypedArray()) + query?.`in`(TimelineEventEntityFields.ROOT.TYPE, includedTypes.toTypedArray()) } else if (excludedTypes.isNotEmpty()) { - query?.not()?.`in`(EventEntityFields.TYPE, excludedTypes.toTypedArray()) + query?.not()?.`in`(TimelineEventEntityFields.ROOT.TYPE, excludedTypes.toTypedArray()) } return query ?.sort(TimelineEventEntityFields.ROOT.DISPLAY_INDEX, Sort.DESCENDING) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/EventsPruner.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/EventsPruner.kt index 53b72fa436..630332874d 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/EventsPruner.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/EventsPruner.kt @@ -22,6 +22,7 @@ import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.internal.database.RealmLiveEntityObserver import im.vector.matrix.android.internal.database.mapper.asDomain import im.vector.matrix.android.internal.database.model.EventEntity +import im.vector.matrix.android.internal.database.query.types import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.di.SessionDatabase import im.vector.matrix.android.internal.session.SessionScope @@ -41,7 +42,7 @@ internal class EventsPruner @Inject constructor(@SessionDatabase realmConfigurat private val taskExecutor: TaskExecutor) : RealmLiveEntityObserver(realmConfiguration) { - override val query = Monarchy.Query { EventEntity.where(it, type = EventType.REDACTION) } + override val query = Monarchy.Query { EventEntity.types(it, listOf(EventType.REDACTION)) } override fun processChanges(inserted: List, updated: List, deleted: List) { Timber.v("Event pruner called with ${inserted.size} insertions") diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultTimeline.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultTimeline.kt index 44d1808e1c..fc0eb2bc9b 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultTimeline.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultTimeline.kt @@ -27,12 +27,12 @@ import im.vector.matrix.android.api.util.addTo import im.vector.matrix.android.internal.crypto.NewSessionListener import im.vector.matrix.android.internal.crypto.model.event.EncryptedEventContent import im.vector.matrix.android.internal.database.mapper.asDomain +import im.vector.matrix.android.internal.database.model.* 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.EventAnnotationsSummaryEntity 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.model.RoomEntity +import im.vector.matrix.android.internal.database.model.TimelineEventEntity import im.vector.matrix.android.internal.database.query.findIncludingEvent import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoom import im.vector.matrix.android.internal.database.query.where @@ -91,7 +91,7 @@ internal class DefaultTimeline( private val cancelableBag = CancelableBag() private val debouncer = Debouncer(mainHandler) - private lateinit var liveEvents: RealmResults + private lateinit var liveEvents: RealmResults private var roomEntity: RoomEntity? = null private var prevDisplayIndex: Int = DISPLAY_INDEX_UNKNOWN @@ -105,7 +105,7 @@ internal class DefaultTimeline( private lateinit var eventRelations: RealmResults - private val eventsChangeListener = OrderedRealmCollectionChangeListener> { results, changeSet -> + private val eventsChangeListener = OrderedRealmCollectionChangeListener> { results, changeSet -> if (changeSet.state == OrderedCollectionChangeSet.State.INITIAL) { handleInitialLoad() } else { @@ -118,9 +118,9 @@ internal class DefaultTimeline( } changeSet.insertionRanges.forEach { range -> val (startDisplayIndex, direction) = if (range.startIndex == 0) { - Pair(liveEvents[range.length - 1]!!.displayIndex, Timeline.Direction.FORWARDS) + Pair(liveEvents[range.length - 1]!!.root!!.displayIndex, Timeline.Direction.FORWARDS) } else { - Pair(liveEvents[range.startIndex]!!.displayIndex, Timeline.Direction.BACKWARDS) + Pair(liveEvents[range.startIndex]!!.root!!.displayIndex, Timeline.Direction.BACKWARDS) } val state = getPaginationState(direction) if (state.isPaginating) { @@ -233,7 +233,7 @@ internal class DefaultTimeline( } liveEvents = buildEventQuery(realm) - .sort(EventEntityFields.DISPLAY_INDEX, Sort.DESCENDING) + .sort(TimelineEventEntityFields.ROOT.DISPLAY_INDEX, Sort.DESCENDING) .findAllAsync() .also { it.addChangeListener(eventsChangeListener) } @@ -268,13 +268,13 @@ internal class DefaultTimeline( private fun hasMoreInCache(direction: Timeline.Direction): Boolean { val localRealm = Realm.getInstance(realmConfiguration) - val eventEntity = buildEventQuery(localRealm).findFirst(direction) ?: return false + val timelineEventEntity = buildEventQuery(localRealm).findFirst(direction) ?: return false val hasMoreInCache = if (direction == Timeline.Direction.FORWARDS) { val firstEvent = builtEvents.firstOrNull() ?: return true - firstEvent.displayIndex < eventEntity.displayIndex + firstEvent.displayIndex < timelineEventEntity.root!!.displayIndex } else { val lastEvent = builtEvents.lastOrNull() ?: return true - lastEvent.displayIndex > eventEntity.displayIndex + lastEvent.displayIndex > timelineEventEntity.root!!.displayIndex } localRealm.close() return hasMoreInCache @@ -287,7 +287,7 @@ internal class DefaultTimeline( currentChunk.isLastForward } else { val eventEntity = buildEventQuery(localRealm).findFirst(direction) - currentChunk.isLastBackward || eventEntity?.type == EventType.STATE_ROOM_CREATE + currentChunk.isLastBackward || eventEntity?.root?.type == EventType.STATE_ROOM_CREATE } localRealm.close() return hasReachedEnd @@ -360,11 +360,11 @@ internal class DefaultTimeline( private fun handleInitialLoad() { var shouldFetchInitialEvent = false val initialDisplayIndex = if (isLive) { - liveEvents.firstOrNull()?.displayIndex + liveEvents.firstOrNull()?.root?.displayIndex } else { - val initialEvent = liveEvents.where().equalTo(EventEntityFields.EVENT_ID, initialEventId).findFirst() + val initialEvent = liveEvents.where().equalTo(TimelineEventEntityFields.EVENT_ID, initialEventId).findFirst() shouldFetchInitialEvent = initialEvent == null - initialEvent?.displayIndex + initialEvent?.root?.displayIndex } ?: DISPLAY_INDEX_UNKNOWN prevDisplayIndex = initialDisplayIndex @@ -448,14 +448,14 @@ internal class DefaultTimeline( if (offsetResults.isEmpty()) { return 0 } - val offsetIndex = offsetResults.last()!!.displayIndex + val offsetIndex = offsetResults.last()!!.root!!.displayIndex if (direction == Timeline.Direction.BACKWARDS) { prevDisplayIndex = offsetIndex - 1 } else { nextDisplayIndex = offsetIndex + 1 } offsetResults.forEach { eventEntity -> - val timelineEvent = timelineEventFactory.create(eventEntity, eventEntity.realm) + val timelineEvent = eventEntity.asDomain() val position = if (direction == Timeline.Direction.FORWARDS) 0 else builtEvents.size builtEvents.add(position, timelineEvent) //Need to shift :/ @@ -472,16 +472,16 @@ internal class DefaultTimeline( */ private fun getOffsetResults(startDisplayIndex: Int, direction: Timeline.Direction, - count: Long): RealmResults { + count: Long): RealmResults { val offsetQuery = liveEvents.where() if (direction == Timeline.Direction.BACKWARDS) { offsetQuery - .sort(EventEntityFields.DISPLAY_INDEX, Sort.DESCENDING) - .lessThanOrEqualTo(EventEntityFields.DISPLAY_INDEX, startDisplayIndex) + .sort(TimelineEventEntityFields.ROOT.DISPLAY_INDEX, Sort.DESCENDING) + .lessThanOrEqualTo(TimelineEventEntityFields.ROOT.DISPLAY_INDEX, startDisplayIndex) } else { offsetQuery - .sort(EventEntityFields.DISPLAY_INDEX, Sort.ASCENDING) - .greaterThanOrEqualTo(EventEntityFields.DISPLAY_INDEX, startDisplayIndex) + .sort(TimelineEventEntityFields.ROOT.DISPLAY_INDEX, Sort.ASCENDING) + .greaterThanOrEqualTo(TimelineEventEntityFields.ROOT.DISPLAY_INDEX, startDisplayIndex) } return offsetQuery .filterAllowedTypes() @@ -490,15 +490,15 @@ internal class DefaultTimeline( } - private fun buildEventQuery(realm: Realm): RealmQuery { + private fun buildEventQuery(realm: Realm): RealmQuery { return if (initialEventId == null) { - EventEntity + TimelineEventEntity .where(realm, roomId = roomId, linkFilterMode = EventEntity.LinkFilterMode.LINKED_ONLY) - .equalTo("${EventEntityFields.CHUNK}.${ChunkEntityFields.IS_LAST_FORWARD}", true) + .equalTo("${TimelineEventEntityFields.CHUNK}.${ChunkEntityFields.IS_LAST_FORWARD}", true) } else { - EventEntity + TimelineEventEntity .where(realm, roomId = roomId, linkFilterMode = EventEntity.LinkFilterMode.BOTH) - .`in`("${EventEntityFields.CHUNK}.${ChunkEntityFields.EVENTS.EVENT_ID}", arrayOf(initialEventId)) + .`in`("${TimelineEventEntityFields.CHUNK}.${ChunkEntityFields.TIMELINE_EVENTS.EVENT_ID}", arrayOf(initialEventId)) } } @@ -514,7 +514,7 @@ internal class DefaultTimeline( realm.executeTransaction { val unlinkedChunks = ChunkEntity .where(it, roomId = roomId) - .equalTo(ChunkEntityFields.EVENTS.IS_UNLINKED, true) + .equalTo("${ChunkEntityFields.TIMELINE_EVENTS.ROOT}.${EventEntityFields.IS_UNLINKED}", true) .findAll() unlinkedChunks.deleteAllFromRealm() } @@ -537,19 +537,19 @@ internal class DefaultTimeline( return if (this == Timeline.Direction.BACKWARDS) PaginationDirection.BACKWARDS else PaginationDirection.FORWARDS } - private fun RealmQuery.findFirst(direction: Timeline.Direction): EventEntity? { + private fun RealmQuery.findFirst(direction: Timeline.Direction): TimelineEventEntity? { return if (direction == Timeline.Direction.FORWARDS) { - sort(EventEntityFields.DISPLAY_INDEX, Sort.DESCENDING) + sort(TimelineEventEntityFields.ROOT.DISPLAY_INDEX, Sort.DESCENDING) } else { - sort(EventEntityFields.DISPLAY_INDEX, Sort.ASCENDING) + sort(TimelineEventEntityFields.ROOT.DISPLAY_INDEX, Sort.ASCENDING) } .filterAllowedTypes() .findFirst() } - private fun RealmQuery.filterAllowedTypes(): RealmQuery { + private fun RealmQuery.filterAllowedTypes(): RealmQuery { if (allowedTypes != null) { - `in`(EventEntityFields.TYPE, allowedTypes.toTypedArray()) + `in`(TimelineEventEntityFields.ROOT.TYPE, allowedTypes.toTypedArray()) } return this } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserEntityUpdater.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserEntityUpdater.kt index bfb9786d52..254381f6ac 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserEntityUpdater.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserEntityUpdater.kt @@ -21,6 +21,7 @@ import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.internal.database.RealmLiveEntityObserver 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.types import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.di.SessionDatabase import im.vector.matrix.android.internal.session.SessionScope @@ -38,7 +39,7 @@ internal class UserEntityUpdater @Inject constructor(@SessionDatabase realmConfi override val query = Monarchy.Query { EventEntity - .where(it, type = EventType.STATE_ROOM_MEMBER) + .types(it, listOf(EventType.STATE_ROOM_MEMBER)) .sort(EventEntityFields.STATE_INDEX, Sort.DESCENDING) .distinct(EventEntityFields.STATE_KEY)