fix: preserve terminal buffer content across float/dock moves and grid rebuilds#76
Conversation
…d rebuilds When a terminal is moved between tiled and floating mode, or when the grid layout rebuilds (e.g. adding a new terminal), the React TerminalPanel component unmounts and remounts. The unmount calls term.dispose() which destroys the xterm.js buffer, leaving the terminal blank. Fix: use @xterm/addon-serialize to snapshot the buffer before dispose and restore it when the component remounts. A lightweight cache module manages the snapshots with a configurable TTL (default 10s) and a 2MB size cap to prevent memory bloat from orphaned or oversized entries. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… test The original PR scheduled a setTimeout per save without tracking it. A re-save of the same id within EXPIRY_MS would leave the older timer running, and that older timer would silently delete the fresher snapshot before the next remount could read it. Realistic trigger: a rapid float → dock → float in <10s. Track timers in a parallel Map keyed by terminal id and clear the previous timer on every save / pop. Adds an e2e regression spec that drops a sentinel into the focused pane's xterm buffer, moves it tiled → floating → tiled, and asserts the sentinel survives both transitions. Locks in the buffer-preservation behavior so future changes can't silently regress it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Pushed two follow-ups onto this branch (commit 7f41459):
Otherwise the original implementation reads cleanly - good catch on flushing |
Problem
When a terminal is moved between tiled ↔ floating mode (dock/undock), or when a new terminal is added in grid mode, the terminal content disappears — the pane goes blank. The PTY process is still alive, but the user loses all visible output and scrollback.
Root Cause
TerminalPanelcreates an xterm.jsTerminalin auseEffect. When moved:floatingPanels(or vice versa) → React unmounts oldTerminalPanel, mounts new one.buildGridTree()creates new split node IDs → React keys change → existing components remount.On unmount,
term.dispose()destroys the entire xterm buffer.Fix
Use
@xterm/addon-serializeto snapshot the buffer beforedispose()and restore it on remount.Cache safety
Files Changed
package.json— added@xterm/addon-serializesrc/renderer/terminal-buffer-cache.ts— new module for buffer snapshotssrc/renderer/components/TerminalPanel.tsx— serialize on cleanup, restore on init