Timeline: continue trying to make Read marker/receipts working
This commit is contained in:
parent
92a37f15d4
commit
52df50a686
@ -44,6 +44,10 @@ data class TimelineEvent(
|
||||
*/
|
||||
val localId: Long,
|
||||
val eventId: String,
|
||||
/**
|
||||
* This display index is the position in the current chunk.
|
||||
* It's not unique on the timeline as it's reset on each chunk.
|
||||
*/
|
||||
val displayIndex: Int,
|
||||
val senderInfo: SenderInfo,
|
||||
val annotations: EventAnnotationsSummary? = null,
|
||||
|
@ -191,3 +191,29 @@ internal fun ChunkEntity.nextDisplayIndex(direction: PaginationDirection): Int {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun ChunkEntity.doesNextChunksVerifyCondition(linkCondition: (ChunkEntity) -> Boolean): Boolean {
|
||||
var nextChunkToCheck = this.nextChunk
|
||||
while (nextChunkToCheck != null) {
|
||||
if (linkCondition(nextChunkToCheck)) {
|
||||
return true
|
||||
}
|
||||
nextChunkToCheck = nextChunkToCheck.nextChunk
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
internal fun ChunkEntity.isMoreRecentThan(chunkToCheck: ChunkEntity): Boolean {
|
||||
if (this.isLastForward) return true
|
||||
if (chunkToCheck.isLastForward) return false
|
||||
// Check if the chunk to check is linked to this one
|
||||
if(chunkToCheck.doesNextChunksVerifyCondition { it == this }){
|
||||
return true
|
||||
}
|
||||
// Otherwise check if this chunk is linked to last forward
|
||||
if(this.doesNextChunksVerifyCondition { it.isLastForward }){
|
||||
return true
|
||||
}
|
||||
// We don't know, so we assume it's false
|
||||
return false
|
||||
}
|
||||
|
@ -28,3 +28,13 @@ internal fun TimelineEventEntity.Companion.nextId(realm: Realm): Long {
|
||||
currentIdNum.toLong() + 1
|
||||
}
|
||||
}
|
||||
|
||||
internal fun TimelineEventEntity.isMoreRecentThan(eventToCheck: TimelineEventEntity): Boolean {
|
||||
val currentChunk = this.chunk?.first() ?: return false
|
||||
val chunkToCheck = eventToCheck.chunk?.firstOrNull() ?: return false
|
||||
return if (currentChunk == chunkToCheck) {
|
||||
this.displayIndex >= eventToCheck.displayIndex
|
||||
} else {
|
||||
currentChunk.isMoreRecentThan(chunkToCheck)
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,8 @@ package org.matrix.android.sdk.internal.database.query
|
||||
import io.realm.Realm
|
||||
import io.realm.RealmConfiguration
|
||||
import org.matrix.android.sdk.api.session.events.model.LocalEcho
|
||||
import org.matrix.android.sdk.internal.database.helper.doesNextChunksVerifyCondition
|
||||
import org.matrix.android.sdk.internal.database.helper.isMoreRecentThan
|
||||
import org.matrix.android.sdk.internal.database.model.ChunkEntity
|
||||
import org.matrix.android.sdk.internal.database.model.ReadMarkerEntity
|
||||
import org.matrix.android.sdk.internal.database.model.ReadReceiptEntity
|
||||
@ -33,28 +35,26 @@ internal fun isEventRead(realmConfiguration: RealmConfiguration,
|
||||
if (LocalEcho.isLocalEchoId(eventId)) {
|
||||
return true
|
||||
}
|
||||
// If we don't know if the event has been read, we assume it's not
|
||||
var isEventRead = false
|
||||
|
||||
Realm.getInstance(realmConfiguration).use { realm ->
|
||||
val liveChunk = ChunkEntity.findLastForwardChunkOfRoom(realm, roomId) ?: return@use
|
||||
val eventToCheck = liveChunk.timelineEvents.find(eventId)
|
||||
val latestEvent = TimelineEventEntity.latestEvent(realm, roomId, true)
|
||||
// If latest event is from you we are sure the event is read
|
||||
if (latestEvent?.root?.sender == userId) {
|
||||
return true
|
||||
}
|
||||
val eventToCheck = TimelineEventEntity.where(realm, roomId, eventId).findFirst()
|
||||
isEventRead = when {
|
||||
eventToCheck == null -> hasReadMissingEvent(
|
||||
realm = realm,
|
||||
latestChunkEntity = liveChunk,
|
||||
roomId = roomId,
|
||||
userId = userId,
|
||||
eventId = eventId
|
||||
)
|
||||
eventToCheck == null -> false
|
||||
eventToCheck.root?.sender == userId -> true
|
||||
else -> {
|
||||
val readReceipt = ReadReceiptEntity.where(realm, roomId, userId).findFirst() ?: return@use
|
||||
val readReceiptIndex = liveChunk.timelineEvents.find(readReceipt.eventId)?.displayIndex ?: Int.MIN_VALUE
|
||||
eventToCheck.displayIndex <= readReceiptIndex
|
||||
val readReceiptEvent = TimelineEventEntity.where(realm, roomId, readReceipt.eventId).findFirst() ?: return@use
|
||||
readReceiptEvent.isMoreRecentThan(eventToCheck)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return isEventRead
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,6 @@ import org.matrix.android.sdk.internal.task.TaskExecutor
|
||||
internal class DefaultReadService @AssistedInject constructor(
|
||||
@Assisted private val roomId: String,
|
||||
@SessionDatabase private val monarchy: Monarchy,
|
||||
private val taskExecutor: TaskExecutor,
|
||||
private val setReadMarkersTask: SetReadMarkersTask,
|
||||
private val readReceiptsSummaryMapper: ReadReceiptsSummaryMapper,
|
||||
@UserId private val userId: String
|
||||
|
@ -794,7 +794,6 @@ class RoomDetailViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun handleNavigateToEvent(action: RoomDetailAction.NavigateToEvent) {
|
||||
stopTrackingUnreadMessages()
|
||||
val targetEventId: String = action.eventId
|
||||
val indexOfEvent = timeline.getIndexOfEvent(targetEventId)
|
||||
if (indexOfEvent == null) {
|
||||
@ -868,12 +867,12 @@ class RoomDetailViewModel @AssistedInject constructor(
|
||||
.buffer(1, TimeUnit.SECONDS)
|
||||
.filter { it.isNotEmpty() }
|
||||
.subscribeBy(onNext = { actions ->
|
||||
val bufferedMostRecentDisplayedEvent = actions.maxByOrNull { it.event.displayIndex }?.event ?: return@subscribeBy
|
||||
val bufferedMostRecentDisplayedEvent = actions.minByOrNull { it.event.indexOfEvent() }?.event ?: return@subscribeBy
|
||||
val globalMostRecentDisplayedEvent = mostRecentDisplayedEvent
|
||||
if (trackUnreadMessages.get()) {
|
||||
if (globalMostRecentDisplayedEvent == null) {
|
||||
mostRecentDisplayedEvent = bufferedMostRecentDisplayedEvent
|
||||
} else if (bufferedMostRecentDisplayedEvent.displayIndex > globalMostRecentDisplayedEvent.displayIndex) {
|
||||
} else if (bufferedMostRecentDisplayedEvent.indexOfEvent() < globalMostRecentDisplayedEvent.indexOfEvent()) {
|
||||
mostRecentDisplayedEvent = bufferedMostRecentDisplayedEvent
|
||||
}
|
||||
}
|
||||
@ -886,6 +885,12 @@ class RoomDetailViewModel @AssistedInject constructor(
|
||||
.disposeOnClear()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of event in the timeline.
|
||||
* Returns Int.MAX_VALUE if not found
|
||||
*/
|
||||
private fun TimelineEvent.indexOfEvent(): Int = timeline.getIndexOfEvent(eventId) ?: Int.MAX_VALUE
|
||||
|
||||
private fun handleMarkAllAsRead() {
|
||||
setState { copy(unreadState = UnreadState.HasNoUnread) }
|
||||
viewModelScope.launch {
|
||||
|
Loading…
x
Reference in New Issue
Block a user