refactor(webui): address review — drop dead field, rename, add fallback intent test (#5637)

Greptile review follow-ups (no behavior change):
- Remove the captured-but-never-read scrollTopAtCapture field from
  _captureMessageViewportAnchor; only scrollHeightAtCapture is consulted.
- Rename _grewAbove -> _grewSinceCapture in the realign guard (the check is
  overall scrollHeight growth since capture, not specifically above-viewport),
  matching the fallback guard's _grewSinceSnap.
- Add a mutation-checked fallback active-intent test: content grew but the reader
  has recent real input intent, so the absolute snapshot.top restore is kept.
This commit is contained in:
allenliang2022 2026-07-06 13:01:40 +08:00
parent 18cd79797f
commit 545681ce4c
2 changed files with 20 additions and 7 deletions

View file

@ -953,12 +953,11 @@ function _captureMessageViewportAnchor(){
key:row&&row.dataset?String(row.dataset.messageAnchorKey||''):'',
topOffset:rect.top-containerRect.top,
topPadBefore,
// Snapshot the scroll geometry at capture so a later realign can detect that
// content grew ABOVE the viewport between capture and restore — the streaming
// case where the anchor's topOffset is stale and realigning to it would yank a
// still reader backward (issue #5637).
// Snapshot the scroll height at capture so a later realign can detect that
// content grew between capture and restore — the streaming case where the
// anchor's topOffset is stale and realigning to it would yank a still reader
// backward (issue #5637).
scrollHeightAtCapture:container.scrollHeight,
scrollTopAtCapture:container.scrollTop,
};
}
}
@ -1050,10 +1049,10 @@ function _restoreMessageViewportAnchor(anchor, rawIdxDelta){
const _realignDelta=(rect.top-containerRect.top)-targetTop;
const _shAtCap=Number(anchor.scrollHeightAtCapture);
if(Number.isFinite(_shAtCap)){
const _grewAbove=(container.scrollHeight-_shAtCap)>4;
const _grewSinceCapture=(container.scrollHeight-_shAtCap)>4;
const _activeIntent=(typeof _recentMessageScrollIntent==='function' && _recentMessageScrollIntent())
|| (typeof _recentMessageTouchScrollIntent==='function' && _recentMessageTouchScrollIntent());
if(_grewAbove&&!_activeIntent&&Math.abs(_realignDelta)>8){
if(_grewSinceCapture&&!_activeIntent&&Math.abs(_realignDelta)>8){
return false;
}
}

View file

@ -217,3 +217,17 @@ def test_fallback_backward_compatible_without_capture_scrollheight():
active_intent=False,
)))
assert m["writes"] == [89577]
def test_fallback_allows_snapshot_top_with_active_intent():
"""Content grew since snapshot, but the reader has recent real input intent -> the
fallback keeps its legitimate absolute restore (an actively-scrolling reader owns the
snapshot). Mirrors the realign-guard active-intent case.
Mutation: drop the `!_activeIntent` term from the fallback guard and this fails
(the write would be wrongly refused)."""
m = json.loads(_run_node(_fallback_harness(
snapshot_scroll_height=90000, cur_scroll_height=90453, snapshot_top=89577,
active_intent=True,
)))
assert m["writes"] == [89577]