import clsx from 'clsx'; import React, { useEffect } from 'react'; import { useSettingsStore } from '@/store/settingsStore'; import { useBookDataStore } from '@/store/bookDataStore'; import { useReaderStore } from '@/store/readerStore'; import { useSidebarStore } from '@/store/sidebarStore'; import { useNotebookStore } from '@/store/notebookStore'; import { useTranslation } from '@/hooks/useTranslation'; import { useEnv } from '@/context/EnvContext'; import useDragBar from '../../hooks/useDragBar'; import NotebookHeader from './Header'; import NoteEditor from './NoteEditor'; import { TextSelection } from '@/utils/sel'; import { BookNote } from '@/types/book'; import { uniqueId } from '@/utils/misc'; import BooknoteItem from '../sidebar/BooknoteItem'; const MIN_NOTEBOOK_WIDTH = 0.15; const MAX_NOTEBOOK_WIDTH = 0.45; const Notebook: React.FC = ({}) => { const _ = useTranslation(); const { envConfig } = useEnv(); const { settings } = useSettingsStore(); const { sideBarBookKey } = useSidebarStore(); const { notebookWidth, isNotebookVisible, isNotebookPinned } = useNotebookStore(); const { notebookNewAnnotation, notebookEditAnnotation, setNotebookPin } = useNotebookStore(); const { getConfig, saveConfig, updateBooknotes } = useBookDataStore(); const { getView } = useReaderStore(); const { setNotebookWidth, setNotebookVisible, toggleNotebookPin } = useNotebookStore(); const { setNotebookNewAnnotation, setNotebookEditAnnotation } = useNotebookStore(); useEffect(() => { setNotebookWidth(settings.globalReadSettings.notebookWidth); setNotebookPin(settings.globalReadSettings.isNotebookPinned); setNotebookVisible(settings.globalReadSettings.isNotebookPinned); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const handleNotebookResize = (newWidth: string) => { setNotebookWidth(newWidth); settings.globalReadSettings.notebookWidth = newWidth; }; const handleTogglePin = () => { toggleNotebookPin(); settings.globalReadSettings.isNotebookPinned = !isNotebookPinned; }; const handleClickOverlay = (event: React.MouseEvent) => { event.preventDefault(); event.stopPropagation(); setNotebookVisible(false); }; const handleDragMove = (e: MouseEvent) => { const widthFraction = 1 - e.clientX / window.innerWidth; const newWidth = Math.max(MIN_NOTEBOOK_WIDTH, Math.min(MAX_NOTEBOOK_WIDTH, widthFraction)); handleNotebookResize(`${Math.round(newWidth * 10000) / 100}%`); }; const handleSaveNote = (selection: TextSelection, note: string) => { if (!sideBarBookKey) return; const view = getView(sideBarBookKey); const config = getConfig(sideBarBookKey)!; const cfi = view?.getCFI(selection.index, selection.range); if (!cfi) return; const { booknotes: annotations = [] } = config; const annotation: BookNote = { id: uniqueId(), type: 'annotation', cfi, note, text: selection.text, createdAt: Date.now(), updatedAt: Date.now(), }; annotations.push(annotation); const updatedConfig = updateBooknotes(sideBarBookKey, annotations); if (updatedConfig) { saveConfig(envConfig, sideBarBookKey, updatedConfig, settings); } setNotebookNewAnnotation(null); }; const handleEditNote = (note: BookNote, isDelete: boolean) => { if (!sideBarBookKey) return; const config = getConfig(sideBarBookKey)!; const { booknotes: annotations = [] } = config; const existingIndex = annotations.findIndex((item) => item.id === note.id); if (existingIndex === -1) return; if (isDelete) { note.deletedAt = Date.now(); } else { note.updatedAt = Date.now(); } annotations[existingIndex] = note; const updatedConfig = updateBooknotes(sideBarBookKey, annotations); if (updatedConfig) { saveConfig(envConfig, sideBarBookKey, updatedConfig, settings); } setNotebookEditAnnotation(null); }; const { handleMouseDown } = useDragBar(handleDragMove); if (!sideBarBookKey) return null; const config = getConfig(sideBarBookKey); const { booknotes: allNotes = [] } = config || {}; const annotationNotes = allNotes .filter((note) => note.type === 'annotation' && note.note && !note.deletedAt) .sort((a, b) => b.createdAt - a.createdAt); const excerptNotes = allNotes .filter((note) => note.type === 'excerpt' && note.text && !note.deletedAt) .sort((a, b) => a.createdAt - b.createdAt); return isNotebookVisible ? ( <> {!isNotebookPinned && (
)}{_('Excerpts')}
}{item.text || `Excerpt ${index + 1}`}
{item.text}
{_('Notes')}
)}