2026-02-22 17:16:20 +01:00
|
|
|
import { useEffect, useMemo } from 'react'
|
2026-02-22 18:42:33 +01:00
|
|
|
import type { ViewMode } from './useViewMode'
|
2026-02-20 19:59:05 +01:00
|
|
|
|
|
|
|
|
interface KeyboardActions {
|
|
|
|
|
onQuickOpen: () => void
|
|
|
|
|
onCreateNote: () => void
|
|
|
|
|
onSave: () => void
|
2026-02-22 13:38:18 +01:00
|
|
|
onOpenSettings: () => void
|
2026-02-21 17:37:15 +01:00
|
|
|
onTrashNote: (path: string) => void
|
2026-02-21 18:45:25 +01:00
|
|
|
onArchiveNote: (path: string) => void
|
2026-02-22 18:42:33 +01:00
|
|
|
onSetViewMode: (mode: ViewMode) => void
|
2026-02-20 19:59:05 +01:00
|
|
|
activeTabPathRef: React.MutableRefObject<string | null>
|
|
|
|
|
handleCloseTabRef: React.MutableRefObject<(path: string) => void>
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-21 18:45:25 +01:00
|
|
|
type ShortcutHandler = () => void
|
|
|
|
|
|
2026-02-22 18:42:33 +01:00
|
|
|
const VIEW_MODE_KEYS: Record<string, ViewMode> = {
|
|
|
|
|
'1': 'editor-only',
|
|
|
|
|
'2': 'editor-list',
|
|
|
|
|
'3': 'all',
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-23 08:13:32 +01:00
|
|
|
function isCmdOnly(e: KeyboardEvent): boolean {
|
|
|
|
|
return (e.metaKey || e.ctrlKey) && !e.altKey
|
2026-02-22 18:42:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleViewModeKey(e: KeyboardEvent, onSetViewMode: (m: ViewMode) => void): boolean {
|
2026-02-23 08:13:32 +01:00
|
|
|
if (!isCmdOnly(e)) return false
|
2026-02-22 18:42:33 +01:00
|
|
|
const mode = VIEW_MODE_KEYS[e.key]
|
|
|
|
|
if (!mode) return false
|
|
|
|
|
e.preventDefault()
|
|
|
|
|
onSetViewMode(mode)
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleCmdKey(e: KeyboardEvent, keyMap: Record<string, ShortcutHandler>): boolean {
|
|
|
|
|
const mod = e.metaKey || e.ctrlKey
|
|
|
|
|
if (!mod) return false
|
|
|
|
|
const handler = keyMap[e.key]
|
|
|
|
|
if (!handler) return false
|
|
|
|
|
e.preventDefault()
|
|
|
|
|
handler()
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-20 19:59:05 +01:00
|
|
|
export function useAppKeyboard({
|
2026-02-22 13:38:18 +01:00
|
|
|
onQuickOpen, onCreateNote, onSave, onOpenSettings, onTrashNote, onArchiveNote,
|
2026-02-22 18:42:33 +01:00
|
|
|
onSetViewMode, activeTabPathRef, handleCloseTabRef,
|
2026-02-20 19:59:05 +01:00
|
|
|
}: KeyboardActions) {
|
2026-02-21 18:45:25 +01:00
|
|
|
const withActiveTab = (fn: (path: string) => void): ShortcutHandler => () => {
|
|
|
|
|
const path = activeTabPathRef.current
|
|
|
|
|
if (path) fn(path)
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-22 18:42:33 +01:00
|
|
|
const cmdKeyMap = useMemo((): Record<string, ShortcutHandler> => ({
|
2026-02-21 18:45:25 +01:00
|
|
|
p: onQuickOpen,
|
|
|
|
|
n: onCreateNote,
|
|
|
|
|
s: onSave,
|
2026-02-22 13:38:18 +01:00
|
|
|
',': onOpenSettings,
|
2026-02-21 18:45:25 +01:00
|
|
|
e: withActiveTab(onArchiveNote),
|
|
|
|
|
w: withActiveTab((path) => handleCloseTabRef.current(path)),
|
|
|
|
|
Backspace: withActiveTab(onTrashNote),
|
|
|
|
|
Delete: withActiveTab(onTrashNote),
|
2026-02-22 13:38:18 +01:00
|
|
|
}), [onQuickOpen, onCreateNote, onSave, onOpenSettings, onTrashNote, onArchiveNote, activeTabPathRef, handleCloseTabRef])
|
2026-02-21 18:45:25 +01:00
|
|
|
|
2026-02-20 19:59:05 +01:00
|
|
|
useEffect(() => {
|
|
|
|
|
const handleKeyDown = (e: KeyboardEvent) => {
|
2026-02-22 18:42:33 +01:00
|
|
|
handleViewModeKey(e, onSetViewMode) || handleCmdKey(e, cmdKeyMap)
|
2026-02-20 19:59:05 +01:00
|
|
|
}
|
|
|
|
|
window.addEventListener('keydown', handleKeyDown)
|
|
|
|
|
return () => window.removeEventListener('keydown', handleKeyDown)
|
2026-02-22 18:42:33 +01:00
|
|
|
}, [cmdKeyMap, onSetViewMode])
|
2026-02-20 19:59:05 +01:00
|
|
|
}
|