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
+34 -22
+34 -22
View File
@@ -1,4 +1,4 @@
import { useEffect, useRef } from "react";
import { useEffect, useRef, useState } from "react";
import * as pdfjs from "pdfjs-dist";
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 }) {
const ref = useRef<HTMLDivElement>(null);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const container = ref.current;
@@ -13,29 +14,35 @@ export function PdfPreview({ data }: { data: Uint8Array }) {
let cancelled = false;
(async () => {
const doc = await pdfjs.getDocument({ data: data.slice() }).promise;
if (cancelled) return;
const width = container.clientWidth;
const dpr = window.devicePixelRatio || 1;
const canvases: HTMLCanvasElement[] = [];
try {
const doc = await pdfjs.getDocument({ data: data.slice() }).promise;
if (cancelled) return;
const width = container.clientWidth;
const dpr = window.devicePixelRatio || 1;
const canvases: HTMLCanvasElement[] = [];
for (let n = 1; n <= doc.numPages; n++) {
const page = await doc.getPage(n);
for (let n = 1; n <= doc.numPages; n++) {
const page = await doc.getPage(n);
if (cancelled) return;
const base = page.getViewport({ scale: 1 });
const scale = width / base.width;
const viewport = page.getViewport({ scale: scale * dpr });
const canvas = document.createElement("canvas");
canvas.className = "pdf-page";
canvas.width = viewport.width;
canvas.height = viewport.height;
canvas.style.width = "100%";
await page.render({ canvas, viewport }).promise;
if (cancelled) return;
canvases.push(canvas);
}
container.replaceChildren(...canvases);
setError(null);
} catch (e) {
if (cancelled) return;
const base = page.getViewport({ scale: 1 });
const scale = width / base.width;
const viewport = page.getViewport({ scale: scale * dpr });
const canvas = document.createElement("canvas");
canvas.className = "pdf-page";
canvas.width = viewport.width;
canvas.height = viewport.height;
canvas.style.width = "100%";
const context = canvas.getContext("2d")!;
await page.render({ canvas, canvasContext: context, viewport }).promise;
if (cancelled) return;
canvases.push(canvas);
container.replaceChildren();
setError(String(e));
}
container.replaceChildren(...canvases);
})();
return () => {
@@ -43,5 +50,10 @@ export function PdfPreview({ data }: { data: Uint8Array }) {
};
}, [data]);
return <div className="pdf-pages" ref={ref} />;
return (
<>
{error && <pre className="dock-error">{error}</pre>}
<div className="pdf-pages" ref={ref} />
</>
);
}