Files
MarkLite/src/renderer/hooks/useKeyboard.ts
T
thzxx 43b0778849 release: v0.3.13 — MeToast 集成与全面质量修复
- 集成 MetonaToast v2.0.0 替换自研 Toast 组件(右上角、进度条、自动关闭、主题联动)
- 修复 sidebar resize 未持久化到 IndexedDB
- 修复 Ctrl+Tab MRU 切换逻辑与文档不一致
- 完善 WYSIWYG 模式标签切换选区恢复
- 清理死代码(useActiveHeading observerRef、旧 Toast 样式、重复滚动条样式、SearchReplace 重复检查)
- 同步 DESIGN.md / docs 文档(CodeMirror→Milkdown、stores 计数、editorStore 字段)
- 新增 .npmrc.example 模板
- 更新关于对话框与文档远程地址为 Gitea
- 版本号 0.3.12 → 0.3.13
2026-07-22 15:55:45 +08:00

55 lines
2.2 KiB
TypeScript

import { useEffect, useCallback } from 'react'
import { useTabStore } from '../stores/tabStore'
import { useEditorStore } from '../stores/editorStore'
export function useKeyboard(handleOpenFile: () => void, handleSave: () => void, handleSaveAs: () => void) {
const setViewMode = useEditorStore(s => s.setViewMode)
const handleKeydown = useCallback((e: KeyboardEvent) => {
const isCtrl = e.ctrlKey || e.metaKey
if (isCtrl && e.key === 'o') { e.preventDefault(); handleOpenFile(); return }
if (isCtrl && e.key === 's' && !e.shiftKey) { e.preventDefault(); handleSave(); return }
if (isCtrl && e.shiftKey && e.key === 'S') { e.preventDefault(); handleSaveAs(); return }
if (isCtrl && e.key === '1') { e.preventDefault(); setViewMode('editor'); return }
if (isCtrl && e.key === '2') { e.preventDefault(); setViewMode('preview'); return }
if (isCtrl && e.key === '3') { e.preventDefault(); setViewMode('source'); return }
const tabState = useTabStore.getState()
if (isCtrl && e.key === 't') { e.preventDefault(); tabState.createTab(null, ''); return }
if (isCtrl && e.key === 'w') {
e.preventDefault()
if (tabState.activeTabId) tabState.closeTab(tabState.activeTabId)
return
}
// Ctrl+Tab / Ctrl+Shift+Tab — MRU 顺序切换
if (isCtrl && e.key === 'Tab') {
e.preventDefault()
const { tabs, activeTabId, mruStack } = tabState
if (tabs.length > 1) {
// mruStack[0] 是最近一个被切走的标签(即上一个活动标签)
if (mruStack.length > 0) {
const targetId = mruStack[0]
if (tabs.find(t => t.id === targetId)) {
tabState.switchToTab(targetId)
return
}
}
// MRU 栈为空或不合法时回退到顺序切换
const idx = tabs.findIndex(t => t.id === activeTabId)
const next = e.shiftKey
? (idx - 1 + tabs.length) % tabs.length
: (idx + 1) % tabs.length
tabState.switchToTab(tabs[next].id)
}
return
}
}, [handleOpenFile, handleSave, handleSaveAs, setViewMode])
useEffect(() => {
document.addEventListener('keydown', handleKeydown)
return () => document.removeEventListener('keydown', handleKeydown)
}, [handleKeydown])
}