refactor(frontend): PDF reader chrome to shadcn (B4)
This commit is contained in:
@@ -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 className="flex items-center justify-center gap-2 border-t border-stone-800/80 px-4 py-2 text-sm">
|
|
||||||
<button
|
|
||||||
className={btn + " inline-flex items-center gap-0.5"}
|
|
||||||
disabled={page === 0}
|
|
||||||
onClick={() => setPage(0)}
|
|
||||||
aria-label="第一页"
|
|
||||||
>
|
|
||||||
<ChevronsLeft size={14} /> 首页
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className={btn + " inline-flex items-center gap-0.5"}
|
|
||||||
disabled={page === 0}
|
|
||||||
onClick={() => setPage((p) => Math.max(0, p - 1))}
|
|
||||||
>
|
|
||||||
<ChevronLeft size={14} /> 上一页
|
|
||||||
</button>
|
|
||||||
<span className="min-w-16 text-center tabular-nums text-stone-400">
|
|
||||||
{page + 1}/{num}
|
|
||||||
</span>
|
|
||||||
<button
|
|
||||||
className={btn + " inline-flex items-center gap-0.5"}
|
|
||||||
disabled={page >= num - 1}
|
|
||||||
onClick={() => setPage((p) => Math.min(num - 1, p + 1))}
|
|
||||||
>
|
|
||||||
下一页 <ChevronRight size={14} />
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className={btn + " inline-flex items-center gap-0.5"}
|
|
||||||
disabled={page >= num - 1}
|
|
||||||
onClick={() => setPage(num - 1)}
|
|
||||||
aria-label="最后一页"
|
|
||||||
>
|
|
||||||
<ChevronsRight size={14} /> 末页
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className="rd-btn inline-flex items-center gap-1.5"
|
|
||||||
aria-expanded={nav}
|
|
||||||
aria-controls="reader-nav"
|
|
||||||
onClick={() => setNav((v) => !v)}
|
|
||||||
>
|
|
||||||
<PanelLeft size={14} /> 导航
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
<ReaderSettings
|
||||||
|
left={
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
className="gap-0.5"
|
||||||
|
disabled={page === 0}
|
||||||
|
onClick={() => setPage(0)}
|
||||||
|
aria-label="第一页"
|
||||||
|
>
|
||||||
|
<ChevronsLeft size={14} /> 首页
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
className="gap-0.5"
|
||||||
|
disabled={page === 0}
|
||||||
|
onClick={() => setPage((p) => Math.max(0, p - 1))}
|
||||||
|
>
|
||||||
|
<ChevronLeft size={14} /> 上一页
|
||||||
|
</Button>
|
||||||
|
<span className="min-w-16 text-center text-muted-foreground tabular-nums">
|
||||||
|
{page + 1}/{num}
|
||||||
|
</span>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
className="gap-0.5"
|
||||||
|
disabled={page >= num - 1}
|
||||||
|
onClick={() => setPage((p) => Math.min(num - 1, p + 1))}
|
||||||
|
>
|
||||||
|
下一页 <ChevronRight size={14} />
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
className="gap-0.5"
|
||||||
|
disabled={page >= num - 1}
|
||||||
|
onClick={() => setPage(num - 1)}
|
||||||
|
aria-label="最后一页"
|
||||||
|
>
|
||||||
|
<ChevronsRight size={14} /> 末页
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
className="gap-1.5"
|
||||||
|
aria-expanded={nav}
|
||||||
|
aria-controls="reader-nav"
|
||||||
|
onClick={() => setNav((v) => !v)}
|
||||||
|
>
|
||||||
|
<PanelLeft size={14} /> 导航
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
{nav && (
|
{nav && (
|
||||||
<ReaderNav
|
<ReaderNav
|
||||||
tab="bm"
|
tab="bm"
|
||||||
|
|||||||
Reference in New Issue
Block a user