Skip to content

Fix UI lock when scrolling up during streaming output - #24

Merged
yogthos merged 1 commit into
mainfrom
fix/scroll-anchor-during-stream
May 19, 2026
Merged

Fix UI lock when scrolling up during streaming output#24
yogthos merged 1 commit into
mainfrom
fix/scroll-anchor-during-stream

Conversation

@yogthos

@yogthos yogthos commented May 19, 2026

Copy link
Copy Markdown
Collaborator

Reported symptom

Scrolling up while the agent streams responses makes the UI "stuck at wherever you scrolled up," especially when mouse-selecting text — the selection rectangle drifts away from the cursor as new content arrives.

Root cause

`scroll_offset` is "lines from the bottom edge," a fixed quantity. The viewport start is computed as:

```rust
start = total - scroll_offset - visible
```

As streaming tokens push new lines into the buffer, `total` grows but `scroll_offset` stays the same → `start` drifts forward. The user's view silently follows the bottom at the fixed offset instead of staying on the absolute content they scrolled to. Selection indices are absolute (correct), but the highlighted rows drift along with the viewport, so mouse-drags select the wrong lines.

Fix

When content is appended to the buffer while `scroll_offset > 0`, bump `scroll_offset` by the number of lines added (clamped to `max_offset`). This keeps `start` anchored to the same absolute index. When `scroll_offset == 0` the view continues to follow the bottom — that path is unchanged.

  • All `buffer.push` sites in `commit_partial` / `write_line` / `write` go through a new private `push_buffer_line` helper.
  • `replace_from` (used by the streaming-token markdown re-render) shifts `scroll_offset` by the size delta on each rewrite to preserve the anchor.

Test coverage (6 new tests)

  • View stays anchored through 8 token appends while scrolled up.
  • `replace_from` preserves the anchor on both grow and shrink rewrites.
  • Bottom-anchored view (`scroll_offset == 0`) still follows new content.
  • Selection indices remain absolute and unchanged under streaming appends.
  • `push_buffer_line` clamps `scroll_offset` to max on tiny buffers.
  • `commit_partial` routes through the anchor-aware push path.

Test plan

  • `cargo build` clean
  • `cargo test --bin dirge -- --skip plugin` → 272 passed, 0 failed
  • Manual: while the agent is mid-stream, scroll up with mouse wheel — content stays put. Mouse-drag a selection across earlier lines — highlight stays where the cursor went.

Reported symptom: scrolling up while the agent streams responses makes
the UI 'stuck at wherever you scrolled up', especially when mouse-
selecting text — the selection rectangle drifts away from the cursor as
new content arrives.

Root cause: scroll_offset is 'lines from the bottom edge', a fixed
quantity. As streaming tokens push new lines into the buffer, total
grows but scroll_offset stays the same, so render_viewport's computed
start = total - scroll_offset - visible drifts forward. The user's view
silently follows the bottom at the fixed offset instead of staying on
the absolute content they scrolled to. Selection indices are absolute
(correct), but the highlighted rows drift along with the viewport so
mouse-drags select the wrong lines.

Fix: when content is appended to the buffer while scroll_offset > 0,
bump scroll_offset by the number of lines added (clamped to max_offset).
This keeps start anchored to the same absolute index. When scroll_offset
== 0 the view continues to follow the bottom — that path is unchanged.

Routes all buffer.push calls in commit_partial / write_line / write
through a new private push_buffer_line helper. replace_from (used by
the streaming-token markdown re-render) shifts scroll_offset by the
size delta to preserve the anchor across rewrites.

6 new tests covering:
- view stays anchored through 8 token appends while scrolled up
- replace_from preserves anchor on both grow and shrink rewrites
- bottom-anchored view (scroll_offset == 0) still follows new content
- selection indices remain absolute under streaming appends
- push_buffer_line clamps scroll_offset to max for tiny buffers
- commit_partial routes through the anchor-aware push path
@yogthos
yogthos force-pushed the fix/scroll-anchor-during-stream branch from b86b819 to 84a23a6 Compare May 19, 2026 20:47
@yogthos
yogthos merged commit ee3ca6c into main May 19, 2026
@yogthos
yogthos deleted the fix/scroll-anchor-during-stream branch May 19, 2026 20:47
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.

1 participant