fix(chat): prevent timeline prefetch ANRs (#985)

This commit is contained in:
AlexDev_ authored and GitHub committed 2026-08-27 10:47:04 +03:00
1 parent ce8fdc45bd
commit c7d7abf4a1
3 files changed
+60 -1

No files matched your search

@@ -92,6 +92,7 @@ import com.m57.hermescontrol.ui.chat.components.ChatLifecycleEffects
import com.m57.hermescontrol.ui.chat.components.ChatLoadingOverlay
import com.m57.hermescontrol.ui.chat.components.ChatResumeErrorOverlay
import com.m57.hermescontrol.ui.chat.components.ChatScrollToBottomFab
import com.m57.hermescontrol.ui.chat.components.ChatTimelineNoPrefetchStrategy
import com.m57.hermescontrol.ui.chat.components.ContextDetailSheet
import com.m57.hermescontrol.ui.chat.components.ContextUsageChip
import com.m57.hermescontrol.ui.chat.components.ReactionHeartsOverlay
@@ -158,7 +159,7 @@ fun ChatScreen(
// read its fields recompose on search changes (bar, matched bubbles).
val searchState = viewModel.searchState
val lifecycleOwner = LocalLifecycleOwner.current
val listState = rememberLazyListState()
val listState = rememberLazyListState(prefetchStrategy = ChatTimelineNoPrefetchStrategy)
val scrollScope = rememberCoroutineScope()
val scrollController = rememberChatScrollController(listState, scrollScope)
var isOlderPagingArmed by remember(state.currentSessionId) { mutableStateOf(false) }
@@ -0,0 +1,25 @@
package com.m57.hermescontrol.ui.chat.components
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.lazy.LazyListLayoutInfo
import androidx.compose.foundation.lazy.LazyListPrefetchScope
import androidx.compose.foundation.lazy.LazyListPrefetchStrategy
import androidx.compose.foundation.lazy.layout.NestedPrefetchScope
/**
* Chat messages can contain very large selectable Markdown blocks. Measuring a
* neighboring item during LazyColumn prefetch can monopolize the main thread
* long enough to trigger an input-dispatch ANR, even though that item is still
* off screen. Measure chat items only when they enter the viewport instead.
*/
@OptIn(ExperimentalFoundationApi::class)
internal object ChatTimelineNoPrefetchStrategy : LazyListPrefetchStrategy {
override fun LazyListPrefetchScope.onScroll(
delta: Float,
layoutInfo: LazyListLayoutInfo,
) = Unit
override fun LazyListPrefetchScope.onVisibleItemsUpdated(layoutInfo: LazyListLayoutInfo) = Unit
override fun NestedPrefetchScope.onNestedPrefetch(firstVisibleItemIndex: Int) = Unit
}