7 Commits
Author SHA1 Message Date
Kevin Meinon 906aebefa9 fix(scroll): do not unpin a pinned tail reader on an above-tail collapse clamp (#7605) 2026-09-16 07:03:36 -07:00
a818be1ed4 Release exp-v0.52.172: preserve reader scroll intent during live renders (#6453) (#6838)
* fix: preserve reader scroll intent during live renders

* fix: enforce programmatic scroll guard freshness

* test: update programmatic scroll guard assertion

* test: update scroll safety valve assertion

* fix: reconcile scroll intent helper after base refresh

* fix: timestamp fallback history scroll writes

* test: cover stale older-message fallback scroll guard

* test: execute the real slow-render history fallback

* test: provide the history fallback DOM helper

* test: retain async declaration in history fallback harness

* test: remove trailing blank line from scroll intent regression

* test(#6414): update scroll-intent harness for window._autoScrollFollow + _messageScrollInputGeneration (master drift)

* Release exp-v0.52.172: preserve reader scroll intent during live renders (#6453)

---------

Co-authored-by: Frank Song <franksong2702@gmail.com>
Co-authored-by: Frank Song <xuefu.song@qq.com>
Co-authored-by: nesquena-hermes <nesquena-hermes@users.noreply.github.com>
2026-08-07 18:37:31 -07:00
fc3d6b68e6 stage batch #4584+#4583 (rodboev): scroll re-pin read-position fix + mobile horizontal-pan fix (#4668)
#4584 (fixes #4295): scroll re-pin requires deliberate downward intent (deltaY<-30 unpin
threshold, re-pin only if not user-unpinned OR bottomDistance<=80, reset counter) so reading
mid-stream isn't hijacked back to bottom. ui.js only + 5 scroll-regression tests (4 existing
assertions adjusted, all green; new test_issue4295_scroll_pin_reentry).
#4583 (fixes #4553): mobile transcript overflow-x:hidden + max-width:100% + word-break so wide
content can't pan sideways. style.css only + own test. Disjoint files. 32 scroll-family tests pass.

Co-authored-by: nesquena-hermes <agent@nesquena-hermes>
Co-authored-by: rodboev <rodboev@users.noreply.github.com>
2026-06-21 23:15:47 -07:00
nesquena-hermesandpamnard d09f2e4efb feat: sticky manual unpin for streaming chat scroll (#3343)
Supersedes the v0.51.199 proximity-re-pin (#3330) and the #3250 upward-intent
timeout with a sticky-unpin model (ChatGPT/Claude/Codex behavior): scroll up =
stay put until you return to the bottom or click the scroll-to-bottom control.
Reconciled against the shipped #3330 code: removed the now-dead
_recentMessageUpwardIntent reference from the #3319 rAF retry, kept the
load-time -Infinity intent-init fix, kept the pinned-only >500 catch-up.

Co-authored-by: pamnard <pamnard@users.noreply.github.com>
2026-06-01 20:34:06 +00:00
ai-ag2026 c65ae46983 fix: prevent chat scroll resets after final render
Keep explicit bottom pins stable across late layout growth and make clicking the already-active sidebar session a no-op before loadSession mutates state. Update scroll regression tests for the delayed settle path.
2026-05-08 20:48:43 +00:00
ai-ag2026 c4328c0a23 fix: keep streaming chat pinned after final render 2026-05-08 16:40:16 +00:00
Sanjays2402andPotato 9bb4fad0e8 fix(streaming): unpin scroll on small upward motion during streaming (#1731)
The streaming scroll listener applied hysteresis symmetrically: an
upward scroll that landed inside the 250px near-bottom dead zone still
reported the user as near the bottom, so _nearBottomCount kept
incrementing and _scrollPinned stayed true. The next streaming token
snapped the user back to the bottom. The user effectively had to escape
the 250px zone in one fling to read earlier output.

The 250px dead zone itself is required by #1360 / #677 (macOS small
window + trackpad momentum re-pin protection) so the fix is direction
detection, not threshold relaxation: track _lastScrollTop and unpin
immediately on an explicit upward movement (>2px decrease), while
downward / stationary movement keeps the original hysteresis re-pin
path so the macOS momentum protection is preserved.

Programmatic scrolls are still masked by the existing _programmaticScroll
guard, so scrollToBottom() never updates _lastScrollTop and never
spuriously unpins.

Adds tests/test_issue1731_upward_scroll_unpins.py covering: direction
tracker exists, upward branch sets _scrollPinned=false and resets the
counter without hysteresis, downward branch preserves the >=2
hysteresis re-pin requirement, the 250px threshold remains, and the
_programmaticScroll bail still runs before the rAF schedule.

Closes #1731.

Co-Authored-By: Potato (OpenClaw assistant) <noreply@openclaw.ai>
2026-05-06 06:26:28 +00:00