diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx index 76133712d4..bd6d481084 100644 --- a/apps/web/src/components/ChatView.tsx +++ b/apps/web/src/components/ChatView.tsx @@ -4309,6 +4309,7 @@ export default function ChatView({ threadId }: ChatViewProps) { onCloseTerminal={closeTerminal} onHeightChange={setTerminalHeight} onAddTerminalContext={addTerminalContextToDraft} + keybindings={keybindings} /> ); })()} diff --git a/apps/web/src/components/ThreadTerminalDrawer.tsx b/apps/web/src/components/ThreadTerminalDrawer.tsx index 1bdbfb6ad6..4bcd531236 100644 --- a/apps/web/src/components/ThreadTerminalDrawer.tsx +++ b/apps/web/src/components/ThreadTerminalDrawer.tsx @@ -1,6 +1,6 @@ import { FitAddon } from "@xterm/addon-fit"; import { Plus, SquareSplitHorizontal, TerminalSquare, Trash2, XIcon } from "lucide-react"; -import { type ThreadId } from "@t3tools/contracts"; +import { type ResolvedKeybindingsConfig, type ThreadId } from "@t3tools/contracts"; import { Terminal, type ITheme } from "@xterm/xterm"; import { type PointerEvent as ReactPointerEvent, @@ -19,7 +19,15 @@ import { isTerminalLinkActivation, resolvePathLinkTarget, } from "../terminal-links"; -import { isTerminalClearShortcut, terminalNavigationShortcutData } from "../keybindings"; +import { + isDiffToggleShortcut, + isTerminalClearShortcut, + isTerminalCloseShortcut, + isTerminalNewShortcut, + isTerminalSplitShortcut, + isTerminalToggleShortcut, + terminalNavigationShortcutData, +} from "../keybindings"; import { DEFAULT_THREAD_TERMINAL_HEIGHT, DEFAULT_THREAD_TERMINAL_ID, @@ -192,6 +200,7 @@ interface TerminalViewportProps { autoFocus: boolean; resizeEpoch: number; drawerHeight: number; + keybindings: ResolvedKeybindingsConfig; } function TerminalViewport({ @@ -206,6 +215,7 @@ function TerminalViewport({ autoFocus, resizeEpoch, drawerHeight, + keybindings, }: TerminalViewportProps) { const containerRef = useRef(null); const terminalRef = useRef(null); @@ -220,6 +230,11 @@ function TerminalViewport({ const selectionActionOpenRef = useRef(false); const selectionActionTimerRef = useRef(null); + const keybindingsRef = useRef(keybindings); + useEffect(() => { + keybindingsRef.current = keybindings; + }, [keybindings]); + useEffect(() => { onSessionExitedRef.current = onSessionExited; }, [onSessionExited]); @@ -343,6 +358,18 @@ function TerminalViewport({ }; terminal.attachCustomKeyEventHandler((event) => { + const currentKeybindings = keybindingsRef.current; + const options = { context: { terminalFocus: true, terminalOpen: true } }; + if ( + isTerminalToggleShortcut(event, currentKeybindings, options) || + isTerminalSplitShortcut(event, currentKeybindings, options) || + isTerminalNewShortcut(event, currentKeybindings, options) || + isTerminalCloseShortcut(event, currentKeybindings, options) || + isDiffToggleShortcut(event, currentKeybindings, options) + ) { + return false; + } + const navigationData = terminalNavigationShortcutData(event); if (navigationData !== null) { event.preventDefault(); @@ -662,6 +689,7 @@ interface ThreadTerminalDrawerProps { onCloseTerminal: (terminalId: string) => void; onHeightChange: (height: number) => void; onAddTerminalContext: (selection: TerminalContextSelection) => void; + keybindings: ResolvedKeybindingsConfig; } interface TerminalActionButtonProps { @@ -712,6 +740,7 @@ export default function ThreadTerminalDrawer({ onCloseTerminal, onHeightChange, onAddTerminalContext, + keybindings, }: ThreadTerminalDrawerProps) { const [drawerHeight, setDrawerHeight] = useState(() => clampDrawerHeight(height)); const [resizeEpoch, setResizeEpoch] = useState(0); @@ -1017,6 +1046,7 @@ export default function ThreadTerminalDrawer({ autoFocus={terminalId === resolvedActiveTerminalId} resizeEpoch={resizeEpoch} drawerHeight={drawerHeight} + keybindings={keybindings} /> @@ -1037,6 +1067,7 @@ export default function ThreadTerminalDrawer({ autoFocus resizeEpoch={resizeEpoch} drawerHeight={drawerHeight} + keybindings={keybindings} /> )}