Paperjet/frontend/src/features/editor/pages/PdfDocument.tsx

64 lines
1.9 KiB
TypeScript

import { useEffect, useState } from 'react';
import * as pdfjsLib from 'pdfjs-dist';
import { PageStack } from './PageStack';
pdfjsLib.GlobalWorkerOptions.workerSrc = new URL(
'pdfjs-dist/build/pdf.worker.mjs',
import.meta.url,
).toString();
interface LoadedDocument {
id: string;
document: pdfjsLib.PDFDocumentProxy;
}
interface DocumentError {
id: string;
message: string;
}
export function PdfDocument({ documentId }: { documentId: string }) {
const [loaded, setLoaded] = useState<LoadedDocument | null>(null);
const [error, setError] = useState<DocumentError | null>(null);
useEffect(() => {
let active = true;
const loadingTask = pdfjsLib.getDocument({ url: `/api/v1/documents/${documentId}/file` });
loadingTask.promise.then((document) => {
if (active) setLoaded({ id: documentId, document });
}).catch((reason: unknown) => {
if (active) {
const message = reason instanceof Error ? reason.message : 'Unable to load this PDF.';
setError({ id: documentId, message });
}
});
return () => {
active = false;
void loadingTask.destroy();
};
}, [documentId]);
const currentError = error?.id === documentId ? error.message : null;
const currentDocument = loaded?.id === documentId ? loaded.document : null;
if (currentError) {
return (
<div className="flex h-full w-full items-center justify-center">
<div className="rounded-lg border border-red-200 bg-red-50 px-4 py-3 text-red-600">Error loading PDF: {currentError}</div>
</div>
);
}
if (!currentDocument) {
return (
<div className="flex h-full w-full flex-col items-center justify-center gap-4">
<div className="h-8 w-8 animate-spin rounded-full border-b-2 border-accent-500" />
<div className="font-medium animate-pulse text-neutral-500">Loading document</div>
</div>
);
}
return <PageStack pdfDoc={currentDocument} />;
}