import { useContext, useState } from "react"; import { API_URL } from "../config/api.ts"; import { AvatarOverrideContext } from "../contexts/AvatarOverrideContext.ts"; interface AvatarProps { userId: string; username: string; hasAvatar: boolean; size?: number; version?: number; } export function Avatar( { userId, username, hasAvatar, size = 36, version }: AvatarProps, ) { const [imgFailed, setImgFailed] = useState(false); const sizeStyle = { width: size, height: size }; // A live `user_updated` override (avatar add/remove/change) wins over the // possibly-stale props the surrounding list was rendered with. const override = useContext(AvatarOverrideContext)[userId]; const effectiveHasAvatar = override ? override.hasAvatar : hasAvatar; const effectiveVersion = override ? override.version : version; // A new image (different version/presence) is a fresh thing to try — clear // any prior load failure during render rather than in an effect. const imgKey = `${effectiveHasAvatar}:${effectiveVersion ?? ""}`; const [prevImgKey, setPrevImgKey] = useState(imgKey); if (prevImgKey !== imgKey) { setPrevImgKey(imgKey); setImgFailed(false); } if (effectiveHasAvatar && !imgFailed) { const src = effectiveVersion ? `${API_URL}/api/avatars/${userId}?v=${effectiveVersion}` : `${API_URL}/api/avatars/${userId}`; return ( {username} setImgFailed(true)} /> ); } return (
{username.charAt(0).toUpperCase()}
); }