refactor(terminal): explicit history buffer + virtual scrolling
Replace the spacer-estimate scrollback model with an explicit history row buffer owned by TerminalCore, rendered with absolute-positioned virtual scrolling so huge outputs (cat of 50k-line files) stay smooth. core.rs: - TerminalCore owns history_rows + a cached screen, captured after each process() via a bounded "conveyor belt" read of vt100 scrollback - feed bytes in newline-bounded safe slices so a capture never reads deeper than viewport_rows (works around vt100 0.15 visible_rows subtract-overflow panic) - handle clear (ESC[3J) by wiping our own history buffer - TerminalSegment carries grid column count for exact-width rendering - collect_window() clones only the visible slice component.rs: - TerminalCore lives in an RwSignal; render driven by an rAF-coalesced render_tick so packet bursts collapse into one frame - virtual_window pins to the bottom in live mode, follows scroll_top in history mode; absolute-positioned rows in a fixed-height sizer keep scroll geometry constant (fixes the "keeps drifting up" bounce) - position-based programmatic-scroll detection replaces the racy ignore-next-scroll flag - alt-screen wheel events translate to arrow keys (vim/less paging) - try_* signal access guards against disposal during hydration style: lock row height to 18px, segment width to Nch (exact grid so fallback-font glyphs like btm braille can't push the row sideways), absolute-position the virtual rows layer. Adds 12 unit tests (capture, clear, alt-screen, window slicing, wheel mapping) and TERMINAL_ROADMAP.md tracking xterm.js parity work. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -631,16 +631,23 @@
|
||||
}
|
||||
|
||||
.terminal-grid {
|
||||
@apply flex min-h-full flex-col;
|
||||
position: relative;
|
||||
display: block;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.terminal-row {
|
||||
height: 18px;
|
||||
min-height: 18px;
|
||||
max-height: 18px;
|
||||
overflow: hidden;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.terminal-segment {
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
vertical-align: top;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
@@ -650,11 +657,23 @@
|
||||
box-shadow: 0 0 0 1px rgb(219 234 254 / 30%);
|
||||
}
|
||||
|
||||
.terminal-scroll-spacer {
|
||||
/* Absolute-positioning virtual scroll: the sizer holds the full content
|
||||
height so the scroll geometry is constant; the rows layer is translated
|
||||
to the visible window's offset. */
|
||||
.terminal-virtual-sizer {
|
||||
display: block;
|
||||
width: 100%;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.terminal-virtual-rows {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.terminal-measure {
|
||||
position: absolute;
|
||||
left: -9999px;
|
||||
|
||||
Reference in New Issue
Block a user