Timeline/Sync: Fix some issues

This commit is contained in:
Ganard 2020-01-30 18:44:49 +01:00
parent 5e1b59f9d3
commit 759b680e63
11 changed files with 109 additions and 82 deletions

View File

@ -24,6 +24,8 @@ 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.EventEntityFields
import im.vector.matrix.android.internal.database.model.ReadReceiptEntity import im.vector.matrix.android.internal.database.model.ReadReceiptEntity
import im.vector.matrix.android.internal.database.model.ReadReceiptsSummaryEntity import im.vector.matrix.android.internal.database.model.ReadReceiptsSummaryEntity
import im.vector.matrix.android.internal.database.model.RoomMemberSummaryEntity
import im.vector.matrix.android.internal.database.model.RoomMemberSummaryEntityFields
import im.vector.matrix.android.internal.database.model.TimelineEventEntity import im.vector.matrix.android.internal.database.model.TimelineEventEntity
import im.vector.matrix.android.internal.database.model.TimelineEventEntityFields import im.vector.matrix.android.internal.database.model.TimelineEventEntityFields
import im.vector.matrix.android.internal.database.query.find import im.vector.matrix.android.internal.database.query.find
@ -31,8 +33,10 @@ import im.vector.matrix.android.internal.database.query.getOrCreate
import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.extensions.assertIsManaged import im.vector.matrix.android.internal.extensions.assertIsManaged
import im.vector.matrix.android.internal.session.room.timeline.PaginationDirection import im.vector.matrix.android.internal.session.room.timeline.PaginationDirection
import io.realm.Realm
import io.realm.Sort import io.realm.Sort
import io.realm.kotlin.createObject import io.realm.kotlin.createObject
import kotlinx.coroutines.coroutineScope
import timber.log.Timber import timber.log.Timber
internal fun ChunkEntity.deleteOnCascade() { internal fun ChunkEntity.deleteOnCascade() {
@ -43,6 +47,7 @@ internal fun ChunkEntity.deleteOnCascade() {
internal fun ChunkEntity.merge(roomId: String, chunkToMerge: ChunkEntity, direction: PaginationDirection) { internal fun ChunkEntity.merge(roomId: String, chunkToMerge: ChunkEntity, direction: PaginationDirection) {
assertIsManaged() assertIsManaged()
val localRealm = this.realm
val eventsToMerge: List<TimelineEventEntity> val eventsToMerge: List<TimelineEventEntity>
if (direction == PaginationDirection.FORWARDS) { if (direction == PaginationDirection.FORWARDS) {
this.nextToken = chunkToMerge.nextToken this.nextToken = chunkToMerge.nextToken
@ -59,15 +64,32 @@ internal fun ChunkEntity.merge(roomId: String, chunkToMerge: ChunkEntity, direct
return eventsToMerge return eventsToMerge
.forEach { .forEach {
if (timelineEvents.find(it.eventId) == null) { if (timelineEvents.find(it.eventId) == null) {
it.displayIndex = nextDisplayIndex(direction) val eventId = it.eventId
this.timelineEvents.add(it) if (timelineEvents.find(eventId) != null) {
return
}
val displayIndex = nextDisplayIndex(direction)
val localId = TimelineEventEntity.nextId(realm)
val copied = localRealm.createObject<TimelineEventEntity>().apply {
this.localId = localId
this.root = it.root
this.eventId = it.eventId
this.roomId = it.roomId
this.annotations = it.annotations
this.readReceipts = it.readReceipts
this.displayIndex = displayIndex
this.senderAvatar = it.senderAvatar
this.senderName = it.senderName
this.isUniqueDisplayName = it.isUniqueDisplayName
}
timelineEvents.add(copied)
} }
} }
} }
internal fun ChunkEntity.addStateEvent(roomId: String, stateEvent: EventEntity, direction: PaginationDirection) { internal fun ChunkEntity.addStateEvent(roomId: String, stateEvent: EventEntity, direction: PaginationDirection) {
if (direction == PaginationDirection.FORWARDS) { if (direction == PaginationDirection.BACKWARDS) {
Timber.v("We don't keep chunk state events when paginating forward") Timber.v("We don't keep chunk state events when paginating backward")
} else { } else {
val stateKey = stateEvent.stateKey ?: return val stateKey = stateEvent.stateKey ?: return
val type = stateEvent.type val type = stateEvent.type
@ -97,27 +119,8 @@ internal fun ChunkEntity.addTimelineEvent(roomId: String,
val localId = TimelineEventEntity.nextId(realm) val localId = TimelineEventEntity.nextId(realm)
val senderId = eventEntity.sender ?: "" val senderId = eventEntity.sender ?: ""
val readReceiptsSummaryEntity = ReadReceiptsSummaryEntity.where(realm, eventId).findFirst()
?: realm.createObject<ReadReceiptsSummaryEntity>(eventId).apply {
this.roomId = roomId
}
// Update RR for the sender of a new message with a dummy one // Update RR for the sender of a new message with a dummy one
val readReceiptsSummaryEntity = handleReadReceipts(realm, roomId, eventEntity, senderId)
val originServerTs = eventEntity.originServerTs
if (originServerTs != null) {
val timestampOfEvent = originServerTs.toDouble()
val readReceiptOfSender = ReadReceiptEntity.getOrCreate(realm, roomId = roomId, userId = senderId)
// If the synced RR is older, update
if (timestampOfEvent > readReceiptOfSender.originServerTs) {
val previousReceiptsSummary = ReadReceiptsSummaryEntity.where(realm, eventId = readReceiptOfSender.eventId).findFirst()
readReceiptOfSender.eventId = eventId
readReceiptOfSender.originServerTs = timestampOfEvent
previousReceiptsSummary?.readReceipts?.remove(readReceiptOfSender)
readReceiptsSummaryEntity.readReceipts.add(readReceiptOfSender)
}
}
val timelineEventEntity = realm.createObject<TimelineEventEntity>().apply { val timelineEventEntity = realm.createObject<TimelineEventEntity>().apply {
this.localId = localId this.localId = localId
this.root = eventEntity this.root = eventEntity
@ -126,19 +129,53 @@ internal fun ChunkEntity.addTimelineEvent(roomId: String,
this.annotations = EventAnnotationsSummaryEntity.where(realm, eventId).findFirst() this.annotations = EventAnnotationsSummaryEntity.where(realm, eventId).findFirst()
this.readReceipts = readReceiptsSummaryEntity this.readReceipts = readReceiptsSummaryEntity
this.displayIndex = displayIndex this.displayIndex = displayIndex
val roomMemberContent = roomMemberContentsByUser[senderId] val roomMemberContent = roomMemberContentsByUser[senderId]
val isUnique = roomMemberContentsByUser.values.find {
roomMemberContent != it &&
it?.displayName == roomMemberContent?.displayName
} == null
this.senderAvatar = roomMemberContent?.avatarUrl this.senderAvatar = roomMemberContent?.avatarUrl
this.senderName = roomMemberContent?.displayName this.senderName = roomMemberContent?.displayName
this.isUniqueDisplayName = isUnique if (roomMemberContent?.displayName != null) {
val isHistoricalUnique = roomMemberContentsByUser.values.find {
roomMemberContent != it &&
it?.displayName == roomMemberContent.displayName
} == null
isUniqueDisplayName = if (isLastForward) {
val isLiveUnique = RoomMemberSummaryEntity
.where(realm, roomId)
.equalTo(RoomMemberSummaryEntityFields.DISPLAY_NAME, roomMemberContent.displayName)
.findAll().none {
!roomMemberContentsByUser.containsKey(it.userId)
}
isHistoricalUnique && isLiveUnique
} else {
isHistoricalUnique
}
} else {
isUniqueDisplayName = true
}
} }
timelineEvents.add(timelineEventEntity) timelineEvents.add(timelineEventEntity)
} }
private fun handleReadReceipts(realm: Realm, roomId: String, eventEntity: EventEntity, senderId: String): ReadReceiptsSummaryEntity {
val readReceiptsSummaryEntity = ReadReceiptsSummaryEntity.where(realm, eventEntity.eventId).findFirst()
?: realm.createObject<ReadReceiptsSummaryEntity>(eventEntity.eventId).apply {
this.roomId = roomId
}
val originServerTs = eventEntity.originServerTs
if (originServerTs != null) {
val timestampOfEvent = originServerTs.toDouble()
val readReceiptOfSender = ReadReceiptEntity.getOrCreate(realm, roomId = roomId, userId = senderId)
// If the synced RR is older, update
if (timestampOfEvent > readReceiptOfSender.originServerTs) {
val previousReceiptsSummary = ReadReceiptsSummaryEntity.where(realm, eventId = readReceiptOfSender.eventId).findFirst()
readReceiptOfSender.eventId = eventEntity.eventId
readReceiptOfSender.originServerTs = timestampOfEvent
previousReceiptsSummary?.readReceipts?.remove(readReceiptOfSender)
readReceiptsSummaryEntity.readReceipts.add(readReceiptOfSender)
}
}
return readReceiptsSummaryEntity
}
internal fun ChunkEntity.nextDisplayIndex(direction: PaginationDirection): Int { internal fun ChunkEntity.nextDisplayIndex(direction: PaginationDirection): Int {
return when (direction) { return when (direction) {
PaginationDirection.FORWARDS -> { PaginationDirection.FORWARDS -> {

View File

@ -44,10 +44,14 @@ internal fun EventEntity.Companion.whereType(realm: Realm,
return query.equalTo(EventEntityFields.TYPE, type) return query.equalTo(EventEntityFields.TYPE, type)
} }
internal fun EventEntity.Companion.types(realm: Realm, internal fun EventEntity.Companion.whereTypes(realm: Realm,
typeList: List<String> = emptyList()): RealmQuery<EventEntity> { typeList: List<String> = emptyList(),
roomId: String? = null): RealmQuery<EventEntity> {
val query = realm.where<EventEntity>() val query = realm.where<EventEntity>()
query.`in`(EventEntityFields.TYPE, typeList.toTypedArray()) query.`in`(EventEntityFields.TYPE, typeList.toTypedArray())
if (roomId != null) {
query.equalTo(EventEntityFields.ROOM_ID, roomId)
}
return query return query
} }

View File

@ -38,17 +38,6 @@ internal fun TimelineEventEntity.Companion.whereRoomId(realm: Realm,
return realm.where<TimelineEventEntity>().equalTo(TimelineEventEntityFields.ROOM_ID, roomId) return realm.where<TimelineEventEntity>().equalTo(TimelineEventEntityFields.ROOM_ID, roomId)
} }
internal fun TimelineEventEntity.Companion.whereType(realm: Realm,
type: String,
roomId: String? = null): RealmQuery<TimelineEventEntity> {
val query = realm.where<TimelineEventEntity>()
query.equalTo(TimelineEventEntityFields.ROOT.TYPE, type)
if (roomId != null) {
query.equalTo(TimelineEventEntityFields.ROOM_ID, roomId)
}
return query
}
internal fun TimelineEventEntity.Companion.findWithSenderMembershipEvent(realm: Realm, senderMembershipEventId: String): List<TimelineEventEntity> { internal fun TimelineEventEntity.Companion.findWithSenderMembershipEvent(realm: Realm, senderMembershipEventId: String): List<TimelineEventEntity> {
return realm.where<TimelineEventEntity>() return realm.where<TimelineEventEntity>()
.equalTo(TimelineEventEntityFields.SENDER_MEMBERSHIP_EVENT_ID, senderMembershipEventId) .equalTo(TimelineEventEntityFields.SENDER_MEMBERSHIP_EVENT_ID, senderMembershipEventId)

View File

@ -20,7 +20,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.RealmLiveEntityObserver
import im.vector.matrix.android.internal.database.mapper.asDomain 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.model.EventEntity
import im.vector.matrix.android.internal.database.query.types import im.vector.matrix.android.internal.database.query.whereTypes
import im.vector.matrix.android.internal.di.SessionDatabase import im.vector.matrix.android.internal.di.SessionDatabase
import im.vector.matrix.android.internal.di.UserId import im.vector.matrix.android.internal.di.UserId
import io.realm.OrderedCollectionChangeSet import io.realm.OrderedCollectionChangeSet
@ -43,7 +43,7 @@ internal class EventRelationsAggregationUpdater @Inject constructor(
RealmLiveEntityObserver<EventEntity>(realmConfiguration) { RealmLiveEntityObserver<EventEntity>(realmConfiguration) {
override val query = Monarchy.Query<EventEntity> { override val query = Monarchy.Query<EventEntity> {
EventEntity.types(it, listOf( EventEntity.whereTypes(it, listOf(
EventType.MESSAGE, EventType.MESSAGE,
EventType.REDACTION, EventType.REDACTION,
EventType.REACTION, EventType.REACTION,

View File

@ -27,7 +27,7 @@ import im.vector.matrix.android.internal.database.awaitTransaction
import im.vector.matrix.android.internal.database.mapper.asDomain 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.model.EventEntity
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
import im.vector.matrix.android.internal.database.query.types import im.vector.matrix.android.internal.database.query.whereTypes
import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.di.SessionDatabase import im.vector.matrix.android.internal.di.SessionDatabase
import io.realm.OrderedCollectionChangeSet import io.realm.OrderedCollectionChangeSet
@ -41,7 +41,7 @@ internal class RoomCreateEventLiveObserver @Inject constructor(@SessionDatabase
: RealmLiveEntityObserver<EventEntity>(realmConfiguration) { : RealmLiveEntityObserver<EventEntity>(realmConfiguration) {
override val query = Monarchy.Query<EventEntity> { override val query = Monarchy.Query<EventEntity> {
EventEntity.types(it, listOf(EventType.STATE_ROOM_CREATE)) EventEntity.whereTypes(it, listOf(EventType.STATE_ROOM_CREATE))
} }
override fun onChange(results: RealmResults<EventEntity>, changeSet: OrderedCollectionChangeSet) { override fun onChange(results: RealmResults<EventEntity>, changeSet: OrderedCollectionChangeSet) {

View File

@ -21,7 +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.RealmLiveEntityObserver
import im.vector.matrix.android.internal.database.mapper.asDomain 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.model.EventEntity
import im.vector.matrix.android.internal.database.query.types import im.vector.matrix.android.internal.database.query.whereTypes
import im.vector.matrix.android.internal.di.SessionDatabase import im.vector.matrix.android.internal.di.SessionDatabase
import io.realm.OrderedCollectionChangeSet import io.realm.OrderedCollectionChangeSet
import io.realm.RealmConfiguration import io.realm.RealmConfiguration
@ -38,7 +38,7 @@ internal class EventsPruner @Inject constructor(@SessionDatabase realmConfigurat
private val pruneEventTask: PruneEventTask) : private val pruneEventTask: PruneEventTask) :
RealmLiveEntityObserver<EventEntity>(realmConfiguration) { RealmLiveEntityObserver<EventEntity>(realmConfiguration) {
override val query = Monarchy.Query<EventEntity> { EventEntity.types(it, listOf(EventType.REDACTION)) } override val query = Monarchy.Query<EventEntity> { EventEntity.whereTypes(it, listOf(EventType.REDACTION)) }
override fun onChange(results: RealmResults<EventEntity>, changeSet: OrderedCollectionChangeSet) { override fun onChange(results: RealmResults<EventEntity>, changeSet: OrderedCollectionChangeSet) {
Timber.v("Event pruner called with ${changeSet.insertions.size} insertions") Timber.v("Event pruner called with ${changeSet.insertions.size} insertions")

View File

@ -95,10 +95,12 @@ internal class DefaultPruneEventTask @Inject constructor(private val monarchy: M
// } // }
} }
} }
// TODO : make it work again. Maybe waits for SQL rework...
if (typeToPrune == EventType.STATE_ROOM_MEMBER && stateKey != null) { if (typeToPrune == EventType.STATE_ROOM_MEMBER && stateKey != null) {
TimelineEventEntity.findWithSenderMembershipEvent(realm, eventToPrune.eventId) TimelineEventEntity.findWithSenderMembershipEvent(realm, eventToPrune.eventId).forEach {
it.senderName = null
it.isUniqueDisplayName = false
it.senderAvatar = null
}
} }
} }

View File

@ -38,13 +38,12 @@ internal class DefaultGetContextOfEventTask @Inject constructor(
private val eventBus: EventBus private val eventBus: EventBus
) : GetContextOfEventTask { ) : GetContextOfEventTask {
override suspend fun execute(params: GetContextOfEventTask.Params): TokenChunkEventPersistor.Result { override suspend fun execute(params: GetContextOfEventTask.Params): TokenChunkEventPersistor.Result {
val filter = filterRepository.getRoomFilter() val filter = filterRepository.getRoomFilter()
val response = executeRequest<EventContextResponse>(eventBus) { val response = executeRequest<EventContextResponse>(eventBus) {
// We are limiting the response to the event with eventId to be sure we don't have any issue with potential merging process. // We are limiting the response to the event with eventId to be sure we don't have any issue with potential merging process.
apiCall = roomAPI.getContextOfEvent(params.roomId, params.eventId, 0, filter) apiCall = roomAPI.getContextOfEvent(params.roomId, params.eventId, 0, filter)
} }
return tokenChunkEventPersistor.insertInDb(response, params.roomId, PaginationDirection.BACKWARDS) return tokenChunkEventPersistor.insertInDb(response, params.roomId, PaginationDirection.FORWARDS)
} }
} }

View File

@ -38,6 +38,8 @@ import im.vector.matrix.android.internal.database.query.create
import im.vector.matrix.android.internal.database.query.find import im.vector.matrix.android.internal.database.query.find
import im.vector.matrix.android.internal.database.query.findAllIncludingEvents 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.findLastLiveChunkFromRoom
import im.vector.matrix.android.internal.database.query.getOrCreate
import im.vector.matrix.android.internal.database.query.getOrNull
import im.vector.matrix.android.internal.database.query.latestEvent import im.vector.matrix.android.internal.database.query.latestEvent
import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater
@ -195,21 +197,12 @@ internal class TokenChunkEventPersistor @Inject constructor(private val monarchy
val eventList = receivedChunk.events val eventList = receivedChunk.events
val stateEvents = receivedChunk.stateEvents val stateEvents = receivedChunk.stateEvents
realm.where(CurrentStateEventEntity::class.java)
.equalTo(CurrentStateEventEntityFields.ROOM_ID, roomId)
.equalTo(CurrentStateEventEntityFields.TYPE, EventType.STATE_ROOM_MEMBER)
.findAll()
.forEach {
val roomMember = ContentMapper.map(it.root?.content).toModel<RoomMemberContent>()
roomMemberContentsByUser[it.stateKey] = roomMember
}
for (stateEvent in stateEvents) { for (stateEvent in stateEvents) {
val stateEventEntity = stateEvent.toEntity(roomId, SendState.SYNCED).let { val stateEventEntity = stateEvent.toEntity(roomId, SendState.SYNCED).let {
realm.copyToRealmOrUpdate(it) realm.copyToRealmOrUpdate(it)
} }
currentChunk.addStateEvent(roomId, stateEventEntity, direction) currentChunk.addStateEvent(roomId, stateEventEntity, direction)
if (stateEvent.type == EventType.STATE_ROOM_MEMBER && stateEvent.stateKey != null && !stateEvent.isRedacted()) { if (stateEvent.type == EventType.STATE_ROOM_MEMBER && stateEvent.stateKey != null) {
roomMemberContentsByUser[stateEvent.stateKey] = stateEvent.content.toModel<RoomMemberContent>() roomMemberContentsByUser[stateEvent.stateKey] = stateEvent.content.toModel<RoomMemberContent>()
} }
} }
@ -222,14 +215,15 @@ internal class TokenChunkEventPersistor @Inject constructor(private val monarchy
val eventEntity = event.toEntity(roomId, SendState.SYNCED).let { val eventEntity = event.toEntity(roomId, SendState.SYNCED).let {
realm.copyToRealmOrUpdate(it) realm.copyToRealmOrUpdate(it)
} }
if (event.type == EventType.STATE_ROOM_MEMBER && event.stateKey != null && !event.isRedacted()) { if (event.type == EventType.STATE_ROOM_MEMBER && event.stateKey != null) {
val contentToUse = if (direction == PaginationDirection.FORWARDS) { val contentToUse = if (direction == PaginationDirection.BACKWARDS) {
event.content
} else {
event.prevContent event.prevContent
} else {
event.content
} }
roomMemberContentsByUser[event.stateKey] = contentToUse.toModel<RoomMemberContent>() roomMemberContentsByUser[event.stateKey] = contentToUse.toModel<RoomMemberContent>()
} }
currentChunk.addTimelineEvent(roomId, eventEntity, direction, roomMemberContentsByUser) currentChunk.addTimelineEvent(roomId, eventEntity, direction, roomMemberContentsByUser)
} }
val chunks = ChunkEntity.findAllIncludingEvents(realm, eventIds) val chunks = ChunkEntity.findAllIncludingEvents(realm, eventIds)
@ -240,8 +234,14 @@ internal class TokenChunkEventPersistor @Inject constructor(private val monarchy
chunksToDelete.add(it) chunksToDelete.add(it)
} }
} }
val shouldUpdateSummary = chunksToDelete.isNotEmpty() && currentChunk.isLastForward && direction == PaginationDirection.FORWARDS
chunksToDelete.forEach { chunksToDelete.forEach {
it.deleteFromRealm() it.deleteOnCascade()
}
if (shouldUpdateSummary) {
val roomSummaryEntity = RoomSummaryEntity.getOrCreate(realm, roomId)
val latestPreviewableEvent = TimelineEventEntity.latestEvent(realm, roomId, includesSending = true, filterTypes = RoomSummaryUpdater.PREVIEWABLE_TYPES)
roomSummaryEntity.latestPreviewableEvent = latestPreviewableEvent
} }
RoomEntity.where(realm, roomId).findFirst()?.addOrUpdate(currentChunk) RoomEntity.where(realm, roomId).findFirst()?.addOrUpdate(currentChunk)
} }

View File

@ -27,7 +27,7 @@ import im.vector.matrix.android.internal.database.awaitTransaction
import im.vector.matrix.android.internal.database.mapper.asDomain 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.model.EventEntity
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
import im.vector.matrix.android.internal.database.query.types import im.vector.matrix.android.internal.database.query.whereTypes
import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.di.SessionDatabase import im.vector.matrix.android.internal.di.SessionDatabase
import io.realm.OrderedCollectionChangeSet import io.realm.OrderedCollectionChangeSet
@ -41,7 +41,7 @@ internal class RoomTombstoneEventLiveObserver @Inject constructor(@SessionDataba
: RealmLiveEntityObserver<EventEntity>(realmConfiguration) { : RealmLiveEntityObserver<EventEntity>(realmConfiguration) {
override val query = Monarchy.Query<EventEntity> { override val query = Monarchy.Query<EventEntity> {
EventEntity.types(it, listOf(EventType.STATE_ROOM_TOMBSTONE)) EventEntity.whereTypes(it, listOf(EventType.STATE_ROOM_TOMBSTONE))
} }
override fun onChange(results: RealmResults<EventEntity>, changeSet: OrderedCollectionChangeSet) { override fun onChange(results: RealmResults<EventEntity>, changeSet: OrderedCollectionChangeSet) {

View File

@ -31,11 +31,11 @@ import im.vector.matrix.android.internal.database.mapper.ContentMapper
import im.vector.matrix.android.internal.database.mapper.toEntity import im.vector.matrix.android.internal.database.mapper.toEntity
import im.vector.matrix.android.internal.database.model.ChunkEntity import im.vector.matrix.android.internal.database.model.ChunkEntity
import im.vector.matrix.android.internal.database.model.CurrentStateEventEntity import im.vector.matrix.android.internal.database.model.CurrentStateEventEntity
import im.vector.matrix.android.internal.database.model.CurrentStateEventEntityFields
import im.vector.matrix.android.internal.database.model.RoomEntity import im.vector.matrix.android.internal.database.model.RoomEntity
import im.vector.matrix.android.internal.database.query.find import im.vector.matrix.android.internal.database.query.find
import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoom import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoom
import im.vector.matrix.android.internal.database.query.getOrCreate import im.vector.matrix.android.internal.database.query.getOrCreate
import im.vector.matrix.android.internal.database.query.getOrNull
import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService
import im.vector.matrix.android.internal.session.mapWithProgress import im.vector.matrix.android.internal.session.mapWithProgress
@ -218,15 +218,6 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
val eventIds = ArrayList<String>(eventList.size) val eventIds = ArrayList<String>(eventList.size)
val roomMemberContentsByUser = HashMap<String, RoomMemberContent?>() val roomMemberContentsByUser = HashMap<String, RoomMemberContent?>()
realm.where(CurrentStateEventEntity::class.java)
.equalTo(CurrentStateEventEntityFields.ROOM_ID, roomId)
.equalTo(CurrentStateEventEntityFields.TYPE, EventType.STATE_ROOM_MEMBER)
.findAll()
.forEach {
val roomMember = ContentMapper.map(it.root?.content).toModel<RoomMemberContent>()
roomMemberContentsByUser[it.stateKey] = roomMember
}
for (event in eventList) { for (event in eventList) {
if (event.eventId == null || event.senderId == null) { if (event.eventId == null || event.senderId == null) {
continue continue
@ -235,7 +226,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
val eventEntity = event.toEntity(roomId, SendState.SYNCED).let { val eventEntity = event.toEntity(roomId, SendState.SYNCED).let {
realm.copyToRealmOrUpdate(it) realm.copyToRealmOrUpdate(it)
} }
if (event.isStateEvent() && event.stateKey != null && !event.isRedacted()) { if (event.isStateEvent() && event.stateKey != null) {
CurrentStateEventEntity.getOrCreate(realm, roomId, event.stateKey, event.type).apply { CurrentStateEventEntity.getOrCreate(realm, roomId, event.stateKey, event.type).apply {
eventId = event.eventId eventId = event.eventId
root = eventEntity root = eventEntity
@ -245,6 +236,11 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
roomMemberEventHandler.handle(realm, roomEntity.roomId, event) roomMemberEventHandler.handle(realm, roomEntity.roomId, event)
} }
} }
roomMemberContentsByUser.getOrPut(event.senderId) {
// If we don't have any new state on this user, get it from db
val rootStateEvent = CurrentStateEventEntity.getOrNull(realm, roomId, event.senderId, EventType.STATE_ROOM_MEMBER)?.root
ContentMapper.map(rootStateEvent?.content).toModel()
}
chunkEntity.addTimelineEvent(roomId, eventEntity, PaginationDirection.FORWARDS, roomMemberContentsByUser) chunkEntity.addTimelineEvent(roomId, eventEntity, PaginationDirection.FORWARDS, roomMemberContentsByUser)
// Give info to crypto module // Give info to crypto module
cryptoService.onLiveEvent(roomEntity.roomId, event) cryptoService.onLiveEvent(roomEntity.roomId, event)