From 2307fbe65fdc4e28b7b0fdc8b3cac5a42a6079a1 Mon Sep 17 00:00:00 2001 From: Vantz Stockwell Date: Thu, 26 Mar 2026 16:48:43 -0400 Subject: [PATCH] fix: terminal resize on tab switch + flickering from activity marking 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) --- src/composables/useTerminal.ts | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/composables/useTerminal.ts b/src/composables/useTerminal.ts index e672fbb..427910c 100644 --- a/src/composables/useTerminal.ts +++ b/src/composables/useTerminal.ts @@ -163,9 +163,16 @@ export function useTerminal(sessionId: string, backend: 'ssh' | 'pty' = 'ssh'): // Subscribe to SSH output events for this session. // Tauri v2 listen() callback receives { payload: T } — the base64 string // is in event.payload (not event.data as in Wails). + // Throttle activity marking to avoid Vue reactivity storms + let lastActivityMark = 0; + unlistenPromise = listen(dataEvent, (event) => { - // Mark tab activity for background sessions - try { useSessionStore().markActivity(sessionId); } catch {} + // Mark tab activity at most once per second + const now = Date.now(); + if (now - lastActivityMark > 1000) { + lastActivityMark = now; + try { useSessionStore().markActivity(sessionId); } catch {} + } const b64data = event.payload; @@ -193,9 +200,12 @@ export function useTerminal(sessionId: string, backend: 'ssh' | 'pty' = 'ssh'): unlistenFn = fn; }); - // Auto-fit when the container resizes - resizeObserver = new ResizeObserver(() => { - fitAddon.fit(); + // Auto-fit when the container resizes — but only if visible + resizeObserver = new ResizeObserver((entries) => { + const entry = entries[0]; + if (entry && entry.contentRect.width > 50 && entry.contentRect.height > 50) { + fitAddon.fit(); + } }); resizeObserver.observe(container); }