From 931ea9794284d36da40288b97cd3ef17b0fe809e Mon Sep 17 00:00:00 2001 From: Christoph Leiter Date: Thu, 18 Jun 2026 18:55:38 +0200 Subject: [PATCH 1/3] fix(app): reveal workspace-jump numbers only for the active modifier (#1580) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Holding the workspace-jump modifier reveals numbered badges in the sidebar for jumping to a workspace (Cmd+1..9). On the desktop app the badges also appeared while holding Option or Control, neither of which performs the jump โ€” only Cmd does on macOS desktop (Ctrl on non-Mac, Alt on web). The keydown/keyup handler flagged badge visibility for Alt on every runtime and for both Meta and Control on desktop โ€” broader than the active workspace.navigate.index binding. Gate the badges to the single modifier that performs the jump on the current runtime, via a new getWorkspaceIndexJumpModifierKey helper. Adds unit tests for the three runtime cases. Co-authored-by: Claude Opus 4.8 --- .../app/src/hooks/use-keyboard-shortcuts.ts | 29 ++++++++++++------- .../src/keyboard/keyboard-shortcuts.test.ts | 16 ++++++++++ .../app/src/keyboard/keyboard-shortcuts.ts | 15 ++++++++++ 3 files changed, 50 insertions(+), 10 deletions(-) diff --git a/packages/app/src/hooks/use-keyboard-shortcuts.ts b/packages/app/src/hooks/use-keyboard-shortcuts.ts index ae0671c25..eb58f3ba6 100644 --- a/packages/app/src/hooks/use-keyboard-shortcuts.ts +++ b/packages/app/src/hooks/use-keyboard-shortcuts.ts @@ -9,6 +9,7 @@ import { type ChordState, resolveKeyboardShortcut, buildEffectiveBindings, + getWorkspaceIndexJumpModifierKey, } from "@/keyboard/keyboard-shortcuts"; import { resolveKeyboardFocusScope } from "@/keyboard/focus-scope"; import { @@ -73,6 +74,20 @@ export function useKeyboardShortcuts({ const isDesktopApp = getIsElectronRuntime(); const isMac = getShortcutOs() === "mac"; + // Only the modifier that actually performs the workspace-index jump on this + // runtime should reveal the sidebar number badges (Alt on web, Cmd on + // desktop Mac, Ctrl on desktop non-Mac). The store ORs altDown/cmdOrCtrlDown + // to drive badge visibility, so we set the flag matching this runtime. + const badgeModifierKey = getWorkspaceIndexJumpModifierKey({ isMac, isDesktop: isDesktopApp }); + const setBadgeModifierDown = (down: boolean) => { + const state = useKeyboardShortcutsStore.getState(); + if (isDesktopApp) { + state.setCmdOrCtrlDown(down); + } else { + state.setAltDown(down); + } + }; + const shouldHandle = () => { if (typeof document === "undefined") return false; if (document.visibilityState !== "visible") return false; @@ -156,11 +171,8 @@ export function useKeyboardShortcuts({ } const key = event.key ?? ""; - if (key === "Alt" && !event.shiftKey) { - useKeyboardShortcutsStore.getState().setAltDown(true); - } - if (isDesktopApp && (key === "Meta" || key === "Control") && !event.shiftKey) { - useKeyboardShortcutsStore.getState().setCmdOrCtrlDown(true); + if (key === badgeModifierKey && !event.shiftKey) { + setBadgeModifierDown(true); } if (key === "Shift") { const state = useKeyboardShortcutsStore.getState(); @@ -231,11 +243,8 @@ export function useKeyboardShortcuts({ const handleKeyUp = (event: KeyboardEvent) => { const key = event.key ?? ""; - if (key === "Alt") { - useKeyboardShortcutsStore.getState().setAltDown(false); - } - if (isDesktopApp && (key === "Meta" || key === "Control")) { - useKeyboardShortcutsStore.getState().setCmdOrCtrlDown(false); + if (key === badgeModifierKey) { + setBadgeModifierDown(false); } }; diff --git a/packages/app/src/keyboard/keyboard-shortcuts.test.ts b/packages/app/src/keyboard/keyboard-shortcuts.test.ts index a797aea9b..bec812563 100644 --- a/packages/app/src/keyboard/keyboard-shortcuts.test.ts +++ b/packages/app/src/keyboard/keyboard-shortcuts.test.ts @@ -3,6 +3,7 @@ import { buildKeyboardShortcutHelpSections, buildEffectiveBindings, getBindingIdForAction, + getWorkspaceIndexJumpModifierKey, resolveKeyboardShortcut, type ChordState, type KeyboardShortcutContext, @@ -638,3 +639,18 @@ describe("keyboard-shortcut help sections", () => { ).toBeNull(); }); }); + +describe("getWorkspaceIndexJumpModifierKey", () => { + it("uses Alt on web, regardless of OS", () => { + expect(getWorkspaceIndexJumpModifierKey({ isMac: true, isDesktop: false })).toBe("Alt"); + expect(getWorkspaceIndexJumpModifierKey({ isMac: false, isDesktop: false })).toBe("Alt"); + }); + + it("uses Cmd (Meta) on desktop Mac, not Control or Alt", () => { + expect(getWorkspaceIndexJumpModifierKey({ isMac: true, isDesktop: true })).toBe("Meta"); + }); + + it("uses Ctrl on desktop non-Mac, not Meta or Alt", () => { + expect(getWorkspaceIndexJumpModifierKey({ isMac: false, isDesktop: true })).toBe("Control"); + }); +}); diff --git a/packages/app/src/keyboard/keyboard-shortcuts.ts b/packages/app/src/keyboard/keyboard-shortcuts.ts index d3fbbd088..40358977d 100644 --- a/packages/app/src/keyboard/keyboard-shortcuts.ts +++ b/packages/app/src/keyboard/keyboard-shortcuts.ts @@ -1344,6 +1344,21 @@ export function getDefaultKeysForAction( return null; } +/** + * The `KeyboardEvent.key` whose hold reveals the sidebar workspace-jump number + * badges. It must match the modifier of the active `workspace.navigate.index` + * binding for this runtime, otherwise the badges appear for a modifier that + * does not actually jump: Alt on web, Cmd (Meta) on desktop Mac, Ctrl on + * desktop non-Mac. + */ +export function getWorkspaceIndexJumpModifierKey(platform: { + isMac: boolean; + isDesktop: boolean; +}): "Alt" | "Meta" | "Control" { + if (!platform.isDesktop) return "Alt"; + return platform.isMac ? "Meta" : "Control"; +} + export function buildKeyboardShortcutHelpSections( input: KeyboardShortcutPlatformContext, bindings: readonly ParsedShortcutBinding[] = DEFAULT_BINDINGS, From 01a2afa7c55e64c71a7d60083962da046ce52027 Mon Sep 17 00:00:00 2001 From: V1rus <34763711+thaning0@users.noreply.github.com> Date: Fri, 19 Jun 2026 01:04:28 +0800 Subject: [PATCH 2/3] Fix markdown rendering hang on unmatched backticks (#1585) * fix: prevent infinite loop on unmatched backtick runs in getInlineCodeRanges * test: cover unmatched inline backtick runs --------- Co-authored-by: Mohamed Boudra --- packages/app/src/components/markdown/html-ish.test.ts | 6 ++++++ packages/app/src/components/markdown/html-ish.ts | 7 ++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/app/src/components/markdown/html-ish.test.ts b/packages/app/src/components/markdown/html-ish.test.ts index ac6f2ad8b..c47a718fe 100644 --- a/packages/app/src/components/markdown/html-ish.test.ts +++ b/packages/app/src/components/markdown/html-ish.test.ts @@ -256,6 +256,12 @@ describe("splitHtmlishMarkdown", () => { expect(splitHtmlishMarkdown(source)).toEqual([{ kind: "markdown", text: source }]); }); + it("terminates when an unmatched backtick follows a closed inline code span", () => { + const source = "Use `
ExampleBody
` before `dangling"; + + expect(splitHtmlishMarkdown(source)).toEqual([{ kind: "markdown", text: source }]); + }); + it("still parses normal details outside code", () => { expect(splitHtmlishMarkdown("`code`\n
RealBody
")).toEqual([ { kind: "markdown", text: "`code`\n" }, diff --git a/packages/app/src/components/markdown/html-ish.ts b/packages/app/src/components/markdown/html-ish.ts index b68e734b5..7a92f0d20 100644 --- a/packages/app/src/components/markdown/html-ish.ts +++ b/packages/app/src/components/markdown/html-ish.ts @@ -651,8 +651,13 @@ function getInlineCodeRanges( } const marker = open[0]; - const close = findClosingBacktickRun(source, BACKTICK_RUN_RE.lastIndex, marker, fencedRanges); + const afterOpen = BACKTICK_RUN_RE.lastIndex; + const close = findClosingBacktickRun(source, afterOpen, marker, fencedRanges); if (!close) { + // Unmatched backtick run โ€” skip past it so the loop doesn't restart from 0. + // findClosingBacktickRun exhausts the global regex, which resets lastIndex + // to 0 when exec() returns null (ECMAScript ยง22.2.7.2). + BACKTICK_RUN_RE.lastIndex = afterOpen; continue; } From 8cc74fb75d690d5df2b284410d6ce0106bf219cb Mon Sep 17 00:00:00 2001 From: Myriad-Dreamin <35292584+Myriad-Dreamin@users.noreply.github.com> Date: Fri, 19 Jun 2026 01:27:47 +0800 Subject: [PATCH 3/3] Document filename:line:column file link parsing (#1560) * Reapply app file-open changes on v0.1.87 * fix: resolve relative assistant file links in workspace * fix: tighten file link and open intent parsing * Remove line and column from editor open targets * fix: drop column offsets from file links --- packages/app/src/assistant-file-links/parse.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/app/src/assistant-file-links/parse.ts b/packages/app/src/assistant-file-links/parse.ts index bd0015f0b..092f3b4dc 100644 --- a/packages/app/src/assistant-file-links/parse.ts +++ b/packages/app/src/assistant-file-links/parse.ts @@ -140,6 +140,7 @@ function parseLineFragment(value: string): Pick