Browse Source

Performance : do not trigger back pagination when opening room.

pull/3186/head
ganfra 2 months ago
parent
commit
5e6bcbd7ac
  1. 31
      libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt
  2. 8
      libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/TimelineItemsSubscriber.kt

31
libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt

@ -81,7 +81,6 @@ import timber.log.Timber
import uniffi.matrix_sdk_ui.LiveBackPaginationStatus import uniffi.matrix_sdk_ui.LiveBackPaginationStatus
import java.io.File import java.io.File
import java.util.Date import java.util.Date
import java.util.concurrent.atomic.AtomicBoolean
import org.matrix.rustcomponents.sdk.Timeline as InnerTimeline import org.matrix.rustcomponents.sdk.Timeline as InnerTimeline
private const val PAGINATION_SIZE = 50 private const val PAGINATION_SIZE = 50
@ -99,7 +98,7 @@ class RustTimeline(
onNewSyncedEvent: () -> Unit, onNewSyncedEvent: () -> Unit,
) : Timeline { ) : Timeline {
private val initLatch = CompletableDeferred<Unit>() private val initLatch = CompletableDeferred<Unit>()
private val isInit = AtomicBoolean(false) private val isInit = MutableStateFlow(false)
private val _timelineItems: MutableStateFlow<List<MatrixTimelineItem>> = private val _timelineItems: MutableStateFlow<List<MatrixTimelineItem>> =
MutableStateFlow(emptyList()) MutableStateFlow(emptyList())
@ -208,7 +207,7 @@ class RustTimeline(
} }
private fun canPaginate(direction: Timeline.PaginationDirection): Boolean { private fun canPaginate(direction: Timeline.PaginationDirection): Boolean {
if (!isInit.get()) return false if (!isInit.value) return false
return when (direction) { return when (direction) {
Timeline.PaginationDirection.BACKWARDS -> backPaginationStatus.value.canPaginate Timeline.PaginationDirection.BACKWARDS -> backPaginationStatus.value.canPaginate
Timeline.PaginationDirection.FORWARDS -> forwardPaginationStatus.value.canPaginate Timeline.PaginationDirection.FORWARDS -> forwardPaginationStatus.value.canPaginate
@ -226,20 +225,25 @@ class RustTimeline(
_timelineItems, _timelineItems,
backPaginationStatus.map { it.hasMoreToLoad }.distinctUntilChanged(), backPaginationStatus.map { it.hasMoreToLoad }.distinctUntilChanged(),
forwardPaginationStatus.map { it.hasMoreToLoad }.distinctUntilChanged(), forwardPaginationStatus.map { it.hasMoreToLoad }.distinctUntilChanged(),
) { timelineItems, hasMoreToLoadBackward, hasMoreToLoadForward -> isInit,
) { timelineItems, hasMoreToLoadBackward, hasMoreToLoadForward, isInit ->
withContext(dispatcher) { withContext(dispatcher) {
timelineItems timelineItems
.let { items -> encryptedHistoryPostProcessor.process(items) } .process { items -> encryptedHistoryPostProcessor.process(items) }
.let { items -> .process { items ->
roomBeginningPostProcessor.process( roomBeginningPostProcessor.process(
items = items, items = items,
isDm = matrixRoom.isDm, isDm = matrixRoom.isDm,
hasMoreToLoadBackwards = hasMoreToLoadBackward hasMoreToLoadBackwards = hasMoreToLoadBackward
) )
} }
.let { items -> loadingIndicatorsPostProcessor.process(items, hasMoreToLoadBackward, hasMoreToLoadForward) } .process(predicate = isInit) { items ->
loadingIndicatorsPostProcessor.process(items, hasMoreToLoadBackward, hasMoreToLoadForward)
}
// Keep lastForwardIndicatorsPostProcessor last // Keep lastForwardIndicatorsPostProcessor last
.let { items -> lastForwardIndicatorsPostProcessor.process(items) } .process(predicate = isInit) { items ->
lastForwardIndicatorsPostProcessor.process(items)
}
} }
}.onStart { }.onStart {
timelineItemsSubscriber.subscribeIfNeeded() timelineItemsSubscriber.subscribeIfNeeded()
@ -545,3 +549,14 @@ class RustTimeline(
} }
} }
} }
private suspend fun List<MatrixTimelineItem>.process(
predicate: Boolean = true,
processor: suspend (List<MatrixTimelineItem>) -> List<MatrixTimelineItem>
): List<MatrixTimelineItem> {
return if (predicate) {
processor(this)
} else {
this
}
}

8
libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/TimelineItemsSubscriber.kt

@ -23,6 +23,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.cancelChildren import kotlinx.coroutines.cancelChildren
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.ensureActive import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
@ -32,7 +33,6 @@ import org.matrix.rustcomponents.sdk.TimelineChange
import org.matrix.rustcomponents.sdk.TimelineDiff import org.matrix.rustcomponents.sdk.TimelineDiff
import org.matrix.rustcomponents.sdk.TimelineItem import org.matrix.rustcomponents.sdk.TimelineItem
import uniffi.matrix_sdk_ui.EventItemOrigin import uniffi.matrix_sdk_ui.EventItemOrigin
import java.util.concurrent.atomic.AtomicBoolean
private const val INITIAL_MAX_SIZE = 50 private const val INITIAL_MAX_SIZE = 50
@ -47,7 +47,7 @@ internal class TimelineItemsSubscriber(
private val timeline: Timeline, private val timeline: Timeline,
private val timelineDiffProcessor: MatrixTimelineDiffProcessor, private val timelineDiffProcessor: MatrixTimelineDiffProcessor,
private val initLatch: CompletableDeferred<Unit>, private val initLatch: CompletableDeferred<Unit>,
private val isInit: AtomicBoolean, private val isInit: MutableStateFlow<Boolean>,
private val onNewSyncedEvent: () -> Unit, private val onNewSyncedEvent: () -> Unit,
) { ) {
private var subscriptionCount = 0 private var subscriptionCount = 0
@ -94,13 +94,13 @@ internal class TimelineItemsSubscriber(
ensureActive() ensureActive()
timelineDiffProcessor.postItems(it) timelineDiffProcessor.postItems(it)
} }
isInit.set(true) isInit.value = true
initLatch.complete(Unit) initLatch.complete(Unit)
} }
private suspend fun postDiffs(diffs: List<TimelineDiff>) { private suspend fun postDiffs(diffs: List<TimelineDiff>) {
val diffsToProcess = diffs.toMutableList() val diffsToProcess = diffs.toMutableList()
if (!isInit.get()) { if (!isInit.value) {
val resetDiff = diffsToProcess.firstOrNull { it.change() == TimelineChange.RESET } val resetDiff = diffsToProcess.firstOrNull { it.change() == TimelineChange.RESET }
if (resetDiff != null) { if (resetDiff != null) {
// Keep using the postItems logic so we can post the timelineItems asap. // Keep using the postItems logic so we can post the timelineItems asap.

Loading…
Cancel
Save