移除对 Mousetrap 的依赖,改为使用自定义的 KeyboardManager 进行快捷键绑定和管理,同时更新相关类型定义,调整菜单项的快捷键配置逻辑。

This commit is contained in:
2024-12-12 23:35:39 +08:00
parent 90ccd8d6d0
commit 8f1964c374
5 changed files with 131 additions and 54 deletions

View File

@@ -0,0 +1,116 @@
type KeyboardCallback = (e: KeyboardEvent) => void
export class KeyboardManager {
private shortcuts: Map<string, KeyboardCallback> = new Map()
private pressedKeys: Set<string> = new Set()
private enabled: boolean = false
constructor() {
this.handleKeyDown = this.handleKeyDown.bind(this)
this.handleKeyUp = this.handleKeyUp.bind(this)
}
/**
* 启用快捷键监听
*/
enable(): void {
if (!this.enabled) {
window.addEventListener('keydown', this.handleKeyDown)
window.addEventListener('keyup', this.handleKeyUp)
this.enabled = true
}
}
/**
* 禁用快捷键监听
*/
disable(): void {
if (this.enabled) {
window.removeEventListener('keydown', this.handleKeyDown)
window.removeEventListener('keyup', this.handleKeyUp)
this.enabled = false
this.pressedKeys.clear()
}
}
/**
* 绑定快捷键
*/
bind(shortcut: string, callback: KeyboardCallback): void {
this.shortcuts.set(this.normalizeShortcut(shortcut), callback)
}
/**
* 解绑快捷键
*/
unbind(shortcut: string): void {
this.shortcuts.delete(this.normalizeShortcut(shortcut))
}
/**
* 清除所有快捷键绑定
*/
clear(): void {
this.shortcuts.clear()
this.pressedKeys.clear()
}
private handleKeyDown(e: KeyboardEvent): void {
// 忽略在输入框中的按键
if (this.shouldIgnoreInput(e)) {
return
}
const key = this.normalizeKey(e.key.toLowerCase())
this.pressedKeys.add(key)
const currentShortcut = Array.from(this.pressedKeys).sort().join('+')
const callback = this.shortcuts.get(currentShortcut)
if (callback) {
e.preventDefault()
e.stopPropagation()
callback(e)
}
}
private handleKeyUp(e: KeyboardEvent): void {
const key = this.normalizeKey(e.key.toLowerCase())
this.pressedKeys.delete(key)
}
private normalizeKey(key: string): string {
const keyMap: Record<string, string> = {
'control': 'ctrl',
'command': 'cmd',
'meta': 'cmd',
'escape': 'esc',
' ': 'space',
'arrowup': 'up',
'arrowdown': 'down',
'arrowleft': 'left',
'arrowright': 'right',
}
return keyMap[key] || key
}
private normalizeShortcut(shortcut: string): string {
return shortcut
.toLowerCase()
.split('+')
.map(key => this.normalizeKey(key.trim()))
.sort()
.join('+')
}
private shouldIgnoreInput(e: KeyboardEvent): boolean {
const element = e.target as HTMLElement
return element.tagName === 'INPUT' ||
element.tagName === 'TEXTAREA' ||
element.tagName === 'SELECT' ||
element.isContentEditable
}
}
// 导出单例实例
export const keyboardManager = new KeyboardManager()