introduce a unified document viewer component.

This commit is contained in:
2025-12-04 02:21:11 +01:00
parent cbd463e1d9
commit f57bb9f6eb
6 changed files with 82 additions and 86 deletions
+7 -40
View File
@@ -1,8 +1,7 @@
import { useCallback, useMemo, useRef } from 'react';
import type { JSX } from 'react';
import DocumentInfoPanel from '../documents/DocumentInfoPanel';
import PdfViewer from './PdfViewer';
import MediaViewer from './MediaViewer';
import UnifiedDocumentViewer from './UnifiedDocumentViewer';
import type { Document } from '../types/documents';
@@ -33,7 +32,6 @@ interface DocumentViewerLayoutProps {
previewLoadingMessage?: string;
layoutMode?: LayoutMode;
}
const DocumentViewerLayout = ({
document,
summaryProps = {},
@@ -49,43 +47,12 @@ const DocumentViewerLayout = ({
const isStacked = layoutMode === 'stacked';
const viewportRef = useRef<HTMLDivElement>(null);
const previewContent = useMemo(() => {
if (!document) {
return null;
}
const downloadUrl = document.current_version?.download?.url;
if (!downloadUrl) {
return null;
}
const normalizedMimeType = (document.mime_type || '').toLowerCase();
const normalizedFilename = document.filename;
const isPdf = normalizedMimeType === 'application/pdf'
|| normalizedMimeType === 'application/x-pdf';
if (isPdf) {
const documentTitle = document.title;
return (
<PdfViewer
src={downloadUrl}
title={documentTitle ? `Preview of ${documentTitle}` : undefined}
viewportRef={viewportRef}
/>
);
}
return (
<MediaViewer
src={downloadUrl}
mimeType={normalizedMimeType}
filename={normalizedFilename}
alt={`Preview of ${document.title}`}
/>
);
}, [document, viewportRef]);
const previewContent = useMemo(() => (
<UnifiedDocumentViewer
document={document}
viewportRef={viewportRef}
/>
), [document, viewportRef]);
const renderViewportPane = useCallback(() => (
<div className="document-viewer__viewport" ref={viewportRef}>
+8 -8
View File
@@ -39,10 +39,10 @@ interface DocumentViewerPanelProps extends DocumentSummarySectionProps {
ensurePreviewData?: (docId: DocumentId, options?: { signal?: AbortSignal }) => Promise<Document | null>;
notifyApiError?: (error: unknown, fallbackMessage?: string) => void;
sidebarToggle?: ReactNode;
onClosePanel?: () => void;
onClose?: () => void;
resolveFolderPath?: (doc: Document | null) => Array<{ id?: string; name?: string }>;
variant?: 'viewer' | 'sidebar';
onMaximizePanel?: (args: { documentIds: Array<string> }) => void;
onMaximize?: (args: { documentIds: Array<string> }) => void;
sidebarMode?: SidebarMode;
}
@@ -95,10 +95,10 @@ const DocumentViewerPanel: React.FC<DocumentViewerPanelProps> = ({
ensurePreviewData,
notifyApiError,
sidebarToggle = null,
onClosePanel,
onClose,
resolveFolderPath,
variant = 'viewer',
onMaximizePanel,
onMaximize,
sidebarMode = 'overlay',
}) => {
const navigate = useNavigate();
@@ -299,7 +299,7 @@ const DocumentViewerPanel: React.FC<DocumentViewerPanelProps> = ({
canZoom: Boolean(document),
});
const maximizeButton = isSidebarVariant && onMaximizePanel
const maximizeButton = isSidebarVariant && onMaximize
? (
<button
type="button"
@@ -310,7 +310,7 @@ const DocumentViewerPanel: React.FC<DocumentViewerPanelProps> = ({
if (targetId == null) {
return;
}
onMaximizePanel?.({ documentIds: [targetId] });
onMaximize?.({ documentIds: [targetId] });
}}
aria-label="Maximize"
title="Maximize"
@@ -320,12 +320,12 @@ const DocumentViewerPanel: React.FC<DocumentViewerPanelProps> = ({
)
: null;
const closeButton = onClosePanel
const closeButton = onClose
? (
<button
type="button"
className="icon-button"
onClick={() => onClosePanel?.()}
onClick={() => onClose?.()}
aria-label="Close preview"
title="Close preview"
>
@@ -0,0 +1,57 @@
import React, { useMemo } from 'react';
import PdfViewer from './PdfViewer';
import MediaViewer from './MediaViewer';
import type { Document } from '../types/documents';
interface UnifiedDocumentViewerProps {
document: Document | null;
viewportRef?: React.RefObject<HTMLDivElement>;
}
const UnifiedDocumentViewer: React.FC<UnifiedDocumentViewerProps> = ({
document,
viewportRef,
}) => {
const content = useMemo(() => {
if (!document) {
return null;
}
const downloadUrl = document.current_version?.download?.url;
if (!downloadUrl) {
return null;
}
const normalizedMimeType = (document.mime_type || '').toLowerCase();
const normalizedFilename = document.filename;
const isPdf = normalizedMimeType === 'application/pdf'
|| normalizedMimeType === 'application/x-pdf';
if (isPdf) {
return (
<PdfViewer
src={downloadUrl}
title={document.title}
viewportRef={viewportRef}
/>
);
}
return (
<MediaViewer
src={downloadUrl}
mimeType={normalizedMimeType}
filename={normalizedFilename}
alt={document.title}
/>
);
}, [
document,
viewportRef,
]);
return content;
};
export default UnifiedDocumentViewer;