From 06683e2a0724916f10b62d26063ea19a66bd76f8 Mon Sep 17 00:00:00 2001 From: Nils Schneider Date: Tue, 11 Nov 2025 23:54:43 +0100 Subject: [PATCH] cleanup --- frontend/src/app/useDocumentPreview.js | 75 +++++++++++++++++-- frontend/src/detail/useDetailWorkspace.js | 7 +- .../hooks/documents/useDocumentsWorkspace.js | 10 ++- frontend/src/styles/documents/viewer.css | 2 - 4 files changed, 80 insertions(+), 14 deletions(-) diff --git a/frontend/src/app/useDocumentPreview.js b/frontend/src/app/useDocumentPreview.js index 4489ec3..36f0671 100644 --- a/frontend/src/app/useDocumentPreview.js +++ b/frontend/src/app/useDocumentPreview.js @@ -4,7 +4,6 @@ const useDocumentPreview = ({ routeDocumentId, documents, searchResults, - setDocuments, selectedFolder, assetManager, api, @@ -17,6 +16,7 @@ const useDocumentPreview = ({ setActivePreviewId, }) => { const [previewEntries, setPreviewEntries] = useState(() => new Map()); + const [previewDocuments, setPreviewDocuments] = useState(() => new Map()); const previewInflightRef = useRef(new Map()); const previewReturnPathRef = useRef(null); @@ -46,6 +46,35 @@ const useDocumentPreview = ({ }); }, []); + const cachePreviewDocument = useCallback((doc) => { + if (!doc?.id) { + return; + } + setPreviewDocuments((prev) => { + const existing = prev.get(doc.id); + if (existing === doc) { + return prev; + } + const next = new Map(prev); + next.set(doc.id, doc); + return next; + }); + }, []); + + const removeCachedPreviewDocument = useCallback((documentId) => { + if (!documentId) { + return; + } + setPreviewDocuments((prev) => { + if (!prev.has(documentId)) { + return prev; + } + const next = new Map(prev); + next.delete(documentId); + return next; + }); + }, []); + const ensurePreviewUrl = useCallback( async (documentId, { force = false } = {}) => { if (!documentId) return null; @@ -116,12 +145,16 @@ const useDocumentPreview = ({ throw new Error('Document metadata unavailable.'); } - setDocuments((prev) => { - if (prev.some((item) => item.id === doc.id)) { - return prev; - } - return [doc, ...prev]; - }); + const existsInDocuments = documents.some((item) => item.id === doc.id); + const existsInSearch = Array.isArray(searchResults) + ? searchResults.some((item) => item.id === doc.id) + : false; + + if (existsInDocuments || existsInSearch) { + removeCachedPreviewDocument(doc.id); + } else { + cachePreviewDocument(doc); + } } if (!previewReturnPathRef.current) { @@ -138,10 +171,11 @@ const useDocumentPreview = ({ searchResults, documents, assetManager, - setDocuments, ensurePreviewUrl, setActivePreviewId, api, + cachePreviewDocument, + removeCachedPreviewDocument, ], ); @@ -207,8 +241,33 @@ const useDocumentPreview = ({ }; }, [routeDocumentId, ensurePreviewData, notifyApiError, closeDocumentPreview]); + useEffect(() => { + setPreviewDocuments((prev) => { + if (!prev.size) { + return prev; + } + const next = new Map(prev); + let changed = false; + const prune = (list) => { + if (!Array.isArray(list)) { + return; + } + list.forEach((doc) => { + if (doc?.id && next.has(doc.id)) { + next.delete(doc.id); + changed = true; + } + }); + }; + prune(documents); + prune(searchResults); + return changed ? next : prev; + }); + }, [documents, searchResults]); + return { previewEntries, + previewDocuments, ensurePreviewUrl, ensurePreviewData, openDocumentPreview, diff --git a/frontend/src/detail/useDetailWorkspace.js b/frontend/src/detail/useDetailWorkspace.js index d802857..2c0478e 100644 --- a/frontend/src/detail/useDetailWorkspace.js +++ b/frontend/src/detail/useDetailWorkspace.js @@ -10,6 +10,7 @@ import { const useDetailWorkspace = ({ documents, searchResults, + previewDocuments, selectionOrder, selectedDocumentIds, documentLookup, @@ -195,8 +196,10 @@ const useDetailWorkspace = ({ return null; } const pool = searchResults ?? documents; - return pool.find((doc) => doc.id === previewDocumentId) || null; - }, [previewDocumentId, searchResults, documents]); + return pool.find((doc) => doc.id === previewDocumentId) + || previewDocuments?.get?.(previewDocumentId) + || null; + }, [previewDocumentId, searchResults, documents, previewDocuments]); const previewActive = Boolean(previewDocumentId && previewWorkspaceDocument); diff --git a/frontend/src/hooks/documents/useDocumentsWorkspace.js b/frontend/src/hooks/documents/useDocumentsWorkspace.js index f17a52c..b376d81 100644 --- a/frontend/src/hooks/documents/useDocumentsWorkspace.js +++ b/frontend/src/hooks/documents/useDocumentsWorkspace.js @@ -328,6 +328,7 @@ const useDocumentsWorkspace = ({ const { previewEntries, + previewDocuments, ensurePreviewData, openDocumentPreview, closeDocumentPreview, @@ -337,7 +338,6 @@ const useDocumentsWorkspace = ({ routeDocumentId: previewDocumentId, documents, searchResults, - setDocuments, selectedFolder, assetManager, api, @@ -410,8 +410,13 @@ const useDocumentsWorkspace = ({ if (Array.isArray(searchResults)) { push(searchResults); } + previewDocuments.forEach((doc, id) => { + if (doc && id && !map.has(id)) { + map.set(id, doc); + } + }); return map; - }, [documents, searchResults]); + }, [documents, searchResults, previewDocuments]); const { tags, @@ -1158,6 +1163,7 @@ const useDocumentsWorkspace = ({ } = useDetailWorkspace({ documents, searchResults, + previewDocuments, focusedDocumentId, selectionOrder, selectedDocumentIds, diff --git a/frontend/src/styles/documents/viewer.css b/frontend/src/styles/documents/viewer.css index 8623424..0037025 100644 --- a/frontend/src/styles/documents/viewer.css +++ b/frontend/src/styles/documents/viewer.css @@ -53,13 +53,11 @@ flex-direction: column; justify-content: center; align-items: center; - flex: 2 2 auto; max-height: calc(var(--document-viewer-portrait-height-ratio) * 100vh); order: -1; } .document-viewer--stacked .document-viewer__details-pane { - flex: 1 1 auto; overflow: visible; order: 0; }