pdfjs
This commit is contained in:
@@ -2,6 +2,11 @@ import { useMemo } from 'react';
|
||||
|
||||
type Identifier = string | number;
|
||||
|
||||
interface PreviewEntryLike {
|
||||
url?: string | null;
|
||||
contentType?: string | null;
|
||||
}
|
||||
|
||||
export interface Breadcrumb {
|
||||
id?: Identifier;
|
||||
name?: string;
|
||||
@@ -65,6 +70,8 @@ export interface UseDocumentsPanelPropsArgs {
|
||||
handleBulkSelectionReanalyze?: (...args: unknown[]) => void;
|
||||
folderOptions?: unknown[];
|
||||
moveDocumentsToFolder?: (...args: unknown[]) => void;
|
||||
previewEntries?: Map<Identifier, PreviewEntryLike>;
|
||||
ensureDownloadUrl?: (documentId: Identifier, options?: { force?: boolean }) => Promise<PreviewEntryLike | null>;
|
||||
}
|
||||
|
||||
export type DocumentsPanelProps = ReturnType<typeof useDocumentsPanelProps>;
|
||||
@@ -93,8 +100,8 @@ const useDocumentsPanelProps = (props: UseDocumentsPanelPropsArgs) => {
|
||||
searchLoading,
|
||||
tagLookupById,
|
||||
activeCorrespondentFilters,
|
||||
ensureAssetUrl,
|
||||
getDocumentAsset,
|
||||
ensureAssetUrl,
|
||||
getDocumentAsset,
|
||||
toggleTagFilter,
|
||||
toggleCorrespondentFilter,
|
||||
handleDocumentTagDrop,
|
||||
@@ -119,6 +126,8 @@ const useDocumentsPanelProps = (props: UseDocumentsPanelPropsArgs) => {
|
||||
handleBulkSelectionReanalyze,
|
||||
folderOptions,
|
||||
moveDocumentsToFolder,
|
||||
previewEntries,
|
||||
ensureDownloadUrl,
|
||||
} = props;
|
||||
|
||||
return useMemo(
|
||||
@@ -173,6 +182,8 @@ const useDocumentsPanelProps = (props: UseDocumentsPanelPropsArgs) => {
|
||||
onBulkReanalyze: handleBulkSelectionReanalyze,
|
||||
folderOptions,
|
||||
onMoveDocumentsToFolder: moveDocumentsToFolder,
|
||||
previewEntries,
|
||||
ensureDownloadUrl,
|
||||
}),
|
||||
[
|
||||
activeCorrespondentFilters,
|
||||
@@ -223,6 +234,8 @@ const useDocumentsPanelProps = (props: UseDocumentsPanelPropsArgs) => {
|
||||
ensureAssetUrl,
|
||||
getDocumentAsset,
|
||||
folderOptions,
|
||||
previewEntries,
|
||||
ensureDownloadUrl,
|
||||
],
|
||||
);
|
||||
};
|
||||
|
||||
@@ -5,7 +5,6 @@ import DocumentsGrid from '../DocumentsGrid';
|
||||
import DocumentsList from '../DocumentsList';
|
||||
import { isTagTransferEvent } from '../tagTransfer';
|
||||
import PreviewZoomOverlay from '../../detail/PreviewZoomOverlay';
|
||||
import { useAssetNavigator } from '../../hooks/useAssetNavigator';
|
||||
import { isPointerModifierEvent, isPrimaryPointerEvent } from '../useEntryPointer';
|
||||
import { useWorkspaceSelectionContext } from '../../app/WorkspaceSelectionContext';
|
||||
|
||||
@@ -22,6 +21,8 @@ interface DocumentsPanelProps {
|
||||
|
||||
const defaultGetDocumentAsset = (_doc?: unknown, _type?: string) => null;
|
||||
|
||||
export type PreviewEntryLike = { url?: string | null; contentType?: string | null };
|
||||
|
||||
const DocumentsPanel: React.FC<DocumentsPanelProps> = ({
|
||||
currentFolderName,
|
||||
breadcrumbs,
|
||||
@@ -55,6 +56,8 @@ const DocumentsPanel: React.FC<DocumentsPanelProps> = ({
|
||||
viewMode = 'list',
|
||||
onViewModeChange,
|
||||
showHeader = true,
|
||||
previewEntries,
|
||||
ensureDownloadUrl,
|
||||
}) => {
|
||||
const {
|
||||
selectedEntries,
|
||||
@@ -65,6 +68,7 @@ const DocumentsPanel: React.FC<DocumentsPanelProps> = ({
|
||||
} = useWorkspaceSelectionContext();
|
||||
const showingSearchResults = searchResults !== null;
|
||||
const rows = showingSearchResults ? searchResults : documents;
|
||||
const previewEntryMap = previewEntries instanceof Map ? previewEntries : null;
|
||||
|
||||
const currentFolderId = useMemo(() => {
|
||||
if (showingSearchResults) {
|
||||
@@ -138,7 +142,10 @@ const DocumentsPanel: React.FC<DocumentsPanelProps> = ({
|
||||
const isGridView = viewMode === 'grid';
|
||||
const isDeskView = viewMode === 'desk';
|
||||
|
||||
const [previewDocId, setPreviewDocId] = useState(null);
|
||||
type Identifier = string | number;
|
||||
type ZoomSource = { url: string; alt?: string | null; contentType?: string | null };
|
||||
|
||||
const [previewDocId, setPreviewDocId] = useState<Identifier | null>(null);
|
||||
|
||||
const previewDoc = useMemo(() => {
|
||||
if (!previewDocId) {
|
||||
@@ -153,38 +160,69 @@ const DocumentsPanel: React.FC<DocumentsPanelProps> = ({
|
||||
}
|
||||
}, [previewDocId, previewDoc]);
|
||||
|
||||
const previewNavigator = useAssetNavigator({
|
||||
document: previewDoc,
|
||||
assetType: 'preview',
|
||||
ensureAssetUrl,
|
||||
getAsset: getDocumentAsset,
|
||||
prefetch: 3,
|
||||
});
|
||||
const [previewZoomSource, setPreviewZoomSource] = useState<ZoomSource | null>(null);
|
||||
const zoomDisplay = previewZoomSource;
|
||||
|
||||
const {
|
||||
currentUrl: previewUrl,
|
||||
canGoPrev: previewCanGoPrev,
|
||||
canGoNext: previewCanGoNext,
|
||||
goPrev: previewGoPrev,
|
||||
goNext: previewGoNext,
|
||||
} = previewNavigator;
|
||||
|
||||
const previewDisplay = useMemo(() => {
|
||||
if (!previewDoc || !previewUrl) {
|
||||
return null;
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
if (!previewDocId || !previewDoc) {
|
||||
setPreviewZoomSource(null);
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}
|
||||
return {
|
||||
url: previewUrl,
|
||||
alt: previewDoc.title,
|
||||
canGoPrev: Boolean(previewCanGoPrev),
|
||||
canGoNext: Boolean(previewCanGoNext),
|
||||
goPrev: previewGoPrev,
|
||||
goNext: previewGoNext,
|
||||
const docContentType = previewDoc.content_type;
|
||||
const versionContentType = previewDoc.current_version?.version?.content_type;
|
||||
const contentFallback = docContentType || versionContentType || null;
|
||||
|
||||
const applyEntry = (entry?: PreviewEntryLike | null) => {
|
||||
if (!entry?.url) {
|
||||
setPreviewZoomSource(null);
|
||||
return;
|
||||
}
|
||||
setPreviewZoomSource({
|
||||
url: entry.url,
|
||||
alt: previewDoc.title,
|
||||
contentType: entry.contentType || contentFallback || undefined,
|
||||
});
|
||||
};
|
||||
}, [previewDoc, previewUrl, previewCanGoPrev, previewCanGoNext, previewGoPrev, previewGoNext]);
|
||||
|
||||
const cachedEntry = previewEntryMap?.get(previewDocId) || null;
|
||||
if (cachedEntry?.url) {
|
||||
applyEntry(cachedEntry);
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}
|
||||
|
||||
if (!ensureDownloadUrl) {
|
||||
setPreviewZoomSource(null);
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}
|
||||
|
||||
ensureDownloadUrl(previewDocId)
|
||||
.then((entry) => {
|
||||
if (cancelled) {
|
||||
return;
|
||||
}
|
||||
applyEntry(entry);
|
||||
})
|
||||
.catch(() => {
|
||||
if (!cancelled) {
|
||||
setPreviewZoomSource(null);
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [previewDocId, previewDoc, previewEntryMap, ensureDownloadUrl]);
|
||||
|
||||
const closePreviewOverlay = useCallback(() => {
|
||||
setPreviewDocId(null);
|
||||
setPreviewZoomSource(null);
|
||||
}, []);
|
||||
|
||||
const handleDocumentPreviewZoom = useCallback(
|
||||
@@ -192,13 +230,12 @@ const DocumentsPanel: React.FC<DocumentsPanelProps> = ({
|
||||
if (!doc || !doc.id) {
|
||||
return;
|
||||
}
|
||||
const previewAsset = getDocumentAsset(doc, 'preview');
|
||||
if (!previewAsset) {
|
||||
if (!ensureDownloadUrl && !(previewEntryMap?.get(doc.id)?.url)) {
|
||||
return;
|
||||
}
|
||||
setPreviewDocId(doc.id);
|
||||
},
|
||||
[getDocumentAsset],
|
||||
[ensureDownloadUrl, previewEntryMap],
|
||||
);
|
||||
|
||||
const handleDocumentActivate = useCallback(
|
||||
@@ -724,8 +761,8 @@ const DocumentsPanel: React.FC<DocumentsPanelProps> = ({
|
||||
)}
|
||||
</section>
|
||||
<PreviewZoomOverlay
|
||||
open={Boolean(previewDocId)}
|
||||
display={previewDisplay}
|
||||
open={Boolean(zoomDisplay?.url)}
|
||||
display={zoomDisplay}
|
||||
onClose={closePreviewOverlay}
|
||||
/>
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user