Merge #4006 (scroll auto-follow setting + pin guards) onto master
# Conflicts: # api/config.py # static/panels.js
This commit is contained in:
@@ -1817,6 +1817,7 @@ function applyBotName(){
|
||||
};
|
||||
window._busyInputMode=(s.busy_input_mode||'queue');
|
||||
window._sessionEndlessScrollEnabled=!!s.session_endless_scroll;
|
||||
window._autoScrollFollow=s.auto_scroll_follow!==false;
|
||||
window._botName=s.bot_name||'Hermes';
|
||||
if(s.default_model_provider) window._activeProvider=s.default_model_provider;
|
||||
if(s.default_model){
|
||||
@@ -1913,6 +1914,7 @@ function applyBotName(){
|
||||
window._pinnedSessionsLimit=3;
|
||||
window._busyInputMode='queue';
|
||||
window._sessionEndlessScrollEnabled=false;
|
||||
window._autoScrollFollow=true;
|
||||
window._botName='Hermes';
|
||||
_bootSettings={check_for_updates:false};
|
||||
if(typeof setLocale==='function'){
|
||||
|
||||
@@ -558,6 +558,8 @@ const LOCALES = {
|
||||
settings_label_session_endless_scroll: 'Load older messages while scrolling up',
|
||||
|
||||
settings_desc_session_endless_scroll: 'When enabled, older messages load automatically as you scroll upward. When disabled, use the older-messages button.',
|
||||
settings_label_auto_scroll_follow: 'Auto-follow new content',
|
||||
settings_desc_auto_scroll_follow: 'When enabled, the view scrolls to the bottom as new tokens stream in. When disabled, you control the scroll position manually.',
|
||||
settings_label_worklog_details_expanded_default: 'Open Worklog details automatically',
|
||||
settings_desc_worklog_details_expanded_default: 'When enabled, new Worklog details start expanded so tool, thinking, and progress cards are visible without an extra click. When off, Worklog details stay folded by default; per-turn manual collapse/expand choices still win.',
|
||||
settings_label_chat_activity_display_mode: 'Activity display',
|
||||
@@ -9452,6 +9454,8 @@ const LOCALES = {
|
||||
settings_label_session_endless_scroll: '向上滚动时加载更早的消息',
|
||||
|
||||
settings_desc_session_endless_scroll: '启用后,向上滚动时会自动加载更早的消息。禁用时请使用加载更早消息按钮。',
|
||||
settings_label_auto_scroll_follow: '自动跟随新内容',
|
||||
settings_desc_auto_scroll_follow: '启用后,流式输出时页面会自动滚动到底部。禁用后,你可以自由控制滚动位置,阅读答案不会被拽到底部。',
|
||||
settings_label_worklog_details_expanded_default: 'Open Worklog details automatically',
|
||||
settings_desc_worklog_details_expanded_default: 'When enabled, new Worklog details start expanded so tool, thinking, and progress cards are visible without an extra click. When off, Worklog details stay folded by default; per-turn manual collapse/expand choices still win.',
|
||||
settings_label_chat_activity_display_mode: 'Activity display',
|
||||
|
||||
@@ -1020,6 +1020,13 @@
|
||||
</select>
|
||||
<div style="font-size:11px;color:var(--muted);margin-top:4px" data-i18n="settings_desc_chat_activity_display_mode">Compact Worklog groups supporting activity into a quiet summary. Transparent Stream keeps each thinking/tool event as its own chronological expandable row.</div>
|
||||
</div>
|
||||
<div class="settings-field" style="margin-top:8px">
|
||||
<label style="display:flex;align-items:center;gap:8px;cursor:pointer">
|
||||
<input type="checkbox" id="settingsAutoScrollFollow" style="width:15px;height:15px;accent-color:var(--accent)">
|
||||
<span data-i18n="settings_label_auto_scroll_follow">Auto-follow new content</span>
|
||||
</label>
|
||||
<div style="font-size:11px;color:var(--muted);margin-top:4px" data-i18n="settings_desc_auto_scroll_follow">When enabled, the view scrolls to the bottom as new tokens stream in. When disabled, you control the scroll position manually.</div>
|
||||
</div>
|
||||
<div class="settings-field" style="margin-top:8px">
|
||||
<label style="display:flex;align-items:center;gap:8px;cursor:pointer">
|
||||
<input type="checkbox" id="settingsWorklogDetailsExpandedDefault" style="width:15px;height:15px;accent-color:var(--accent)">
|
||||
|
||||
@@ -3310,7 +3310,7 @@ function attachLiveStream(activeSid, streamId, uploaded=[], options={}){
|
||||
_messageRenderWindowSize=Math.max(typeof _currentMessageRenderWindowSize==='function'?_currentMessageRenderWindowSize():50, _messageRenderableMessageCount());
|
||||
}
|
||||
syncTopbar();renderMessages({preserveScroll:true});
|
||||
if(shouldFollowOnDone&&typeof scrollToBottom==='function') scrollToBottom();
|
||||
if(shouldFollowOnDone&&typeof scrollToBottom==='function'&&typeof _isMessagePaneNearBottom==='function'&&_isMessagePaneNearBottom(250)) scrollToBottom();
|
||||
if(typeof noteWorkspaceMutationsFromToolCalls==='function') noteWorkspaceMutationsFromToolCalls(S.toolCalls);
|
||||
loadDir('.', { preservePreview: true });
|
||||
// TTS auto-read: speak the last assistant response if enabled (#499)
|
||||
|
||||
@@ -6220,6 +6220,7 @@ function _appearancePayloadFromUi(){
|
||||
chat_activity_display_mode: chatActivityModeSel&&chatActivityModeSel.value==='transparent_stream'?'transparent_stream':'compact_worklog',
|
||||
session_jump_buttons: !!($('settingsSessionJumpButtons')||{}).checked,
|
||||
session_endless_scroll: !!($('settingsSessionEndlessScroll')||{}).checked,
|
||||
auto_scroll_follow: !!($('settingsAutoScrollFollow')||{}).checked,
|
||||
worklog_details_expanded_default: worklogDetailsExpanded,
|
||||
activity_feed_expanded_default: worklogDetailsExpanded,
|
||||
hidden_tabs: _getHiddenTabs(),
|
||||
@@ -6305,6 +6306,7 @@ async function _autosaveAppearanceSettings(payload){
|
||||
if(typeof _applySessionNavigationPrefs==='function') _applySessionNavigationPrefs();
|
||||
}
|
||||
window._sessionEndlessScrollEnabled=!!(saved&&saved.session_endless_scroll);
|
||||
window._autoScrollFollow=!!(saved&&saved.auto_scroll_follow);
|
||||
if(saved&&payload&&Object.prototype.hasOwnProperty.call(payload,'worklog_details_expanded_default')&&(
|
||||
Object.prototype.hasOwnProperty.call(saved,'worklog_details_expanded_default') ||
|
||||
Object.prototype.hasOwnProperty.call(saved,'activity_feed_expanded_default')
|
||||
@@ -6539,6 +6541,15 @@ async function loadSettingsPanel(){
|
||||
_scheduleAppearanceAutosave();
|
||||
};
|
||||
}
|
||||
const autoScrollFollowCb=$('settingsAutoScrollFollow');
|
||||
if(autoScrollFollowCb){
|
||||
autoScrollFollowCb.checked=settings.auto_scroll_follow!==false;
|
||||
window._autoScrollFollow=autoScrollFollowCb.checked;
|
||||
autoScrollFollowCb.onchange=function(){
|
||||
window._autoScrollFollow=this.checked;
|
||||
_scheduleAppearanceAutosave();
|
||||
};
|
||||
}
|
||||
const worklogDetailsExpandedCb=$('settingsWorklogDetailsExpandedDefault');
|
||||
const chatActivityModeSel=$('settingsChatActivityDisplayMode');
|
||||
if(chatActivityModeSel){
|
||||
@@ -7823,6 +7834,7 @@ function _applySavedSettingsUi(saved, body, opts){
|
||||
window._sidebarDensity=sidebarDensity==='detailed'?'detailed':'compact';
|
||||
window._busyInputMode=body.busy_input_mode||'queue';
|
||||
window._sessionEndlessScrollEnabled=!!body.session_endless_scroll;
|
||||
window._autoScrollFollow=!!body.auto_scroll_follow;
|
||||
window._botName=body.bot_name||'Hermes';
|
||||
if(typeof applyBotName==='function') applyBotName();
|
||||
if(typeof setLocale==='function') setLocale(language);
|
||||
@@ -8155,6 +8167,7 @@ async function saveSettings(andClose){
|
||||
body.session_jump_buttons=!!($('settingsSessionJumpButtons')||{}).checked;
|
||||
body.session_endless_scroll=!!($('settingsSessionEndlessScroll')||{}).checked;
|
||||
body.chat_activity_display_mode=(($('settingsChatActivityDisplayMode')||{}).value==='transparent_stream')?'transparent_stream':'compact_worklog';
|
||||
body.auto_scroll_follow=!!($('settingsAutoScrollFollow')||{}).checked;
|
||||
body.language=language;
|
||||
body.show_token_usage=showTokenUsage;
|
||||
body.show_quota_chip=showQuotaChip===true;
|
||||
|
||||
@@ -3103,7 +3103,7 @@ function _shouldFollowMessagesOnDomReplace(){
|
||||
// following only for users who are still pinned or effectively at the tail.
|
||||
// A broad near-bottom window causes long answers/mobile readers who scroll up
|
||||
// a little to read mid-stream to get snapped back to the bottom on completion.
|
||||
return !_messageUserUnpinned && (_scrollPinned || _isMessagePaneNearBottom(120));
|
||||
return _autoScrollFollow && !_messageUserUnpinned && (_scrollPinned || _isMessagePaneNearBottom(120));
|
||||
}
|
||||
function _followMessagesAfterDomReplace(){
|
||||
if(_shouldFollowMessagesOnDomReplace()){
|
||||
@@ -3202,6 +3202,7 @@ function _settleFinalScroll(token){
|
||||
});
|
||||
}
|
||||
function scrollIfPinned(){
|
||||
if(!_autoScrollFollow) return;
|
||||
if(_messageUserUnpinned) return;
|
||||
if(!_scrollPinned) return;
|
||||
if(_recentNonMessageScrollIntent()) return;
|
||||
@@ -8640,7 +8641,7 @@ function _scrollAfterMessageRender(preserveScroll, scrollSnapshot){
|
||||
// new-message cue. (Using scrollIfPinned() here instead would skip the forced
|
||||
// write unless distance>500 and let the DOM-rebuild scroll event cancel the
|
||||
// delayed settles — Codex CORE catch on #3631.)
|
||||
if(_followMessagesAfterDomReplace()) return;
|
||||
if(!_messageUserUnpinned && _followMessagesAfterDomReplace()) return;
|
||||
_restoreMessageScrollSnapshot(scrollSnapshot);
|
||||
_maybeShowNewMessageScrollCue(scrollSnapshot);
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user