Fix stuck timeline for new messages

Change-Id: Id560898844438d88194a7211cac6d4db9853bceb
This commit is contained in:
SpiritCroc 2022-04-29 15:30:14 +02:00
parent afe9c47086
commit 099bf5a016
2 changed files with 42 additions and 0 deletions

View File

@ -108,6 +108,7 @@ internal class DefaultTimeline(private val roomId: String,
lightweightSettingsStorage = lightweightSettingsStorage,
onEventsUpdated = this::sendSignalToPostSnapshot,
onLimitedTimeline = this::onLimitedTimeline,
onLastForwardDeleted = this::onLastForwardDeleted,
onNewTimelineEvents = this::onNewTimelineEvents
)
@ -317,12 +318,32 @@ internal class DefaultTimeline(private val roomId: String,
private fun onLimitedTimeline() {
timelineScope.launch {
Timber.i("onLimitedTimeline: load more backwards")
initPaginationStates(null)
loadMore(settings.initialSize, Timeline.Direction.BACKWARDS, false)
postSnapshot()
}
}
private fun onLastForwardDeleted() {
timelineScope.launch {
// If we noticed before we don't have more to load, we want to re-try now.
// Since the last forward chunk got deleted, more may be available now using pagination.
if (hasMoreToLoad(Timeline.Direction.FORWARDS)) {
Timber.i("onLastForwardDeleted: no action necessary")
return@launch
}
Timber.i("onLastForwardDeleted: load more forwards")
//initPaginationStates(null)
updateState(Timeline.Direction.FORWARDS) {
it.copy(hasMoreToLoad = true)
}
loadMore(settings.initialSize, Timeline.Direction.FORWARDS, true)
postSnapshot()
}
}
private suspend fun postSnapshot() {
val snapshot = strategy.buildSnapshot()
Timber.v("Post snapshot of ${snapshot.size} events")

View File

@ -104,6 +104,7 @@ internal class LoadTimelineStrategy(
val lightweightSettingsStorage: LightweightSettingsStorage,
val onEventsUpdated: (Boolean) -> Unit,
val onLimitedTimeline: () -> Unit,
val onLastForwardDeleted: () -> Unit,
val onNewTimelineEvents: (List<String>) -> Unit
)
@ -111,6 +112,7 @@ internal class LoadTimelineStrategy(
private var chunkEntity: RealmResults<ChunkEntity>? = null
private var timelineChunk: TimelineChunk? = null
private var sendingEventCount: Int = 0
private var lastForwardChunkEntity: RealmResults<ChunkEntity>? = null
private val chunkEntityListener = OrderedRealmCollectionChangeListener { _: RealmResults<ChunkEntity>, changeSet: OrderedCollectionChangeSet ->
// Can be call either when you open a permalink on an unknown event
@ -128,6 +130,14 @@ internal class LoadTimelineStrategy(
}
}
private val lastForwardChunkEntityListener = OrderedRealmCollectionChangeListener { _: RealmResults<ChunkEntity>, changeSet: OrderedCollectionChangeSet ->
// When the last forward chunk changes and we had previously reached that, load forward again to avoid a stuck timeline
val shouldRebuildChunk = changeSet.deletions.isNotEmpty()
if (shouldRebuildChunk) {
dependencies.onLastForwardDeleted()
}
}
private val uiEchoManagerListener = object : UIEchoManager.Listener {
override fun rebuildEvent(eventId: String, builder: (TimelineEvent) -> TimelineEvent?): Boolean {
return timelineChunk?.rebuildEvent(eventId, builder, searchInNext = true, searchInPrev = true).orFalse()
@ -180,12 +190,16 @@ internal class LoadTimelineStrategy(
it.addChangeListener(chunkEntityListener)
timelineChunk = it.createTimelineChunk()
}
lastForwardChunkEntity = getLastForwardChunkEntity(realm).also {
it.addChangeListener(lastForwardChunkEntityListener)
}
}
fun onStop() {
dependencies.eventDecryptor.destroy()
dependencies.timelineInput.listeners.remove(timelineInputListener)
chunkEntity?.removeChangeListener(chunkEntityListener)
lastForwardChunkEntity?.removeChangeListener(lastForwardChunkEntityListener)
sendingEventsDataSource.stop()
timelineChunk?.close(closeNext = true, closePrev = true)
getContextLatch?.cancel()
@ -194,6 +208,7 @@ internal class LoadTimelineStrategy(
if (mode is Mode.Thread) {
clearThreadChunkEntity(dependencies.realm.get(), mode.rootThreadEventId)
}
lastForwardChunkEntity = null
}
suspend fun loadMore(count: Int, direction: Timeline.Direction, fetchOnServerIfNeeded: Boolean = true): LoadMoreResult {
@ -293,6 +308,12 @@ internal class LoadTimelineStrategy(
}
}
private fun getLastForwardChunkEntity(realm: Realm): RealmResults<ChunkEntity> {
return ChunkEntity.where(realm, roomId)
.equalTo(ChunkEntityFields.IS_LAST_FORWARD, true)
.findAll()
}
private fun hasReachedLastForward(): Boolean {
return timelineChunk?.hasReachedLastForward().orFalse()
}