Files
community-rule/app/(app)/create/components/CreateFlowPendingAvatarFlush.tsx
T

62 lines
1.9 KiB
TypeScript

"use client";
import { useEffect, useRef } from "react";
import { useCreateFlow } from "../context/CreateFlowContext";
import {
CreateFlowUploadValidationError,
uploadCreateFlowFile,
} from "../../../../lib/create/uploadToServer";
import {
clearPendingCommunityAvatarFile,
readPendingCommunityAvatarFile,
} from "../../../../lib/create/pendingCommunityAvatarUpload";
/**
* After sign-in, uploads a community avatar staged in IndexedDB (anonymous pick)
* and writes `communityAvatarUrl` on success.
*/
export function CreateFlowPendingAvatarFlush({
sessionUser,
sessionResolved,
}: {
sessionUser: { id: string; email: string } | null | undefined;
sessionResolved: boolean;
}) {
const { state, updateState } = useCreateFlow();
/** One successful flush per signed-in user id (survives React StrictMode remounts). */
const lastFlushedUserIdRef = useRef<string | null>(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;
let cancelled = false;
void (async () => {
const file = await readPendingCommunityAvatarFile();
if (cancelled || !file) return;
try {
const { url } = await uploadCreateFlowFile(file, "communityAvatar");
if (cancelled) return;
await clearPendingCommunityAvatarFile();
updateState({ communityAvatarUrl: url });
lastFlushedUserIdRef.current = sessionUser.id;
} catch (err) {
if (err instanceof CreateFlowUploadValidationError) {
await clearPendingCommunityAvatarFile();
}
// Leave a transient (auth / UPLOAD_ROOT) failure in place to retry.
}
})();
return () => {
cancelled = true;
};
}, [hasServerAvatar, sessionResolved, sessionUser, updateState]);
return null;
}