From 98bb5720d1b548ed76f371c75309bcfe8d7c17d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 12 Mar 2025 16:19:36 +0100 Subject: [PATCH] Add timeline prefetching This should trigger when getting close the start of the loaded timeline, making scrolling back smoother, specially when combined with the persistent event cache. --- .../features/messages/impl/timeline/TimelineView.kt | 13 +++++++++++++ .../timeline/components/TimelineItemVirtualRow.kt | 2 ++ 2 files changed, 15 insertions(+) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index 115039a284..d11d655ec5 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -70,8 +70,10 @@ import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.utils.animateScrollToItemCenter 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.launch +import timber.log.Timber @Composable fun TimelineView( @@ -175,6 +177,17 @@ 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)) + } + } + TimelineScrollHelper( hasAnyEvent = state.hasAnyEvent, lazyListState = lazyListState, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemVirtualRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemVirtualRow.kt index aa4a006249..2507fb9f01 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemVirtualRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemVirtualRow.kt @@ -28,6 +28,7 @@ import io.element.android.features.messages.impl.timeline.model.virtual.Timeline import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemRoomBeginningModel import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemTypingNotificationModel import io.element.android.features.messages.impl.typing.TypingNotificationView +import timber.log.Timber @Composable fun TimelineItemVirtualRow( @@ -45,6 +46,7 @@ fun TimelineItemVirtualRow( TimelineLoadingMoreIndicator(virtual.model.direction) val latestEventSink by rememberUpdatedState(eventSink) LaunchedEffect(virtual.model.timestamp) { + Timber.d("Pagination triggered by load more indicator") latestEventSink(TimelineEvents.LoadMore(virtual.model.direction)) } }