import React, { useEffect, useState } from 'react'; import { View } from 'react-native'; import { CustomAvatar, ImageAvatar, TextAvatar } from './components'; import { fetchImage, generateBackgroundColor, generateBackgroundStyle, getContainerStyle, } from './helpers'; import { DEFAULT_BG_COLORS } from './types'; import type { UserAvatarProps } from './types'; const UserAvatar = ({ name = 'John Doe', src, bgColor, bgColors = DEFAULT_BG_COLORS, textColor = '#fff', textStyle, size = 32, imageStyle, style, borderRadius, component, noUpperCase = false, ignoreContentType = false, }: UserAvatarProps) => { let avatarSize = size; if (typeof avatarSize === 'string') { console.warn('react-native-user-avatar: size prop should be a number'); avatarSize = parseInt(avatarSize, 10); } // Whether the remote `src` has resolved to a usable image. Reset whenever the // inputs that affect resolution change, so a new `src` never shows a stale image. const [isImage, setIsImage] = useState(false); useEffect(() => { if (!src || component) { setIsImage(false); return; } let isMounted = true; const controller = new AbortController(); fetchImage(src, { signal: controller.signal }, ignoreContentType).then( (resolved) => { if (isMounted) { setIsImage(resolved); } } ); return () => { isMounted = false; controller.abort(); }; }, [src, component, ignoreContentType]); let inner: React.ReactNode; if (component) { inner = ; } else if (src && isImage) { inner = ( ); } else { // Initials fallback — always receives every text-related prop. (#117) inner = ( ); } return ( {inner} ); }; export { generateBackgroundColor }; export type { UserAvatarProps }; export { DEFAULT_BG_COLORS }; export default UserAvatar;