Timeline is back

This commit is contained in:
Valere 2019-07-05 17:00:13 +02:00
parent cbfd2af74b
commit f01e796271
5 changed files with 67 additions and 41 deletions

View file

@ -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)

View file

@ -37,6 +37,24 @@ internal fun TimelineEventEntity.Companion.where(realm: Realm, eventIds: List<St
return realm.where<TimelineEventEntity>().`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<TimelineEventEntity> {
val query = realm.where<TimelineEventEntity>()
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)

View file

@ -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<EventEntity>(realmConfiguration) {
override val query = Monarchy.Query<EventEntity> { EventEntity.where(it, type = EventType.REDACTION) }
override val query = Monarchy.Query<EventEntity> { EventEntity.types(it, listOf(EventType.REDACTION)) }
override fun processChanges(inserted: List<EventEntity>, updated: List<EventEntity>, deleted: List<EventEntity>) {
Timber.v("Event pruner called with ${inserted.size} insertions")

View file

@ -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<EventEntity>
private lateinit var liveEvents: RealmResults<TimelineEventEntity>
private var roomEntity: RoomEntity? = null
private var prevDisplayIndex: Int = DISPLAY_INDEX_UNKNOWN
@ -105,7 +105,7 @@ internal class DefaultTimeline(
private lateinit var eventRelations: RealmResults<EventAnnotationsSummaryEntity>
private val eventsChangeListener = OrderedRealmCollectionChangeListener<RealmResults<EventEntity>> { results, changeSet ->
private val eventsChangeListener = OrderedRealmCollectionChangeListener<RealmResults<TimelineEventEntity>> { 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<EventEntity> {
count: Long): RealmResults<TimelineEventEntity> {
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<EventEntity> {
private fun buildEventQuery(realm: Realm): RealmQuery<TimelineEventEntity> {
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<EventEntity>.findFirst(direction: Timeline.Direction): EventEntity? {
private fun RealmQuery<TimelineEventEntity>.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<EventEntity>.filterAllowedTypes(): RealmQuery<EventEntity> {
private fun RealmQuery<TimelineEventEntity>.filterAllowedTypes(): RealmQuery<TimelineEventEntity> {
if (allowedTypes != null) {
`in`(EventEntityFields.TYPE, allowedTypes.toTypedArray())
`in`(TimelineEventEntityFields.ROOT.TYPE, allowedTypes.toTypedArray())
}
return this
}

View file

@ -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> {
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)