diff --git a/apps/desktop/src/renderer/hotkeys/hooks/useRecordHotkeys/useRecordHotkeys.ts b/apps/desktop/src/renderer/hotkeys/hooks/useRecordHotkeys/useRecordHotkeys.ts index 8b52d9e552d..1ebda67fc62 100644 --- a/apps/desktop/src/renderer/hotkeys/hooks/useRecordHotkeys/useRecordHotkeys.ts +++ b/apps/desktop/src/renderer/hotkeys/hooks/useRecordHotkeys/useRecordHotkeys.ts @@ -136,7 +136,10 @@ export function useRecordHotkeys( } const defaultKey = HOTKEYS[recordingId].key; - if (canonicalizeChord(captured) === canonicalizeChord(defaultKey)) { + if ( + defaultKey && + canonicalizeChord(captured) === canonicalizeChord(defaultKey) + ) { resetOverride(recordingId); } else { setOverride(recordingId, captured); diff --git a/apps/desktop/src/renderer/hotkeys/registry.ts b/apps/desktop/src/renderer/hotkeys/registry.ts index d79b3e514bb..4f0cffe8b44 100644 --- a/apps/desktop/src/renderer/hotkeys/registry.ts +++ b/apps/desktop/src/renderer/hotkeys/registry.ts @@ -102,22 +102,16 @@ export const HOTKEYS_REGISTRY = { category: "Workspace", }, PREV_WORKSPACE: { - key: { - mac: "meta+alt+up", - windows: "ctrl+shift+alt+up", - linux: "ctrl+shift+alt+up", - }, + key: { mac: null, windows: null, linux: null }, label: "Previous Workspace", category: "Workspace", + description: "Navigate to the previous workspace in the sidebar", }, NEXT_WORKSPACE: { - key: { - mac: "meta+alt+down", - windows: "ctrl+shift+alt+down", - linux: "ctrl+shift+alt+down", - }, + key: { mac: null, windows: null, linux: null }, label: "Next Workspace", category: "Workspace", + description: "Navigate to the next workspace in the sidebar", }, CLOSE_WORKSPACE: { key: { @@ -334,24 +328,6 @@ export const HOTKEYS_REGISTRY = { category: "Terminal", description: "Scroll the active terminal to the bottom", }, - PREV_TAB: { - key: { - mac: "meta+alt+left", - windows: "ctrl+shift+alt+left", - linux: "ctrl+shift+alt+left", - }, - label: "Previous Tab", - category: "Terminal", - }, - NEXT_TAB: { - key: { - mac: "meta+alt+right", - windows: "ctrl+shift+alt+right", - linux: "ctrl+shift+alt+right", - }, - label: "Next Tab", - category: "Terminal", - }, PREV_TAB_ALT: { key: { mac: "ctrl+shift+tab", @@ -366,6 +342,20 @@ export const HOTKEYS_REGISTRY = { label: "Next Tab (Alt)", category: "Terminal", }, + PREV_TAB: { + key: { mac: null, windows: null, linux: null }, + label: "Previous Tab", + category: "Terminal", + description: "Focus the previous tab in the active workspace", + }, + NEXT_TAB: { + key: { mac: null, windows: null, linux: null }, + label: "Next Tab", + category: "Terminal", + description: "Focus the next tab in the active workspace", + }, + // FORK NOTE: upstream renamed PREV_PANE → FOCUS_PANE_LEFT in #3403 (PR#3). + // Keep PREV_PANE until that cherry-pick is applied. PREV_PANE: { key: { mac: "meta+shift+left", diff --git a/apps/desktop/src/renderer/hotkeys/types.ts b/apps/desktop/src/renderer/hotkeys/types.ts index 7dc1e9d99e7..e98558c6e93 100644 --- a/apps/desktop/src/renderer/hotkeys/types.ts +++ b/apps/desktop/src/renderer/hotkeys/types.ts @@ -1,6 +1,10 @@ export type Platform = "mac" | "windows" | "linux"; -export type PlatformKey = { mac: string; windows: string; linux: string }; +export type PlatformKey = { + mac: string | null; + windows: string | null; + linux: string | null; +}; export type HotkeyCategory = | "Navigation" @@ -19,7 +23,7 @@ export interface HotkeyDisplay { } export interface HotkeyDefinition { - key: string; + key: string | null; label: string; category: HotkeyCategory; description?: string; diff --git a/apps/desktop/src/renderer/hotkeys/utils/resolveHotkeyFromEvent.test.ts b/apps/desktop/src/renderer/hotkeys/utils/resolveHotkeyFromEvent.test.ts index e2336f26946..237c328e983 100644 --- a/apps/desktop/src/renderer/hotkeys/utils/resolveHotkeyFromEvent.test.ts +++ b/apps/desktop/src/renderer/hotkeys/utils/resolveHotkeyFromEvent.test.ts @@ -1,6 +1,7 @@ import { afterEach, beforeEach, describe, expect, it } from "bun:test"; -import { HOTKEYS } from "../registry"; +import { HOTKEYS, type HotkeyId } from "../registry"; import { useHotkeyOverridesStore } from "../stores/hotkeyOverridesStore"; +import type { HotkeyDefinition } from "../types"; import { canonicalizeChord, eventToChord, @@ -148,10 +149,13 @@ describe("resolveHotkeyFromEvent — live override index", () => { }); // Resolve once so registry reorders / removals surface as a test failure - // here instead of silently skipping the cases below. - const sampleEntry = ( - Object.entries(HOTKEYS) as [keyof typeof HOTKEYS, { key: string }][] - ).find(([, hotkey]) => !!hotkey.key); + // here instead of silently skipping the cases below. The type predicate + // narrows to a HotkeyDefinition whose .key is guaranteed non-null after + // the filter, so sampleDef.key can be passed to string-only helpers below. + const sampleEntry = Object.entries(HOTKEYS).find( + (entry): entry is [HotkeyId, HotkeyDefinition & { key: string }] => + entry[1].key !== null, + ); if (!sampleEntry) throw new Error("HOTKEYS has no bound default"); const [sampleId, sampleDef] = sampleEntry; diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/hooks/useDashboardSidebarShortcuts/useDashboardSidebarShortcuts.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/hooks/useDashboardSidebarShortcuts/useDashboardSidebarShortcuts.ts index eaedf913f8a..ae1947b96a0 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/hooks/useDashboardSidebarShortcuts/useDashboardSidebarShortcuts.ts +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/hooks/useDashboardSidebarShortcuts/useDashboardSidebarShortcuts.ts @@ -48,7 +48,6 @@ export function useDashboardSidebarShortcuts( useHotkey("JUMP_TO_WORKSPACE_8", () => switchToWorkspace(7)); useHotkey("JUMP_TO_WORKSPACE_9", () => switchToWorkspace(8)); - // Prev/next workspace navigation (cycles) const matchRoute = useMatchRoute(); const currentWorkspaceMatch = matchRoute({ to: "/v2-workspace/$workspaceId", @@ -62,6 +61,7 @@ export function useDashboardSidebarShortcuts( const index = flattenedWorkspaces.findIndex( (w) => w.id === currentWorkspaceId, ); + if (index === -1) return; const prevIndex = index <= 0 ? flattenedWorkspaces.length - 1 : index - 1; navigateToV2Workspace(flattenedWorkspaces[prevIndex].id, navigate); }); @@ -71,8 +71,8 @@ export function useDashboardSidebarShortcuts( const index = flattenedWorkspaces.findIndex( (w) => w.id === currentWorkspaceId, ); - const nextIndex = - index >= flattenedWorkspaces.length - 1 || index === -1 ? 0 : index + 1; + if (index === -1) return; + const nextIndex = index >= flattenedWorkspaces.length - 1 ? 0 : index + 1; navigateToV2Workspace(flattenedWorkspaces[nextIndex].id, navigate); });