From eb222144de7b45606f5b4bcc3f3c34ed65d84a7c Mon Sep 17 00:00:00 2001 From: Thomas Petersen Date: Wed, 3 Jun 2026 16:09:25 -0400 Subject: [PATCH] fix(desktop): keep profile shortcut out of editors Co-authored-by: Cursor --- desktop/src/app/AppShell.tsx | 35 +++---------- desktop/src/app/useSettingsShortcuts.ts | 66 +++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 28 deletions(-) create mode 100644 desktop/src/app/useSettingsShortcuts.ts diff --git a/desktop/src/app/AppShell.tsx b/desktop/src/app/AppShell.tsx index 1480c33159..b61f9ae6ba 100644 --- a/desktop/src/app/AppShell.tsx +++ b/desktop/src/app/AppShell.tsx @@ -12,6 +12,7 @@ import { AppTopChrome } from "@/app/AppTopChrome"; import { useAppNavigation } from "@/app/navigation/useAppNavigation"; import { useBackForwardControls } from "@/app/navigation/useBackForwardControls"; import { useMarkAsReadShortcuts } from "@/app/useMarkAsReadShortcuts"; +import { useSettingsShortcuts } from "@/app/useSettingsShortcuts"; import { useWebviewZoomShortcuts } from "@/app/useWebviewZoomShortcuts"; import { channelsQueryKey, @@ -588,34 +589,12 @@ export function AppShell() { settingsOpen, ]); - React.useLayoutEffect(() => { - function handleKeyDown(event: KeyboardEvent) { - const hasSettingsShortcutModifiers = - hasPrimaryShortcutModifier(event) && !event.altKey && !event.shiftKey; - const isSettingsShortcut = - hasSettingsShortcutModifiers && - (event.key === "," || event.code === "Comma"); - const isProfileShortcut = - hasSettingsShortcutModifiers && event.key.toLowerCase() === "u"; - - if (!isSettingsShortcut && !isProfileShortcut) { - return; - } - - event.preventDefault(); - if (settingsOpen && (!isProfileShortcut || settingsMode === "profile")) { - handleCloseSettings(); - return; - } - - handleOpenSettings(isProfileShortcut ? "profile" : undefined); - } - - window.addEventListener("keydown", handleKeyDown); - return () => { - window.removeEventListener("keydown", handleKeyDown); - }; - }, [handleCloseSettings, handleOpenSettings, settingsMode, settingsOpen]); + useSettingsShortcuts({ + mode: settingsMode, + onClose: handleCloseSettings, + onOpenSettings: handleOpenSettings, + open: settingsOpen, + }); useMarkAsReadShortcuts({ activeChannelId: activeChannel?.id ?? null, diff --git a/desktop/src/app/useSettingsShortcuts.ts b/desktop/src/app/useSettingsShortcuts.ts new file mode 100644 index 0000000000..952d6cbf88 --- /dev/null +++ b/desktop/src/app/useSettingsShortcuts.ts @@ -0,0 +1,66 @@ +import * as React from "react"; + +import { hasPrimaryShortcutModifier } from "@/shared/lib/platform"; + +const EDITABLE_SHORTCUT_TARGET_SELECTOR = + 'input, textarea, select, [contenteditable="true"]'; + +type SettingsMode = "profile" | "preferences"; + +type UseSettingsShortcutsOptions = { + mode: SettingsMode; + onClose: () => void; + onOpenSettings: (section?: "profile") => void; + open: boolean; +}; + +function isEditableShortcutTarget(event: KeyboardEvent) { + const target = event.target; + return ( + target instanceof Element && + target.closest(EDITABLE_SHORTCUT_TARGET_SELECTOR) + ); +} + +export function useSettingsShortcuts({ + mode, + onClose, + onOpenSettings, + open, +}: UseSettingsShortcutsOptions) { + React.useLayoutEffect(() => { + function handleKeyDown(event: KeyboardEvent) { + const hasSettingsShortcutModifiers = + hasPrimaryShortcutModifier(event) && !event.altKey && !event.shiftKey; + const isSettingsShortcut = + hasSettingsShortcutModifiers && + (event.key === "," || event.code === "Comma"); + const isProfileShortcut = + hasSettingsShortcutModifiers && + event.key.toLowerCase() === "u" && + !isEditableShortcutTarget(event); + + if (!isSettingsShortcut && !isProfileShortcut) { + return; + } + + event.preventDefault(); + if (open && (!isProfileShortcut || mode === "profile")) { + onClose(); + return; + } + + if (isProfileShortcut) { + onOpenSettings("profile"); + return; + } + + onOpenSettings(); + } + + window.addEventListener("keydown", handleKeyDown); + return () => { + window.removeEventListener("keydown", handleKeyDown); + }; + }, [mode, onClose, onOpenSettings, open]); +}