fix: global shortcut keys (#8084)

* refactor: shortcut keys

* fix:  backward compatibility with old data
This commit is contained in:
fullex 2025-07-15 02:23:39 +08:00 committed by GitHub
parent d4dde58e13
commit c606972f0a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 91 additions and 30 deletions

View File

@ -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':

View File

@ -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)

View File

@ -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