[TEST] Fight duplicate read markers in main timeline
Let synced null and main markers both update the main marker.
Looks like desktop does the same:
7158a99a1c/src/sync-accumulator.ts (L459-L460)
Change-Id: Ic4bf8b4d947fdd9882a3da053ac2b93747f1f20a
This commit is contained in:
parent
3b57c6c5f6
commit
cd9a3b9be2
|
@ -23,6 +23,7 @@ import io.realm.kotlin.createObject
|
||||||
import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent
|
import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent
|
||||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
|
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
|
||||||
|
import org.matrix.android.sdk.api.session.room.read.ReadService.Companion.THREAD_ID_MAIN
|
||||||
import org.matrix.android.sdk.internal.crypto.model.SessionInfo
|
import org.matrix.android.sdk.internal.crypto.model.SessionInfo
|
||||||
import org.matrix.android.sdk.internal.database.mapper.asDomain
|
import org.matrix.android.sdk.internal.database.mapper.asDomain
|
||||||
import org.matrix.android.sdk.internal.database.model.ChunkEntity
|
import org.matrix.android.sdk.internal.database.model.ChunkEntity
|
||||||
|
@ -136,17 +137,21 @@ private fun handleReadReceipts(realm: Realm, roomId: String, eventEntity: EventE
|
||||||
val originServerTs = eventEntity.originServerTs
|
val originServerTs = eventEntity.originServerTs
|
||||||
if (originServerTs != null) {
|
if (originServerTs != null) {
|
||||||
val timestampOfEvent = originServerTs.toDouble()
|
val timestampOfEvent = originServerTs.toDouble()
|
||||||
val readReceiptOfSender = ReadReceiptEntity.getOrCreate(realm, roomId = roomId, userId = senderId, threadId = eventEntity.rootThreadEventId)
|
// null receipts also update the main receipt
|
||||||
|
val receiptDestination = eventEntity.rootThreadEventId ?: THREAD_ID_MAIN
|
||||||
|
setOf(receiptDestination, eventEntity.rootThreadEventId).distinct().forEach { rootThreadEventId ->
|
||||||
|
val readReceiptOfSender = ReadReceiptEntity.getOrCreate(realm, roomId = roomId, userId = senderId, threadId = rootThreadEventId)
|
||||||
// If the synced RR is older, update
|
// If the synced RR is older, update
|
||||||
if (timestampOfEvent > readReceiptOfSender.originServerTs) {
|
if (timestampOfEvent > readReceiptOfSender.originServerTs) {
|
||||||
val previousReceiptsSummary = ReadReceiptsSummaryEntity.where(realm, eventId = readReceiptOfSender.eventId).findFirst()
|
val previousReceiptsSummary = ReadReceiptsSummaryEntity.where(realm, eventId = readReceiptOfSender.eventId).findFirst()
|
||||||
rrDimber.i{"Handle outdated chunk RR $roomId / $senderId thread ${eventEntity.rootThreadEventId}: event ${readReceiptOfSender.eventId} -> ${eventEntity.eventId}"}
|
rrDimber.i { "Handle outdated chunk RR $roomId / $senderId thread $rootThreadEventId(${eventEntity.rootThreadEventId}): event ${readReceiptOfSender.eventId} -> ${eventEntity.eventId}" }
|
||||||
readReceiptOfSender.eventId = eventEntity.eventId
|
readReceiptOfSender.eventId = eventEntity.eventId
|
||||||
readReceiptOfSender.originServerTs = timestampOfEvent
|
readReceiptOfSender.originServerTs = timestampOfEvent
|
||||||
previousReceiptsSummary?.readReceipts?.remove(readReceiptOfSender)
|
previousReceiptsSummary?.readReceipts?.remove(readReceiptOfSender)
|
||||||
readReceiptsSummaryEntity.readReceipts.add(readReceiptOfSender)
|
readReceiptsSummaryEntity.readReceipts.add(readReceiptOfSender)
|
||||||
} else {
|
} else {
|
||||||
rrDimber.i{"Handled chunk RR $roomId / $senderId thread ${eventEntity.rootThreadEventId}: keep ${readReceiptOfSender.eventId} (not ${eventEntity.eventId})"}
|
rrDimber.i { "Handled chunk RR $roomId / $senderId thread $rootThreadEventId(${eventEntity.rootThreadEventId}): keep ${readReceiptOfSender.eventId} (not ${eventEntity.eventId})" }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return readReceiptsSummaryEntity
|
return readReceiptsSummaryEntity
|
||||||
|
|
|
@ -20,6 +20,7 @@ import de.spiritcroc.matrixsdk.util.DbgUtil
|
||||||
import de.spiritcroc.matrixsdk.util.Dimber
|
import de.spiritcroc.matrixsdk.util.Dimber
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||||
|
import org.matrix.android.sdk.api.session.room.read.ReadService
|
||||||
import org.matrix.android.sdk.internal.database.model.ReadReceiptEntity
|
import org.matrix.android.sdk.internal.database.model.ReadReceiptEntity
|
||||||
import org.matrix.android.sdk.internal.database.model.ReadReceiptsSummaryEntity
|
import org.matrix.android.sdk.internal.database.model.ReadReceiptsSummaryEntity
|
||||||
import org.matrix.android.sdk.internal.database.query.createUnmanaged
|
import org.matrix.android.sdk.internal.database.query.createUnmanaged
|
||||||
|
@ -145,11 +146,13 @@ internal class ReadReceiptHandler @Inject constructor(
|
||||||
|
|
||||||
for ((userId, paramsDict) in userIdsDict) {
|
for ((userId, paramsDict) in userIdsDict) {
|
||||||
val ts = paramsDict[TIMESTAMP_KEY] as? Double ?: 0.0
|
val ts = paramsDict[TIMESTAMP_KEY] as? Double ?: 0.0
|
||||||
val threadId = paramsDict[THREAD_ID_KEY] as String?
|
val syncedThreadId = paramsDict[THREAD_ID_KEY] as String?
|
||||||
|
val receiptDestination = syncedThreadId ?: ReadService.THREAD_ID_MAIN
|
||||||
|
setOf(receiptDestination, syncedThreadId).distinct().forEach { threadId ->
|
||||||
val receiptEntity = ReadReceiptEntity.getOrCreate(realm, roomId, userId, threadId)
|
val receiptEntity = ReadReceiptEntity.getOrCreate(realm, roomId, userId, threadId)
|
||||||
// ensure new ts is superior to the previous one
|
// ensure new ts is superior to the previous one
|
||||||
if (ts > receiptEntity.originServerTs) {
|
if (ts > receiptEntity.originServerTs) {
|
||||||
rrDimber.i{"Handle outdated sync RR $roomId / $userId thread $threadId: event ${receiptEntity.eventId} -> $eventId"}
|
rrDimber.i { "Handle outdated sync RR $roomId / $userId thread $threadId($syncedThreadId): event ${receiptEntity.eventId} -> $eventId" }
|
||||||
ReadReceiptsSummaryEntity.where(realm, receiptEntity.eventId).findFirst()?.also {
|
ReadReceiptsSummaryEntity.where(realm, receiptEntity.eventId).findFirst()?.also {
|
||||||
it.readReceipts.remove(receiptEntity)
|
it.readReceipts.remove(receiptEntity)
|
||||||
}
|
}
|
||||||
|
@ -157,7 +160,8 @@ internal class ReadReceiptHandler @Inject constructor(
|
||||||
receiptEntity.originServerTs = ts
|
receiptEntity.originServerTs = ts
|
||||||
readReceiptsSummary.readReceipts.add(receiptEntity)
|
readReceiptsSummary.readReceipts.add(receiptEntity)
|
||||||
} else {
|
} else {
|
||||||
rrDimber.i{"Handle keep sync RR $roomId / $userId thread $threadId: event ${receiptEntity.eventId} (not $eventId)"}
|
rrDimber.i { "Handle keep sync RR $roomId / $userId thread $threadId($syncedThreadId): event ${receiptEntity.eventId} (not $eventId)" }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -628,7 +628,7 @@ class TimelineEventController @Inject constructor(
|
||||||
return if (partialState.isFromThreadTimeline()) {
|
return if (partialState.isFromThreadTimeline()) {
|
||||||
this.threadId == partialState.rootThreadEventId
|
this.threadId == partialState.rootThreadEventId
|
||||||
} else {
|
} else {
|
||||||
this.threadId == null || this.threadId == ReadService.THREAD_ID_MAIN
|
this.threadId == ReadService.THREAD_ID_MAIN
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue