import { useEffect, useMemo, useState } from 'react'; import { resolveAssetUrl } from '../asset_manager'; import type { Identifier } from '../types/identifiers'; type DocumentLike = { id?: Identifier; [key: string]: unknown; }; type AssetObject = { url?: string | null; metadata?: Record | null; expires_at?: number | null; [key: string]: unknown; }; type AssetLike = { id?: Identifier; url?: string | null; expires_at?: number | null; metadata?: Record | null; objects?: AssetObject[]; [key: string]: unknown; }; type EnsureAssetUrl = ( documentId: Identifier, asset: AssetLike, options?: { force?: boolean;[key: string]: unknown }, ) => Promise; type GetAsset = (document: DocumentLike, assetType: string) => AssetLike | null; type AssetViewLike = { url: string | null; metadata: Record | null; }; interface UseAssetNavigatorOptions { document?: DocumentLike | null; assetType: string; ensureAssetUrl?: EnsureAssetUrl | null; getAsset?: GetAsset; } interface AssetNavigatorReturn { document: DocumentLike | null; documentId: Identifier | null; asset: AssetLike | null; assetType: string; currentUrl: string | null; currentMetadata: Record | null; isLoading: boolean; } export const useAssetNavigator = ({ document, assetType, ensureAssetUrl, getAsset, }: UseAssetNavigatorOptions): AssetNavigatorReturn => { const documentId = (document?.id ?? null) as Identifier | null; const asset = useMemo(() => { if (!document || !getAsset) { return null; } return getAsset(document, assetType) || null; }, [document, assetType, getAsset]); const view = useMemo( () => ({ url: resolveAssetUrl(asset), metadata: (asset?.metadata as Record | null) || null, }), [asset], ); const currentUrl = view.url || null; const currentMetadata = view.metadata || null; const [isLoading, setIsLoading] = useState(false); useEffect(() => { if (!ensureAssetUrl || !documentId || !asset) { return undefined; } if (currentUrl) { return undefined; } let cancelled = false; setIsLoading(true); ensureAssetUrl(documentId, asset, { force: true }) .catch(() => { }) .finally(() => { if (!cancelled) { setIsLoading(false); } }); return () => { cancelled = true; }; }, [asset, currentUrl, documentId, ensureAssetUrl]); return { document, documentId, asset, assetType, currentUrl, currentMetadata, isLoading, }; }; export default useAssetNavigator;