feat(web): unify reader TOC and bookmarks into one left nav drawer with tabs

This commit is contained in:
2026-09-08 21:08:42 +08:00
parent 4f4c7e5434
commit 48161ea1ff
7 changed files with 340 additions and 211 deletions
+23 -11
View File
@@ -1,7 +1,8 @@
import { useEffect, useRef, useState, type KeyboardEvent } from "react";
import * as pdfjs from "pdfjs-dist";
import { apiRaw } from "../api/client";
import { useBookmarks } from "../components/Bookmarks";
import { BookmarksTab } from "../components/Bookmarks";
import { ReaderNav } from "../components/reader-nav";
import { btn } from "../components/ui";
import { useProgressSaver, type ReaderProps } from "../lib/useProgress";
@@ -21,14 +22,7 @@ export default function PdfReader({ book, initialLocator, initialPercent }: Read
const taskRef = useRef<RenderTask | null>(null);
const restored = useRef(false);
const saver = useProgressSaver(book.id, { locator: initialLocator, percent: initialPercent });
const bm = useBookmarks({
book,
capture: saver.capture,
seek: (l) => {
const p = Number(l.page);
if (Number.isInteger(p) && p >= 0 && p < num) setPage(p);
},
});
const [nav, setNav] = useState(false);
const [num, setNum] = useState(0);
const [page, setPage] = useState(0); // 0 基
const [err, setErr] = useState("");
@@ -160,9 +154,27 @@ export default function PdfReader({ book, initialLocator, initialPercent }: Read
<button className={btn} disabled={page >= num - 1} onClick={() => setPage(num - 1)} aria-label="最后一页">
末页
</button>
{bm.btn}
<button className="rd-btn" aria-expanded={nav} aria-controls="reader-nav" onClick={() => setNav((v) => !v)}>
书签
</button>
</div>
{bm.panel}
{nav && (
<ReaderNav
tab="bm"
onClose={() => setNav(false)}
bookmarks={
<BookmarksTab
book={book}
capture={saver.capture}
seek={(l) => {
const p = Number(l.page);
setNav(false);
if (Number.isInteger(p) && p >= 0 && p < num) setPage(p);
}}
/>
}
/>
)}
</div>
);
}