fix(#4006): gate the #3920 RO settle + render fall-through on _autoScrollFollow (Codex cross-PR catch)
Codex found that with Auto-follow OFF the #3920 ResizeObserver settle + 2s fallback + the non-preserve render path still force-scrolled to bottom (the setting was incomplete vs the scroll machinery shipped in #3920). Fixes: 1. RO settle guard (ui.js:3153): bail when !_autoScrollFollow. 2. 2s static fallback guard (ui.js:3186): bail when !_autoScrollFollow. 3. non-preserve render fall-through (ui.js:8653): when Auto-follow off AND the user has unpinned, restore the scroll snapshot instead of scrollToBottom() — also closes the send() race (renderMessages runs before S.activeStreamId is set). A fresh session load (not unpinned) still lands at the bottom. Explicit user-initiated scrollToBottom() (End button) is untouched.
This commit is contained in:
13
static/ui.js
13
static/ui.js
@@ -3150,7 +3150,7 @@ function _settleMessageScrollToBottom(force){
|
||||
// active one that may now be in the global _settleRO. (Codex review #3.)
|
||||
const ro=new ResizeObserver(()=>{
|
||||
if(token!==_bottomSettleToken){ ro.disconnect(); if(_settleRO===ro) _settleRO=null; return; }
|
||||
if(!_scrollPinned||_messageUserUnpinned||_recentNonMessageScrollIntent()){
|
||||
if(!_autoScrollFollow||!_scrollPinned||_messageUserUnpinned||_recentNonMessageScrollIntent()){
|
||||
ro.disconnect(); if(_settleRO===ro) _settleRO=null;
|
||||
_programmaticScroll=false;
|
||||
return;
|
||||
@@ -3183,7 +3183,7 @@ function _settleMessageScrollToBottom(force){
|
||||
_settleFinalTimer=setTimeout(()=>{
|
||||
if(token!==_bottomSettleToken) return;
|
||||
ro.disconnect(); if(_settleRO===ro) _settleRO=null;
|
||||
if(!_scrollPinned||_messageUserUnpinned||_recentNonMessageScrollIntent()){ _programmaticScroll=false; return; }
|
||||
if(!_autoScrollFollow||!_scrollPinned||_messageUserUnpinned||_recentNonMessageScrollIntent()){ _programmaticScroll=false; return; }
|
||||
_settleFinalScroll(token);
|
||||
},2000);
|
||||
}
|
||||
@@ -8650,6 +8650,15 @@ function _scrollAfterMessageRender(preserveScroll, scrollSnapshot){
|
||||
scrollIfPinned();
|
||||
return;
|
||||
}
|
||||
// Auto-follow OFF + the user has scrolled up: don't yank them to the bottom on
|
||||
// an automatic (non-preserve) re-render. This also covers the send() race where
|
||||
// renderMessages() runs before S.activeStreamId is set, so a stream-start
|
||||
// wouldn't otherwise be caught by the scrollIfPinned() branch above. A fresh
|
||||
// session load (not unpinned) still lands at the bottom as expected. (Codex #4006.)
|
||||
if(!_autoScrollFollow && _messageUserUnpinned){
|
||||
_restoreMessageScrollSnapshot(scrollSnapshot);
|
||||
return;
|
||||
}
|
||||
scrollToBottom();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user