From fa17b1341319b7de3807d5a77f1496a477dc0598 Mon Sep 17 00:00:00 2001 From: Fusion Date: Sun, 24 May 2026 15:25:47 +0200 Subject: [PATCH] fix: wait for fonts and retry fit until proper dimensions - Wait for document.fonts.ready before fitting (ensures correct cell metrics) - Retry fit every 100ms if rows <= 1 or cols <= 10 (layout still settling) - Up to 30 retries (3 seconds) for layout to stabilize - Remove redundant delayed fits, keep only header auto-hide fit at 4s --- apps/web/src/components/terminal.tsx | 77 ++++++++++++---------------- 1 file changed, 34 insertions(+), 43 deletions(-) diff --git a/apps/web/src/components/terminal.tsx b/apps/web/src/components/terminal.tsx index f69bac2..93745f0 100644 --- a/apps/web/src/components/terminal.tsx +++ b/apps/web/src/components/terminal.tsx @@ -212,52 +212,43 @@ export const TerminalComponent: React.FC = ({ // Connect WebSocket ws = connectWebSocket(); - // Fit after layout settles - requestAnimationFrame(() => { + // Robust fitting: wait for fonts and stable dimensions + const performFit = () => { + fitAddon.fit(); + const { cols, rows } = term; + if (ws.readyState === WebSocket.OPEN) { + ws.send( + JSON.stringify({ + type: "resize", + cols, + rows, + }) + ); + } + return { cols, rows }; + }; + + const ensureProperFit = (attempt = 0) => { + const { cols, rows } = performFit(); + // If dimensions are unreasonably small, retry (layout still settling) + if ((rows <= 1 || cols <= 10) && attempt < 30) { + setTimeout(() => ensureProperFit(attempt + 1), 100); + } + }; + + // Wait for fonts to load, then fit with retry logic + document.fonts.ready.then(() => { requestAnimationFrame(() => { - fitAddon.fit(); - const { cols, rows } = term; - if (ws.readyState === WebSocket.OPEN) { - ws.send( - JSON.stringify({ - type: "resize", - cols, - rows, - }) - ); - } - - // Force a second fit after layout fully settles - setTimeout(() => { - fitAddon.fit(); - const { cols, rows } = term; - if (ws.readyState === WebSocket.OPEN) { - ws.send( - JSON.stringify({ - type: "resize", - cols, - rows, - }) - ); - } - }, 500); - - // Fit after mobile header auto-hides (3s delay + 0.3s transition) - setTimeout(() => { - fitAddon.fit(); - const { cols, rows } = term; - if (ws.readyState === WebSocket.OPEN) { - ws.send( - JSON.stringify({ - type: "resize", - cols, - rows, - }) - ); - } - }, 4000); + requestAnimationFrame(() => { + ensureProperFit(); + }); }); }); + + // Fit after mobile header auto-hides (3s delay + 0.3s transition) + setTimeout(() => { + performFit(); + }, 4000); }; // Check if container already has dimensions