feat: add useStickerWall hook for shared fetch/render logic

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-24 01:38:25 -04:00
parent 00673fd2c9
commit dbf1f43e9e

View File

@@ -0,0 +1,76 @@
import { useState, useEffect, useRef, useCallback } from 'react';
import api from '../api/axios';
export function useStickerWall(sessionId) {
const [imageUrl, setImageUrl] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(false);
const urlRef = useRef(null);
const revokeUrl = useCallback(() => {
if (urlRef.current) {
URL.revokeObjectURL(urlRef.current);
urlRef.current = null;
}
}, []);
const setBlobUrl = useCallback((blob) => {
revokeUrl();
const url = URL.createObjectURL(blob);
urlRef.current = url;
setImageUrl(url);
}, [revokeUrl]);
const fetchWall = useCallback(async (id) => {
setLoading(true);
setError(false);
try {
const res = await api.get(`/stickerwalls/${id}`, { responseType: 'blob' });
setBlobUrl(res.data);
} catch (err) {
if (err.response?.status === 404) {
try {
const renderRes = await api.post(`/stickerwalls/${id}/render`, null, { responseType: 'blob' });
setBlobUrl(renderRes.data);
} catch (renderErr) {
revokeUrl();
setImageUrl(null);
setError(true);
}
} else {
revokeUrl();
setImageUrl(null);
setError(true);
}
} finally {
setLoading(false);
}
}, [setBlobUrl, revokeUrl]);
const refresh = useCallback(async () => {
if (!sessionId) return;
setLoading(true);
setError(false);
try {
const res = await api.post(`/stickerwalls/${sessionId}/render`, null, { responseType: 'blob' });
setBlobUrl(res.data);
} catch {
setError(true);
} finally {
setLoading(false);
}
}, [sessionId, setBlobUrl]);
useEffect(() => {
if (sessionId) {
fetchWall(sessionId);
} else {
revokeUrl();
setImageUrl(null);
setError(false);
}
return revokeUrl;
}, [sessionId, fetchWall, revokeUrl]);
return { imageUrl, loading, error, refresh };
}