64 lines
1.9 KiB
TypeScript
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} />;
|
|
}
|