import React, { useCallback, useLayoutEffect, useMemo, useState } from 'react'; import { Image, ImageStyle, ImageSourcePropType, StyleSheet, StyleProp, TextStyle, View, ViewProps, ViewStyle, } from 'react-native'; import Initials from './Initials'; import Badge, { Props as BadgeProps } from './Badge'; import { clamp, colorScheme, getGravatarSource } from './helpers'; const DEFAULT_COLOR = colorScheme('#aeaeb2', '#636366'); const DEFAULT_SOURCE: ImageSourcePropType = require('./assets/default.png'); export interface Props extends ViewProps { size?: number; name?: string; email?: string; source?: ImageSourcePropType; defaultSource?: ImageSourcePropType; color?: string; radius?: number; colorize?: boolean; style?: StyleProp; textStyle?: StyleProp; badge?: BadgeProps['value']; badgeColor?: BadgeProps['color']; badgeProps?: Omit; } const Avatar = ({ size = 50, name, email, source, defaultSource = DEFAULT_SOURCE, color = DEFAULT_COLOR, radius = size / 2, colorize = false, style, textStyle, badge, badgeColor, badgeProps, ...props }: Props) => { const avatarSource = useMemo(() => { return source || (email ? getGravatarSource(size, email) : defaultSource); }, [source, size, email, defaultSource]); const [imageSource, setImageSource] = useState(avatarSource); const borderRadius = clamp(radius, 0, size / 2); useLayoutEffect(() => { setImageSource(avatarSource); }, [avatarSource]); const onImageError = useCallback(() => { setImageSource(defaultSource); }, [defaultSource]); // debug('RENDER ', name || email || imageSource); return ( {name?.trim() && imageSource === defaultSource ? ( ) : ( )} {badge !== undefined && ( )} ); }; const styles = StyleSheet.create({ root: { alignSelf: 'center', }, image: { width: '100%', height: '100%', }, }); export default React.memo(Avatar);