import { useEffect, useState } from 'react'; export const fetchImage = (url: string): Promise => { return new Promise((resolve, reject) => { const request = new XMLHttpRequest(); request.open('GET', url, true); request.responseType = 'arraybuffer'; request.onloadend = () => { if (request.response !== undefined && (request.status === 200 || request.status === 304)) { resolve(request.response); } else { reject(new Error(`XMLHttpRequest, ${request.statusText}`)); } }; request.send(); }); }; export const readImage = (file: File): Promise => { return new Promise((resolve) => { const reader = new FileReader(); reader.onload = () => { resolve(reader.result as ArrayBuffer); }; reader.readAsArrayBuffer(file); }); }; const parseGif = async (buf: ArrayBuffer): Promise => { const image = new Image(); await new Promise((resolve) => { image.src = URL.createObjectURL(new Blob([buf])); image.onload = resolve; }); const canvas = document.createElement('canvas'); canvas.width = image.width; canvas.height = image.height; const ctx = canvas.getContext('2d'); if (ctx === null) throw new Error('Canvas Context null'); ctx.drawImage(image, 0, 0, image.width, image.height); return await new Promise((resolve, reject) => canvas.toBlob((blob) => { if (blob === null) { reject('Canvas Blob null'); } else { resolve(blob); } }), ); }; const useFetchGifFirstFrame = (url: string | undefined) => { const [frameUrl, setFrameUrl] = useState(null); useEffect(() => { if (!url) { setFrameUrl(null); return; } let isActive = true; const fetchFrame = async () => { try { const blob = typeof url === 'string' ? await parseGif(await fetchImage(url)) : await parseGif(await readImage(url as File)); const objectUrl = URL.createObjectURL(blob); if (isActive) setFrameUrl(objectUrl); } catch (error) { console.error('Failed to load GIF frame:', error); if (isActive) setFrameUrl(null); } }; fetchFrame(); // Cleanup function to avoid setting state on unmounted component return () => { isActive = false; }; }, [url]); return frameUrl; }; export default useFetchGifFirstFrame;