mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-08 16:39:42 +02:00
fix(terminal): stop the backpressure refresh yanking and shrinking the buffer
Two further instances of the same root cause, both in _onSessionNeedsRefresh, which is SERVER-triggered (it fires after SSE backpressure clears) so the user has no gesture to blame the result on. 1. It ended in an unconditional scrollToBottom, so a user quietly reading scrollback was dropped to the live output by a background event. It now holds their place. The rewrite REPLACES the buffer, so an absolute viewportY captured beforehand is meaningless afterwards; distance from the bottom is the anchor that survives, via computeRewriteScrollLine(). 2. It rebuilt the terminal from a 1MB TAIL. Measured end to end on a 900-line shell pane: an 869-row buffer came back as 158 rows, so the refresh meant to REPAIR the display was destroying most of the scrollback every time it ran. It now asks for full history, and falls back to the tail only when _replayWouldShrinkBuffer refuses the capture, which keeps repaint-mode panes (tmux holds roughly one frame for them) exactly as they were. Also records truncation state here, so the #258 banner stops describing the pre-refresh buffer. Verified in a real browser against a live session: baseY 869 -> 869 where it used to be 869 -> 158, a reader 200 lines up stays 200 lines up, and a follower stays pinned to the bottom. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -848,6 +848,26 @@ function computeHistoryTruncationNotice(state = {}) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Where to land after a rewrite that REPLACES the whole buffer (#259).
|
||||
*
|
||||
* The backpressure refresh clears and reloads the terminal from a fresh tail,
|
||||
* so an absolute viewportY captured beforehand means nothing afterwards: the
|
||||
* line it pointed at may not even exist. Distance from the BOTTOM is the anchor
|
||||
* that survives a rewrite, so a reader stays roughly where they were reading.
|
||||
*
|
||||
* Returns null when the user was following live output, which the caller reads
|
||||
* as "scroll to bottom" — the historical behavior, kept for that case.
|
||||
*
|
||||
* @param {{linesFromBottom?: number, baseY?: number}} input
|
||||
* @returns {number|null}
|
||||
*/
|
||||
function computeRewriteScrollLine(input) {
|
||||
const linesFromBottom = input?.linesFromBottom || 0;
|
||||
if (!(linesFromBottom > 0)) return null;
|
||||
return Math.max(0, (input?.baseY || 0) - linesFromBottom);
|
||||
}
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
window.CodemanHistoryFormat = { formatHistoryBytes, computeHistoryTruncationNotice };
|
||||
window.CodemanHistoryFormat = { formatHistoryBytes, computeHistoryTruncationNotice, computeRewriteScrollLine };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user