import { useEffect, useState } from 'react'; import { isGeneratedLegacyPath, resolveAssetReadUrl, } from '../services/assetReadUrlService'; type UseResolvedAssetReadUrlOptions = { enabled?: boolean; expireSeconds?: number; }; export function useResolvedAssetReadUrl( source: string | null | undefined, options: UseResolvedAssetReadUrlOptions = {}, ) { const enabled = options.enabled !== false; const normalizedSource = source?.trim() ?? ''; const shouldResolve = enabled && Boolean(normalizedSource) && isGeneratedLegacyPath(normalizedSource); const [resolvedUrl, setResolvedUrl] = useState( shouldResolve ? '' : normalizedSource, ); useEffect(() => { if (!normalizedSource) { setResolvedUrl(''); return; } if (!shouldResolve) { setResolvedUrl(normalizedSource); return; } let cancelled = false; // 生成资源通常是 OSS 私有对象;签名 URL 未就绪前不能把裸 generated 路径交给 img 触发无鉴权 GET。 setResolvedUrl(''); void resolveAssetReadUrl(normalizedSource, { expireSeconds: options.expireSeconds, }) .then((nextUrl) => { if (!cancelled) { setResolvedUrl(nextUrl); } }) .catch(() => { if (!cancelled) { // 签名失败时保持空 src,避免继续请求无签名的私有对象兼容路径。 setResolvedUrl(''); } }); return () => { cancelled = true; }; }, [normalizedSource, options.expireSeconds, shouldResolve]); return { resolvedUrl, isResolving: shouldResolve && !resolvedUrl, shouldResolve, }; }