import { ContentObject, DocumentMetadata } from "@vertesia/common"; import { Button, ErrorBox, ResizableHandle, ResizablePanel, ResizablePanelGroup, useFetch } from "@vertesia/ui/core"; import { useUserSession } from "@vertesia/ui/session"; import { X } from "lucide-react"; import { Component, ErrorInfo, ReactNode, useState } from "react"; import { useUITranslation, i18nInstance, NAMESPACE } from '../../i18n/index.js'; import { PdfPageSlider } from "../pdf-viewer/PdfPageSlider"; import { AnnotatedImageSlider } from "./AnnotatedImageSlider"; import { DownloadPopover } from "./DownloadPopover"; import { ExtractedContentView } from "./ExtractedContentView"; import { MagicPdfProvider, useMagicPdfContext } from "./MagicPdfProvider"; // Error boundary for PDF view interface ErrorBoundaryProps { children: ReactNode; onClose?: () => void; } interface ErrorBoundaryState { hasError: boolean; error: Error | null; } class PdfViewErrorBoundary extends Component { constructor(props: ErrorBoundaryProps) { super(props); this.state = { hasError: false, error: null }; } static getDerivedStateFromError(error: Error): ErrorBoundaryState { return { hasError: true, error }; } componentDidCatch(error: Error, errorInfo: ErrorInfo) { console.error('PDF View error:', error, errorInfo); } render() { if (this.state.hasError) { return (
{this.state.error?.message || 'An unexpected error occurred'} {this.props.onClose && ( )}
); } return this.props.children; } } interface MagicPdfViewProps { objectId: string; onClose?: () => void; } export function MagicPdfView({ objectId, onClose }: MagicPdfViewProps) { const { t } = useUITranslation(); const { client } = useUserSession(); const { data: object, error } = useFetch(() => client.store.objects.retrieve(objectId, "+text"), [objectId]); if (error) { return (
{error.message} {onClose && ( )}
); } if (!object) { return (
{/* Header matching the main view layout */}
{onClose && ( )}
); } return (
); } interface _MagicPdfViewProps { object: ContentObject; onClose?: () => void; } function MagicPdfViewImpl({ object, onClose }: _MagicPdfViewProps) { const { t } = useUITranslation(); const { count: totalPages, pdfUrl, pdfUrlLoading } = useMagicPdfContext(); const getProcessorType = (): "xml" | "markdown" => { if (object.metadata?.type === "document") { const docMetadata = object.metadata as DocumentMetadata; const type = docMetadata.content_processor?.type; if (type === "markdown") return "markdown"; } return "xml"; // default }; const [pageNumber, setPageNumber] = useState(1); const processorType = getProcessorType(); // XML processor: ImageSlider (annotated images) on left, XML/JSON/Markdown text on right // Markdown processor: PageSlider (PDF thumbnails) on left, Markdown on right if (processorType === "xml") { return ( {/* Header */}
{t('pdf.pageOf', { pageNumber, totalPages })}
{!!onClose && ( )}
{/* Content */}
); } // Markdown processor: PDF thumbnails on left, Markdown on right return ( {/* Header */}
{t('pdf.pageOf', { pageNumber, totalPages })}
{!!onClose && ( )}
{/* Content */}
); }