[TEST] Don't set main_or_null read receipt to old events

Context:
https://github.com/SchildiChat/SchildiChat-android-rageshakes/issues/951

If main RR updates after null RR, but to an older event than the null
RR, we still want to keep the null one.

Change-Id: Ib865965b6975536421b15146c863b9ea46f793b0
This commit is contained in:
SpiritCroc 2023-03-12 14:20:47 +01:00
parent a6cbe7a0da
commit 1004bd19e3
2 changed files with 22 additions and 6 deletions

View file

@ -146,8 +146,16 @@ private fun handleReadReceipts(realm: Realm, roomId: String, eventEntity: EventE
}
receiptDestinations.forEach { rootThreadEventId ->
val readReceiptOfSender = ReadReceiptEntity.getOrCreate(realm, roomId = roomId, userId = senderId, threadId = rootThreadEventId)
val shouldSkipMon = if (rootThreadEventId == THREAD_ID_MAIN_OR_NULL) {
val previousReceiptsSummary = ReadReceiptsSummaryEntity.where(realm, eventId = readReceiptOfSender.eventId).findFirst()
val oldEventTs = previousReceiptsSummary?.let { EventEntity.where(realm, roomId, it.eventId).findFirst()?.originServerTs }
val newEventTs = EventEntity.where(realm, roomId, eventEntity.eventId).findFirst()?.originServerTs
oldEventTs != null && newEventTs != null && oldEventTs > newEventTs
} else {
false
}
// If the synced RR is older, update
if (timestampOfEvent > readReceiptOfSender.originServerTs) {
if (timestampOfEvent > readReceiptOfSender.originServerTs && !shouldSkipMon) {
val previousReceiptsSummary = ReadReceiptsSummaryEntity.where(realm, eventId = readReceiptOfSender.eventId).findFirst()
rrDimber.i { "Handle outdated chunk RR $roomId / $senderId thread $rootThreadEventId(${eventEntity.rootThreadEventId}): event ${readReceiptOfSender.eventId} -> ${eventEntity.eventId}" }
readReceiptOfSender.eventId = eventEntity.eventId
@ -155,7 +163,7 @@ private fun handleReadReceipts(realm: Realm, roomId: String, eventEntity: EventE
previousReceiptsSummary?.readReceipts?.remove(readReceiptOfSender)
readReceiptsSummaryEntity.readReceipts.add(readReceiptOfSender)
} else {
rrDimber.i { "Handled chunk RR $roomId / $senderId thread $rootThreadEventId(${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}) || $shouldSkipMon" }
}
}
}

View file

@ -24,6 +24,7 @@ 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.api.session.room.read.ReadService.Companion.THREAD_ID_MAIN
import org.matrix.android.sdk.api.session.room.read.ReadService.Companion.THREAD_ID_MAIN_OR_NULL
import org.matrix.android.sdk.internal.database.model.EventEntity
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.query.createUnmanaged
@ -164,15 +165,22 @@ internal class ReadReceiptHandler @Inject constructor(
val syncedThreadId = paramsDict[THREAD_ID_KEY] as String?
// SC: fight duplicate read receipts in main timeline
val receiptDestinations = if (syncedThreadId in listOf(null, ReadService.THREAD_ID_MAIN)) {
setOf(syncedThreadId, ReadService.THREAD_ID_MAIN_OR_NULL)
val receiptDestinations = if (syncedThreadId in listOf(null, THREAD_ID_MAIN)) {
setOf(syncedThreadId, THREAD_ID_MAIN_OR_NULL)
} else {
setOf(syncedThreadId)
}
receiptDestinations.forEach { threadId ->
val receiptEntity = ReadReceiptEntity.getOrCreate(realm, roomId, userId, threadId)
val shouldSkipMon = if (threadId == THREAD_ID_MAIN_OR_NULL) {
val oldEventTs = EventEntity.where(realm, roomId, receiptEntity.eventId).findFirst()?.originServerTs
val newEventTs = EventEntity.where(realm, roomId, eventId).findFirst()?.originServerTs
oldEventTs != null && newEventTs != null && oldEventTs > newEventTs
} else {
false
}
// ensure new ts is superior to the previous one
if (ts > receiptEntity.originServerTs) {
if (ts > receiptEntity.originServerTs && !shouldSkipMon) {
rrDimber.i { "Handle outdated sync RR $roomId / $userId thread $threadId($syncedThreadId): event ${receiptEntity.eventId} -> $eventId" }
ReadReceiptsSummaryEntity.where(realm, receiptEntity.eventId).findFirst()?.also {
it.readReceipts.remove(receiptEntity)
@ -181,7 +189,7 @@ internal class ReadReceiptHandler @Inject constructor(
receiptEntity.originServerTs = ts
readReceiptsSummary.readReceipts.add(receiptEntity)
} else {
rrDimber.i { "Handle keep sync RR $roomId / $userId thread $threadId($syncedThreadId): event ${receiptEntity.eventId} (not $eventId)" }
rrDimber.i { "Handle keep sync RR $roomId / $userId thread $threadId($syncedThreadId): event ${receiptEntity.eventId} (not $eventId) || $shouldSkipMon" }
}
}
}