From d894cd9723a03cd232aa7fb3889067dece366b2c Mon Sep 17 00:00:00 2001 From: Developer Date: Tue, 2 Jun 2026 14:03:47 +0000 Subject: [PATCH] fix: terminal shift-left bug and session sidebar naming/filtering - Guard ResizeObserver in terminal against internal xterm DOM changes by tracking last width/height and only calling fit() on real resize - Remove padding from .terminal-container and conflicting .xterm height override that caused measurement mismatches with xterm-addon-fit - Filter live session sidebar to active statuses only (running, building, pending) instead of showing all sessions including stopped ones - Add display name fallback across sidebar, sessions page, and instance list to prevent blank names when display_name is empty Quality gates: tsc (pass), eslint (pass) --- .gitignore | 5 +++++ apps/web/src/components/app-shell.tsx | 17 +++++++++++------ apps/web/src/components/instance-list.tsx | 2 +- apps/web/src/components/terminal.tsx | 16 +++++++++++++++- apps/web/src/pages/sessions.tsx | 6 +++--- apps/web/src/styles.css | 5 ----- 6 files changed, 35 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index f2bf502..1be2f5c 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,8 @@ apps/web/dist/ # OS .DS_Store Thumbs.db + +# Local runtime state +.atl/ +.pi/ +swap-pane diff --git a/apps/web/src/components/app-shell.tsx b/apps/web/src/components/app-shell.tsx index fd2a02f..8d88626 100644 --- a/apps/web/src/components/app-shell.tsx +++ b/apps/web/src/components/app-shell.tsx @@ -16,8 +16,11 @@ const NAV_ITEMS: { to: string; label: string; icon: IconName }[] = [ { to: "/settings", label: "Settings", icon: "settings" } ]; +const ACTIVE_STATUSES = ["running", "building", "pending"]; + const SessionItem = ({ session }: { session: Session }) => { const isRunning = session.status === "running"; + const displayName = session.display_name || session.tool_type_name || "Unnamed Session"; return ( { target={session.url ? "_blank" : undefined} rel={session.url ? "noopener noreferrer" : undefined} className="nav-item session-item" - title={`${session.display_name} (${session.status})`} + title={`${displayName} (${session.status})`} > - {session.display_name} + {displayName} ); }; @@ -101,13 +104,15 @@ export const AppShell = () => { ); })} - {sessions.length > 0 && ( + {sessions.filter((s) => ACTIVE_STATUSES.includes(s.status)).length > 0 && ( <>
Live sessions
- {sessions.map((session) => ( - - ))} + {sessions + .filter((s) => ACTIVE_STATUSES.includes(s.status)) + .map((session) => ( + + ))} )} diff --git a/apps/web/src/components/instance-list.tsx b/apps/web/src/components/instance-list.tsx index d9ec05a..8079e20 100644 --- a/apps/web/src/components/instance-list.tsx +++ b/apps/web/src/components/instance-list.tsx @@ -194,7 +194,7 @@ export const InstanceList = ({ projectId, repoId, toolTypes }: InstanceListProps {instances.map((instance) => (
-
{instance.display_name}
+
{instance.display_name || instance.tool_type_name || "Unnamed Instance"}
= ({ // Resize observer for container-level resize detection let resizeTimeout: ReturnType | null = null; - const resizeObserver = new ResizeObserver(() => { + let lastWidth = 0; + let lastHeight = 0; + const resizeObserver = new ResizeObserver((entries) => { if (resizeTimeout) { clearTimeout(resizeTimeout); } + const entry = entries[0]; + if (!entry) return; + const { width, height } = entry.contentRect; resizeTimeout = setTimeout(() => { resizeTimeout = null; + // Guard against internal xterm DOM changes that don't affect container size + if ( + Math.abs(width - lastWidth) < 1 && + Math.abs(height - lastHeight) < 1 + ) { + return; + } + lastWidth = width; + lastHeight = height; const prevCols = term.cols; const prevRows = term.rows; fitAddon.fit(); diff --git a/apps/web/src/pages/sessions.tsx b/apps/web/src/pages/sessions.tsx index a548d19..72b8e41 100644 --- a/apps/web/src/pages/sessions.tsx +++ b/apps/web/src/pages/sessions.tsx @@ -266,7 +266,7 @@ export const SessionsPage = () => {

Last Session

-

{lastSession.display_name}

+

{lastSession.display_name || lastSession.tool_type_name || "Unnamed Session"}

{lastSession.tool_type_name} · {lastSession.project_name} · {lastSession.repository_name}

@@ -316,7 +316,7 @@ export const SessionsPage = () => { {activeSessions.map((session) => (
-

{session.display_name}

+

{session.display_name || session.tool_type_name || "Unnamed Session"}

{session.tool_type_name} · {session.project_name}

@@ -445,7 +445,7 @@ export const SessionsPage = () => { {recentSessions.map((session) => (
- {session.display_name} + {session.display_name || session.tool_type_name || "Unnamed Session"} {session.tool_type_name} · {session.project_name} diff --git a/apps/web/src/styles.css b/apps/web/src/styles.css index a03aaf4..b2ba341 100644 --- a/apps/web/src/styles.css +++ b/apps/web/src/styles.css @@ -2748,11 +2748,6 @@ a.nav-item, .terminal-container { flex: 1; min-height: 0; - padding: 0.25rem; -} - -.terminal-container .xterm { - height: 100%; } .terminal-container .xterm-viewport {