fix: pdf bookmark

for pdfs only select pages not text
This commit is contained in:
2026-06-03 23:01:12 -05:00
parent f091386974
commit f989b144cf
11 changed files with 111 additions and 198 deletions
@@ -7,16 +7,14 @@ import { useNavigate } from "react-router-dom";
import { useTranslation } from "react-i18n-lite";
import { useAnnotations } from "@/context/AnnotationsContext";
import { useBookmarkRailLayout } from "../../hooks/useBookmarkRailLayout";
import { usePdfHighlights } from "../../hooks/usePdfHighlights";
import { usePdfReader } from "../../hooks/usePdfReader";
import { usePdfSelection } from "../../hooks/usePdfSelection";
import { useReadingSettings } from "../../hooks/useReadingSettings";
import { useToast } from "../../hooks/useToast";
import { booksApi } from "../../api/books";
import type { EBookDetail } from "../../types/book";
import type { EpubTocItem } from "./TableOfContents";
import { parsePageHref } from "../../utils/pdfAnchor";
import { parsePageHref, serializePdfAnchor } from "../../utils/pdfAnchor";
import { fallbackPdfPageToc } from "../../utils/pdfToc";
import { SelectionPopover } from "./SelectionPopover";
import { BookMarkersPanel } from "./BookMarkersPanel";
import { BookmarkReaderRail } from "./BookmarkReaderRail";
import { ResumeReadingButton } from "./ResumeReadingButton";
@@ -37,6 +35,8 @@ interface PdfReadingViewProps {
export function PdfReadingView({ book, bookId, initialAnchor }: PdfReadingViewProps) {
const { t } = useTranslation();
const navigate = useNavigate();
const { showToast } = useToast();
const { markers, addMarker, loadBookmarks } = useAnnotations();
const [tocOpen, setTocOpen] = useState(false);
const [settingsOpen, setSettingsOpen] = useState(false);
@@ -57,7 +57,6 @@ export function PdfReadingView({ book, bookId, initialAnchor }: PdfReadingViewPr
error,
isBookmarkPeekActive,
readingAnchor,
pageWrapRef,
goToPage,
goToNextPage,
goToPrevPage,
@@ -66,21 +65,18 @@ export function PdfReadingView({ book, bookId, initialAnchor }: PdfReadingViewPr
goToAnchor,
} = usePdfReader(bookId, book.page_count, initialAnchor);
const { pendingSelection, clearSelection } = usePdfSelection(
pageWrapRef,
currentPage,
chapterTitle,
);
const { markers } = useAnnotations();
const bookMarkers = useMemo(
() => markers.filter((m) => m.ebook_id === bookId),
[markers, bookId],
);
const pdfHighlights = usePdfHighlights(bookId, currentPage);
const railItems = useBookmarkRailLayout(bookMarkers);
useEffect(() => {
if (!bookId || Number.isNaN(bookId)) return;
void loadBookmarks(bookId);
}, [bookId, loadBookmarks]);
useEffect(() => {
void booksApi
.getToc(bookId)
@@ -129,6 +125,29 @@ export function PdfReadingView({ book, bookId, initialAnchor }: PdfReadingViewPr
[beginBookmarkPeek],
);
const handleBookmarkPage = useCallback(() => {
const anchor = serializePdfAnchor(currentPage);
const exists = bookMarkers.some((m) => m.epub_cfi === anchor);
if (exists) {
showToast({ message: t("reader.pageAlreadyBookmarked"), variant: "warning" });
return;
}
void addMarker({
ebook: bookId,
epub_cfi: anchor,
chapter_index: currentPage - 1,
chapter_title: t("reader.pdfPageLabel", { page: String(currentPage) }),
location_text: "",
content: "",
})
.then(() => {
showToast({ message: t("reader.pageBookmarked"), variant: "success" });
})
.catch(() => {
showToast({ message: t("annotations.saveFailed"), variant: "error" });
});
}, [addMarker, bookId, bookMarkers, currentPage, showToast, t]);
const progressForToolbar = useMemo(() => {
if (!progress) return progress;
const pct = pageCount > 0 ? Math.round((currentPage / pageCount) * 100) : 0;
@@ -140,6 +159,11 @@ export function PdfReadingView({ book, bookId, initialAnchor }: PdfReadingViewPr
};
}, [progress, currentPage, pageCount]);
const isCurrentPageBookmarked = useMemo(() => {
const anchor = serializePdfAnchor(currentPage);
return bookMarkers.some((m) => m.epub_cfi === anchor);
}, [bookMarkers, currentPage]);
if (isLoading) {
return (
<div className="reader-loading">
@@ -179,6 +203,8 @@ export function PdfReadingView({ book, bookId, initialAnchor }: PdfReadingViewPr
onToggleToc={() => setTocOpen((v) => !v)}
onToggleSettings={() => setSettingsOpen((v) => !v)}
onToggleMarkers={() => setMarkersOpen((v) => !v)}
onBookmarkPage={handleBookmarkPage}
isCurrentPageBookmarked={isCurrentPageBookmarked}
/>
<PdfLimitationsNotice bookId={bookId} />
@@ -195,6 +221,7 @@ export function PdfReadingView({ book, bookId, initialAnchor }: PdfReadingViewPr
isOpen={markersOpen}
onClose={() => setMarkersOpen(false)}
onGoToPassage={handleGoToMarker}
emptyHintKey="annotations.pdfPageBookmarkHint"
/>
<ReadingSettingsPanel
@@ -208,23 +235,12 @@ export function PdfReadingView({ book, bookId, initialAnchor }: PdfReadingViewPr
onFlush={flushSettings}
/>
{pendingSelection && (
<SelectionPopover
ebookId={bookId}
selection={pendingSelection}
onClose={clearSelection}
onSaved={clearSelection}
/>
)}
<main className="reader-pdf-container">
<div className="reader-pdf-scroll">
<PdfViewer
document={pdfDocument}
pageNumber={currentPage}
scale={scale}
highlights={pdfHighlights}
pageWrapRef={pageWrapRef}
/>
</div>
<BookmarkReaderRail