Files
readest/apps/readest-app/src/app/reader/components/sidebar/BooknoteItem.tsx
T
2024-11-19 20:26:11 +01:00

127 lines
4.0 KiB
TypeScript

import clsx from 'clsx';
import React from 'react';
import { useEnv } from '@/context/EnvContext';
import { BookNote } from '@/types/book';
import { useReaderStore } from '@/store/readerStore';
import useScrollToItem from '../../hooks/useScrollToItem';
interface BooknoteItemProps {
bookKey: string;
item: BookNote;
editable?: boolean;
}
const BooknoteItem: React.FC<BooknoteItemProps> = ({ bookKey, item, editable = false }) => {
const { envConfig } = useEnv();
const { settings, getConfig, saveConfig, getProgress, getView } = useReaderStore();
const { updateBooknotes, setNotebookEditAnnotation, setNotebookVisible } = useReaderStore();
const { text, cfi, note } = item;
const progress = getProgress(bookKey);
const { isCurrent, viewRef } = useScrollToItem(cfi, progress);
const handleClickItem = (event: React.MouseEvent) => {
event.preventDefault();
getView(bookKey)?.goTo(cfi);
if (note) {
setNotebookVisible(true);
}
};
const deleteNote = (note: BookNote) => {
if (!bookKey) return;
const config = getConfig(bookKey);
if (!config) return;
const { booknotes = [] } = config;
const updatedNotes = booknotes.filter((item) => item.id !== note.id);
const updatedConfig = updateBooknotes(bookKey, updatedNotes);
if (updatedConfig) {
saveConfig(envConfig, bookKey, updatedConfig, settings);
}
};
const editNote = (note: BookNote) => {
setNotebookEditAnnotation(note);
};
return (
<li
ref={viewRef}
className={clsx(
'border-base-300 my-2 cursor-pointer rounded-lg p-2 text-sm',
editable && 'collapse-arrow collapse',
isCurrent ? 'bg-base-300/85 hover:bg-base-300' : 'hover:bg-base-200 bg-base-100',
)}
tabIndex={0}
onClick={handleClickItem}
>
<div
className={clsx('collapse-title min-h-4 p-0', editable && 'pr-4')}
style={
{
'--top-override': '0.7rem',
'--end-override': '0.3rem',
} as React.CSSProperties
}
>
{item.note && <span className='line-clamp-3 font-normal'>{item.note}</span>}
<div className='flex items-start'>
{item.note && (
<div className='my-1 mr-2 min-h-full self-stretch border-l-2 border-gray-300'></div>
)}
<div className='line-clamp-3'>
<span
className={clsx(
'inline',
item.note && 'text-xs text-gray-500',
(item.style === 'underline' || item.style === 'squiggly') &&
'underline decoration-2',
item.style === 'highlight' && `bg-${item.color}-100`,
item.style === 'underline' && `decoration-${item.color}-400`,
item.style === 'squiggly' && `decoration-wavy decoration-${item.color}-400`,
)}
>
{text || ''}
</span>
</div>
</div>
</div>
{editable && (
<div
className={clsx('collapse-content invisible !p-0 text-xs')}
style={
{
'--bottom-override': 0,
} as React.CSSProperties
}
onClick={(e) => e.stopPropagation()}
>
<div className='flex justify-end space-x-3'>
<button
className={clsx(
'btn btn-ghost settings-content hover:bg-transparent',
'flex h-4 min-h-4 items-end p-0',
)}
onClick={editNote.bind(null, item)}
>
<div className='align-bottom text-xs text-blue-400'>Edit</div>
</button>
<button
className={clsx(
'btn btn-ghost settings-content hover:bg-transparent',
'flex h-4 min-h-4 items-end p-0',
)}
onClick={deleteNote.bind(null, item)}
>
<div className='align-bottom text-xs text-red-400'>Delete</div>
</button>
</div>
</div>
)}
</li>
);
};
export default BooknoteItem;