import { useEffect, useState } from 'react'; import { createAssetView } from '../../asset_manager'; interface DocumentLike { id?: string | number; current_version?: unknown; tags?: unknown; } interface AssetLike { id?: string | number; [key: string]: unknown; } interface PreviewMetadataEntry { docId: string; width: number; height: number; } type GetDocumentAsset = (doc: DocumentLike, type: string) => AssetLike | null; type EnsureAssetUrl = (docId: string | number, asset: AssetLike, options?: { start?: number; limit?: number }) => Promise; const usePreviewMetadata = ( documents: DocumentLike[] | null, getDocumentAsset?: GetDocumentAsset, ensureAssetUrl?: EnsureAssetUrl, ) => { const [metadataMap, setMetadataMap] = useState>(() => new Map()); useEffect(() => { let cancelled = false; const docs = Array.isArray(documents) ? documents : []; if (!docs.length) { setMetadataMap(new Map()); return () => { cancelled = true; }; } const fetchMetadataForDoc = async (doc: DocumentLike) => { if (!doc?.id) { return null; } const docId = String(doc.id); const resolveAsset = (type: string) => getDocumentAsset?.(doc, type) ?? null; let asset = resolveAsset('preview') || resolveAsset('thumbnail'); let view = createAssetView(asset); let metadata = view.getPrimaryMetadata(); const hasDimensions = (meta: { width?: number | string; height?: number | string } | null) => Number.isFinite(Number(meta?.width)) && Number.isFinite(Number(meta?.height)) && Number(meta.width) > 0 && Number(meta.height) > 0; if (!hasDimensions(metadata) && ensureAssetUrl && docId && asset?.id) { try { const ensured = await ensureAssetUrl(doc.id, asset, { start: 1, limit: 1 }); if (ensured) { asset = ensured; view = createAssetView(asset); metadata = view.getPrimaryMetadata(); } } catch (error) { console.warn('[desk] ensureDocumentSize metadata fetch failed', error); } } if (!hasDimensions(metadata)) { return null; } return { docId, width: Number(metadata.width), height: Number(metadata.height), }; }; let mounted = true; (async () => { const entries = await Promise.all(docs.map(fetchMetadataForDoc)); if (!mounted || cancelled) { return; } const next = new Map(); entries.forEach((entry) => { if (entry && entry.docId) { next.set(entry.docId, entry); } }); if (!cancelled) { setMetadataMap(next); } })(); return () => { cancelled = true; mounted = false; }; }, [documents, getDocumentAsset, ensureAssetUrl]); return metadataMap; }; export default usePreviewMetadata;