fix terminal autoscroll
3clyp50 committed
Jan 21, 2026 at 15:00 UTC
9698e9150488887db0ede74afb131551841cef15
1 file changed
+18
-5
webui/js/messages.js
+18
-5
@@ -1590,9 +1590,15 @@ function updateProcessStep(stepElement, id, type, heading, content, kvps, durati
1590
let skipFullRender = false;
1591
1592
if (detailContent) {
1593
- // Capture scroll state before re-render (uses existing Scroller pattern)
1593
+ // Capture scroll state before re-render
1594
const terminal = detailContent.querySelector(".terminal-output");
1595
- const scroller = terminal ? new Scroller(terminal) : null;
1595
+ let wasAtBottom = true; // Default to true for new terminals
1596
+ let previousScrollTop = 0;
1597
+ if (terminal) {
1598
+ const distanceFromBottom = terminal.scrollHeight - terminal.clientHeight - terminal.scrollTop;
1599
+ wasAtBottom = distanceFromBottom <= 10;
1600
+ previousScrollTop = terminal.scrollTop;
1601
+ }
1602
1603
// For browser, update image src incrementally to avoid flashing
1604
if (type === "browser" && kvps?.screenshot) {
@@ -1611,10 +1617,17 @@ function updateProcessStep(stepElement, id, type, heading, content, kvps, durati
1617
if (!skipFullRender) {
1618
renderStepDetailContent(detailContent, content, kvps, type);
1619
1614
- // Re-apply scroll (stays at bottom if was at bottom)
1620
+ // Restore scroll position after re-render
1621
const newTerminal = detailContent.querySelector(".terminal-output");
1616
- if (newTerminal && scroller?.wasAtBottom) {
1617
- newTerminal.scrollTop = newTerminal.scrollHeight;
1622
+ if (newTerminal) {
1623
+ if (wasAtBottom) {
1624
+ // Pin to bottom if was at bottom
1625
+ newTerminal.scrollTop = newTerminal.scrollHeight;
1626
+ } else {
1627
+ // Restore previous position (clamped to max)
1628
+ const maxScroll = Math.max(newTerminal.scrollHeight - newTerminal.clientHeight, 0);
1629
+ newTerminal.scrollTop = Math.min(previousScrollTop, maxScroll);
1630
+ }
1631
}
1632
}
1633
}