Merge pull request #4129 from vector-im/feature/adm/sync-read-notifications

Fixing notifications not being dismissed when read from other devices
This commit is contained in:
Benoit Marty 2021-10-01 18:11:46 +02:00 committed by GitHub
commit 2366227133
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 29 additions and 11 deletions

1
changelog.d/3347.bugfix Normal file
View File

@ -0,0 +1 @@
Fixes notifications not dismissing when reading messages on other devices

View File

@ -39,19 +39,18 @@ internal fun isEventRead(realmConfiguration: RealmConfiguration,
val liveChunk = ChunkEntity.findLastForwardChunkOfRoom(realm, roomId) ?: return@use val liveChunk = ChunkEntity.findLastForwardChunkOfRoom(realm, roomId) ?: return@use
val eventToCheck = liveChunk.timelineEvents.find(eventId) val eventToCheck = liveChunk.timelineEvents.find(eventId)
isEventRead = when { isEventRead = when {
eventToCheck == null -> { eventToCheck == null -> hasReadMissingEvent(
// This can happen in case of fast lane Event realm = realm,
false latestChunkEntity = liveChunk,
} roomId = roomId,
userId = userId,
eventId = eventId
)
eventToCheck.root?.sender == userId -> true eventToCheck.root?.sender == userId -> true
else -> { else -> {
val readReceipt = ReadReceiptEntity.where(realm, roomId, userId).findFirst() val readReceipt = ReadReceiptEntity.where(realm, roomId, userId).findFirst() ?: return@use
?: return@use val readReceiptIndex = liveChunk.timelineEvents.find(readReceipt.eventId)?.displayIndex ?: Int.MIN_VALUE
val readReceiptIndex = liveChunk.timelineEvents.find(readReceipt.eventId)?.displayIndex eventToCheck.displayIndex <= readReceiptIndex
?: Int.MIN_VALUE
val eventToCheckIndex = eventToCheck.displayIndex
eventToCheckIndex <= readReceiptIndex
} }
} }
} }
@ -59,6 +58,24 @@ internal fun isEventRead(realmConfiguration: RealmConfiguration,
return isEventRead return isEventRead
} }
/**
* Missing events can be caused by the latest timeline chunk no longer contain an older event or
* by fast lane eagerly displaying events before the database has finished updating
*/
private fun hasReadMissingEvent(realm: Realm, latestChunkEntity: ChunkEntity, roomId: String, userId: String, eventId: String): Boolean {
return realm.doesEventExistInChunkHistory(eventId) && realm.hasReadReceiptInLatestChunk(latestChunkEntity, roomId, userId)
}
private fun Realm.doesEventExistInChunkHistory(eventId: String): Boolean {
return ChunkEntity.findIncludingEvent(this, eventId) != null
}
private fun Realm.hasReadReceiptInLatestChunk(latestChunkEntity: ChunkEntity, roomId: String, userId: String): Boolean {
return ReadReceiptEntity.where(this, roomId = roomId, userId = userId).findFirst()?.let {
latestChunkEntity.timelineEvents.find(it.eventId)
} != null
}
internal fun isReadMarkerMoreRecent(realmConfiguration: RealmConfiguration, internal fun isReadMarkerMoreRecent(realmConfiguration: RealmConfiguration,
roomId: String?, roomId: String?,
eventId: String?): Boolean { eventId: String?): Boolean {