Remove document link and download URL management from frontend components

This commit is contained in:
2025-12-04 00:23:27 +01:00
parent 4b02d1c7d5
commit 9f88823315
4 changed files with 3 additions and 127 deletions
+3 -104
View File
@@ -1,23 +1,15 @@
import { useCallback, useEffect, useRef, useState } from 'react';
import { useCallback, useEffect, useRef } from 'react';
import type {
Dispatch,
MutableRefObject,
SetStateAction,
} from 'react';
import { fetchDocument } from '../lib/apiClient';
import type { DocumentId } from '../types/identifiers';
type FolderId = DocumentId | 'root';
import type { Document } from '../types/documents';
type DocumentLink = {
url?: string;
mimeType?: string | null;
filename?: string | null;
expiresAt?: number;
};
type NavigateHandler = (path: string, options?: { replace?: boolean }) => void;
interface UseDocumentPreviewArgs {
@@ -42,13 +34,10 @@ interface UseDocumentPreviewArgs {
}
interface UseDocumentPreviewResult {
documentLinks: Map<DocumentId, DocumentLink>;
ensureDownloadUrl: (documentId: DocumentId, options?: { force?: boolean }) => Promise<DocumentLink | null>;
ensurePreviewData: (documentId: DocumentId) => Promise<Document | null>;
openDocumentPreview: (documentId: DocumentId, options?: { replace?: boolean }) => void;
closeDocumentPreview: (folderId?: FolderId) => void;
resetPreviewState: () => void;
removeDocumentLinks: (ids: DocumentId[]) => void;
}
const useDocumentPreview = ({
@@ -62,105 +51,20 @@ const useDocumentPreview = ({
detailPanelControlRef,
setActivePreviewId,
}: UseDocumentPreviewArgs): UseDocumentPreviewResult => {
const [documentLinks, setDocumentLinks] = useState<Map<DocumentId, DocumentLink>>(() => new Map());
const previewInflightRef = useRef<Map<DocumentId, Promise<DocumentLink | null>>>(new Map());
const previewReturnPathRef = useRef<string | null>(null);
const resetPreviewState = useCallback(() => {
setDocumentLinks(() => new Map());
previewInflightRef.current = new Map();
previewReturnPathRef.current = null;
}, []);
const removeDocumentLinks = useCallback((ids: DocumentId[]) => {
if (!Array.isArray(ids) || ids.length === 0) {
return;
}
setDocumentLinks((prev) => {
if (!prev.size) {
return prev;
}
let changed = false;
const next = new Map(prev);
ids.forEach((id) => {
if (next.delete(id)) {
changed = true;
}
previewInflightRef.current.delete(id);
});
return changed ? next : prev;
});
}, []);
const ensureDownloadUrl = useCallback(
async (documentId: DocumentId, { force = false }: { force?: boolean } = {}): Promise<DocumentLink | null> => {
if (!documentId) return null;
const existing = documentLinks.get(documentId);
const now = Date.now();
const expiresAt = existing?.expiresAt ?? null;
if (!force && existing && (!expiresAt || expiresAt > now)) {
return existing;
}
if (!force && previewInflightRef.current.has(documentId)) {
return previewInflightRef.current.get(documentId) || null;
}
const request: Promise<DocumentLink | null> = (async () => {
try {
const docResponse = await fetchDocument(documentId);
const download = docResponse?.current_version?.download || null;
const downloadUrl = download?.url;
if (!downloadUrl) {
throw new Error('Document missing download url');
}
const entry: DocumentLink = {
url: downloadUrl,
mimeType: docResponse?.mime_type || null,
filename: docResponse?.filename,
expiresAt: download?.expires_at,
};
setDocumentLinks((prev) => {
const next = new Map(prev);
next.set(documentId, entry);
return next;
});
return entry;
} catch (error) {
notifyApiError(error, 'Unable to fetch document preview.');
throw error;
} finally {
previewInflightRef.current.delete(documentId);
}
})();
previewInflightRef.current.set(documentId, request);
return request;
},
[documentLinks, notifyApiError],
);
const ensurePreviewData = useCallback(
async (documentId: DocumentId): Promise<Document | null> => {
if (!documentId) return null;
const findInCache = () => documentsManager.getById(documentId);
let doc = findInCache();
const doc = await documentsManager.ensure(documentId);
if (!doc) {
doc = await documentsManager.ensure(documentId);
}
if (!doc) {
const fetched = await fetchDocument(documentId);
const { canonical } = documentsManager.ingest([fetched as unknown]);
doc = (canonical[0] as Document | undefined) || null;
if (!doc) {
throw new Error('Document metadata unavailable.');
}
throw new Error('Document metadata unavailable.');
}
if (!previewReturnPathRef.current) {
@@ -169,13 +73,11 @@ const useDocumentPreview = ({
fallbackFolderId === 'root' ? '/documents' : `/documents/folder/${fallbackFolderId}`;
}
await ensureDownloadUrl(documentId, { force: false });
setActivePreviewId(documentId);
return doc;
},
[
documentsManager,
ensureDownloadUrl,
setActivePreviewId,
],
);
@@ -228,13 +130,10 @@ const useDocumentPreview = ({
}, [routeDocumentId, ensurePreviewData, notifyApiError, closeDocumentPreview]);
return {
documentLinks,
ensureDownloadUrl,
ensurePreviewData,
openDocumentPreview,
closeDocumentPreview,
resetPreviewState,
removeDocumentLinks,
};
};
@@ -2,11 +2,6 @@ import { useMemo } from 'react';
import type { WorkspaceSelectionValue } from '../../app/WorkspaceSelectionContext';
import type { Identifier } from '../../types/identifiers';
interface DocumentLinkLike {
url?: string | null;
mimeType?: string | null;
}
export interface Breadcrumb {
id?: Identifier;
name?: string;
@@ -68,8 +63,6 @@ export interface UseDocumentsPanelPropsArgs {
handleBulkSelectionReanalyze?: (...args: unknown[]) => void;
folderOptions?: unknown[];
moveDocumentsToFolder?: (...args: unknown[]) => void;
documentLinks?: Map<Identifier, DocumentLinkLike>;
ensureDownloadUrl?: (documentId: Identifier, options?: { force?: boolean }) => Promise<DocumentLinkLike | null>;
selectionValue: WorkspaceSelectionValue;
currentTenantId?: Identifier | null;
}
@@ -124,8 +117,6 @@ const useDocumentsPanelProps = (props: UseDocumentsPanelPropsArgs) => {
handleBulkSelectionReanalyze,
folderOptions,
moveDocumentsToFolder,
documentLinks,
ensureDownloadUrl,
selectionValue,
currentTenantId,
} = props;
@@ -181,8 +172,6 @@ const useDocumentsPanelProps = (props: UseDocumentsPanelPropsArgs) => {
onBulkReanalyze: handleBulkSelectionReanalyze,
folderOptions,
onMoveDocumentsToFolder: moveDocumentsToFolder,
documentLinks,
ensureDownloadUrl,
selectionValue,
currentTenantId,
}),
@@ -233,8 +222,6 @@ const useDocumentsPanelProps = (props: UseDocumentsPanelPropsArgs) => {
ensureAssetUrl,
getDocumentAsset,
folderOptions,
documentLinks,
ensureDownloadUrl,
selectionValue,
currentTenantId,
],
@@ -51,8 +51,6 @@ interface DocumentsPanelProps extends DocumentsPanelInnerProps {
selectionValue: WorkspaceSelectionValue;
}
export type DocumentLinkLike = { url?: string | null; mimeType?: string | null };
export interface DocumentsViewProps {
entries: DocumentsListEntry[];
draggingDocumentIdsSet?: Set<Identifier> | null;
@@ -85,7 +83,6 @@ export interface DocumentsViewProps {
// Desk specific (optional for now or handled via intersection)
tenantId?: Identifier | null;
viewId?: string | null;
ensureDownloadUrl?: (docId: Identifier, options?: { force?: boolean }) => Promise<any>;
activeTagFilters?: Array<Identifier | null>;
}
@@ -432,12 +432,9 @@ const useDocumentsWorkspace = ({
);
const {
documentLinks,
ensureDownloadUrl,
openDocumentPreview,
closeDocumentPreview,
resetPreviewState,
removeDocumentLinks,
} = useDocumentPreview({
routeDocumentId: previewDocumentId,
documentsManager,
@@ -719,14 +716,12 @@ const useDocumentsWorkspace = ({
});
removeDocumentsFromLookup(Array.from(idSet));
removeDocumentLinks(Array.from(idSet));
},
[
setDocuments,
setSearchResultIds,
setFolderContents,
removeDocumentsFromLookup,
removeDocumentLinks,
],
);
@@ -1195,8 +1190,6 @@ const useDocumentsWorkspace = ({
folderOptions,
moveDocumentsToFolder,
selectFolder,
documentLinks,
ensureDownloadUrl,
selectionValue: selection,
currentTenantId,
});