"use client"; import { useEffect, useRef, useState } from "react"; import { useCreateFlow } from "../context/CreateFlowContext"; import { flushPendingCommunityAvatar } from "../../../../lib/create/flushPendingCommunityAvatar"; /** Background tries after a transient upload failure. The file stays staged. */ const MAX_FLUSH_ATTEMPTS = 4; /** * After sign-in, uploads a community avatar staged in IndexedDB (anonymous pick) * and writes `communityAvatarUrl` on success. A transient failure retries with * backoff while this layout stays mounted. */ export function CreateFlowPendingAvatarFlush({ sessionUser, sessionResolved, }: { sessionUser: { id: string; email: string } | null | undefined; sessionResolved: boolean; }) { const { state, updateState } = useCreateFlow(); const [attempt, setAttempt] = useState(0); /** One successful flush per signed-in user id (survives the effect re-running). */ const lastFlushedUserIdRef = useRef(null); const hasServerAvatar = typeof state.communityAvatarUrl === "string" && state.communityAvatarUrl.trim().length > 0; useEffect(() => { if (!sessionResolved || !sessionUser) return; if (lastFlushedUserIdRef.current === sessionUser.id) return; if (hasServerAvatar) return; if (attempt >= MAX_FLUSH_ATTEMPTS) return; let cancelled = false; let timer: ReturnType | undefined; void (async () => { const result = await flushPendingCommunityAvatar(); if (cancelled) return; if (result.status === "uploaded") { updateState({ communityAvatarUrl: result.url }); lastFlushedUserIdRef.current = sessionUser.id; return; } if (result.status !== "failed") return; if (attempt + 1 >= MAX_FLUSH_ATTEMPTS) return; const delay = Math.min(20_000, 5_000 * 2 ** attempt); timer = setTimeout(() => { if (!cancelled) setAttempt((current) => current + 1); }, delay); })(); return () => { cancelled = true; if (timer) clearTimeout(timer); }; }, [attempt, hasServerAvatar, sessionResolved, sessionUser, updateState]); return null; }