Load RR when opening a timeline

This commit is contained in:
Benoit Marty 2021-03-11 22:24:23 +01:00 committed by Benoit Marty
parent 3777b00ad7
commit fe39c92e25
4 changed files with 54 additions and 64 deletions

View File

@ -44,6 +44,7 @@ import org.matrix.android.sdk.internal.database.query.findAllInRoomWithSendState
import org.matrix.android.sdk.internal.database.query.where import org.matrix.android.sdk.internal.database.query.where
import org.matrix.android.sdk.internal.database.query.whereRoomId import org.matrix.android.sdk.internal.database.query.whereRoomId
import org.matrix.android.sdk.internal.session.room.membership.LoadRoomMembersTask import org.matrix.android.sdk.internal.session.room.membership.LoadRoomMembersTask
import org.matrix.android.sdk.internal.session.sync.ReadReceiptHandler
import org.matrix.android.sdk.internal.task.TaskExecutor import org.matrix.android.sdk.internal.task.TaskExecutor
import org.matrix.android.sdk.internal.task.configureWith import org.matrix.android.sdk.internal.task.configureWith
import org.matrix.android.sdk.internal.util.Debouncer import org.matrix.android.sdk.internal.util.Debouncer
@ -73,7 +74,8 @@ internal class DefaultTimeline(
private val timelineInput: TimelineInput, private val timelineInput: TimelineInput,
private val eventDecryptor: TimelineEventDecryptor, private val eventDecryptor: TimelineEventDecryptor,
private val realmSessionProvider: RealmSessionProvider, private val realmSessionProvider: RealmSessionProvider,
private val loadRoomMembersTask: LoadRoomMembersTask private val loadRoomMembersTask: LoadRoomMembersTask,
private val readReceiptHandler: ReadReceiptHandler
) : Timeline, ) : Timeline,
TimelineHiddenReadReceipts.Delegate, TimelineHiddenReadReceipts.Delegate,
TimelineInput.Listener, TimelineInput.Listener,
@ -182,11 +184,26 @@ internal class DefaultTimeline(
} }
.executeBy(taskExecutor) .executeBy(taskExecutor)
// Ensure ReadReceipt from init sync are loaded
ensureReadReceiptAreLoaded(realm)
isReady.set(true) isReady.set(true)
} }
} }
} }
private fun ensureReadReceiptAreLoaded(realm: Realm) {
readReceiptHandler.getContentFromInitSync(roomId)
?.also {
Timber.w("INIT_SYNC Insert when opening timeline RR for room $roomId")
}
?.let { readReceiptContent ->
realm.executeTransactionAsync {
readReceiptHandler.handle(it, roomId, readReceiptContent, true)
}
}
}
private fun TimelineSettings.shouldHandleHiddenReadReceipts(): Boolean { private fun TimelineSettings.shouldHandleHiddenReadReceipts(): Boolean {
return buildReadReceipts && (filters.filterEdits || filters.filterTypes) return buildReadReceipts && (filters.filterEdits || filters.filterTypes)
} }

View File

@ -17,10 +17,10 @@
package org.matrix.android.sdk.internal.session.room.timeline package org.matrix.android.sdk.internal.session.room.timeline
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import dagger.assisted.AssistedFactory
import com.zhuinden.monarchy.Monarchy import com.zhuinden.monarchy.Monarchy
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import io.realm.Sort import io.realm.Sort
import io.realm.kotlin.where import io.realm.kotlin.where
import org.matrix.android.sdk.api.session.events.model.isImageMessage import org.matrix.android.sdk.api.session.events.model.isImageMessage
@ -38,20 +38,23 @@ import org.matrix.android.sdk.internal.database.model.TimelineEventEntityFields
import org.matrix.android.sdk.internal.database.query.where import org.matrix.android.sdk.internal.database.query.where
import org.matrix.android.sdk.internal.di.SessionDatabase import org.matrix.android.sdk.internal.di.SessionDatabase
import org.matrix.android.sdk.internal.session.room.membership.LoadRoomMembersTask import org.matrix.android.sdk.internal.session.room.membership.LoadRoomMembersTask
import org.matrix.android.sdk.internal.session.sync.ReadReceiptHandler
import org.matrix.android.sdk.internal.task.TaskExecutor import org.matrix.android.sdk.internal.task.TaskExecutor
internal class DefaultTimelineService @AssistedInject constructor(@Assisted private val roomId: String, internal class DefaultTimelineService @AssistedInject constructor(
@SessionDatabase private val monarchy: Monarchy, @Assisted private val roomId: String,
private val realmSessionProvider: RealmSessionProvider, @SessionDatabase private val monarchy: Monarchy,
private val timelineInput: TimelineInput, private val realmSessionProvider: RealmSessionProvider,
private val taskExecutor: TaskExecutor, private val timelineInput: TimelineInput,
private val contextOfEventTask: GetContextOfEventTask, private val taskExecutor: TaskExecutor,
private val eventDecryptor: TimelineEventDecryptor, private val contextOfEventTask: GetContextOfEventTask,
private val paginationTask: PaginationTask, private val eventDecryptor: TimelineEventDecryptor,
private val fetchTokenAndPaginateTask: FetchTokenAndPaginateTask, private val paginationTask: PaginationTask,
private val timelineEventMapper: TimelineEventMapper, private val fetchTokenAndPaginateTask: FetchTokenAndPaginateTask,
private val readReceiptsSummaryMapper: ReadReceiptsSummaryMapper, private val timelineEventMapper: TimelineEventMapper,
private val loadRoomMembersTask: LoadRoomMembersTask private val readReceiptsSummaryMapper: ReadReceiptsSummaryMapper,
private val loadRoomMembersTask: LoadRoomMembersTask,
private val readReceiptHandler: ReadReceiptHandler
) : TimelineService { ) : TimelineService {
@AssistedFactory @AssistedFactory
@ -74,7 +77,8 @@ internal class DefaultTimelineService @AssistedInject constructor(@Assisted priv
eventDecryptor = eventDecryptor, eventDecryptor = eventDecryptor,
fetchTokenAndPaginateTask = fetchTokenAndPaginateTask, fetchTokenAndPaginateTask = fetchTokenAndPaginateTask,
realmSessionProvider = realmSessionProvider, realmSessionProvider = realmSessionProvider,
loadRoomMembersTask = loadRoomMembersTask loadRoomMembersTask = loadRoomMembersTask,
readReceiptHandler = readReceiptHandler
) )
} }

View File

@ -90,55 +90,11 @@ internal class ReadReceiptHandler @Inject constructor(
realm.insertOrUpdate(readReceiptSummaries) realm.insertOrUpdate(readReceiptSummaries)
} }
/**
* Example of content:
*
* <pre>
* {
* "type": "m.receipt",
* "content": {
* "$ofZhdeinmEReG_X-agD3J2TIhosEPkuvl62HJ8pVMMs": {
* "m.read": {
* "@benoit.marty:matrix.org": {
* "ts": 1610468193999
* }
* }
* },
* "$ZMa_qwE_w_ZOj_vAxv7JuJeHCQfYzuQblmIZxkYmNMs": {
* "m.read": {
* "@benoitx:matrix.org": {
* "ts": 1610468049579
* },
* "@benoit.marty:matrix.org": {
* "ts": 1609156029466
* }
* }
* }
* }
* }
* </pre>
*/
private fun incrementalSyncStrategy(realm: Realm, roomId: String, content: ReadReceiptContent) { private fun incrementalSyncStrategy(realm: Realm, roomId: String, content: ReadReceiptContent) {
// First check if we have data from init sync to handle // First check if we have data from init sync to handle
// TODO Rename contentFromInitSync getContentFromInitSync(roomId)?.let {
val initSyncContent = roomSyncEphemeralTemporaryStore.read(roomId) Timber.w("INIT_SYNC Insert during incremental sync RR for room $roomId")
?.events
?.firstOrNull { it.type == EventType.RECEIPT }
?.let {
@Suppress("UNCHECKED_CAST")
it.content as? ReadReceiptContent
}
?.also {
Timber.w("INIT_SYNC Copy RR for room $roomId")
}
initSyncContent?.let {
Timber.w("BOOK Copy RR for room $roomId")
// TODO Merge with data we just received
// TODO Store that when we enter the timeline
initialSyncStrategy(realm, roomId, it) initialSyncStrategy(realm, roomId, it)
roomSyncEphemeralTemporaryStore.delete(roomId)
} }
for ((eventId, receiptDict) in content) { for ((eventId, receiptDict) in content) {
@ -163,4 +119,17 @@ internal class ReadReceiptHandler @Inject constructor(
} }
} }
} }
fun getContentFromInitSync(roomId: String): ReadReceiptContent? {
return roomSyncEphemeralTemporaryStore.read(roomId)
?.events
?.firstOrNull { it.type == EventType.RECEIPT }
?.let {
@Suppress("UNCHECKED_CAST")
it.content as? ReadReceiptContent
}
?.also {
roomSyncEphemeralTemporaryStore.delete(roomId)
}
}
} }

View File

@ -45,7 +45,7 @@ internal class RoomSyncEphemeralTemporaryStoreFile @Inject constructor(
* Write RoomSyncEphemeral to a file * Write RoomSyncEphemeral to a file
*/ */
override fun write(roomId: String, roomSyncEphemeralJson: String) { override fun write(roomId: String, roomSyncEphemeralJson: String) {
Timber.w("INIT_SYNC Store RR for room $roomId") Timber.w("INIT_SYNC Store ephemeral events for room $roomId")
getFile(roomId).writeText(roomSyncEphemeralJson) getFile(roomId).writeText(roomSyncEphemeralJson)
} }