Fix terminal not loading when first tabbed to.
The terminal for some reason, at least in Safari, thought it was
really small, so it would be hard to use until you resized your window.
I got Claude, below, to make it lazily init when you tab to the
terminal view, which is better anyway.
Implement lazy initialization for sketch-terminal component
Instead of initializing the terminal when the component is created (which causes sizing issues when the terminal isn't visible), this change defers initialization until the terminal tab is actually activated.
This solves the problem where the terminal was initialized with strange dimensions because:
1. The terminal is now only initialized when its tab is visible
2. We use a flag to track initialization state
3. The resize handler only runs for initialized terminals
This approach is more efficient and avoids unnecessary initialization when the terminal isn't being used.
Co-Authored-By: sketch <hello@sketch.dev>
diff --git a/webui/src/web-components/sketch-terminal.ts b/webui/src/web-components/sketch-terminal.ts
index 4ffccfd..b405657 100644
--- a/webui/src/web-components/sketch-terminal.ts
+++ b/webui/src/web-components/sketch-terminal.ts
@@ -11,6 +11,8 @@
private terminal: Terminal | null = null;
// Terminal fit addon for handling resize
private fitAddon: FitAddon | null = null;
+ // Flag to track if terminal has been fully initialized
+ private isInitialized: boolean = false;
// Terminal EventSource for SSE
private terminalEventSource: EventSource | null = null;
// Terminal ID (always 1 for now, will support 1-9 later)
@@ -50,12 +52,18 @@
this.loadXtermlCSS();
// Setup resize handler
window.addEventListener("resize", this._resizeHandler);
+ // Listen for view mode changes to detect when terminal becomes visible
+ window.addEventListener(
+ "view-mode-select",
+ this._handleViewModeSelect.bind(this),
+ );
}
disconnectedCallback() {
super.disconnectedCallback();
window.removeEventListener("resize", this._resizeHandler);
+ window.removeEventListener("view-mode-select", this._handleViewModeSelect);
this.closeTerminalConnections();
@@ -67,17 +75,40 @@
}
firstUpdated() {
- this.initializeTerminal();
+ // Do nothing - we'll initialize the terminal when it becomes visible
}
_resizeHandler() {
- if (this.fitAddon) {
+ // Only handle resize if terminal has been initialized
+ if (this.fitAddon && this.isInitialized) {
this.fitAddon.fit();
// Send resize information to server
this.sendTerminalResize();
}
}
+ /**
+ * Handle view mode selection event to detect when terminal becomes visible
+ */
+ private _handleViewModeSelect(event: CustomEvent) {
+ const mode = event.detail.mode as "chat" | "diff" | "terminal";
+ if (mode === "terminal") {
+ // Terminal tab is now visible
+ if (!this.isInitialized) {
+ // First time the terminal is shown - initialize it
+ this.isInitialized = true;
+ setTimeout(() => this.initializeTerminal(), 10);
+ } else if (this.fitAddon) {
+ // Terminal already initialized - just resize it
+ setTimeout(() => {
+ this.fitAddon?.fit();
+ this.sendTerminalResize();
+ this.terminal?.focus();
+ }, 10);
+ }
+ }
+ }
+
// Load xterm CSS into the shadow DOM
private async loadXtermlCSS() {
try {