diff --git a/changelog.d/3347.bugfix b/changelog.d/3347.bugfix new file mode 100644 index 0000000000..8ba1d7af88 --- /dev/null +++ b/changelog.d/3347.bugfix @@ -0,0 +1 @@ +Fixes notifications not dismissing when reading messages on other devices \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ReadQueries.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ReadQueries.kt index be26886aaa..60096777d9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ReadQueries.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ReadQueries.kt @@ -39,19 +39,18 @@ internal fun isEventRead(realmConfiguration: RealmConfiguration, val liveChunk = ChunkEntity.findLastForwardChunkOfRoom(realm, roomId) ?: return@use val eventToCheck = liveChunk.timelineEvents.find(eventId) isEventRead = when { - eventToCheck == null -> { - // This can happen in case of fast lane Event - false - } + eventToCheck == null -> hasReadMissingEvent( + realm = realm, + latestChunkEntity = liveChunk, + roomId = roomId, + userId = userId, + eventId = eventId + ) 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 - val eventToCheckIndex = eventToCheck.displayIndex - - eventToCheckIndex <= readReceiptIndex + val readReceipt = ReadReceiptEntity.where(realm, roomId, userId).findFirst() ?: return@use + val readReceiptIndex = liveChunk.timelineEvents.find(readReceipt.eventId)?.displayIndex ?: Int.MIN_VALUE + eventToCheck.displayIndex <= readReceiptIndex } } } @@ -59,6 +58,24 @@ internal fun isEventRead(realmConfiguration: RealmConfiguration, 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, roomId: String?, eventId: String?): Boolean {