forked from akai/readest
layout: apply custom css also to the library page, tweaks on fitted cover images (#1481)
This commit is contained in:
@@ -54,7 +54,7 @@ const BookItem: React.FC<BookItemProps> = ({
|
||||
<div
|
||||
className={clsx(
|
||||
'book-item flex',
|
||||
mode === 'grid' && 'h-full flex-col',
|
||||
mode === 'grid' && 'h-full flex-col justify-end',
|
||||
mode === 'list' && 'h-28 flex-row gap-4 overflow-hidden',
|
||||
appService?.hasContextMenu ? 'cursor-pointer' : '',
|
||||
)}
|
||||
@@ -65,7 +65,7 @@ const BookItem: React.FC<BookItemProps> = ({
|
||||
mode === 'list' && 'min-w-20',
|
||||
)}
|
||||
>
|
||||
<BookCover mode={mode} book={book} coverFit={coverFit} className='drop-shadow-md' />
|
||||
<BookCover mode={mode} book={book} coverFit={coverFit} />
|
||||
{selectedBooks.includes(book.hash) && (
|
||||
<div className='absolute inset-0 bg-black opacity-30 transition-opacity duration-300'></div>
|
||||
)}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import clsx from 'clsx';
|
||||
import { MdCheckCircle, MdCheckCircleOutline } from 'react-icons/md';
|
||||
import { useEnv } from '@/context/EnvContext';
|
||||
import { useResponsiveSize } from '@/hooks/useResponsiveSize';
|
||||
import { BooksGroup } from '@/types/book';
|
||||
import BookCover from '@/components/BookCover';
|
||||
|
||||
@@ -12,10 +13,12 @@ interface GroupItemProps {
|
||||
|
||||
const GroupItem: React.FC<GroupItemProps> = ({ group, isSelectMode, selectedBooks }) => {
|
||||
const { appService } = useEnv();
|
||||
const iconSize15 = useResponsiveSize(15);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
'group-item flex h-full flex-col',
|
||||
'group-item flex h-full flex-col justify-end',
|
||||
appService?.hasContextMenu ? 'cursor-pointer' : '',
|
||||
)}
|
||||
>
|
||||
@@ -40,10 +43,13 @@ const GroupItem: React.FC<GroupItemProps> = ({ group, isSelectMode, selectedBook
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className='min-w-0 flex-1 pt-2'>
|
||||
<h4 className='block overflow-hidden text-ellipsis whitespace-nowrap text-xs font-semibold'>
|
||||
{group.name}
|
||||
</h4>
|
||||
<div className={clsx('flex w-full flex-col pt-2')}>
|
||||
<div className='min-w-0 flex-1'>
|
||||
<h4 className='block overflow-hidden text-ellipsis whitespace-nowrap text-xs font-semibold'>
|
||||
{group.name}
|
||||
</h4>
|
||||
</div>
|
||||
<div className='placeholder' style={{ height: `${iconSize15}px` }}></div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -26,6 +26,7 @@ import { useLibraryStore } from '@/store/libraryStore';
|
||||
import { useSettingsStore } from '@/store/settingsStore';
|
||||
import { usePullToRefresh } from '@/hooks/usePullToRefresh';
|
||||
import { useTheme } from '@/hooks/useTheme';
|
||||
import { useUICSS } from '@/hooks/useUICSS';
|
||||
import { useDemoBooks } from './hooks/useDemoBooks';
|
||||
import { useBooksSync } from './hooks/useBooksSync';
|
||||
import { useSafeAreaInsets } from '@/hooks/useSafeAreaInsets';
|
||||
@@ -68,7 +69,6 @@ const LibraryPageContent = ({ searchParams }: { searchParams: ReadonlyURLSearchP
|
||||
setCheckLastOpenBooks,
|
||||
} = useLibraryStore();
|
||||
const _ = useTranslation();
|
||||
useTheme({ systemUIVisible: true, appThemeColor: 'base-200' });
|
||||
const insets = useSafeAreaInsets();
|
||||
const { settings, setSettings, saveSettings } = useSettingsStore();
|
||||
const [loading, setLoading] = useState(false);
|
||||
@@ -87,6 +87,9 @@ const LibraryPageContent = ({ searchParams }: { searchParams: ReadonlyURLSearchP
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const pageRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useTheme({ systemUIVisible: true, appThemeColor: 'base-200' });
|
||||
useUICSS();
|
||||
|
||||
useOpenWithBooks();
|
||||
|
||||
const { pullLibrary, pushLibrary } = useBooksSync({
|
||||
|
||||
@@ -22,22 +22,34 @@ const BookCover: React.FC<BookCoverProps> = ({
|
||||
isPreview,
|
||||
}) => {
|
||||
return (
|
||||
<div className={clsx('relative flex h-full w-full', className)}>
|
||||
<Image
|
||||
src={book.coverImageUrl!}
|
||||
alt={book.title}
|
||||
fill={true}
|
||||
className={clsx(
|
||||
coverFit === 'crop'
|
||||
? 'object-cover'
|
||||
: `object-contain ${mode === 'grid' ? 'object-bottom' : ''}`,
|
||||
imageClassName,
|
||||
)}
|
||||
onError={(e) => {
|
||||
(e.target as HTMLImageElement).style.display = 'none';
|
||||
(e.target as HTMLImageElement).nextElementSibling?.classList.remove('invisible');
|
||||
}}
|
||||
/>
|
||||
<div className={clsx('relative flex h-full w-full shadow-md', className)}>
|
||||
{coverFit === 'crop' ? (
|
||||
<Image
|
||||
src={book.coverImageUrl!}
|
||||
alt={book.title}
|
||||
fill={true}
|
||||
className={clsx('crop-cover-img object-cover', imageClassName)}
|
||||
onError={(e) => {
|
||||
(e.target as HTMLImageElement).style.display = 'none';
|
||||
(e.target as HTMLImageElement).nextElementSibling?.classList.remove('invisible');
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<div className='flex h-full w-full items-end justify-center'>
|
||||
<Image
|
||||
src={book.coverImageUrl!}
|
||||
alt={book.title}
|
||||
width={0}
|
||||
height={0}
|
||||
sizes='100vw'
|
||||
className={clsx('fit-cover-img h-auto max-h-full w-auto max-w-full', imageClassName)}
|
||||
onError={(e) => {
|
||||
(e.target as HTMLImageElement).style.display = 'none';
|
||||
(e.target as HTMLImageElement).nextElementSibling?.classList.remove('invisible');
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
className={clsx(
|
||||
'invisible absolute inset-0 rounded-none p-2',
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useReaderStore } from '@/store/readerStore';
|
||||
import { useSettingsStore } from '@/store/settingsStore';
|
||||
|
||||
// This hook allows you to inject custom CSS into the reader UI.
|
||||
// Note that the book content is rendered in an iframe, so UI CSS won't affect book rendering.
|
||||
export const useUICSS = (bookKey: string) => {
|
||||
export const useUICSS = (bookKey?: string) => {
|
||||
const { settings } = useSettingsStore();
|
||||
const { getViewSettings } = useReaderStore();
|
||||
const viewSettings = getViewSettings(bookKey);
|
||||
const viewSettings = getViewSettings(bookKey || '');
|
||||
const [styleElement, setStyleElement] = useState<HTMLStyleElement | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!viewSettings) return;
|
||||
if (styleElement) {
|
||||
styleElement.remove();
|
||||
}
|
||||
|
||||
const rawCSS = viewSettings.userUIStylesheet || '';
|
||||
const rawCSS =
|
||||
viewSettings?.userUIStylesheet || settings?.globalViewSettings?.userUIStylesheet || '';
|
||||
|
||||
const newStyleEl = document.createElement('style');
|
||||
newStyleEl.textContent = rawCSS.replace('foliate-view', `#foliate-view-${bookKey}`);
|
||||
document.head.appendChild(newStyleEl);
|
||||
@@ -24,5 +27,5 @@ export const useUICSS = (bookKey: string) => {
|
||||
newStyleEl.remove();
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [viewSettings]);
|
||||
}, [viewSettings?.userUIStylesheet, settings?.globalViewSettings?.userUIStylesheet, bookKey]);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user