移除对 Mousetrap 的依赖,改为使用自定义的 KeyboardManager 进行快捷键绑定和管理,同时更新相关类型定义,调整菜单项的快捷键配置逻辑。
This commit is contained in:
116
src/utils/KeyboardManager.ts
Normal file
116
src/utils/KeyboardManager.ts
Normal 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()
|
||||
Reference in New Issue
Block a user