Try improved version using snapshotFlow, which seems more performant, as well as an extended threshold (-40 items)
This commit is contained in:
parent
d15b227c33
commit
8f129eb285
1 changed files with 42 additions and 11 deletions
|
|
@ -36,6 +36,7 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.runtime.snapshotFlow
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.rotate
|
||||
|
|
@ -72,6 +73,10 @@ import io.element.android.libraries.matrix.api.core.EventId
|
|||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.timeline.Timeline
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
||||
|
|
@ -177,17 +182,8 @@ fun TimelineView(
|
|||
onClearFocusRequestState = ::clearFocusRequestState
|
||||
)
|
||||
|
||||
val isCloseToStartOfLoadedTimeline by remember {
|
||||
derivedStateOf {
|
||||
lazyListState.firstVisibleItemIndex + lazyListState.layoutInfo.visibleItemsInfo.size >= lazyListState.layoutInfo.totalItemsCount - 10
|
||||
}
|
||||
}
|
||||
LaunchedEffect(isCloseToStartOfLoadedTimeline) {
|
||||
// Only back paginate when we're close to the start of the loaded timeline items and the user is actively scrolling
|
||||
if (lazyListState.isScrollInProgress && isCloseToStartOfLoadedTimeline) {
|
||||
Timber.d("Prefetching pagination with ${lazyListState.layoutInfo.totalItemsCount} items")
|
||||
state.eventSink(TimelineEvents.LoadMore(Timeline.PaginationDirection.BACKWARDS))
|
||||
}
|
||||
TimelinePrefetchingHelper(lazyListState = lazyListState) {
|
||||
state.eventSink(TimelineEvents.LoadMore(Timeline.PaginationDirection.BACKWARDS))
|
||||
}
|
||||
|
||||
TimelineScrollHelper(
|
||||
|
|
@ -218,6 +214,41 @@ private fun MessageShieldDialog(state: TimelineState) {
|
|||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
@Composable
|
||||
private fun TimelinePrefetchingHelper(
|
||||
lazyListState: LazyListState,
|
||||
prefetch: () -> Unit,
|
||||
) {
|
||||
// We're using snapshot flows for these because using `LaunchedEffect` with `derivedState` doesn't seem to be responsive enough
|
||||
val firstVisibleItemIndexFlow = snapshotFlow {
|
||||
lazyListState.firstVisibleItemIndex
|
||||
}
|
||||
val layoutInfoFlow = snapshotFlow {
|
||||
lazyListState.layoutInfo
|
||||
}
|
||||
val isScrollingFlow = snapshotFlow {
|
||||
lazyListState.isScrollInProgress
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
val isCloseToStartOfLoadedTimelineFlow = combine(layoutInfoFlow, firstVisibleItemIndexFlow) { layoutInfo, firstVisibleItemIndex ->
|
||||
firstVisibleItemIndex + layoutInfo.visibleItemsInfo.size >= layoutInfo.totalItemsCount - 40
|
||||
}
|
||||
|
||||
combine(isCloseToStartOfLoadedTimelineFlow, isScrollingFlow) { needsPrefetch, isScrolling ->
|
||||
needsPrefetch && isScrolling
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
.collectLatest { needsPrefetch ->
|
||||
if (needsPrefetch) {
|
||||
Timber.d("Prefetching pagination with ${lazyListState.layoutInfo.totalItemsCount} items")
|
||||
prefetch()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BoxScope.TimelineScrollHelper(
|
||||
hasAnyEvent: Boolean,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue