diff --git a/src/main/services/ShortcutService.ts b/src/main/services/ShortcutService.ts index 24ea2324fd..92544e17c0 100644 --- a/src/main/services/ShortcutService.ts +++ b/src/main/services/ShortcutService.ts @@ -55,7 +55,8 @@ function formatShortcutKey(shortcut: string[]): string { return shortcut.join('+') } -// convert the shortcut recorded by keyboard event key value to electron global shortcut format +// convert the shortcut recorded by JS keyboard event key value to electron global shortcut format +// see: https://www.electronjs.org/zh/docs/latest/api/accelerator const convertShortcutFormat = (shortcut: string | string[]): string => { const accelerator = (() => { if (Array.isArray(shortcut)) { @@ -68,12 +69,34 @@ const convertShortcutFormat = (shortcut: string | string[]): string => { return accelerator .map((key) => { switch (key) { + // OLD WAY FOR MODIFIER KEYS, KEEP THEM HERE FOR REFERENCE + // case 'Command': + // return 'CommandOrControl' + // case 'Control': + // return 'Control' + // case 'Ctrl': + // return 'Control' + + // NEW WAY FOR MODIFIER KEYS + // you can see all the modifier keys in the same + case 'CommandOrControl': + return 'CommandOrControl' + case 'Ctrl': + return 'Ctrl' + case 'Alt': + return 'Alt' // Use `Alt` instead of `Option`. The `Option` key only exists on macOS, whereas the `Alt` key is available on all platforms. + case 'Meta': + return 'Meta' // `Meta` key is mapped to the Windows key on Windows and Linux, `Cmd` on macOS. + case 'Shift': + return 'Shift' + + // For backward compatibility with old data case 'Command': + case 'Cmd': return 'CommandOrControl' case 'Control': - return 'Control' - case 'Ctrl': - return 'Control' + return 'Ctrl' + case 'ArrowUp': return 'Up' case 'ArrowDown': @@ -83,7 +106,7 @@ const convertShortcutFormat = (shortcut: string | string[]): string => { case 'ArrowRight': return 'Right' case 'AltGraph': - return 'Alt' + return 'AltGr' case 'Slash': return '/' case 'Semicolon': diff --git a/src/renderer/src/pages/settings/ShortcutSettings.tsx b/src/renderer/src/pages/settings/ShortcutSettings.tsx index 909790f95a..ce6bef3690 100644 --- a/src/renderer/src/pages/settings/ShortcutSettings.tsx +++ b/src/renderer/src/pages/settings/ShortcutSettings.tsx @@ -64,8 +64,14 @@ const ShortcutSettings: FC = () => { } const isValidShortcut = (keys: string[]): boolean => { - const hasModifier = keys.some((key) => ['Control', 'Ctrl', 'Command', 'Alt', 'Shift'].includes(key)) - const hasNonModifier = keys.some((key) => !['Control', 'Ctrl', 'Command', 'Alt', 'Shift'].includes(key)) + // OLD WAY FOR MODIFIER KEYS, KEEP THEM HERE FOR REFERENCE + // const hasModifier = keys.some((key) => ['Control', 'Ctrl', 'Command', 'Alt', 'Shift'].includes(key)) + // const hasNonModifier = keys.some((key) => !['Control', 'Ctrl', 'Command', 'Alt', 'Shift'].includes(key)) + + // NEW WAY FOR MODIFIER KEYS + const hasModifier = keys.some((key) => ['CommandOrControl', 'Ctrl', 'Alt', 'Meta', 'Shift'].includes(key)) + const hasNonModifier = keys.some((key) => !['CommandOrControl', 'Ctrl', 'Alt', 'Meta', 'Shift'].includes(key)) + const hasFnKey = keys.some((key) => /^F\d+$/.test(key)) return (hasModifier && hasNonModifier && keys.length >= 2) || hasFnKey @@ -77,22 +83,44 @@ const ShortcutSettings: FC = () => { ) } + // how the shortcut is displayed in the UI const formatShortcut = (shortcut: string[]): string => { return shortcut .map((key) => { switch (key) { - case 'Control': - return isMac ? '⌃' : 'Ctrl' - case 'Ctrl': - return isMac ? '⌃' : 'Ctrl' - case 'Command': - return isMac ? '⌘' : isWin ? 'Win' : 'Super' - case 'Alt': - return isMac ? '⌥' : 'Alt' - case 'Shift': - return isMac ? '⇧' : 'Shift' + // OLD WAY FOR MODIFIER KEYS, KEEP THEM HERE FOR REFERENCE + // case 'Control': + // return isMac ? '⌃' : 'Ctrl' + // case 'Ctrl': + // return isMac ? '⌃' : 'Ctrl' + // case 'Command': + // return isMac ? '⌘' : isWin ? 'Win' : 'Super' + // case 'Alt': + // return isMac ? '⌥' : 'Alt' + // case 'Shift': + // return isMac ? '⇧' : 'Shift' + // case 'CommandOrControl': + // return isMac ? '⌘' : 'Ctrl' + + // new way for modifier keys case 'CommandOrControl': return isMac ? '⌘' : 'Ctrl' + case 'Ctrl': + return isMac ? '⌃' : 'Ctrl' + case 'Alt': + return isMac ? '⌥' : 'Alt' + case 'Meta': + return isMac ? '⌘' : isWin ? 'Win' : 'Super' + case 'Shift': + return isMac ? '⇧' : 'Shift' + + // for backward compatibility with old data + case 'Command': + case 'Cmd': + return isMac ? '⌘' : 'Ctrl' + case 'Control': + return isMac ? '⌃' : 'Ctrl' + case 'ArrowUp': return '↑' case 'ArrowDown': @@ -239,10 +267,21 @@ const ShortcutSettings: FC = () => { e.preventDefault() const keys: string[] = [] - if (e.ctrlKey) keys.push(isMac ? 'Control' : 'Ctrl') - if (e.metaKey) keys.push('Command') + + // OLD WAY FOR MODIFIER KEYS, KEEP THEM HERE FOR REFERENCE + // if (e.ctrlKey) keys.push(isMac ? 'Control' : 'Ctrl') + // if (e.metaKey) keys.push('Command') + // if (e.altKey) keys.push('Alt') + // if (e.shiftKey) keys.push('Shift') + + // NEW WAY FOR MODIFIER KEYS + // for capability across platforms, we transform the modifier keys to the really meaning keys + // mainly consider the habit of users on different platforms + if (e.ctrlKey) keys.push(isMac ? 'Ctrl' : 'CommandOrControl') // for win&linux, ctrl key is almost the same as command key in macOS if (e.altKey) keys.push('Alt') + if (e.metaKey) keys.push(isMac ? 'CommandOrControl' : 'Meta') // for macOS, meta(Command) key is almost the same as Ctrl key in win&linux if (e.shiftKey) keys.push('Shift') + const endKey = usableEndKeys(e) if (endKey) { keys.push(endKey) diff --git a/src/renderer/src/store/shortcuts.ts b/src/renderer/src/store/shortcuts.ts index b6a4f7a0d7..b2a823ff0c 100644 --- a/src/renderer/src/store/shortcuts.ts +++ b/src/renderer/src/store/shortcuts.ts @@ -1,5 +1,4 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit' -import { isMac } from '@renderer/config/constant' import { Shortcut } from '@renderer/types' import { ZOOM_SHORTCUTS } from '@shared/config/constant' @@ -12,7 +11,7 @@ const initialState: ShortcutsState = { ...ZOOM_SHORTCUTS, { key: 'show_settings', - shortcut: [isMac ? 'Command' : 'Ctrl', ','], + shortcut: ['CommandOrControl', ','], editable: false, enabled: true, system: true @@ -26,7 +25,7 @@ const initialState: ShortcutsState = { }, { key: 'mini_window', - shortcut: [isMac ? 'Command' : 'Ctrl', 'E'], + shortcut: ['CommandOrControl', 'E'], editable: true, enabled: false, system: true @@ -49,14 +48,14 @@ const initialState: ShortcutsState = { }, { key: 'new_topic', - shortcut: [isMac ? 'Command' : 'Ctrl', 'N'], + shortcut: ['CommandOrControl', 'N'], editable: true, enabled: true, system: false }, { key: 'toggle_show_assistants', - shortcut: [isMac ? 'Command' : 'Ctrl', '['], + shortcut: ['CommandOrControl', '['], editable: true, enabled: true, system: false @@ -64,42 +63,42 @@ const initialState: ShortcutsState = { { key: 'toggle_show_topics', - shortcut: [isMac ? 'Command' : 'Ctrl', ']'], + shortcut: ['CommandOrControl', ']'], editable: true, enabled: true, system: false }, { key: 'copy_last_message', - shortcut: [isMac ? 'Command' : 'Ctrl', 'Shift', 'C'], + shortcut: ['CommandOrControl', 'Shift', 'C'], editable: true, enabled: false, system: false }, { key: 'search_message_in_chat', - shortcut: [isMac ? 'Command' : 'Ctrl', 'F'], + shortcut: ['CommandOrControl', 'F'], editable: true, enabled: true, system: false }, { key: 'search_message', - shortcut: [isMac ? 'Command' : 'Ctrl', 'Shift', 'F'], + shortcut: ['CommandOrControl', 'Shift', 'F'], editable: true, enabled: true, system: false }, { key: 'clear_topic', - shortcut: [isMac ? 'Command' : 'Ctrl', 'L'], + shortcut: ['CommandOrControl', 'L'], editable: true, enabled: true, system: false }, { key: 'toggle_new_context', - shortcut: [isMac ? 'Command' : 'Ctrl', 'K'], + shortcut: ['CommandOrControl', 'K'], editable: true, enabled: true, system: false