Fix custom shortcut synchronization across platforms

This commit is contained in:
eezd committed 2026-10-21 18:02:25 +08:00
1 parent b4054189cf
commit 73ff88c3c3
2 files changed
+22 -4

No files matched your search

+17 -1
View File
@@ -1,5 +1,5 @@
// @vitest-environment happy-dom // @vitest-environment happy-dom
import { describe, expect, it } from 'vitest' import { describe, expect, it, vi } from 'vitest'
import { matchKeys, recordedKeys } from './keys' import { matchKeys, recordedKeys } from './keys'
describe('快捷键匹配与录入', () => { describe('快捷键匹配与录入', () => {
@@ -13,4 +13,20 @@ describe('快捷键匹配与录入', () => {
expect(recordedKeys(new KeyboardEvent('keydown', { key: 'Control', ctrlKey: true }))).toBeNull() expect(recordedKeys(new KeyboardEvent('keydown', { key: 'Control', ctrlKey: true }))).toBeNull()
expect(recordedKeys(new KeyboardEvent('keydown', { key: '+', ctrlKey: true, shiftKey: true }))).toContain('Plus') expect(recordedKeys(new KeyboardEvent('keydown', { key: '+', ctrlKey: true, shiftKey: true }))).toContain('Plus')
}) })
it.each(['MacIntel', 'Win32'])('%s 录入双修饰键后可跨平台匹配,已有 Mod 组合也不会抛错', async (platform) => {
vi.stubGlobal('navigator', { platform })
vi.resetModules()
try {
const keys = await import('./keys')
const event = new KeyboardEvent('keydown', { key: 'b', code: 'KeyB', ctrlKey: true, metaKey: true })
expect(keys.recordedKeys(event)).toBe('Ctrl+Meta+B')
expect(keys.matchKeys(event, 'Ctrl+Meta+B')).toBe(true)
const alias = platform === 'MacIntel' ? 'Mod+Meta+B' : 'Mod+Ctrl+B'
expect(keys.physicalKeys(alias)).toBe(platform === 'MacIntel' ? 'Meta+B' : 'Ctrl+B')
expect(keys.matchKeys(new KeyboardEvent('keydown', { key: 'F1' }), alias)).toBe(false)
} finally {
vi.unstubAllGlobals()
vi.resetModules()
}
})
}) })
+5 -3
View File
@@ -10,7 +10,8 @@ export function normalizeKeys(value: string): string {
} }
export function physicalKeys(value: string): string { export function physicalKeys(value: string): string {
return normalizeKeys(value.replace(/\bMod\b/g, isMac ? 'Meta' : 'Ctrl')) const parts = normalizeKeys(value).split('+').map((part) => part === 'Mod' ? isMac ? 'Meta' : 'Ctrl' : part)
return normalizeKeys([...new Set(parts)].join('+'))
} }
export function matchKeys(event: KeyboardEvent, value: string): boolean { export function matchKeys(event: KeyboardEvent, value: string): boolean {
@@ -26,8 +27,9 @@ export function matchKeys(event: KeyboardEvent, value: string): boolean {
export function recordedKeys(event: KeyboardEvent): string | null { export function recordedKeys(event: KeyboardEvent): string | null {
if (['Control', 'Meta', 'Alt', 'Shift', 'AltGraph', 'Dead', 'Process', 'Unidentified'].includes(event.key) || event.isComposing) return null if (['Control', 'Meta', 'Alt', 'Shift', 'AltGraph', 'Dead', 'Process', 'Unidentified'].includes(event.key) || event.isComposing) return null
const parts: string[] = [] const parts: string[] = []
if (event.ctrlKey) parts.push(isMac ? 'Ctrl' : 'Mod') // 同时按下两种修饰键时保留物理组合,避免同步后 Mod 与另一键重合。
if (event.metaKey) parts.push(isMac ? 'Mod' : 'Meta') if (event.ctrlKey) parts.push(isMac || event.metaKey ? 'Ctrl' : 'Mod')
if (event.metaKey) parts.push(!isMac || event.ctrlKey ? 'Meta' : 'Mod')
if (event.altKey) parts.push('Alt') if (event.altKey) parts.push('Alt')
if (event.shiftKey) parts.push('Shift') if (event.shiftKey) parts.push('Shift')
const key = /^Digit[0-9]$/.test(event.code) ? event.code.slice(5) : event.key === ' ' ? 'Space' : event.key === '+' ? 'Plus' : event.key const key = /^Digit[0-9]$/.test(event.code) ? event.code.slice(5) : event.key === ' ' ? 'Space' : event.key === '+' ? 'Plus' : event.key