import * as AvatarPrimitive from '@rn-primitives/avatar'; import * as React from 'react'; import { useState } from 'react'; import { cn } from '@/lib/utils'; import { Image, TouchableOpacity, TouchableOpacityProps } from 'react-native'; import { getRobohashUrl } from '@/utils/avatar'; const AvatarPrimitiveRoot = AvatarPrimitive.Root; const AvatarPrimitiveImage = AvatarPrimitive.Image; const AvatarPrimitiveFallback = AvatarPrimitive.Fallback; const Avatar = React.forwardRef( ({ className, ...props }, ref) => ( ) ); Avatar.displayName = AvatarPrimitiveRoot.displayName; const AvatarImage = React.forwardRef( ({ className, ...props }, ref) => ( ) ); AvatarImage.displayName = AvatarPrimitiveImage.displayName; const AvatarFallback = React.forwardRef( ({ className, ...props }, ref) => ( ) ); AvatarFallback.displayName = AvatarPrimitiveFallback.displayName; // RobohashFallback: A specialized fallback that uses Robohash for avatars interface RobohashFallbackProps extends AvatarPrimitive.FallbackProps { seed?: string; size?: string; } const RobohashFallback = React.forwardRef( ({ className, seed = 'anonymous', size = '150x150', ...props }, ref) => ( ) ); RobohashFallback.displayName = 'RobohashFallback'; // RobohashAvatar: A complete avatar component with Robohash fallback interface RobohashAvatarProps extends TouchableOpacityProps { uri?: string; seed?: string; size?: 'sm' | 'md' | 'lg' | 'xl'; isInteractive?: boolean; className?: string; onImageError?: () => void; } const RobohashAvatar: React.FC = ({ uri, seed, size = 'md', isInteractive = true, className, onPress, onImageError, ...props }) => { const [imageError, setImageError] = useState(false); // Ensure we always have a valid seed value const safeSeed = React.useMemo(() => { // If an explicit seed is provided, use it if (seed) return seed; // If no seed but we have a URI, use that as fallback if (uri) return uri; // Default fallback that will always work return 'anonymous-user'; }, [seed, uri]); const containerStyles = cn( { 'w-8 h-8': size === 'sm', 'w-10 h-10': size === 'md', 'w-12 h-12': size === 'lg', 'w-24 h-24': size === 'xl', }, className ); const handleImageError = () => { setImageError(true); if (onImageError) { onImageError(); } }; const avatarContent = ( {uri && !imageError ? ( ) : ( )} ); if (!isInteractive) return avatarContent; return ( {avatarContent} ); }; export { Avatar, AvatarFallback, AvatarImage, RobohashFallback, RobohashAvatar };