1import { useEffect, useMemo, useState } from 'react'; 2 3import { OnErrorEvent } from './ImageWrapper.types'; 4import { ImageNativeProps, ImageSource } from '../Image.types'; 5import { useBlurhash } from '../utils/blurhash/useBlurhash'; 6import { isThumbhashString } from '../utils/resolveSources'; 7import { thumbHashStringToDataURL } from '../utils/thumbhash/thumbhash'; 8 9export function useThumbhash(source: ImageSource | null | undefined) { 10 const isThumbhash = isThumbhashString(source?.uri || ''); 11 const strippedThumbhashString = source?.uri?.replace(/thumbhash:\//, '') ?? ''; 12 const thumbhashSource = useMemo( 13 () => (isThumbhash ? { uri: thumbHashStringToDataURL(strippedThumbhashString) } : null), 14 [strippedThumbhashString, isThumbhash] 15 ); 16 return thumbhashSource; 17} 18 19export function useImageHashes(source: ImageSource | null | undefined) { 20 const thumbhash = useThumbhash(source); 21 const blurhash = useBlurhash(source); 22 return useMemo( 23 () => ({ 24 resolvedSource: blurhash ?? thumbhash ?? source, 25 isImageHash: !!blurhash || !!thumbhash, 26 }), 27 [blurhash, thumbhash] 28 ); 29} 30 31export function useHeaders( 32 source: ImageSource | null | undefined, 33 cachePolicy: ImageNativeProps['cachePolicy'], 34 onError?: OnErrorEvent[] 35): ImageSource | null | undefined { 36 const [objectURL, setObjectURL] = useState<string | null>(null); 37 useEffect(() => { 38 (async () => { 39 if (!source?.headers || !source.uri) { 40 return; 41 } 42 try { 43 const result = await fetch(source.uri, { 44 headers: source.headers, 45 cache: cachePolicy === 'none' ? 'no-cache' : 'default', 46 redirect: 'follow', 47 }); 48 if (!result.ok) { 49 throw new Error(`Failed to fetch image: ${result.status} ${result.statusText}`); 50 } 51 const blob = await result.blob(); 52 setObjectURL((prevObjURL) => { 53 if (prevObjURL) { 54 URL.revokeObjectURL(prevObjURL); 55 } 56 return URL.createObjectURL(blob); 57 }); 58 // eslint-disable-next-line @typescript-eslint/no-unused-vars 59 } catch (error) { 60 onError?.forEach((e) => e?.({ source })); 61 } 62 })(); 63 }, [source]); 64 if (!source?.headers) { 65 return source; 66 } 67 if (!objectURL) { 68 // Avoid fetching a URL without headers if we have headers 69 return null; 70 } 71 return { ...source, uri: objectURL }; 72} 73