fix(preview): show render errors instead of a blank pane

The render loop swallowed getDocument/render rejections, leaving the
preview silently blank with no signal about what failed. Surface the
error in the pane and recover on the next compile. Also drop the
redundant canvasContext arg (pdf.js v6 renders via the canvas itself).
This commit is contained in:
pj committed 2026-06-22 12:01:25 -04:00
1 parent 19c4823d3d
commit 3177b2f1eb
1 file changed
+16 -4
+16 -4
View File
@@ -1,4 +1,4 @@
import { useEffect, useRef } from "react"; import { useEffect, useRef, useState } from "react";
import * as pdfjs from "pdfjs-dist"; import * as pdfjs from "pdfjs-dist";
import workerUrl from "pdfjs-dist/build/pdf.worker.min.mjs?url"; import workerUrl from "pdfjs-dist/build/pdf.worker.min.mjs?url";
@@ -6,6 +6,7 @@ pdfjs.GlobalWorkerOptions.workerSrc = workerUrl;
export function PdfPreview({ data }: { data: Uint8Array }) { export function PdfPreview({ data }: { data: Uint8Array }) {
const ref = useRef<HTMLDivElement>(null); const ref = useRef<HTMLDivElement>(null);
const [error, setError] = useState<string | null>(null);
useEffect(() => { useEffect(() => {
const container = ref.current; const container = ref.current;
@@ -13,6 +14,7 @@ export function PdfPreview({ data }: { data: Uint8Array }) {
let cancelled = false; let cancelled = false;
(async () => { (async () => {
try {
const doc = await pdfjs.getDocument({ data: data.slice() }).promise; const doc = await pdfjs.getDocument({ data: data.slice() }).promise;
if (cancelled) return; if (cancelled) return;
const width = container.clientWidth; const width = container.clientWidth;
@@ -30,12 +32,17 @@ export function PdfPreview({ data }: { data: Uint8Array }) {
canvas.width = viewport.width; canvas.width = viewport.width;
canvas.height = viewport.height; canvas.height = viewport.height;
canvas.style.width = "100%"; canvas.style.width = "100%";
const context = canvas.getContext("2d")!; await page.render({ canvas, viewport }).promise;
await page.render({ canvas, canvasContext: context, viewport }).promise;
if (cancelled) return; if (cancelled) return;
canvases.push(canvas); canvases.push(canvas);
} }
container.replaceChildren(...canvases); container.replaceChildren(...canvases);
setError(null);
} catch (e) {
if (cancelled) return;
container.replaceChildren();
setError(String(e));
}
})(); })();
return () => { return () => {
@@ -43,5 +50,10 @@ export function PdfPreview({ data }: { data: Uint8Array }) {
}; };
}, [data]); }, [data]);
return <div className="pdf-pages" ref={ref} />; return (
<>
{error && <pre className="dock-error">{error}</pre>}
<div className="pdf-pages" ref={ref} />
</>
);
} }