feat: 快捷键录入重绑(FR-K3,keymap:load/save IPC+config.json,SettingsPanel 录入 UI+冲突检测,use-hotkeys 读 store 实时生效,重开恢复)
This commit is contained in:
@@ -1,13 +1,27 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import hotkeys from 'hotkeys-js';
|
||||
import { useKeymap } from './keymap-service';
|
||||
|
||||
// 从 keymap store 读组合键绑定(FR-K3 重绑后实时生效);? 帮助键保留硬编码
|
||||
export function useGlobalHotkeys(opts: { onNewDoc: () => void; onSave: () => void; onFocusSearch: () => void; onToggleOutline: () => void; onCheat: () => void; onSettings: () => void }) {
|
||||
const optsRef = useRef(opts);
|
||||
optsRef.current = opts;
|
||||
const bindings = useKeymap(s => s.bindings);
|
||||
const sig = bindings.map(b => b.id + '@' + b.combo).join('|');
|
||||
useEffect(() => {
|
||||
hotkeys('ctrl+n', e => { e.preventDefault(); opts.onNewDoc(); });
|
||||
hotkeys('ctrl+s', e => { e.preventDefault(); opts.onSave(); });
|
||||
hotkeys('ctrl+shift+f', e => { e.preventDefault(); opts.onFocusSearch(); });
|
||||
hotkeys('ctrl+shift+l', e => { e.preventDefault(); opts.onToggleOutline(); });
|
||||
hotkeys('?', e => { if (document.activeElement?.tagName !== 'INPUT' && document.activeElement?.tagName !== 'TEXTAREA') { e.preventDefault(); opts.onCheat(); } });
|
||||
return () => { hotkeys.unbind('ctrl+n'); hotkeys.unbind('ctrl+s'); hotkeys.unbind('ctrl+shift+f'); hotkeys.unbind('ctrl+shift+l'); hotkeys.unbind('?'); };
|
||||
}, [opts.onNewDoc, opts.onSave, opts.onFocusSearch, opts.onToggleOutline, opts.onCheat, opts.onSettings]);
|
||||
const actions: Record<string, () => void> = {
|
||||
newDoc: () => optsRef.current.onNewDoc(),
|
||||
save: () => optsRef.current.onSave(),
|
||||
focusSearch: () => optsRef.current.onFocusSearch(),
|
||||
toggleOutline: () => optsRef.current.onToggleOutline(),
|
||||
};
|
||||
const bound: string[] = [];
|
||||
for (const b of bindings) {
|
||||
const act = actions[b.id];
|
||||
if (act) { hotkeys(b.combo, (e) => { e.preventDefault(); act(); }); bound.push(b.combo); }
|
||||
}
|
||||
hotkeys('?', (e) => { if (document.activeElement?.tagName !== 'INPUT' && document.activeElement?.tagName !== 'TEXTAREA') { e.preventDefault(); optsRef.current.onCheat(); } });
|
||||
bound.push('?');
|
||||
return () => { for (const c of bound) hotkeys.unbind(c); };
|
||||
}, [sig]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user