mirror of
https://github.com/priyanshujain/margin.git
synced 2026-10-02 11:07:04 +00:00
feat(pdf): wire live Typst PDF dock with HTML fallback
This commit is contained in:
1 parent
29af847179
commit
6769570de3
1 file changed
+50
-2
+50
-2
@@ -1,7 +1,10 @@
|
||||
import { useMemo } from "react";
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { generateHTML } from "@tiptap/core";
|
||||
import { useBook } from "../store/useBook";
|
||||
import { editorExtensions } from "../editor/extensions";
|
||||
import { bookToPdfInputs } from "../export/typst";
|
||||
import { compilePdf } from "../ipc";
|
||||
import { PdfPreview } from "./PdfPreview";
|
||||
|
||||
const TRIM_LABEL: Record<string, string> = {
|
||||
"6x9": "6 × 9 in",
|
||||
@@ -10,11 +13,56 @@ const TRIM_LABEL: Record<string, string> = {
|
||||
a5: "A5",
|
||||
};
|
||||
|
||||
const inTauri = typeof window !== "undefined" && "__TAURI_INTERNALS__" in window;
|
||||
|
||||
export function Dock() {
|
||||
return inTauri ? <PdfDock /> : <HtmlDock />;
|
||||
}
|
||||
|
||||
function PdfDock() {
|
||||
const book = useBook((s) => s.book);
|
||||
const [pdf, setPdf] = useState<Uint8Array | null>(null);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [busy, setBusy] = useState(false);
|
||||
const timer = useRef<ReturnType<typeof setTimeout>>(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
clearTimeout(timer.current);
|
||||
setBusy(true);
|
||||
timer.current = setTimeout(() => {
|
||||
const { source, images } = bookToPdfInputs(book);
|
||||
compilePdf(source, images)
|
||||
.then((bytes) => {
|
||||
setPdf(bytes);
|
||||
setError(null);
|
||||
})
|
||||
.catch((e) => setError(String(e)))
|
||||
.finally(() => setBusy(false));
|
||||
}, 350);
|
||||
return () => clearTimeout(timer.current);
|
||||
}, [book]);
|
||||
|
||||
return (
|
||||
<section className="dock">
|
||||
<div className="dock-head">
|
||||
<span className="label">Preview</span>
|
||||
<span className="meta">{busy ? "updating…" : TRIM_LABEL[book.settings.trim]}</span>
|
||||
</div>
|
||||
{error ? (
|
||||
<pre className="dock-error">{error}</pre>
|
||||
) : pdf ? (
|
||||
<PdfPreview data={pdf} />
|
||||
) : (
|
||||
<div className="dock-empty">Typesetting…</div>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
function HtmlDock() {
|
||||
const chapters = useBook((s) => s.book.chapters);
|
||||
const trim = useBook((s) => s.book.settings.trim);
|
||||
const activeChapterId = useBook((s) => s.activeChapterId);
|
||||
|
||||
const idx = chapters.findIndex((c) => c.id === activeChapterId);
|
||||
const chapter = chapters[idx];
|
||||
const html = useMemo(() => generateHTML(chapter.content, editorExtensions), [chapter.content]);
|
||||
|
||||
Reference in new issue
Block a user