diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx index 428826f6ad..19dcba58ee 100644 --- a/packages/app/src/pages/session.tsx +++ b/packages/app/src/pages/session.tsx @@ -41,7 +41,13 @@ import { useSync } from "@/context/sync" import { useTerminal } from "@/context/terminal" import { type FollowupDraft, sendFollowupDraft } from "@/components/prompt-input/submit" import { createSessionComposerState, SessionComposerRegion } from "@/pages/session/composer" -import { createOpenReviewFile, createSessionTabs, createSizing, focusTerminalById } from "@/pages/session/helpers" +import { + createOpenReviewFile, + createSessionTabs, + createSizing, + focusTerminalById, + shouldFocusTerminalOnKeyDown, +} from "@/pages/session/helpers" import { MessageTimeline } from "@/pages/session/message-timeline" import { type DiffStyle, SessionReviewTab, type SessionReviewTabProps } from "@/pages/session/review-tab" import { useSessionLayout } from "@/pages/session/session-layout" @@ -850,7 +856,7 @@ export default function Page() { // Prefer the open terminal over the composer when it can take focus if (view().terminal.opened()) { const id = terminal.active() - if (id && focusTerminalById(id)) return + if (id && shouldFocusTerminalOnKeyDown(event) && focusTerminalById(id)) return } // Only treat explicit scroll keys as potential "user scroll" gestures. diff --git a/packages/app/src/pages/session/helpers.test.ts b/packages/app/src/pages/session/helpers.test.ts index 047946fc1e..95f7cd384d 100644 --- a/packages/app/src/pages/session/helpers.test.ts +++ b/packages/app/src/pages/session/helpers.test.ts @@ -7,6 +7,7 @@ import { createSessionTabs, focusTerminalById, getTabReorderIndex, + shouldFocusTerminalOnKeyDown, } from "./helpers" describe("createOpenReviewFile", () => { @@ -86,6 +87,26 @@ describe("focusTerminalById", () => { }) }) +describe("shouldFocusTerminalOnKeyDown", () => { + test("skips pure modifier keys", () => { + expect(shouldFocusTerminalOnKeyDown(new KeyboardEvent("keydown", { key: "Meta", metaKey: true }))).toBe(false) + expect(shouldFocusTerminalOnKeyDown(new KeyboardEvent("keydown", { key: "Control", ctrlKey: true }))).toBe(false) + expect(shouldFocusTerminalOnKeyDown(new KeyboardEvent("keydown", { key: "Alt", altKey: true }))).toBe(false) + expect(shouldFocusTerminalOnKeyDown(new KeyboardEvent("keydown", { key: "Shift", shiftKey: true }))).toBe(false) + }) + + test("skips shortcut key combos", () => { + expect(shouldFocusTerminalOnKeyDown(new KeyboardEvent("keydown", { key: "c", metaKey: true }))).toBe(false) + expect(shouldFocusTerminalOnKeyDown(new KeyboardEvent("keydown", { key: "c", ctrlKey: true }))).toBe(false) + expect(shouldFocusTerminalOnKeyDown(new KeyboardEvent("keydown", { key: "ArrowLeft", altKey: true }))).toBe(false) + }) + + test("keeps plain typing focused on terminal", () => { + expect(shouldFocusTerminalOnKeyDown(new KeyboardEvent("keydown", { key: "a" }))).toBe(true) + expect(shouldFocusTerminalOnKeyDown(new KeyboardEvent("keydown", { key: "A", shiftKey: true }))).toBe(true) + }) +}) + describe("getTabReorderIndex", () => { test("returns target index for valid drag reorder", () => { expect(getTabReorderIndex(["a", "b", "c"], "a", "c")).toBe(2) diff --git a/packages/app/src/pages/session/helpers.ts b/packages/app/src/pages/session/helpers.ts index c3571f3ffc..7e2c1ccf7b 100644 --- a/packages/app/src/pages/session/helpers.ts +++ b/packages/app/src/pages/session/helpers.ts @@ -93,6 +93,13 @@ export const focusTerminalById = (id: string) => { return true } +const skip = new Set(["Alt", "Control", "Meta", "Shift"]) + +export const shouldFocusTerminalOnKeyDown = (event: Pick) => { + if (skip.has(event.key)) return false + return !(event.ctrlKey || event.metaKey || event.altKey) +} + export const createOpenReviewFile = (input: { showAllFiles: () => void tabForPath: (path: string) => string