Skip to content

fix(macos): make long chats resize and scroll smoothly - #2135

Merged
LHagfoss merged 2 commits into
mainfrom
fix/macos-chat-scroll-resize
Oct 19, 2026
Merged

LHagfoss merged 2 commits into
mainfrom
fix/macos-chat-scroll-resize

Conversation

@LHagfoss

Copy link
Copy Markdown
Owner

Problem

After #2132, long chats still scrolled slowly, resizing the window was very laggy, and after Latest → scroll up → scroll back to the end, Latest stayed visible.

Measurements

Offscreen benchmark rendering the real 253-item session (01a14ffb777a-…) in an NSHostingView, release build, scrolled to the end, average per resize step (700–1300 pt):

Layout Resize step Scroll frame
Before: eager rows + pinned Latest footer 173 ms 4.4 ms
Eager rows, no pinned footer 42 ms 2.9 ms
After: lazy older rows, newest 20 eager, overlay button ~15 ms (~1 ms when column width is unchanged) ~1.4 ms

A pinned section footer re-lays out its whole section every frame, and that section was the entire eagerly laid-out chat.

Changes

  • Latest is an overlay over the scroll view instead of a pinned footer.
  • Rows older than the newest 20 are in a LazyVStack. The newest 20 stay eager, along with the working indicator and the bottom anchor, so the area being read near the end never changes height while you scroll. (Fully eager rows were added in fix(macos): steady chat scrolling and list new chats at once #2105 to stop that jump.)
  • Following resumes whenever the chat is at its end, and again on onScrollPhaseChange(.idle). Before, it resumed only while input events were still arriving, so a scroll that settled at the end after its last event left Latest up. Letting go still requires the reader's own upward input.

Tests

swift build, swift test (85) pass. Built and installed locally (/Applications/RustCode.app). Scrolling far up into the lazy region may still correct its row height estimates; that region was never the reported problem.

Measured offscreen on a 253-item session scrolled to its end, each
window resize step cost 173 ms: every row was laid out eagerly, and the
Latest button was a pinned section footer, which re-lays out its whole
section on every frame. Moving the button to an overlay cuts that to
42 ms; making older rows lazy while the newest 20 stay eager brings it
to about 15 ms (about 1 ms when the column width does not change) and
halves the cost of each scrolled frame.

Following the end of the chat now resumes whenever the chat is at its
end, and again when a scroll comes to rest there. It used to resume only
while input events were still arriving, so a scroll that settled at the
end after its last event left Latest showing.
@github-actions github-actions Bot added the fix A bug fix label Oct 19, 2026
@LHagfoss
LHagfoss merged commit 2d113fb into main Oct 19, 2026
7 checks passed
@LHagfoss
LHagfoss deleted the fix/macos-chat-scroll-resize branch October 19, 2026 11:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix A bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant