fix(metadata): no need to download book to display book details, closes #2857 (#2897)

This commit is contained in:
Huang Xin
2026-01-09 15:58:01 +01:00
committed by GitHub
parent 941be80cc4
commit 7cb523eefc
4 changed files with 20 additions and 29 deletions
@@ -115,9 +115,7 @@ const BookshelfItem: React.FC<BookshelfItemProps> = ({
const { updateBook } = useLibraryStore();
const showBookDetailsModal = useCallback(async (book: Book) => {
if (await makeBookAvailable(book)) {
handleShowDetailsBook(book);
}
handleShowDetailsBook(book);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
@@ -10,7 +10,6 @@ import { useMetadataEdit } from './useMetadataEdit';
import { DeleteAction } from '@/types/system';
import Alert from '@/components/Alert';
import Dialog from '@/components/Dialog';
import Spinner from '@/components/Spinner';
import BookDetailView from './BookDetailView';
import BookDetailEdit from './BookDetailEdit';
import SourceSelector from './SourceSelector';
@@ -47,7 +46,6 @@ const BookDetailModal: React.FC<BookDetailModalProps> = ({
const _ = useTranslation();
const { envConfig } = useEnv();
const { safeAreaInsets } = useThemeStore();
const [loading, setLoading] = useState(false);
const [activeDeleteAction, setActiveDeleteAction] = useState<DeleteAction | null>(null);
const [editMode, setEditMode] = useState(false);
const [bookMeta, setBookMeta] = useState<BookMetadata | null>(null);
@@ -91,17 +89,17 @@ const BookDetailModal: React.FC<BookDetailModalProps> = ({
};
useEffect(() => {
const loadingTimeout = setTimeout(() => setLoading(true), 300);
const fetchBookDetails = async () => {
const appService = await envConfig.getAppService();
try {
const details = book.metadata || (await appService.fetchBookDetails(book));
let details = book.metadata || null;
if (!details && book.downloadedAt) {
details = await appService.fetchBookDetails(book);
}
setBookMeta(details);
const size = await appService.getBookFileSize(book);
setFileSize(size);
} finally {
if (loadingTimeout) clearTimeout(loadingTimeout);
setLoading(false);
}
};
fetchBookDetails();
@@ -171,15 +169,6 @@ const BookDetailModal: React.FC<BookDetailModalProps> = ({
const currentDeleteConfig = activeDeleteAction ? deleteConfigs[activeDeleteAction] : null;
if (!bookMeta)
return (
loading && (
<div className='fixed inset-0 z-50 flex items-center justify-center'>
<Spinner loading />
</div>
)
);
return (
<>
<div className='fixed inset-0 z-50 flex items-center justify-center'>
@@ -194,7 +183,7 @@ const BookDetailModal: React.FC<BookDetailModalProps> = ({
contentClassName='!px-6 !py-4'
>
<div className='flex w-full select-text items-start justify-center'>
{editMode ? (
{editMode && bookMeta ? (
<BookDetailEdit
book={book}
metadata={editedMeta}
@@ -24,7 +24,7 @@ import MenuItem from '../MenuItem';
interface BookDetailViewProps {
book: Book;
metadata: BookMetadata;
metadata: BookMetadata | null;
fileSize: number | null;
onEdit?: () => void;
onDelete?: () => void;
@@ -64,8 +64,12 @@ const BookDetailView: React.FC<BookDetailViewProps> = ({
</div>
<div className='flex flex-wrap items-center gap-x-4'>
{onEdit && (
<button onClick={onEdit} title={_('Edit Metadata')}>
<MdOutlineEdit className='fill-base-content hover:fill-blue-500' />
<button
onClick={onEdit}
className={!metadata ? 'btn-disabled opacity-50' : ''}
title={_('Edit Metadata')}
>
<MdOutlineEdit className='hover:fill-blue-500' />
</button>
)}
{onDelete && (
@@ -123,13 +127,13 @@ const BookDetailView: React.FC<BookDetailViewProps> = ({
<div className='overflow-hidden'>
<span className='font-bold'>{_('Publisher')}</span>
<p className='text-neutral-content text-sm'>
{formatPublisher(metadata.publisher || '') || _('Unknown')}
{formatPublisher(metadata?.publisher || '') || _('Unknown')}
</p>
</div>
<div className='overflow-hidden'>
<span className='font-bold'>{_('Published')}</span>
<p className='text-neutral-content text-sm'>
{formatDate(metadata.published, true) || _('Unknown')}
{formatDate(metadata?.published, true) || _('Unknown')}
</p>
</div>
<div className='overflow-hidden'>
@@ -143,13 +147,13 @@ const BookDetailView: React.FC<BookDetailViewProps> = ({
<div className='overflow-hidden'>
<span className='font-bold'>{_('Language')}</span>
<p className='text-neutral-content text-sm'>
{formatLanguage(metadata.language) || _('Unknown')}
{formatLanguage(metadata?.language) || _('Unknown')}
</p>
</div>
<div className='overflow-hidden'>
<span className='font-bold'>{_('Subjects')}</span>
<p className='text-neutral-content line-clamp-3 text-sm'>
{formatAuthors(metadata.subject || '') || _('Unknown')}
{formatAuthors(metadata?.subject || '') || _('Unknown')}
</p>
</div>
<div className='overflow-hidden'>
@@ -164,9 +168,9 @@ const BookDetailView: React.FC<BookDetailViewProps> = ({
<div>
<span className='font-bold'>{_('Description')}</span>
<p
className='text-neutral-content prose prose-sm max-w-full text-sm'
className='text-neutral-content prose prose-sm max-w-full whitespace-pre-line text-sm'
dangerouslySetInnerHTML={{
__html: metadata.description || _('No description available'),
__html: metadata?.description || _('No description available'),
}}
></p>
</div>
@@ -57,7 +57,7 @@ const SourceSelector: React.FC<SourceSelectorProps> = ({ sources, isOpen, onSele
tabIndex={0}
key={index}
onClick={() => onSelect(source)}
className='hover:bg-base-300/75 bg-base-200 border-base-200 cursor-pointer rounded-md border p-3 transition-colors'
className='hover:bg-base-300/75 bg-base-200 border-base-200 w-full cursor-pointer rounded-md border p-3 transition-colors'
>
<div className='flex items-start gap-4'>
<div className='aspect-[28/41] h-full w-[40%] max-w-32 shadow-md'>