forked from akai/readest
@@ -4,6 +4,7 @@ import { useNotebookStore } from '@/store/notebookStore';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { TextSelection } from '@/utils/sel';
|
||||
import { BookNote } from '@/types/book';
|
||||
import useShortcuts from '@/hooks/useShortcuts';
|
||||
|
||||
interface NoteEditorProps {
|
||||
onSave: (selection: TextSelection, note: string) => void;
|
||||
@@ -12,7 +13,7 @@ interface NoteEditorProps {
|
||||
|
||||
const NoteEditor: React.FC<NoteEditorProps> = ({ onSave, onEdit }) => {
|
||||
const _ = useTranslation();
|
||||
const { notebookNewAnnotation, notebookEditAnnotation } = useNotebookStore();
|
||||
const { notebookNewAnnotation, notebookEditAnnotation, setNotebookNewAnnotation, setNotebookEditAnnotation } = useNotebookStore();
|
||||
const editorRef = useRef<HTMLTextAreaElement>(null);
|
||||
const [note, setNote] = React.useState('');
|
||||
|
||||
@@ -49,6 +50,21 @@ const NoteEditor: React.FC<NoteEditorProps> = ({ onSave, onEdit }) => {
|
||||
}
|
||||
};
|
||||
|
||||
useShortcuts({
|
||||
onSaveNote: () => {
|
||||
if (editorRef.current && editorRef.current.value) {
|
||||
handleSaveNote();
|
||||
}
|
||||
},
|
||||
onCloseNote: () => {
|
||||
if (notebookNewAnnotation) {
|
||||
setNotebookNewAnnotation(null)
|
||||
} else if (notebookEditAnnotation) {
|
||||
setNotebookEditAnnotation(null)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
<div className='note-editor-container bg-base-100 mt-2 rounded-md p-2'>
|
||||
<div className='flex w-full justify-between space-x-2'>
|
||||
|
||||
@@ -16,6 +16,8 @@ export interface ShortcutConfig {
|
||||
onZoomIn: string[];
|
||||
onZoomOut: string[];
|
||||
onResetZoom: string[];
|
||||
onSaveNote: string[];
|
||||
onCloseNote: string[];
|
||||
}
|
||||
|
||||
const DEFAULT_SHORTCUTS: ShortcutConfig = {
|
||||
@@ -36,6 +38,8 @@ const DEFAULT_SHORTCUTS: ShortcutConfig = {
|
||||
onZoomIn: ['ctrl+=', 'cmd+=', 'shift+='],
|
||||
onZoomOut: ['ctrl+-', 'cmd+-', 'shift+-'],
|
||||
onResetZoom: ['ctrl+0', 'cmd+0'],
|
||||
onSaveNote: ['ctrl+Enter'],
|
||||
onCloseNote: ['Escape']
|
||||
};
|
||||
|
||||
// Load shortcuts from localStorage or fallback to defaults
|
||||
|
||||
@@ -63,8 +63,8 @@ const useShortcuts = (actions: KeyActionHandlers, dependencies: React.Dependency
|
||||
handler &&
|
||||
shortcutList?.some((shortcut) =>
|
||||
isShortcutMatch(shortcut, key, ctrlKey, altKey, metaKey, shiftKey),
|
||||
)
|
||||
) {
|
||||
)
|
||||
) {
|
||||
handler();
|
||||
return true;
|
||||
}
|
||||
@@ -76,16 +76,23 @@ const useShortcuts = (actions: KeyActionHandlers, dependencies: React.Dependency
|
||||
// Check if the focus is on an input, textarea, or contenteditable element
|
||||
const activeElement = document.activeElement as HTMLElement;
|
||||
const isInteractiveElement =
|
||||
activeElement.tagName === 'INPUT' ||
|
||||
(activeElement.tagName === 'INPUT' ||
|
||||
activeElement.tagName === 'TEXTAREA' ||
|
||||
activeElement.isContentEditable;
|
||||
activeElement.isContentEditable);
|
||||
|
||||
if (isInteractiveElement) {
|
||||
const isNoteEditor = (activeElement.tagName === 'TEXTAREA' && activeElement.classList.contains('note-editor'))
|
||||
|
||||
if (isInteractiveElement && !isNoteEditor) {
|
||||
return; // Skip handling if the user is typing in an input, textarea, or contenteditable
|
||||
}
|
||||
|
||||
if (event instanceof KeyboardEvent) {
|
||||
const { key, ctrlKey, altKey, metaKey, shiftKey } = event;
|
||||
|
||||
if (isNoteEditor && !((key === "Enter" && ctrlKey) || (key == "Escape"))) {
|
||||
return;
|
||||
}
|
||||
|
||||
const handled = processKeyEvent(key.toLowerCase(), ctrlKey, altKey, metaKey, shiftKey);
|
||||
if (handled) event.preventDefault();
|
||||
} else if (
|
||||
|
||||
Reference in New Issue
Block a user