diff --git a/app/androidApp/src/main/kotlin/com/example/aiapp/SessionScreen.kt b/app/androidApp/src/main/kotlin/com/example/aiapp/SessionScreen.kt index 140b8ff..a07efe5 100644 --- a/app/androidApp/src/main/kotlin/com/example/aiapp/SessionScreen.kt +++ b/app/androidApp/src/main/kotlin/com/example/aiapp/SessionScreen.kt @@ -449,11 +449,22 @@ fun SessionScreen( } // Reaching the far end of what is loaded -- the oldest item, which in // this layout is the last index -- fetches the page before it. - LaunchedEffect(listState, items.size, moreHistory) { - snapshotFlow { listState.layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: 0 } - .collect { last -> - if (!moreHistory || loadingHistory || items.isEmpty()) return@collect - if (last < items.size - 3) return@collect + // + // Both numbers come from the list itself, and that is the point: an index into what is drawn + // can only be compared against how much is drawn. Three things already make that differ from + // the event count -- a run of adjacent tool calls is one row, and the queued bubble and the + // working indicator are rows with no event behind them at all -- so measuring the far end in + // events meant the threshold could not be reached, and a session with tool calls in it simply + // stopped scrolling back. Anything added to this list later is a fourth, and totalItemsCount + // already counts it. + LaunchedEffect(listState, rows.size, moreHistory) { + snapshotFlow { + val layout = listState.layoutInfo + Pair(layout.visibleItemsInfo.lastOrNull()?.index ?: 0, layout.totalItemsCount) + } + .collect { (last, total) -> + if (!moreHistory || loadingHistory || total == 0) return@collect + if (last < total - 3) return@collect loadingHistory = true try { val older =