feat: Add Download type and document download field, unify preview zoom styling

This commit is contained in:
2025-12-03 23:56:35 +01:00
parent dad6f1e0b8
commit c6a627af8a
8 changed files with 76 additions and 334 deletions
+12 -47
View File
@@ -1,4 +1,4 @@
import React, { createContext, useContext, useState, useCallback, useMemo, useEffect } from 'react';
import React, { createContext, useContext, useState, useCallback, useMemo, useRef } from 'react';
import PreviewZoomOverlay from '../detail/PreviewZoomOverlay';
import type { Document } from '../types/documents';
import type { Identifier } from '../types/identifiers';
@@ -20,21 +20,26 @@ export const usePreviewContext = () => {
interface PreviewProviderProps {
children: React.ReactNode;
ensureDownloadUrl?: (docId: Identifier) => Promise<any>;
onNavigate?: (documentId: Identifier) => void;
}
export const PreviewProvider: React.FC<PreviewProviderProps> = ({ children, ensureDownloadUrl, onNavigate }) => {
export const PreviewProvider: React.FC<PreviewProviderProps> = ({ children, onNavigate }) => {
const [previewDoc, setPreviewDoc] = useState<Document | null>(null);
const [previewUrl, setPreviewUrl] = useState<string | null>(null);
const lastFocusedElement = useRef<HTMLElement | null>(null);
const openPreview = useCallback((doc: Document) => {
if (!lastFocusedElement.current) {
lastFocusedElement.current = document.activeElement as HTMLElement;
}
setPreviewDoc(doc);
}, []);
const closePreview = useCallback(() => {
setPreviewDoc(null);
setPreviewUrl(null);
if (lastFocusedElement.current) {
lastFocusedElement.current.focus();
lastFocusedElement.current = null;
}
}, []);
const handleMaximize = useCallback(() => {
@@ -44,46 +49,6 @@ export const PreviewProvider: React.FC<PreviewProviderProps> = ({ children, ensu
}
}, [previewDoc, onNavigate, closePreview]);
useEffect(() => {
if (!previewDoc) {
setPreviewUrl(null);
return;
}
let cancelled = false;
if (ensureDownloadUrl) {
ensureDownloadUrl(previewDoc.id)
.then((entry) => {
if (!cancelled && entry?.url) {
setPreviewUrl(entry.url);
}
})
.catch(() => {
if (!cancelled) {
setPreviewUrl(null);
}
});
}
return () => {
cancelled = true;
};
}, [previewDoc, ensureDownloadUrl]);
const overlayDocument = useMemo(() => {
if (!previewDoc || !previewUrl) {
return previewDoc;
}
return {
...previewDoc,
documentLink: {
url: previewUrl,
alt: previewDoc.title,
mimeType: previewDoc.mime_type,
},
};
}, [previewDoc, previewUrl]);
const value = useMemo(() => ({
openPreview,
closePreview,
@@ -93,10 +58,10 @@ export const PreviewProvider: React.FC<PreviewProviderProps> = ({ children, ensu
<PreviewContext.Provider value={value}>
{children}
<PreviewZoomOverlay
open={Boolean(previewUrl)}
open={Boolean(previewDoc)}
onClose={closePreview}
onMaximize={onNavigate ? handleMaximize : undefined}
document={overlayDocument}
document={previewDoc}
/>
</PreviewContext.Provider>
);