fix: terminal resize on tab switch + flickering from activity marking
All checks were successful
Build & Sign Wraith / Build Windows + Sign (push) Successful in 4m8s

Resize fix:
- ResizeObserver now checks contentRect dimensions before fitting
- Ignores resize events when container width/height < 50px (hidden tab)
- Prevents xterm.js from calculating 8-char columns on zero-width containers

Flickering fix:
- markActivity throttled to once per second per session
- Was firing on every single data event (hundreds per second during
  active output), triggering Vue reactivity updates on the sessions
  array, causing tab bar and session container re-renders

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Vantz Stockwell 2026-03-26 16:48:43 -04:00
parent 661490e925
commit 2307fbe65f

View File

@ -163,9 +163,16 @@ export function useTerminal(sessionId: string, backend: 'ssh' | 'pty' = 'ssh'):
// Subscribe to SSH output events for this session. // Subscribe to SSH output events for this session.
// Tauri v2 listen() callback receives { payload: T } — the base64 string // Tauri v2 listen() callback receives { payload: T } — the base64 string
// is in event.payload (not event.data as in Wails). // is in event.payload (not event.data as in Wails).
// Throttle activity marking to avoid Vue reactivity storms
let lastActivityMark = 0;
unlistenPromise = listen<string>(dataEvent, (event) => { unlistenPromise = listen<string>(dataEvent, (event) => {
// Mark tab activity for background sessions // Mark tab activity at most once per second
try { useSessionStore().markActivity(sessionId); } catch {} const now = Date.now();
if (now - lastActivityMark > 1000) {
lastActivityMark = now;
try { useSessionStore().markActivity(sessionId); } catch {}
}
const b64data = event.payload; const b64data = event.payload;
@ -193,9 +200,12 @@ export function useTerminal(sessionId: string, backend: 'ssh' | 'pty' = 'ssh'):
unlistenFn = fn; unlistenFn = fn;
}); });
// Auto-fit when the container resizes // Auto-fit when the container resizes — but only if visible
resizeObserver = new ResizeObserver(() => { resizeObserver = new ResizeObserver((entries) => {
fitAddon.fit(); const entry = entries[0];
if (entry && entry.contentRect.width > 50 && entry.contentRect.height > 50) {
fitAddon.fit();
}
}); });
resizeObserver.observe(container); resizeObserver.observe(container);
} }