diff --git a/changelog.d/5554.bugfix b/changelog.d/5554.bugfix new file mode 100644 index 00000000000..ee69f0dbfec --- /dev/null +++ b/changelog.d/5554.bugfix @@ -0,0 +1 @@ +Fix sometimes endless loading timeline diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ChunkEntityQueries.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ChunkEntityQueries.kt index ece46555a7e..a33ba82f7aa 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ChunkEntityQueries.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ChunkEntityQueries.kt @@ -40,6 +40,17 @@ internal fun ChunkEntity.Companion.find(realm: Realm, roomId: String, prevToken: return query.findFirst() } +internal fun ChunkEntity.Companion.findAll(realm: Realm, roomId: String, prevToken: String? = null, nextToken: String? = null): RealmResults? { + val query = where(realm, roomId) + if (prevToken != null) { + query.equalTo(ChunkEntityFields.PREV_TOKEN, prevToken) + } + if (nextToken != null) { + query.equalTo(ChunkEntityFields.NEXT_TOKEN, nextToken) + } + return query.findAll() +} + internal fun ChunkEntity.Companion.findLastForwardChunkOfRoom(realm: Realm, roomId: String): ChunkEntity? { return where(realm, roomId) .equalTo(ChunkEntityFields.IS_LAST_FORWARD, true) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistor.kt index 63383a99b3c..1f76b36ef77 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistor.kt @@ -38,6 +38,7 @@ import org.matrix.android.sdk.internal.database.model.TimelineEventEntityFields import org.matrix.android.sdk.internal.database.query.copyToRealmOrIgnore import org.matrix.android.sdk.internal.database.query.create import org.matrix.android.sdk.internal.database.query.find +import org.matrix.android.sdk.internal.database.query.findAll import org.matrix.android.sdk.internal.database.query.where import org.matrix.android.sdk.internal.di.SessionDatabase import org.matrix.android.sdk.internal.di.UserId @@ -80,7 +81,8 @@ internal class TokenChunkEventPersistor @Inject constructor( val existingChunk = ChunkEntity.find(realm, roomId, prevToken = prevToken, nextToken = nextToken) if (existingChunk != null) { - Timber.v("This chunk is already in the db, returns") + Timber.v("This chunk is already in the db, checking if this might be caused by broken links") + existingChunk.fixChunkLinks(realm, roomId, direction, prevToken, nextToken) return@awaitTransaction } val prevChunk = ChunkEntity.find(realm, roomId, nextToken = prevToken) @@ -89,8 +91,14 @@ internal class TokenChunkEventPersistor @Inject constructor( this.nextChunk = nextChunk this.prevChunk = prevChunk } - nextChunk?.prevChunk = currentChunk - prevChunk?.nextChunk = currentChunk + val allNextChunks = ChunkEntity.findAll(realm, roomId, prevToken = nextToken) + val allPrevChunks = ChunkEntity.findAll(realm, roomId, nextToken = prevToken) + allNextChunks?.forEach { + it.prevChunk = currentChunk + } + allPrevChunks?.forEach { + it.nextChunk = currentChunk + } if (receivedChunk.events.isEmpty() && !receivedChunk.hasMore()) { handleReachEnd(roomId, direction, currentChunk) } else { @@ -109,6 +117,34 @@ internal class TokenChunkEventPersistor @Inject constructor( } } + private fun ChunkEntity.fixChunkLinks( + realm: Realm, + roomId: String, + direction: PaginationDirection, + prevToken: String?, + nextToken: String?, + ) { + if (direction == PaginationDirection.FORWARDS) { + val prevChunks = ChunkEntity.findAll(realm, roomId, nextToken = prevToken) + Timber.v("Found ${prevChunks?.size} prevChunks") + prevChunks?.forEach { + if (it.nextChunk != this) { + Timber.i("Set nextChunk for ${it.identifier()} from ${it.nextChunk?.identifier()} to ${identifier()}") + it.nextChunk = this + } + } + } else { + val nextChunks = ChunkEntity.findAll(realm, roomId, prevToken = nextToken) + Timber.v("Found ${nextChunks?.size} nextChunks") + nextChunks?.forEach { + if (it.prevChunk != this) { + Timber.i("Set prevChunk for ${it.identifier()} from ${it.prevChunk?.identifier()} to ${identifier()}") + it.prevChunk = this + } + } + } + } + private fun handleReachEnd(roomId: String, direction: PaginationDirection, currentChunk: ChunkEntity) { Timber.v("Reach end of $roomId") if (direction == PaginationDirection.FORWARDS) {