mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2025-03-17 19:58:57 +03:00
Sync/pagination: get a working version
This commit is contained in:
parent
15b0bea870
commit
bf7c53ecab
13 changed files with 157 additions and 154 deletions
|
@ -26,10 +26,12 @@ 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.TimelineEventEntity
|
||||
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.getOrCreate
|
||||
import im.vector.matrix.android.internal.database.query.where
|
||||
import im.vector.matrix.android.internal.extensions.assertIsManaged
|
||||
import im.vector.matrix.android.internal.session.room.timeline.PaginationDirection
|
||||
import io.realm.Sort
|
||||
import io.realm.kotlin.createObject
|
||||
|
||||
internal fun ChunkEntity.deleteOnCascade() {
|
||||
|
@ -38,14 +40,38 @@ internal fun ChunkEntity.deleteOnCascade() {
|
|||
this.deleteFromRealm()
|
||||
}
|
||||
|
||||
internal fun ChunkEntity.merge(chunkToMerge: ChunkEntity, direction: PaginationDirection) {
|
||||
assertIsManaged()
|
||||
val eventsToMerge: List<TimelineEventEntity>
|
||||
if (direction == PaginationDirection.FORWARDS) {
|
||||
this.nextToken = chunkToMerge.nextToken
|
||||
this.isLastForward = chunkToMerge.isLastForward
|
||||
eventsToMerge = chunkToMerge.timelineEvents.sort(TimelineEventEntityFields.DISPLAY_INDEX, Sort.ASCENDING)
|
||||
} else {
|
||||
this.prevToken = chunkToMerge.prevToken
|
||||
this.isLastBackward = chunkToMerge.isLastBackward
|
||||
eventsToMerge = chunkToMerge.timelineEvents.sort(TimelineEventEntityFields.DISPLAY_INDEX, Sort.DESCENDING)
|
||||
}
|
||||
return eventsToMerge
|
||||
.forEach {
|
||||
if (timelineEvents.find(it.eventId) == null) {
|
||||
it.displayIndex = nextDisplayIndex(direction)
|
||||
this.timelineEvents.add(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun ChunkEntity.addTimelineEvent(roomId: String,
|
||||
eventEntity: EventEntity,
|
||||
direction: PaginationDirection,
|
||||
roomMemberEvent: Event?): TimelineEventEntity {
|
||||
roomMemberEvent: Event?) {
|
||||
|
||||
val eventId = eventEntity.eventId
|
||||
if (timelineEvents.find(eventId) != null) {
|
||||
return
|
||||
}
|
||||
val displayIndex = nextDisplayIndex(direction)
|
||||
val localId = TimelineEventEntity.nextId(realm)
|
||||
val eventId = eventEntity.eventId
|
||||
val senderId = eventEntity.sender ?: ""
|
||||
|
||||
val readReceiptsSummaryEntity = ReadReceiptsSummaryEntity.where(realm, eventId).findFirst()
|
||||
|
@ -69,24 +95,23 @@ internal fun ChunkEntity.addTimelineEvent(roomId: String,
|
|||
}
|
||||
}
|
||||
|
||||
val timelineEventEntity = TimelineEventEntity().also {
|
||||
it.localId = localId
|
||||
it.root = eventEntity
|
||||
it.eventId = eventId
|
||||
it.roomId = roomId
|
||||
it.annotations = EventAnnotationsSummaryEntity.where(realm, eventId).findFirst()
|
||||
it.readReceipts = readReceiptsSummaryEntity
|
||||
it.displayIndex = displayIndex
|
||||
}
|
||||
if (roomMemberEvent != null) {
|
||||
val roomMemberContent = roomMemberEvent.content.toModel<RoomMemberContent>()
|
||||
timelineEventEntity.senderAvatar = roomMemberContent?.avatarUrl
|
||||
timelineEventEntity.senderName = roomMemberContent?.displayName
|
||||
timelineEventEntity.isUniqueDisplayName = false
|
||||
timelineEventEntity.senderMembershipEventId = roomMemberEvent.eventId
|
||||
val timelineEventEntity = realm.createObject<TimelineEventEntity>().apply {
|
||||
this.localId = localId
|
||||
this.root = eventEntity
|
||||
this.eventId = eventId
|
||||
this.roomId = roomId
|
||||
this.annotations = EventAnnotationsSummaryEntity.where(realm, eventId).findFirst()
|
||||
this.readReceipts = readReceiptsSummaryEntity
|
||||
this.displayIndex = displayIndex
|
||||
if (roomMemberEvent != null) {
|
||||
val roomMemberContent = roomMemberEvent.content.toModel<RoomMemberContent>()
|
||||
this.senderAvatar = roomMemberContent?.avatarUrl
|
||||
this.senderName = roomMemberContent?.displayName
|
||||
this.isUniqueDisplayName = false
|
||||
this.senderMembershipEventId = roomMemberEvent.eventId
|
||||
}
|
||||
}
|
||||
timelineEvents.add(timelineEventEntity)
|
||||
return timelineEventEntity
|
||||
}
|
||||
|
||||
internal fun ChunkEntity.nextDisplayIndex(direction: PaginationDirection): Int {
|
||||
|
|
|
@ -26,9 +26,7 @@ internal open class ChunkEntity(@Index var prevToken: String? = null,
|
|||
@Index var nextToken: String? = null,
|
||||
var timelineEvents: RealmList<TimelineEventEntity> = RealmList(),
|
||||
@Index var isLastForward: Boolean = false,
|
||||
@Index var isLastBackward: Boolean = false,
|
||||
var backwardsDisplayIndex: Int? = null,
|
||||
var forwardsDisplayIndex: Int? = null
|
||||
@Index var isLastBackward: Boolean = false
|
||||
) : RealmObject() {
|
||||
|
||||
fun identifier() = "${prevToken}_$nextToken"
|
||||
|
|
|
@ -41,12 +41,6 @@ internal open class EventEntity(@PrimaryKey var eventId: String = "",
|
|||
var decryptionErrorCode: String? = null
|
||||
) : RealmObject() {
|
||||
|
||||
enum class LinkFilterMode {
|
||||
LINKED_ONLY,
|
||||
UNLINKED_ONLY,
|
||||
BOTH
|
||||
}
|
||||
|
||||
private var sendStateStr: String = SendState.UNKNOWN.name
|
||||
|
||||
var sendState: SendState
|
||||
|
@ -59,9 +53,6 @@ internal open class EventEntity(@PrimaryKey var eventId: String = "",
|
|||
|
||||
companion object
|
||||
|
||||
@LinkingObjects("root")
|
||||
val timelineEventEntity: RealmResults<TimelineEventEntity>? = null
|
||||
|
||||
fun setDecryptionResult(result: MXEventDecryptionResult) {
|
||||
val decryptionResult = OlmDecryptionResult(
|
||||
payload = result.clearEvent,
|
||||
|
@ -72,6 +63,5 @@ internal open class EventEntity(@PrimaryKey var eventId: String = "",
|
|||
val adapter = MoshiProvider.providesMoshi().adapter<OlmDecryptionResult>(OlmDecryptionResult::class.java)
|
||||
decryptionResultJson = adapter.toJson(decryptionResult)
|
||||
decryptionErrorCode = null
|
||||
timelineEventEntity?.firstOrNull()?.root = this
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ import io.realm.annotations.LinkingObjects
|
|||
import io.realm.annotations.PrimaryKey
|
||||
|
||||
internal open class TimelineEventEntity(var localId: Long = 0,
|
||||
@PrimaryKey var eventId: String = "",
|
||||
@Index var eventId: String = "",
|
||||
@Index var roomId: String = "",
|
||||
@Index var displayIndex: Int = 0,
|
||||
var root: EventEntity? = null,
|
||||
|
|
|
@ -17,12 +17,10 @@
|
|||
package im.vector.matrix.android.internal.database.query
|
||||
|
||||
import im.vector.matrix.android.internal.database.model.EventEntity
|
||||
import im.vector.matrix.android.internal.database.model.EventEntity.LinkFilterMode.*
|
||||
import im.vector.matrix.android.internal.database.model.EventEntityFields
|
||||
import io.realm.Realm
|
||||
import io.realm.RealmList
|
||||
import io.realm.RealmQuery
|
||||
import io.realm.Sort
|
||||
import io.realm.kotlin.where
|
||||
|
||||
internal fun EventEntity.Companion.where(realm: Realm, eventId: String): RealmQuery<EventEntity> {
|
||||
|
|
|
@ -18,7 +18,6 @@ package im.vector.matrix.android.internal.database.query
|
|||
|
||||
import im.vector.matrix.android.api.session.room.send.SendState
|
||||
import im.vector.matrix.android.internal.database.model.*
|
||||
import im.vector.matrix.android.internal.database.model.EventEntity.LinkFilterMode.*
|
||||
import io.realm.*
|
||||
import io.realm.kotlin.where
|
||||
|
||||
|
|
|
@ -129,9 +129,6 @@ internal abstract class RoomModule {
|
|||
@Binds
|
||||
abstract fun bindGetContextOfEventTask(task: DefaultGetContextOfEventTask): GetContextOfEventTask
|
||||
|
||||
@Binds
|
||||
abstract fun bindClearUnlinkedEventsTask(task: DefaultClearUnlinkedEventsTask): ClearUnlinkedEventsTask
|
||||
|
||||
@Binds
|
||||
abstract fun bindPaginationTask(task: DefaultPaginationTask): PaginationTask
|
||||
|
||||
|
|
|
@ -48,21 +48,23 @@ internal class RoomSummaryUpdater @Inject constructor(
|
|||
private val monarchy: Monarchy) {
|
||||
|
||||
// TODO: maybe allow user of SDK to give that list
|
||||
private val PREVIEWABLE_TYPES = listOf(
|
||||
EventType.MESSAGE,
|
||||
EventType.STATE_ROOM_NAME,
|
||||
EventType.STATE_ROOM_TOPIC,
|
||||
EventType.STATE_ROOM_MEMBER,
|
||||
EventType.STATE_ROOM_HISTORY_VISIBILITY,
|
||||
EventType.CALL_INVITE,
|
||||
EventType.CALL_HANGUP,
|
||||
EventType.CALL_ANSWER,
|
||||
EventType.ENCRYPTED,
|
||||
EventType.STATE_ROOM_ENCRYPTION,
|
||||
EventType.STATE_ROOM_THIRD_PARTY_INVITE,
|
||||
EventType.STICKER,
|
||||
EventType.STATE_ROOM_CREATE
|
||||
)
|
||||
companion object {
|
||||
val PREVIEWABLE_TYPES = listOf(
|
||||
EventType.MESSAGE,
|
||||
EventType.STATE_ROOM_NAME,
|
||||
EventType.STATE_ROOM_TOPIC,
|
||||
EventType.STATE_ROOM_MEMBER,
|
||||
EventType.STATE_ROOM_HISTORY_VISIBILITY,
|
||||
EventType.CALL_INVITE,
|
||||
EventType.CALL_HANGUP,
|
||||
EventType.CALL_ANSWER,
|
||||
EventType.ENCRYPTED,
|
||||
EventType.STATE_ROOM_ENCRYPTION,
|
||||
EventType.STATE_ROOM_THIRD_PARTY_INVITE,
|
||||
EventType.STICKER,
|
||||
EventType.STATE_ROOM_CREATE
|
||||
)
|
||||
}
|
||||
|
||||
fun update(realm: Realm,
|
||||
roomId: String,
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
|
||||
* Copyright 2019 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
|
||||
*/
|
||||
package im.vector.matrix.android.internal.session.room.timeline
|
||||
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import im.vector.matrix.android.internal.database.helper.deleteOnCascade
|
||||
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.query.where
|
||||
import im.vector.matrix.android.internal.task.Task
|
||||
import im.vector.matrix.android.internal.util.awaitTransaction
|
||||
import javax.inject.Inject
|
||||
|
||||
internal interface ClearUnlinkedEventsTask : Task<ClearUnlinkedEventsTask.Params, Unit> {
|
||||
|
||||
data class Params(val roomId: String)
|
||||
}
|
||||
|
||||
internal class DefaultClearUnlinkedEventsTask @Inject constructor() : ClearUnlinkedEventsTask {
|
||||
|
||||
override suspend fun execute(params: ClearUnlinkedEventsTask.Params) {
|
||||
return
|
||||
/*monarchy.awaitTransaction { localRealm ->
|
||||
val unlinkedChunks = ChunkEntity
|
||||
.where(localRealm, roomId = params.roomId)
|
||||
.findAll()
|
||||
unlinkedChunks.forEach {
|
||||
it.deleteOnCascade()
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
|
@ -27,8 +27,7 @@ internal interface GetContextOfEventTask : Task<GetContextOfEventTask.Params, To
|
|||
|
||||
data class Params(
|
||||
val roomId: String,
|
||||
val eventId: String,
|
||||
val limit: Int
|
||||
val eventId: String
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -39,10 +38,12 @@ internal class DefaultGetContextOfEventTask @Inject constructor(
|
|||
private val eventBus: EventBus
|
||||
) : GetContextOfEventTask {
|
||||
|
||||
|
||||
override suspend fun execute(params: GetContextOfEventTask.Params): TokenChunkEventPersistor.Result {
|
||||
val filter = filterRepository.getRoomFilter()
|
||||
val response = executeRequest<EventContextResponse>(eventBus) {
|
||||
apiCall = roomAPI.getContextOfEvent(params.roomId, params.eventId, params.limit, filter)
|
||||
// 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, 1, filter)
|
||||
}
|
||||
return tokenChunkEventPersistor.insertInDb(response, params.roomId, PaginationDirection.BACKWARDS)
|
||||
}
|
||||
|
|
|
@ -71,7 +71,6 @@ internal class DefaultTimeline(
|
|||
private val realmConfiguration: RealmConfiguration,
|
||||
private val taskExecutor: TaskExecutor,
|
||||
private val contextOfEventTask: GetContextOfEventTask,
|
||||
private val clearUnlinkedEventsTask: ClearUnlinkedEventsTask,
|
||||
private val paginationTask: PaginationTask,
|
||||
private val cryptoService: CryptoService,
|
||||
private val timelineEventMapper: TimelineEventMapper,
|
||||
|
@ -225,9 +224,6 @@ internal class DefaultTimeline(
|
|||
}
|
||||
eventDecryptor.destroy()
|
||||
}
|
||||
clearUnlinkedEventsTask
|
||||
.configureWith(ClearUnlinkedEventsTask.Params(roomId))
|
||||
.executeBy(taskExecutor)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -653,7 +649,7 @@ internal class DefaultTimeline(
|
|||
}
|
||||
|
||||
private fun fetchEvent(eventId: String) {
|
||||
val params = GetContextOfEventTask.Params(roomId, eventId, settings.initialSize)
|
||||
val params = GetContextOfEventTask.Params(roomId, eventId)
|
||||
cancelableBag += contextOfEventTask.configureWith(params) {
|
||||
callback = object : MatrixCallback<TokenChunkEventPersistor.Result> {
|
||||
override fun onFailure(failure: Throwable) {
|
||||
|
|
|
@ -44,8 +44,7 @@ internal class DefaultTimelineService @AssistedInject constructor(@Assisted priv
|
|||
private val cryptoService: CryptoService,
|
||||
private val paginationTask: PaginationTask,
|
||||
private val timelineEventMapper: TimelineEventMapper,
|
||||
private val readReceiptsSummaryMapper: ReadReceiptsSummaryMapper,
|
||||
private val clearUnlinkedEventsTask: ClearUnlinkedEventsTask
|
||||
private val readReceiptsSummaryMapper: ReadReceiptsSummaryMapper
|
||||
) : TimelineService {
|
||||
|
||||
@AssistedInject.Factory
|
||||
|
@ -60,7 +59,6 @@ internal class DefaultTimelineService @AssistedInject constructor(@Assisted priv
|
|||
realmConfiguration = monarchy.realmConfiguration,
|
||||
taskExecutor = taskExecutor,
|
||||
contextOfEventTask = contextOfEventTask,
|
||||
clearUnlinkedEventsTask = clearUnlinkedEventsTask,
|
||||
paginationTask = paginationTask,
|
||||
cryptoService = cryptoService,
|
||||
timelineEventMapper = timelineEventMapper,
|
||||
|
|
|
@ -22,17 +22,27 @@ 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.helper.addOrUpdate
|
||||
import im.vector.matrix.android.internal.database.helper.addTimelineEvent
|
||||
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.mapper.asDomain
|
||||
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.CurrentStateEventEntity
|
||||
import im.vector.matrix.android.internal.database.model.EventEntity
|
||||
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.model.TimelineEventEntity
|
||||
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.findAllIncludingEvents
|
||||
import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoom
|
||||
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.where
|
||||
import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater
|
||||
import im.vector.matrix.android.internal.util.awaitTransaction
|
||||
import io.realm.Realm
|
||||
import io.realm.RealmList
|
||||
import io.realm.kotlin.createObject
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
@ -117,8 +127,6 @@ internal class TokenChunkEventPersistor @Inject constructor(private val monarchy
|
|||
monarchy
|
||||
.awaitTransaction { realm ->
|
||||
Timber.v("Start persisting ${receivedChunk.events.size} events in $roomId towards $direction")
|
||||
val roomEntity = RoomEntity.where(realm, roomId).findFirst()
|
||||
?: realm.createObject(roomId)
|
||||
|
||||
val nextToken: String?
|
||||
val prevToken: String?
|
||||
|
@ -144,47 +152,9 @@ internal class TokenChunkEventPersistor @Inject constructor(private val monarchy
|
|||
?: ChunkEntity.create(realm, prevToken, nextToken)
|
||||
|
||||
if (receivedChunk.events.isEmpty() && receivedChunk.end == receivedChunk.start) {
|
||||
Timber.v("Reach end of $roomId")
|
||||
currentChunk.isLastBackward = true
|
||||
handleReachEnd(realm, roomId, direction, currentChunk)
|
||||
} else {
|
||||
Timber.v("Add ${receivedChunk.events.size} events in chunk(${currentChunk.nextToken} | ${currentChunk.prevToken}")
|
||||
val roomMemberEventsByUser = HashMap<String, Event?>()
|
||||
val eventList = if (direction == PaginationDirection.FORWARDS) {
|
||||
receivedChunk.events
|
||||
} else {
|
||||
receivedChunk.events.asReversed()
|
||||
}
|
||||
val stateEvents = receivedChunk.stateEvents
|
||||
for (stateEvent in stateEvents) {
|
||||
if (stateEvent.type == EventType.STATE_ROOM_MEMBER && stateEvent.stateKey != null && !stateEvent.isRedacted()) {
|
||||
roomMemberEventsByUser[stateEvent.stateKey] = stateEvent
|
||||
}
|
||||
}
|
||||
val eventEntities = ArrayList<EventEntity>(eventList.size)
|
||||
for (event in eventList) {
|
||||
if (event.eventId == null || event.senderId == null) {
|
||||
continue
|
||||
}
|
||||
val eventEntity = event.toEntity(roomId, SendState.SYNCED).also {
|
||||
realm.copyToRealmOrUpdate(it)
|
||||
}
|
||||
if(direction == PaginationDirection.FORWARDS){
|
||||
eventEntities.add(eventEntity)
|
||||
}else {
|
||||
eventEntities.add(0, eventEntity)
|
||||
}
|
||||
if (event.type == EventType.STATE_ROOM_MEMBER && event.stateKey != null && !event.isRedacted()) {
|
||||
roomMemberEventsByUser[event.stateKey] = event
|
||||
}
|
||||
}
|
||||
for (eventEntity in eventEntities) {
|
||||
val senderId = eventEntity.sender ?: continue
|
||||
val roomMemberEvent = roomMemberEventsByUser.getOrPut(senderId) {
|
||||
CurrentStateEventEntity.getOrNull(realm, roomId, senderId, EventType.STATE_ROOM_MEMBER)?.root?.asDomain()
|
||||
}
|
||||
currentChunk.addTimelineEvent(roomId, eventEntity, direction, roomMemberEvent)
|
||||
}
|
||||
roomEntity.addOrUpdate(currentChunk)
|
||||
handlePagination(realm, roomId, direction, receivedChunk, currentChunk)
|
||||
}
|
||||
}
|
||||
return if (receivedChunk.events.isEmpty()) {
|
||||
|
@ -197,4 +167,81 @@ internal class TokenChunkEventPersistor @Inject constructor(private val monarchy
|
|||
Result.SUCCESS
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleReachEnd(realm: Realm, roomId: String, direction: PaginationDirection, currentChunk: ChunkEntity) {
|
||||
Timber.v("Reach end of $roomId")
|
||||
if (direction == PaginationDirection.FORWARDS) {
|
||||
val currentLiveChunk = ChunkEntity.findLastLiveChunkFromRoom(realm, roomId)
|
||||
if (currentChunk != currentLiveChunk) {
|
||||
currentChunk.isLastForward = true
|
||||
currentLiveChunk?.deleteOnCascade()
|
||||
RoomSummaryEntity.where(realm, roomId).findFirst()?.apply {
|
||||
latestPreviewableEvent = TimelineEventEntity.latestEvent(realm, roomId, includesSending = true, filterTypes = RoomSummaryUpdater.PREVIEWABLE_TYPES)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
currentChunk.isLastBackward = true
|
||||
}
|
||||
}
|
||||
|
||||
private fun handlePagination(
|
||||
realm: Realm,
|
||||
roomId: String,
|
||||
direction: PaginationDirection,
|
||||
receivedChunk: TokenChunkEvent,
|
||||
currentChunk: ChunkEntity
|
||||
) {
|
||||
Timber.v("Add ${receivedChunk.events.size} events in chunk(${currentChunk.nextToken} | ${currentChunk.prevToken}")
|
||||
val roomMemberEventsByUser = HashMap<String, Event?>()
|
||||
val eventList = if (direction == PaginationDirection.FORWARDS) {
|
||||
receivedChunk.events
|
||||
} else {
|
||||
receivedChunk.events.asReversed()
|
||||
}
|
||||
val stateEvents = receivedChunk.stateEvents
|
||||
for (stateEvent in stateEvents) {
|
||||
if (stateEvent.type == EventType.STATE_ROOM_MEMBER && stateEvent.stateKey != null && !stateEvent.isRedacted()) {
|
||||
roomMemberEventsByUser[stateEvent.stateKey] = stateEvent
|
||||
}
|
||||
}
|
||||
val eventIds = ArrayList<String>(eventList.size)
|
||||
val eventEntities = ArrayList<EventEntity>(eventList.size)
|
||||
for (event in eventList) {
|
||||
if (event.eventId == null || event.senderId == null) {
|
||||
continue
|
||||
}
|
||||
eventIds.add(event.eventId)
|
||||
val eventEntity = event.toEntity(roomId, SendState.SYNCED).let {
|
||||
realm.copyToRealmOrUpdate(it)
|
||||
}
|
||||
if (direction == PaginationDirection.FORWARDS) {
|
||||
eventEntities.add(eventEntity)
|
||||
} else {
|
||||
eventEntities.add(0, eventEntity)
|
||||
}
|
||||
if (event.type == EventType.STATE_ROOM_MEMBER && event.stateKey != null && !event.isRedacted()) {
|
||||
roomMemberEventsByUser[event.stateKey] = event
|
||||
}
|
||||
}
|
||||
for (eventEntity in eventEntities) {
|
||||
val senderId = eventEntity.sender ?: continue
|
||||
val roomMemberEvent = roomMemberEventsByUser.getOrPut(senderId) {
|
||||
CurrentStateEventEntity.getOrNull(realm, roomId, senderId, EventType.STATE_ROOM_MEMBER)?.root?.asDomain()
|
||||
}
|
||||
currentChunk.addTimelineEvent(roomId, eventEntity, direction, roomMemberEvent)
|
||||
}
|
||||
|
||||
val chunks = ChunkEntity.findAllIncludingEvents(realm, eventIds)
|
||||
val chunksToDelete = ArrayList<ChunkEntity>()
|
||||
chunks.forEach {
|
||||
if (it != currentChunk) {
|
||||
currentChunk.merge(it, direction)
|
||||
chunksToDelete.add(it)
|
||||
}
|
||||
}
|
||||
chunksToDelete.forEach {
|
||||
it.deleteFromRealm()
|
||||
}
|
||||
RoomEntity.where(realm, roomId).findFirst()?.addOrUpdate(currentChunk)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue