refactor(frontend): PDF reader chrome to shadcn (B4)

This commit is contained in:
2026-09-16 17:43:51 +08:00
parent 8831a9b277
commit 4767ee7fec
+42 -27
View File
@@ -4,7 +4,8 @@ import * as pdfjs from "pdfjs-dist";
import { apiRaw } from "../api/client"; import { apiRaw } from "../api/client";
import { BookmarksTab } from "../components/Bookmarks"; import { BookmarksTab } from "../components/Bookmarks";
import { ReaderNav } from "../components/reader-nav"; import { ReaderNav } from "../components/reader-nav";
import { btn } from "../components/ui"; import { ReaderSettings } from "../components/reader-settings";
import { Button } from "@/components/ui/button";
import { useProgressSaver, type ReaderProps } from "../lib/useProgress"; import { useProgressSaver, type ReaderProps } from "../lib/useProgress";
// Vite 原生 worker 语法;pdfjs v5 要求 module worker // Vite 原生 worker 语法;pdfjs v5 要求 module worker
@@ -124,70 +125,84 @@ export default function PdfReader({ book, initialLocator, initialPercent }: Read
if (err) if (err)
return ( return (
<div className="grid h-full place-items-center p-8 text-center"> <div className="bg-muted grid h-full place-items-center p-8 text-center">
<div> <div>
<p className="mb-3 text-red-400">{err}</p> <p className="text-destructive mb-3">{err}</p>
<button className={btn} onClick={() => setNonce((x) => x + 1)}> <Button variant="secondary" onClick={() => setNonce((x) => x + 1)}>
重试 重试
</button> </Button>
</div> </div>
</div> </div>
); );
if (num === 0) return <div className="grid h-full place-items-center text-stone-500">PDF 加载中…</div>; if (num === 0) return <div className="text-muted-foreground grid h-full place-items-center">PDF 加载中…</div>;
return ( return (
<div <div
tabIndex={0} tabIndex={0}
onKeyDown={onKey} onKeyDown={onKey}
aria-label="PDF 阅读器,可用左右方向键翻页" aria-label="PDF 阅读器,可用左右方向键翻页"
className="relative grid h-full grid-rows-[1fr_auto] focus:outline-none" className="relative grid h-full grid-rows-[1fr_auto] bg-background text-foreground focus:outline-none focus-visible:outline-hidden"
> >
<div ref={wrapRef} className="flex min-h-0 items-start justify-center overflow-y-auto bg-stone-900/70 p-4"> <div ref={wrapRef} className="bg-muted/50 flex min-h-0 items-start justify-center overflow-y-auto p-4">
<canvas ref={canvasRef} className="max-w-3xl rounded-md shadow-2xl ring-1 ring-stone-700/50" /> <canvas ref={canvasRef} className="ring-border max-w-3xl rounded-md shadow-2xl ring-1" />
</div> </div>
<div className="flex items-center justify-center gap-2 border-t border-stone-800/80 px-4 py-2 text-sm"> <ReaderSettings
<button left={
className={btn + " inline-flex items-center gap-0.5"} <>
<Button
variant="ghost"
size="sm"
className="gap-0.5"
disabled={page === 0} disabled={page === 0}
onClick={() => setPage(0)} onClick={() => setPage(0)}
aria-label="第一页" aria-label="第一页"
> >
<ChevronsLeft size={14} /> 首页 <ChevronsLeft size={14} /> 首页
</button> </Button>
<button <Button
className={btn + " inline-flex items-center gap-0.5"} variant="ghost"
size="sm"
className="gap-0.5"
disabled={page === 0} disabled={page === 0}
onClick={() => setPage((p) => Math.max(0, p - 1))} onClick={() => setPage((p) => Math.max(0, p - 1))}
> >
<ChevronLeft size={14} /> 上一页 <ChevronLeft size={14} /> 上一页
</button> </Button>
<span className="min-w-16 text-center tabular-nums text-stone-400"> <span className="min-w-16 text-center text-muted-foreground tabular-nums">
{page + 1}/{num} {page + 1}/{num}
</span> </span>
<button <Button
className={btn + " inline-flex items-center gap-0.5"} variant="ghost"
size="sm"
className="gap-0.5"
disabled={page >= num - 1} disabled={page >= num - 1}
onClick={() => setPage((p) => Math.min(num - 1, p + 1))} onClick={() => setPage((p) => Math.min(num - 1, p + 1))}
> >
下一页 <ChevronRight size={14} /> 下一页 <ChevronRight size={14} />
</button> </Button>
<button <Button
className={btn + " inline-flex items-center gap-0.5"} variant="ghost"
size="sm"
className="gap-0.5"
disabled={page >= num - 1} disabled={page >= num - 1}
onClick={() => setPage(num - 1)} onClick={() => setPage(num - 1)}
aria-label="最后一页" aria-label="最后一页"
> >
<ChevronsRight size={14} /> 末页 <ChevronsRight size={14} /> 末页
</button> </Button>
<button <Button
className="rd-btn inline-flex items-center gap-1.5" variant="ghost"
size="sm"
className="gap-1.5"
aria-expanded={nav} aria-expanded={nav}
aria-controls="reader-nav" aria-controls="reader-nav"
onClick={() => setNav((v) => !v)} onClick={() => setNav((v) => !v)}
> >
<PanelLeft size={14} /> 导航 <PanelLeft size={14} /> 导航
</button> </Button>
</div> </>
}
/>
{nav && ( {nav && (
<ReaderNav <ReaderNav
tab="bm" tab="bm"