Merge pull request #5554 from SpiritCroc/endless-loading

Fix endless loading timeline due to conflicting chunks
This commit is contained in:
ganfra 2022-04-11 18:52:24 +02:00 committed by GitHub
commit f7e8c01121
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 51 additions and 3 deletions

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

@ -0,0 +1 @@
Fix sometimes endless loading timeline

View File

@ -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<ChunkEntity>? {
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)

View File

@ -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) {