Skip to content

feat(ios): paginate older turns with infinite scroll - #308

Closed
DatScreamer wants to merge 1 commit into
0xSero:mainfrom
DatScreamer:feat/ios-infinite-scroll-older-turns
Closed

DatScreamer wants to merge 1 commit into
0xSero:mainfrom
DatScreamer:feat/ios-infinite-scroll-older-turns

Conversation

@DatScreamer

Copy link
Copy Markdown
Contributor

Closes part of #306
Depends on #307 (land after it so the paged cursor behaves predictably).

Problem

iOS conversation history loading was manual (a "Load earlier messages" button), page size 5, and the "Latest" jump button could be consumed just by stopping a decelerating ScrollView.

Changes (ConversationView, AppModel, TranscriptTurn, Settings, tests)

  • Scroll-triggered prefetch: tracks visible turn IDs and loads the next older page as the user approaches the top, debounced per cursor so concurrent prefetches collapse.
  • Page size 5 → 20; loadOlderTurns now returns whether a page loaded.
  • "Latest" re-routed through semantic ScrollPosition + a UIKit scroll-view resolver so the jump executes even while momentum is decelerating.
  • Merged exploration rows anchored to their newest constituent turn so prepending older pages keeps scroll identity stable.
  • Auto-collapse conversations past 200 items.

Scope

iOS only; the conversation surface is shared across all runtimes, so this improves every provider (codex, claude, pi, local-studio, opencode).

Parity note

Android still uses a manual "Load earlier messages" button (ConversationScreen.kt). The Rust metadata-read fix (#307) benefits both; the infinite-scroll UX is iOS-only in this change. Android parity is a follow-up.

Tests

  • 3 new PerformanceHelpersTests: auto-collapse, prefetch-before-cache-edge, exploration identity.

Verification

  • make ios-sim-fast

Replace the explicit Load-earlier-messages button with scroll-triggered
pagination. Track visible turn IDs and prefetch the next older page as the
user approaches the top, debounced per cursor so concurrent prefetches
collapse. Bump page size to 20, make loadOlderTurns report whether a page
was actually loaded, and re-route the Latest button through a semantic
ScrollPosition with a UIKit scroll-view resolver so the jump executes even
while momentum is decelerating. Anchor merged exploration rows to their
newest constituent turn so prepending older pages keeps scroll identity
stable, and auto-collapse large conversations past a 200-item threshold.
@DatScreamer

Copy link
Copy Markdown
Contributor Author

Depends on the server-side pagination from 0xSero/alleycat#49 (issue 0xSero/alleycat#48), pinned via #307's Cargo.lock bump.

@0xSero

0xSero commented Aug 18, 2026

Copy link
Copy Markdown
Owner

#319 has merged (0824605d) and rewrote ConversationView.swift substantially, so this will need a rebase. The Rust half of #306 is now in — include_turns=false is authoritative and page size is 20 — so what remains here is the scroll integration itself: prefetch, the "Latest" jump, and auto-collapse. Still wanted.

@DatScreamer

Copy link
Copy Markdown
Contributor Author

This PR is superseded by #331 (feat(home): infinite scroll + pull-to-refresh for the home sessions list). The conversation older-turns infinite scroll work is now carried on the feat/home-sessions-infinite-scroll branch (commit d3ab5a22), which this PR's home branch already contains. Keeping both open would race on the same AppModel.swift paging code and Rust cursor state. Recommend closing this one in favor of #331.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants