From 132bfcebc0475d2925eba61fdc737dbb60de4020 Mon Sep 17 00:00:00 2001 From: 7418 <7418@openclaw.ai> Date: Fri, 13 Mar 2026 02:26:57 +0800 Subject: [PATCH] fix: disable terminal UI, fix hydration mismatch - Remove terminal button from UnifiedTopBar and TerminalDrawer rendering Terminal feature disabled until proper node-pty + xterm.js integration - Fix ChatListPanel hydration mismatch: chatListOpenRaw/chatListWidth used window-dependent initializers causing SSR/client divergence - Improve TerminalInstance for future use: stable useEffect deps, ANSI rendering via ansi-to-react, focus management - Clear CLAUDECODE env var in terminal-manager to allow nested sessions Co-Authored-By: Claude Opus 4.6 --- electron/terminal-manager.ts | 2 + package-lock.json | 4 +- package.json | 2 +- src/components/layout/AppShell.tsx | 38 +++++----- src/components/layout/UnifiedTopBar.tsx | 18 ----- src/components/terminal/TerminalInstance.tsx | 77 ++++++++++++++------ 6 files changed, 77 insertions(+), 64 deletions(-) diff --git a/electron/terminal-manager.ts b/electron/terminal-manager.ts index c4833d2..b128e8a 100644 --- a/electron/terminal-manager.ts +++ b/electron/terminal-manager.ts @@ -51,6 +51,8 @@ export class TerminalManager { COLUMNS: String(opts.cols), LINES: String(opts.rows), }; + // Allow launching Claude Code inside the terminal + delete env.CLAUDECODE; const child = spawn(shell, shellArgs, { cwd: opts.cwd, diff --git a/package-lock.json b/package-lock.json index 01a6198..212fff3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "codepilot", - "version": "0.34.1", + "version": "0.34.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "codepilot", - "version": "0.34.1", + "version": "0.34.2", "workspaces": [ "apps/*", "packages/*" diff --git a/package.json b/package.json index f58b35a..167b239 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "codepilot", - "version": "0.34.1", + "version": "0.34.2", "private": true, "workspaces": [ "apps/*", diff --git a/src/components/layout/AppShell.tsx b/src/components/layout/AppShell.tsx index 5142b6e..2d68717 100644 --- a/src/components/layout/AppShell.tsx +++ b/src/components/layout/AppShell.tsx @@ -17,7 +17,6 @@ import { ImageGenContext, useImageGenState } from "@/hooks/useImageGen"; import { BatchImageGenContext, useBatchImageGenState } from "@/hooks/useBatchImageGen"; import { SplitContext, type SplitSession } from "@/hooks/useSplit"; import { SplitChatContainer } from "./SplitChatContainer"; -import { TerminalDrawer } from "@/components/terminal/TerminalDrawer"; import { ErrorBoundary } from "./ErrorBoundary"; import { getActiveSessionIds, getSnapshot } from "@/lib/stream-session-manager"; import { useGitStatus } from "@/hooks/useGitStatus"; @@ -69,16 +68,25 @@ export function AppShell({ children }: { children: React.ReactNode }) { const pathname = usePathname(); const router = useRouter(); - const [chatListOpenRaw, setChatListOpenRaw] = useState(() => { - if (typeof window === "undefined") return false; - return window.matchMedia(`(min-width: ${LG_BREAKPOINT}px)`).matches; - }); + const [chatListOpenRaw, setChatListOpenRaw] = useState(false); + + // Sync with viewport after hydration to avoid SSR mismatch + /* eslint-disable react-hooks/set-state-in-effect */ + useEffect(() => { + setChatListOpenRaw(window.matchMedia(`(min-width: ${LG_BREAKPOINT}px)`).matches); + }, []); + /* eslint-enable react-hooks/set-state-in-effect */ // Panel width state with localStorage persistence - const [chatListWidth, setChatListWidth] = useState(() => { - if (typeof window === "undefined") return 240; - return parseInt(localStorage.getItem("codepilot_chatlist_width") || "240"); - }); + const [chatListWidth, setChatListWidth] = useState(240); + + // Restore persisted width after hydration + /* eslint-disable react-hooks/set-state-in-effect */ + useEffect(() => { + const saved = localStorage.getItem("codepilot_chatlist_width"); + if (saved) setChatListWidth(parseInt(saved)); + }, []); + /* eslint-enable react-hooks/set-state-in-effect */ const handleChatListResize = useCallback((delta: number) => { setChatListWidth((w) => Math.min(CHATLIST_MAX, Math.max(CHATLIST_MIN, w + delta))); @@ -305,17 +313,6 @@ export function AppShell({ children }: { children: React.ReactNode }) { return () => mql.removeEventListener("change", handler); }, []); - // Ctrl+` / Cmd+` toggles terminal drawer - useEffect(() => { - const handler = (e: KeyboardEvent) => { - if (e.key === '`' && (e.ctrlKey || e.metaKey)) { - e.preventDefault(); - setTerminalOpen((prev) => !prev); - } - }; - window.addEventListener('keydown', handler); - return () => window.removeEventListener('keydown', handler); - }, []); // --- Skip-permissions indicator --- const [skipPermissionsActive, setSkipPermissionsActive] = useState(false); @@ -417,7 +414,6 @@ export function AppShell({ children }: { children: React.ReactNode }) { {children} )} - {isChatDetailRoute && } {isChatDetailRoute && } diff --git a/src/components/layout/UnifiedTopBar.tsx b/src/components/layout/UnifiedTopBar.tsx index f85c89e..a3e6f85 100644 --- a/src/components/layout/UnifiedTopBar.tsx +++ b/src/components/layout/UnifiedTopBar.tsx @@ -7,7 +7,6 @@ import { GitCommit, CloudArrowUp, TreeStructure, - Terminal, PencilSimple, DotOutline, CaretDown, @@ -39,8 +38,6 @@ export function UnifiedTopBar() { setFileTreeOpen, gitPanelOpen, setGitPanelOpen, - terminalOpen, - setTerminalOpen, currentBranch, gitDirtyCount, } = usePanel(); @@ -291,21 +288,6 @@ export function UnifiedTopBar() { {t('topBar.git')} - - - - - {t('topBar.terminal')} - -