Timeline: fix back pagination state

This commit is contained in:
ganfra 2019-09-30 14:56:06 +02:00
parent 28315be7b9
commit e842bf13b2
2 changed files with 27 additions and 18 deletions

View file

@ -18,6 +18,7 @@ package im.vector.matrix.android.internal.session.room.timeline
import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.session.crypto.CryptoService import im.vector.matrix.android.api.session.crypto.CryptoService
import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.room.model.ReadReceipt import im.vector.matrix.android.api.session.room.model.ReadReceipt
import im.vector.matrix.android.api.session.room.send.SendState import im.vector.matrix.android.api.session.room.send.SendState
import im.vector.matrix.android.api.session.room.timeline.Timeline import im.vector.matrix.android.api.session.room.timeline.Timeline
@ -351,7 +352,7 @@ internal class DefaultTimeline(
updateState(Timeline.Direction.BACKWARDS) { updateState(Timeline.Direction.BACKWARDS) {
it.copy( it.copy(
hasMoreInCache = lastBuiltEvent == null || lastBuiltEvent.displayIndex > lastCacheEvent?.root?.displayIndex ?: Int.MAX_VALUE, hasMoreInCache = lastBuiltEvent == null || lastBuiltEvent.displayIndex > lastCacheEvent?.root?.displayIndex ?: Int.MAX_VALUE,
hasReachedEnd = chunkEntity?.isLastBackward ?: false hasReachedEnd = chunkEntity?.isLastBackward ?: false || lastCacheEvent?.root?.type == EventType.STATE_ROOM_CREATE
) )
} }
} }
@ -499,9 +500,9 @@ internal class DefaultTimeline(
return return
} }
val params = PaginationTask.Params(roomId = roomId, val params = PaginationTask.Params(roomId = roomId,
from = token, from = token,
direction = direction.toPaginationDirection(), direction = direction.toPaginationDirection(),
limit = limit) limit = limit)
Timber.v("Should fetch $limit items $direction") Timber.v("Should fetch $limit items $direction")
cancelableBag += paginationTask cancelableBag += paginationTask
@ -510,13 +511,18 @@ internal class DefaultTimeline(
this.constraints = TaskConstraints(connectedToNetwork = true) this.constraints = TaskConstraints(connectedToNetwork = true)
this.callback = object : MatrixCallback<TokenChunkEventPersistor.Result> { this.callback = object : MatrixCallback<TokenChunkEventPersistor.Result> {
override fun onSuccess(data: TokenChunkEventPersistor.Result) { override fun onSuccess(data: TokenChunkEventPersistor.Result) {
if (data == TokenChunkEventPersistor.Result.SUCCESS) { when (data) {
Timber.v("Success fetching $limit items $direction from pagination request") TokenChunkEventPersistor.Result.SUCCESS -> {
} else { Timber.v("Success fetching $limit items $direction from pagination request")
// Database won't be updated, so we force pagination request
BACKGROUND_HANDLER.post {
executePaginationTask(direction, limit)
} }
TokenChunkEventPersistor.Result.REACHED_END -> {
postSnapshot()
}
TokenChunkEventPersistor.Result.SHOULD_FETCH_MORE ->
// Database won't be updated, so we force pagination request
BACKGROUND_HANDLER.post {
executePaginationTask(direction, limit)
}
} }
} }
@ -572,7 +578,7 @@ internal class DefaultTimeline(
val timelineEvent = buildTimelineEvent(eventEntity) val timelineEvent = buildTimelineEvent(eventEntity)
if (timelineEvent.isEncrypted() if (timelineEvent.isEncrypted()
&& timelineEvent.root.mxDecryptionResult == null) { && timelineEvent.root.mxDecryptionResult == null) {
timelineEvent.root.eventId?.let { eventDecryptor.requestDecryption(it) } timelineEvent.root.eventId?.let { eventDecryptor.requestDecryption(it) }
} }

View file

@ -100,6 +100,7 @@ internal class TokenChunkEventPersistor @Inject constructor(private val monarchy
enum class Result { enum class Result {
SHOULD_FETCH_MORE, SHOULD_FETCH_MORE,
REACHED_END,
SUCCESS SUCCESS
} }
@ -124,10 +125,8 @@ internal class TokenChunkEventPersistor @Inject constructor(private val monarchy
prevToken = receivedChunk.end prevToken = receivedChunk.end
} }
if (ChunkEntity.find(realm, roomId, nextToken = nextToken) != null || ChunkEntity.find(realm, roomId, prevToken = prevToken) != null) { val shouldSkip = ChunkEntity.find(realm, roomId, nextToken = nextToken) != null
Timber.v("Already inserted - SKIP") || ChunkEntity.find(realm, roomId, prevToken = prevToken) != null
return@awaitTransaction
}
val prevChunk = ChunkEntity.find(realm, roomId, nextToken = prevToken) val prevChunk = ChunkEntity.find(realm, roomId, nextToken = prevToken)
val nextChunk = ChunkEntity.find(realm, roomId, prevToken = nextToken) val nextChunk = ChunkEntity.find(realm, roomId, prevToken = nextToken)
@ -146,7 +145,7 @@ internal class TokenChunkEventPersistor @Inject constructor(private val monarchy
if (receivedChunk.events.isEmpty() && receivedChunk.end == receivedChunk.start) { if (receivedChunk.events.isEmpty() && receivedChunk.end == receivedChunk.start) {
Timber.v("Reach end of $roomId") Timber.v("Reach end of $roomId")
currentChunk.isLastBackward = true currentChunk.isLastBackward = true
} else { } else if (!shouldSkip) {
Timber.v("Add ${receivedChunk.events.size} events in chunk(${currentChunk.nextToken} | ${currentChunk.prevToken}") Timber.v("Add ${receivedChunk.events.size} events in chunk(${currentChunk.nextToken} | ${currentChunk.prevToken}")
val eventIds = ArrayList<String>(receivedChunk.events.size) val eventIds = ArrayList<String>(receivedChunk.events.size)
for (event in receivedChunk.events) { for (event in receivedChunk.events) {
@ -180,8 +179,12 @@ internal class TokenChunkEventPersistor @Inject constructor(private val monarchy
currentChunk.updateSenderDataFor(eventIds) currentChunk.updateSenderDataFor(eventIds)
} }
} }
return if (receivedChunk.events.isEmpty() && receivedChunk.stateEvents.isEmpty() && receivedChunk.start != receivedChunk.end) { return if (receivedChunk.events.isEmpty()) {
Result.SHOULD_FETCH_MORE if (receivedChunk.start != receivedChunk.end) {
Result.SHOULD_FETCH_MORE
} else {
Result.REACHED_END
}
} else { } else {
Result.SUCCESS Result.SUCCESS
} }