import React, { useState, useMemo, useCallback } from 'react'; import type { TUser } from 'librechat-data-provider'; import { Skeleton } from './Skeleton'; import { useAvatar } from '~/hooks'; import { UserIcon } from '~/svgs'; export interface AvatarProps { user?: TUser; size?: number; className?: string; alt?: string; showDefaultWhenEmpty?: boolean; } const Avatar: React.FC = ({ user, size = 32, className = '', alt, showDefaultWhenEmpty = true, }) => { const avatarSrc = useAvatar(user); const [imageLoaded, setImageLoaded] = useState(false); const [imageError, setImageError] = useState(false); const avatarSeed = useMemo( () => user?.avatar || user?.username || user?.email || '', [user?.avatar, user?.username, user?.email], ); const altText = useMemo( () => alt || `${user?.name || user?.username || user?.email || ''}'s avatar`, [alt, user?.name, user?.username, user?.email], ); const imageSrc = useMemo(() => { if (!avatarSeed || imageError) return ''; return (user?.avatar ?? '') || avatarSrc || ''; }, [user?.avatar, avatarSrc, avatarSeed, imageError]); const handleImageLoad = useCallback(() => { setImageLoaded(true); }, []); const handleImageError = useCallback(() => { setImageError(true); setImageLoaded(false); }, []); const DefaultAvatar = useCallback( () => ( ), [size, className], ); if (avatarSeed.length === 0 && showDefaultWhenEmpty) { return ; } if (avatarSeed.length > 0 && !imageError) { return (
{!imageLoaded && ( )} {altText}
); } if (imageError && showDefaultWhenEmpty) { return ; } return null; }; export default Avatar;