This commit is contained in:
@@ -6,11 +6,15 @@ import {
|
||||
MdOutlineDelete,
|
||||
MdOutlineEdit,
|
||||
MdSaveAlt,
|
||||
MdExpandMore,
|
||||
MdExpandLess,
|
||||
} from 'react-icons/md';
|
||||
|
||||
import { Book } from '@/types/book';
|
||||
import { BookMetadata } from '@/libs/document';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { useSettingsStore } from '@/store/settingsStore';
|
||||
import { useEnv } from '@/context/EnvContext';
|
||||
import {
|
||||
formatAuthors,
|
||||
formatDate,
|
||||
@@ -19,6 +23,7 @@ import {
|
||||
formatPublisher,
|
||||
formatTitle,
|
||||
} from '@/utils/book';
|
||||
import { saveSysSettings } from '@/helpers/settings';
|
||||
import BookCover from '@/components/BookCover';
|
||||
import Dropdown from '../Dropdown';
|
||||
import MenuItem from '../MenuItem';
|
||||
@@ -49,6 +54,24 @@ const BookDetailView: React.FC<BookDetailViewProps> = ({
|
||||
onExport,
|
||||
}) => {
|
||||
const _ = useTranslation();
|
||||
const { envConfig } = useEnv();
|
||||
const { settings } = useSettingsStore();
|
||||
|
||||
const toggleSeriesCollapse = () => {
|
||||
saveSysSettings(envConfig, 'metadataSeriesCollapsed', !settings.metadataSeriesCollapsed);
|
||||
};
|
||||
|
||||
const toggleOthersCollapse = () => {
|
||||
saveSysSettings(envConfig, 'metadataOthersCollapsed', !settings.metadataOthersCollapsed);
|
||||
};
|
||||
|
||||
const toggleDescriptionCollapse = () => {
|
||||
saveSysSettings(
|
||||
envConfig,
|
||||
'metadataDescriptionCollapsed',
|
||||
!settings.metadataDescriptionCollapsed,
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className='relative w-full rounded-lg'>
|
||||
@@ -131,56 +154,141 @@ const BookDetailView: React.FC<BookDetailViewProps> = ({
|
||||
</div>
|
||||
|
||||
<div className='text-base-content my-4'>
|
||||
<div className='mb-4 grid grid-cols-2 gap-4 sm:grid-cols-3'>
|
||||
<div className='overflow-hidden'>
|
||||
<span className='font-bold'>{_('Publisher')}</span>
|
||||
<p className='text-neutral-content text-sm'>
|
||||
{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')}
|
||||
</p>
|
||||
</div>
|
||||
<div className='overflow-hidden'>
|
||||
<span className='font-bold'>{_('Updated')}</span>
|
||||
<p className='text-neutral-content text-sm'>{formatDate(book.updatedAt) || ''}</p>
|
||||
</div>
|
||||
<div className='overflow-hidden'>
|
||||
<span className='font-bold'>{_('Added')}</span>
|
||||
<p className='text-neutral-content text-sm'>{formatDate(book.createdAt) || ''}</p>
|
||||
</div>
|
||||
<div className='overflow-hidden'>
|
||||
<span className='font-bold'>{_('Language')}</span>
|
||||
<p className='text-neutral-content text-sm'>
|
||||
{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')}
|
||||
</p>
|
||||
</div>
|
||||
<div className='overflow-hidden'>
|
||||
<span className='font-bold'>{_('Format')}</span>
|
||||
<p className='text-neutral-content text-sm'>{book.format || _('Unknown')}</p>
|
||||
</div>
|
||||
<div className='overflow-hidden'>
|
||||
<span className='font-bold'>{_('File Size')}</span>
|
||||
<p className='text-neutral-content text-sm'>{formatBytes(fileSize) || _('Unknown')}</p>
|
||||
</div>
|
||||
<div className='metadata-others'>
|
||||
<button
|
||||
className={clsx(
|
||||
'flex w-full items-center justify-between px-4 py-3 text-left transition-colors',
|
||||
settings.metadataOthersCollapsed ? 'hover:bg-base-200 rounded-lg' : '',
|
||||
)}
|
||||
onClick={toggleOthersCollapse}
|
||||
>
|
||||
<span className='text-neutral-content/85 text-base font-semibold'>{_('Metadata')}</span>
|
||||
<div className='transition-transform duration-200'>
|
||||
{settings.metadataOthersCollapsed ? (
|
||||
<MdExpandMore className='h-5 w-5' />
|
||||
) : (
|
||||
<MdExpandLess className='h-5 w-5' />
|
||||
)}
|
||||
</div>
|
||||
</button>
|
||||
{!settings.metadataOthersCollapsed && (
|
||||
<div className='px-4 py-1'>
|
||||
<div className='grid grid-cols-2 gap-4 sm:grid-cols-3'>
|
||||
<div className='overflow-hidden'>
|
||||
<span className='font-bold'>{_('Publisher')}</span>
|
||||
<p className='text-neutral-content text-sm'>
|
||||
{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')}
|
||||
</p>
|
||||
</div>
|
||||
<div className='overflow-hidden'>
|
||||
<span className='font-bold'>{_('Updated')}</span>
|
||||
<p className='text-neutral-content text-sm'>{formatDate(book.updatedAt) || ''}</p>
|
||||
</div>
|
||||
<div className='overflow-hidden'>
|
||||
<span className='font-bold'>{_('Added')}</span>
|
||||
<p className='text-neutral-content text-sm'>{formatDate(book.createdAt) || ''}</p>
|
||||
</div>
|
||||
<div className='overflow-hidden'>
|
||||
<span className='font-bold'>{_('Language')}</span>
|
||||
<p className='text-neutral-content text-sm'>
|
||||
{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')}
|
||||
</p>
|
||||
</div>
|
||||
<div className='overflow-hidden'>
|
||||
<span className='font-bold'>{_('Format')}</span>
|
||||
<p className='text-neutral-content text-sm'>{book.format || _('Unknown')}</p>
|
||||
</div>
|
||||
<div className='overflow-hidden'>
|
||||
<span className='font-bold'>{_('File Size')}</span>
|
||||
<p className='text-neutral-content text-sm'>
|
||||
{formatBytes(fileSize) || _('Unknown')}
|
||||
</p>
|
||||
</div>
|
||||
<div className='overflow-hidden'>
|
||||
<span className='font-bold'>{_('Identifier')}</span>
|
||||
<p className='text-neutral-content line-clamp-1 text-sm'>
|
||||
{metadata?.identifier || _('Unknown')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<span className='font-bold'>{_('Description')}</span>
|
||||
<p
|
||||
className='text-neutral-content prose prose-sm max-w-full whitespace-pre-line text-sm'
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: metadata?.description || _('No description available'),
|
||||
}}
|
||||
></p>
|
||||
<div className='metadata-series'>
|
||||
<button
|
||||
className={clsx(
|
||||
'flex w-full items-center justify-between px-4 py-3 text-left transition-colors',
|
||||
settings.metadataSeriesCollapsed ? 'hover:bg-base-200 rounded-lg' : '',
|
||||
)}
|
||||
onClick={toggleSeriesCollapse}
|
||||
>
|
||||
<span className='text-neutral-content/85 text-base font-semibold'>{_('Series')}</span>
|
||||
<div className='transition-transform duration-200'>
|
||||
{settings.metadataSeriesCollapsed ? (
|
||||
<MdExpandMore className='h-5 w-5' />
|
||||
) : (
|
||||
<MdExpandLess className='h-5 w-5' />
|
||||
)}
|
||||
</div>
|
||||
</button>
|
||||
{!settings.metadataSeriesCollapsed && (
|
||||
<div className='px-4 py-1'>
|
||||
<div className='grid grid-cols-3 gap-4'>
|
||||
<div className='col-span-2 overflow-hidden'>
|
||||
<span className='font-bold'>{_('Series')}</span>
|
||||
<p className='text-neutral-content text-sm'>{metadata?.series || _('Unknown')}</p>
|
||||
</div>
|
||||
<div className='overflow-hidden'>
|
||||
<span className='font-bold'>{_('Series Index')}</span>
|
||||
<p className='text-neutral-content text-sm'>
|
||||
{metadata?.seriesIndex || _('Unknown')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className='metadata-description'>
|
||||
<button
|
||||
className={clsx(
|
||||
'flex w-full items-center justify-between rounded-lg px-4 py-3 text-left transition-colors',
|
||||
settings.metadataDescriptionCollapsed ? 'hover:bg-base-200' : '',
|
||||
)}
|
||||
onClick={toggleDescriptionCollapse}
|
||||
>
|
||||
<span className='text-neutral-content/85 text-base font-semibold'>
|
||||
{_('Description')}
|
||||
</span>
|
||||
<div className='transition-transform duration-200'>
|
||||
{settings.metadataDescriptionCollapsed ? (
|
||||
<MdExpandMore className='h-5 w-5' />
|
||||
) : (
|
||||
<MdExpandLess className='h-5 w-5' />
|
||||
)}
|
||||
</div>
|
||||
</button>
|
||||
{!settings.metadataDescriptionCollapsed && (
|
||||
<div className='px-4 py-1'>
|
||||
<p
|
||||
className='text-neutral-content prose prose-sm max-w-full whitespace-pre-line text-sm'
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: metadata?.description || _('No description available'),
|
||||
}}
|
||||
></p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -88,6 +88,10 @@ export const DEFAULT_SYSTEM_SETTINGS: Partial<SystemSettings> = {
|
||||
libraryAutoColumns: true,
|
||||
libraryColumns: 6,
|
||||
|
||||
metadataSeriesCollapsed: false,
|
||||
metadataOthersCollapsed: false,
|
||||
metadataDescriptionCollapsed: false,
|
||||
|
||||
kosync: DEFAULT_KOSYNC_SETTINGS,
|
||||
aiSettings: DEFAULT_AI_SETTINGS,
|
||||
|
||||
|
||||
@@ -95,6 +95,9 @@ export interface SystemSettings {
|
||||
customFonts: CustomFont[];
|
||||
customTextures: CustomTexture[];
|
||||
opdsCatalogs: OPDSCatalog[];
|
||||
metadataSeriesCollapsed: boolean;
|
||||
metadataOthersCollapsed: boolean;
|
||||
metadataDescriptionCollapsed: boolean;
|
||||
|
||||
kosync: KOSyncSettings;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user