import React, {useMemo} from 'react' import {StyleSheet, View} from 'react-native' import Svg, {Circle, Rect, Path} from 'react-native-svg' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {IconProp} from '@fortawesome/fontawesome-svg-core' import {HighPriorityImage} from 'view/com/util/images/Image' import {openCamera, openCropper, openPicker} from '../../../lib/media/picker' import { usePhotoLibraryPermission, useCameraPermission, } from 'lib/hooks/usePermissions' import {useStores} from 'state/index' import {colors} from 'lib/styles' import {DropdownButton} from './forms/DropdownButton' import {usePalette} from 'lib/hooks/usePalette' import {isWeb, isAndroid} from 'platform/detection' import {Image as RNImage} from 'react-native-image-crop-picker' import {AvatarModeration} from 'lib/labeling/types' type Type = 'user' | 'algo' | 'list' const BLUR_AMOUNT = isWeb ? 5 : 100 function DefaultAvatar({type, size}: {type: Type; size: number}) { if (type === 'algo') { // Font Awesome Pro 6.4.0 by @fontawesome -https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. return ( ) } if (type === 'list') { // Font Awesome Pro 6.4.0 by @fontawesome -https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. return ( ) } return ( ) } export function UserAvatar({ type = 'user', size, avatar, moderation, onSelectNewAvatar, }: { type?: Type size: number avatar?: string | null moderation?: AvatarModeration onSelectNewAvatar?: (img: RNImage | null) => void }) { const store = useStores() const pal = usePalette('default') const {requestCameraAccessIfNeeded} = useCameraPermission() const {requestPhotoAccessIfNeeded} = usePhotoLibraryPermission() const aviStyle = useMemo(() => { if (type === 'algo' || type === 'list') { return { width: size, height: size, borderRadius: 8, } } return { width: size, height: size, borderRadius: Math.floor(size / 2), } }, [type, size]) const dropdownItems = useMemo( () => [ !isWeb && { testID: 'changeAvatarCameraBtn', label: 'Camera', icon: 'camera' as IconProp, onPress: async () => { if (!(await requestCameraAccessIfNeeded())) { return } onSelectNewAvatar?.( await openCamera(store, { width: 1000, height: 1000, cropperCircleOverlay: true, }), ) }, }, { testID: 'changeAvatarLibraryBtn', label: 'Library', icon: 'image' as IconProp, onPress: async () => { if (!(await requestPhotoAccessIfNeeded())) { return } const items = await openPicker(store, { aspect: [1, 1], }) const item = items[0] const croppedImage = await openCropper(store, { mediaType: 'photo', cropperCircleOverlay: true, height: item.height, width: item.width, path: item.path, }) onSelectNewAvatar?.(croppedImage) }, }, { testID: 'changeAvatarRemoveBtn', label: 'Remove', icon: ['far', 'trash-can'] as IconProp, onPress: async () => { onSelectNewAvatar?.(null) }, }, ], [ onSelectNewAvatar, requestCameraAccessIfNeeded, requestPhotoAccessIfNeeded, store, ], ) const warning = useMemo(() => { if (!moderation?.warn) { return null } return ( ) }, [moderation?.warn, size, pal]) // onSelectNewAvatar is only passed as prop on the EditProfile component return onSelectNewAvatar ? ( {avatar ? ( ) : ( )} ) : avatar && !((moderation?.blur && isAndroid) /* android crashes with blur */) ? ( {warning} ) : ( {warning} ) } const styles = StyleSheet.create({ editButtonContainer: { position: 'absolute', width: 24, height: 24, bottom: 0, right: 0, borderRadius: 12, alignItems: 'center', justifyContent: 'center', backgroundColor: colors.gray5, }, warningIconContainer: { position: 'absolute', right: 0, bottom: 0, borderRadius: 100, }, warningIcon: { color: colors.red3, }, })