import clsx from 'clsx'; import React, { useEffect } from 'react'; import { useEnv } from '@/context/EnvContext'; import { useSettingsStore } from '@/store/settingsStore'; import { useReaderStore } from '@/store/readerStore'; import { useSidebarStore } from '@/store/sidebarStore'; import { useBookDataStore } from '@/store/bookDataStore'; import { useSafeAreaInsets } from '@/hooks/useSafeAreaInsets'; import { getGridTemplate, getInsetEdges } from '@/utils/grid'; import { getViewInsets } from '@/utils/insets'; import FoliateViewer from './FoliateViewer'; import SectionInfo from './SectionInfo'; import HeaderBar from './HeaderBar'; import FooterBar from './FooterBar'; import ProgressInfoView from './ProgressInfo'; import Ribbon from './Ribbon'; import SettingsDialog from './settings/SettingsDialog'; import Annotator from './annotator/Annotator'; import FootnotePopup from './FootnotePopup'; import HintInfo from './HintInfo'; import DoubleBorder from './DoubleBorder'; interface BooksGridProps { bookKeys: string[]; onCloseBook: (bookKey: string) => void; } const BooksGrid: React.FC = ({ bookKeys, onCloseBook }) => { const { appService } = useEnv(); const { getConfig, getBookData } = useBookDataStore(); const { getProgress, getViewState, getViewSettings } = useReaderStore(); const { setGridInsets, hoveredBookKey } = useReaderStore(); const { sideBarBookKey } = useSidebarStore(); const { isFontLayoutSettingsDialogOpen, setFontLayoutSettingsDialogOpen } = useSettingsStore(); const screenInsets = useSafeAreaInsets(); const aspectRatio = window.innerWidth / window.innerHeight; const gridTemplate = getGridTemplate(bookKeys.length, aspectRatio); useEffect(() => { if (!sideBarBookKey) return; const bookData = getBookData(sideBarBookKey); if (!bookData || !bookData.book) return; document.title = bookData.book.title; // eslint-disable-next-line react-hooks/exhaustive-deps }, [sideBarBookKey]); const calcGridInsets = (index: number, count: number) => { if (!screenInsets) return { top: 0, right: 0, bottom: 0, left: 0 }; const { top, right, bottom, left } = getInsetEdges(index, count, aspectRatio); return { top: top ? screenInsets.top : 0, right: right ? screenInsets.right : 0, bottom: bottom ? screenInsets.bottom : 0, left: left ? screenInsets.left : 0, }; }; useEffect(() => { if (!screenInsets) return; bookKeys.forEach((bookKey, index) => { const gridInsets = calcGridInsets(index, bookKeys.length); setGridInsets(bookKey, gridInsets); }); // eslint-disable-next-line react-hooks/exhaustive-deps }, [bookKeys, screenInsets]); if (!screenInsets) return null; return (
{bookKeys.map((bookKey, index) => { const bookData = getBookData(bookKey); const config = getConfig(bookKey); const progress = getProgress(bookKey); const viewSettings = getViewSettings(bookKey); const gridInsets = calcGridInsets(index, bookKeys.length); const { book, bookDoc } = bookData || {}; if (!book || !config || !bookDoc || !viewSettings) return null; const { section, pageinfo, timeinfo, sectionLabel } = progress || {}; const isBookmarked = getViewState(bookKey)?.ribbonVisible; const horizontalGapPercent = viewSettings.gapPercent; const viewInsets = getViewInsets(viewSettings); const contentInsets = { top: gridInsets.top + viewInsets.top, right: gridInsets.right + viewInsets.right, bottom: gridInsets.bottom + viewInsets.bottom, left: gridInsets.left + viewInsets.left, }; const scrolled = viewSettings.scrolled; const showBarsOnScroll = viewSettings.showBarsOnScroll; const showHeader = viewSettings.showHeader && (scrolled ? showBarsOnScroll : true); const showFooter = viewSettings.showFooter && (scrolled ? showBarsOnScroll : true); return (
{isBookmarked && !hoveredBookKey && } 2} onCloseBook={onCloseBook} onSetSettingsDialogOpen={setFontLayoutSettingsDialogOpen} gridInsets={gridInsets} /> {viewSettings.vertical && viewSettings.scrolled && ( <> {(showFooter || viewSettings.doubleBorder) && (
)} {(showHeader || viewSettings.doubleBorder) && (
)} )} {viewSettings.vertical && viewSettings.doubleBorder && ( )} {showHeader && ( )} {showFooter && ( )} {isFontLayoutSettingsDialogOpen && }
); })}
); }; export default BooksGrid;