diff options
-rw-r--r-- | src/assets/icons/grey-purple-plus.svg | 5 | ||||
-rw-r--r-- | src/assets/icons/purple-plus.svg | 15 | ||||
-rw-r--r-- | src/components/common/BasicButton.tsx | 12 | ||||
-rw-r--r-- | src/components/messages/MessageButton.tsx | 73 | ||||
-rw-r--r-- | src/components/messages/index.ts | 1 | ||||
-rw-r--r-- | src/components/moments/MomentPostContent.tsx | 4 | ||||
-rw-r--r-- | src/components/notifications/Notification.tsx | 41 | ||||
-rw-r--r-- | src/components/profile/Cover.tsx | 108 | ||||
-rw-r--r-- | src/components/profile/ProfileBody.tsx | 58 | ||||
-rw-r--r-- | src/components/profile/TaggAvatar.tsx | 67 | ||||
-rw-r--r-- | src/components/taggs/TaggsBar.tsx | 14 | ||||
-rw-r--r-- | src/utils/common.ts | 17 | ||||
-rw-r--r-- | src/utils/users.ts | 82 |
13 files changed, 414 insertions, 83 deletions
diff --git a/src/assets/icons/grey-purple-plus.svg b/src/assets/icons/grey-purple-plus.svg new file mode 100644 index 00000000..2053d4a7 --- /dev/null +++ b/src/assets/icons/grey-purple-plus.svg @@ -0,0 +1,5 @@ +<svg width="31" height="31" viewBox="0 0 31 31" fill="none" xmlns="http://www.w3.org/2000/svg"> +<circle cx="15.5" cy="15.5" r="15.5" fill="white"/> +<rect width="2.38462" height="16.6923" rx="1.19231" transform="matrix(-1 0 0 1 16.6934 7.15381)" fill="#8F00FF"/> +<rect width="2.38462" height="16.6923" rx="1.19231" transform="matrix(0.00550217 0.999985 0.999985 -0.00550217 7.1543 14.4004)" fill="#8F00FF"/> +</svg> diff --git a/src/assets/icons/purple-plus.svg b/src/assets/icons/purple-plus.svg new file mode 100644 index 00000000..20949b6d --- /dev/null +++ b/src/assets/icons/purple-plus.svg @@ -0,0 +1,15 @@ +<svg width="23" height="23" viewBox="0 0 23 23" fill="none" xmlns="http://www.w3.org/2000/svg"> +<circle cx="11.5" cy="11.5" r="11.25" fill="url(#paint0_linear)" stroke="url(#paint1_linear)" stroke-width="0.5"/> +<rect width="1.76923" height="12.3846" rx="0.884615" transform="matrix(-1 0 0 1 12.3848 5.30762)" fill="white"/> +<rect width="1.76923" height="12.3846" rx="0.884615" transform="matrix(0.00550217 0.999985 0.999985 -0.00550217 5.30859 10.6841)" fill="white"/> +<defs> +<linearGradient id="paint0_linear" x1="11.5" y1="0" x2="10.9524" y2="30.119" gradientUnits="userSpaceOnUse"> +<stop stop-color="#8F01FF"/> +<stop offset="1" stop-color="#6EE7E7"/> +</linearGradient> +<linearGradient id="paint1_linear" x1="11.5" y1="0" x2="10.9524" y2="32.8571" gradientUnits="userSpaceOnUse"> +<stop stop-color="#8F01FF"/> +<stop offset="1" stop-color="#6EE7E7"/> +</linearGradient> +</defs> +</svg> diff --git a/src/components/common/BasicButton.tsx b/src/components/common/BasicButton.tsx index 1fe29cd9..e2274dbd 100644 --- a/src/components/common/BasicButton.tsx +++ b/src/components/common/BasicButton.tsx @@ -1,5 +1,12 @@ import React from 'react'; -import {StyleProp, StyleSheet, Text, View, ViewStyle} from 'react-native'; +import { + StyleProp, + StyleSheet, + Text, + TextStyle, + View, + ViewStyle, +} from 'react-native'; import {TAGG_LIGHT_BLUE} from '../../constants'; import {TouchableOpacity} from 'react-native-gesture-handler'; import {normalize} from '../../utils'; @@ -8,7 +15,7 @@ interface BasicButtonProps { title: string; onPress: () => void; solid?: boolean; - externalStyles?: Record<string, StyleProp<ViewStyle>>; + externalStyles?: Record<string, StyleProp<ViewStyle | TextStyle>>; } const BasicButton: React.FC<BasicButtonProps> = ({ title, @@ -27,6 +34,7 @@ const BasicButton: React.FC<BasicButtonProps> = ({ <Text style={[ styles.buttonTitle, + externalStyles?.buttonTitle, solid ? styles.solidButtonTitleColor : styles.outlineButtonTitleColor, diff --git a/src/components/messages/MessageButton.tsx b/src/components/messages/MessageButton.tsx new file mode 100644 index 00000000..5ac42c4c --- /dev/null +++ b/src/components/messages/MessageButton.tsx @@ -0,0 +1,73 @@ +import React from 'react'; +import {Fragment, useContext} from 'react'; +import {useStore} from 'react-redux'; +import {ChatContext} from '../../App'; +import {RootState} from '../../store/rootReducer'; +import {FriendshipStatusType} from '../../types'; +import {createChannel} from '../../utils'; +import {Alert, StyleProp, TextStyle, ViewStyle} from 'react-native'; +import {BasicButton} from '../common'; +import {useNavigation} from '@react-navigation/native'; +import {ERROR_UNABLE_CONNECT_CHAT} from '../../constants/strings'; + +interface MessageButtonProps { + userXId: string; + isBlocked: boolean; + friendship_status: FriendshipStatusType; + friendship_requester_id?: string; + solid?: boolean; + externalStyles?: Record<string, StyleProp<ViewStyle | TextStyle>>; +} + +const MessageButton: React.FC<MessageButtonProps> = ({ + userXId, + isBlocked, + friendship_status, + friendship_requester_id, + solid, + externalStyles, +}) => { + const navigation = useNavigation(); + const {chatClient, setChannel} = useContext(ChatContext); + + const state: RootState = useStore().getState(); + const loggedInUserId = state.user.user.userId; + + const canMessage = () => { + if ( + userXId && + !isBlocked && + (friendship_status === 'no_record' || + friendship_status === 'friends' || + (friendship_status === 'requested' && + friendship_requester_id === loggedInUserId)) + ) { + return true; + } else { + return false; + } + }; + + const onPressMessage = async () => { + if (chatClient.user && userXId) { + const channel = await createChannel(loggedInUserId, userXId, chatClient); + setChannel(channel); + navigation.navigate('Chat'); + } else { + Alert.alert(ERROR_UNABLE_CONNECT_CHAT); + } + }; + + return canMessage() ? ( + <BasicButton + title={'Message'} + onPress={onPressMessage} + externalStyles={externalStyles} + solid={solid ? solid : false} + /> + ) : ( + <Fragment /> + ); +}; + +export default MessageButton; diff --git a/src/components/messages/index.ts b/src/components/messages/index.ts index b19067ca..7270e2e2 100644 --- a/src/components/messages/index.ts +++ b/src/components/messages/index.ts @@ -7,3 +7,4 @@ export {default as MessageAvatar} from './MessageAvatar'; export {default as TypingIndicator} from './TypingIndicator'; export {default as MessageFooter} from './MessageFooter'; export {default as DateHeader} from './DateHeader'; +export {default as MessageButton} from './MessageButton'; diff --git a/src/components/moments/MomentPostContent.tsx b/src/components/moments/MomentPostContent.tsx index 45186ba1..193bf40c 100644 --- a/src/components/moments/MomentPostContent.tsx +++ b/src/components/moments/MomentPostContent.tsx @@ -10,6 +10,7 @@ import { navigateToProfile, SCREEN_HEIGHT, SCREEN_WIDTH, + normalize, } from '../../utils'; import {mentionPartTypes, renderTextWithMentions} from '../../utils/comments'; import {CommentsCount} from '../comments'; @@ -103,6 +104,9 @@ const styles = StyleSheet.create({ marginRight: '5%', color: '#ffffff', fontWeight: '500', + fontSize: normalize(13), + lineHeight: normalize(15.51), + letterSpacing: normalize(0.6), }, }); export default MomentPostContent; diff --git a/src/components/notifications/Notification.tsx b/src/components/notifications/Notification.tsx index ae884b42..cb62047a 100644 --- a/src/components/notifications/Notification.tsx +++ b/src/components/notifications/Notification.tsx @@ -34,6 +34,7 @@ import { } from '../../utils'; import {Avatar} from '../common'; import AcceptDeclineButtons from '../common/AcceptDeclineButtons'; +import {MessageButton} from '../messages'; interface NotificationProps { item: NotificationType; @@ -61,6 +62,10 @@ const Notification: React.FC<NotificationProps> = (props) => { const [avatar, setAvatar] = useState<string | undefined>(undefined); const [momentURI, setMomentURI] = useState<string | undefined>(undefined); + const notification_title = + notification_type === 'FRD_ACPT' + ? `Say Hi to ${first_name}!` + : `${first_name} ${last_name}`; useEffect(() => { (async () => { @@ -246,9 +251,7 @@ const Notification: React.FC<NotificationProps> = (props) => { {/* Text content: Actor name and verbage*/} <View style={styles.contentContainer}> <TouchableWithoutFeedback onPress={navigateToProfile}> - <Text style={styles.actorName}> - {first_name} {last_name} - </Text> + <Text style={styles.actorName}>{notification_title}</Text> </TouchableWithoutFeedback> <TouchableWithoutFeedback style={styles.textContainerStyles} @@ -273,6 +276,30 @@ const Notification: React.FC<NotificationProps> = (props) => { /> </View> )} + {notification_type === 'FRD_ACPT' && ( + <View style={styles.buttonsContainer}> + <MessageButton + userXId={id} + isBlocked={false} + friendship_status={'friends'} + externalStyles={{ + container: { + width: normalize(63), + height: normalize(21), + marginTop: '7%', + }, + buttonTitle: { + fontSize: normalize(11), + lineHeight: normalize(13.13), + letterSpacing: normalize(0.5), + fontWeight: '700', + textAlign: 'center', + }, + }} + solid + /> + </View> + )} {/* Moment Image Preview */} {(notification_type === 'CMT' || notification_type === 'MOM_3+' || @@ -306,7 +333,7 @@ const styles = StyleSheet.create({ flex: 1, alignSelf: 'center', alignItems: 'center', - paddingHorizontal: '8%', + paddingHorizontal: '6.3%', }, avatarContainer: { height: 42, @@ -348,9 +375,9 @@ const styles = StyleSheet.create({ lineHeight: normalize(13.13), }, timeStampStyles: { - fontWeight: '700', - fontSize: normalize(12), - lineHeight: normalize(14.32), + fontWeight: '500', + fontSize: normalize(11), + lineHeight: normalize(13.13), marginHorizontal: 2, color: '#828282', textAlignVertical: 'center', diff --git a/src/components/profile/Cover.tsx b/src/components/profile/Cover.tsx index 27777b64..5d5b4234 100644 --- a/src/components/profile/Cover.tsx +++ b/src/components/profile/Cover.tsx @@ -1,28 +1,93 @@ -import React from 'react'; -import {Image, StyleSheet, View} from 'react-native'; -import {useSelector} from 'react-redux'; +import React, {useState, useEffect} from 'react'; +import { + Image, + StyleSheet, + View, + TouchableOpacity, + Text, + ImageBackground, +} from 'react-native'; import {COVER_HEIGHT, IMAGE_WIDTH} from '../../constants'; -import {RootState} from '../../store/rootreducer'; import {ScreenType} from '../../types'; +import GreyPurplePlus from '../../assets/icons/grey-purple-plus.svg'; +import {useDispatch, useSelector} from 'react-redux'; +import {loadUserData, resetHeaderAndProfileImage} from '../../store/actions'; +import {RootState} from '../../store/rootreducer'; +import {normalize, patchProfile, validateImageLink} from '../../utils'; interface CoverProps { userXId: string | undefined; screenType: ScreenType; } const Cover: React.FC<CoverProps> = ({userXId, screenType}) => { - const {cover} = useSelector((state: RootState) => + const dispatch = useDispatch(); + const {cover, user} = useSelector((state: RootState) => userXId ? state.userX[screenType][userXId] : state.user, ); - return ( - <View style={[styles.container]}> - <Image - style={styles.image} - defaultSource={require('../../assets/images/cover-placeholder.png')} - source={{uri: cover, cache: 'reload'}} - /> - </View> - ); + const [needsUpdate, setNeedsUpdate] = useState(false); + const [loading, setLoading] = useState(false); + const [validImage, setValidImage] = useState<boolean>(true); + + useEffect(() => { + checkAvatar(cover); + }, []); + + useEffect(() => { + if (needsUpdate) { + const userId = user.userId; + const username = user.username; + dispatch(resetHeaderAndProfileImage()); + dispatch(loadUserData({userId, username})); + } + }, [dispatch, needsUpdate]); + + const handleNewImage = async () => { + setLoading(true); + const result = await patchProfile('header', user.userId); + setLoading(true); + if (result) { + setNeedsUpdate(true); + } else { + setLoading(false); + } + }; + + const checkAvatar = async (url: string | undefined) => { + const valid = await validateImageLink(url); + if (valid !== validImage) { + setValidImage(valid); + } + }; + + if (!validImage && userXId === undefined && !loading) { + return ( + <View style={[styles.container]}> + <ImageBackground + style={styles.image} + defaultSource={require('../../assets/images/cover-placeholder.png')} + source={{uri: cover, cache: 'reload'}}> + <TouchableOpacity + accessible={true} + accessibilityLabel="ADD HEADER PICTURE" + onPress={() => handleNewImage()}> + <GreyPurplePlus style={styles.plus} /> + <Text style={styles.text}>Add Picture</Text> + </TouchableOpacity> + </ImageBackground> + </View> + ); + } else { + return ( + <View style={styles.container}> + <Image + style={styles.image} + defaultSource={require('../../assets/images/cover-placeholder.png')} + source={{uri: cover, cache: 'reload'}} + /> + </View> + ); + } }; const styles = StyleSheet.create({ @@ -33,5 +98,20 @@ const styles = StyleSheet.create({ width: IMAGE_WIDTH, height: COVER_HEIGHT, }, + plus: { + position: 'absolute', + top: 75, + right: 125, + }, + text: { + color: 'white', + position: 'absolute', + fontSize: normalize(16), + top: 80, + right: 20, + }, + touch: { + flex: 1, + }, }); export default Cover; diff --git a/src/components/profile/ProfileBody.tsx b/src/components/profile/ProfileBody.tsx index 3d654724..7557de00 100644 --- a/src/components/profile/ProfileBody.tsx +++ b/src/components/profile/ProfileBody.tsx @@ -1,17 +1,7 @@ -import {useNavigation} from '@react-navigation/core'; -import React, {useContext} from 'react'; -import { - Alert, - LayoutChangeEvent, - Linking, - StyleSheet, - Text, - View, -} from 'react-native'; +import React from 'react'; +import {LayoutChangeEvent, Linking, StyleSheet, Text, View} from 'react-native'; import {useDispatch, useSelector, useStore} from 'react-redux'; -import {ChatContext} from '../../App'; import {TAGG_DARK_BLUE, TOGGLE_BUTTON_TYPE} from '../../constants'; -import {ERROR_UNABLE_CONNECT_CHAT} from '../../constants/strings'; import { acceptFriendRequest, declineFriendRequest, @@ -22,14 +12,14 @@ import {NO_PROFILE} from '../../store/initialStates'; import {RootState} from '../../store/rootReducer'; import {ScreenType} from '../../types'; import { - createChannel, getUserAsProfilePreviewType, normalize, SCREEN_HEIGHT, SCREEN_WIDTH, } from '../../utils'; import {canViewProfile} from '../../utils/users'; -import {BasicButton, FriendsButton} from '../common'; +import {FriendsButton} from '../common'; +import {MessageButton} from '../messages'; import ToggleButton from './ToggleButton'; interface ProfileBodyProps { @@ -47,7 +37,6 @@ const ProfileBody: React.FC<ProfileBodyProps> = ({ screenType, }) => { const dispatch = useDispatch(); - const navigation = useNavigation(); const {profile = NO_PROFILE, user} = useSelector((state: RootState) => userXId ? state.userX[screenType][userXId] : state.user, @@ -65,10 +54,7 @@ const ProfileBody: React.FC<ProfileBodyProps> = ({ profile, ); - const {chatClient, setChannel} = useContext(ChatContext); - const state: RootState = useStore().getState(); - const loggedInUserId = state.user.user.userId; const handleAcceptRequest = async () => { await dispatch(acceptFriendRequest({id, username, first_name, last_name})); @@ -81,32 +67,6 @@ const ProfileBody: React.FC<ProfileBodyProps> = ({ dispatch(updateUserXProfileAllScreens(id, state)); }; - const canMessage = () => { - if ( - userXId && - !isBlocked && - (friendship_status === 'no_record' || - friendship_status === 'friends' || - (friendship_status === 'requested' && - friendship_requester_id === loggedInUserId)) && - canViewProfile(state, userXId, screenType) - ) { - return true; - } else { - return false; - } - }; - - const onPressMessage = async () => { - if (chatClient.user && userXId) { - const channel = await createChannel(loggedInUserId, userXId, chatClient); - setChannel(channel); - navigation.navigate('Chat'); - } else { - Alert.alert(ERROR_UNABLE_CONNECT_CHAT); - } - }; - return ( <View onLayout={onLayout} style={styles.container}> <Text style={styles.username}>{`@${username}`}</Text> @@ -142,10 +102,12 @@ const ProfileBody: React.FC<ProfileBodyProps> = ({ onAcceptRequest={handleAcceptRequest} onRejectRequest={handleDeclineFriendRequest} /> - {canMessage() && ( - <BasicButton - title={'Message'} - onPress={onPressMessage} + {canViewProfile(state, userXId, screenType) && ( + <MessageButton + userXId={userXId} + isBlocked={isBlocked} + friendship_status={friendship_status} + friendship_requester_id={friendship_requester_id} externalStyles={{ container: { width: SCREEN_WIDTH * 0.42, diff --git a/src/components/profile/TaggAvatar.tsx b/src/components/profile/TaggAvatar.tsx index ea0bdb65..304b9e3a 100644 --- a/src/components/profile/TaggAvatar.tsx +++ b/src/components/profile/TaggAvatar.tsx @@ -1,9 +1,12 @@ -import React from 'react'; -import {StyleSheet} from 'react-native'; -import {useSelector} from 'react-redux'; +import React, {useState, useEffect} from 'react'; +import {StyleSheet, TouchableOpacity} from 'react-native'; import {RootState} from '../../store/rootreducer'; import {ScreenType} from '../../types'; import {Avatar} from '../common'; +import {useDispatch, useSelector} from 'react-redux'; +import {loadUserData, resetHeaderAndProfileImage} from '../../store/actions'; +import PurplePlus from '../../assets/icons/purple-plus.svg'; +import {patchProfile, validateImageLink} from '../../utils'; const PROFILE_DIM = 100; @@ -20,8 +23,59 @@ const TaggAvatar: React.FC<TaggAvatarProps> = ({ const {avatar} = useSelector((state: RootState) => userXId ? state.userX[screenType][userXId] : state.user, ); + const dispatch = useDispatch(); + const [needsUpdate, setNeedsUpdate] = useState(false); + const [loading, setLoading] = useState(false); + const [validImage, setValidImage] = useState<boolean>(true); + const {user} = useSelector((state: RootState) => + userXId ? state.userX[screenType][userXId] : state.user, + ); + + useEffect(() => { + checkAvatar(avatar); + }, []); + + useEffect(() => { + if (needsUpdate) { + const userId = user.userId; + const username = user.username; + dispatch(resetHeaderAndProfileImage()); + dispatch(loadUserData({userId, username})); + } + }, [dispatch, needsUpdate]); - return <Avatar style={[styles.image, style]} uri={avatar} />; + const handleNewImage = async () => { + setLoading(true); + const result = await patchProfile('profile', user.userId); + if (result) { + setNeedsUpdate(true); + } else { + setLoading(false); + } + }; + + const checkAvatar = async (url: string | undefined) => { + const valid = await validateImageLink(url); + if (valid !== validImage) { + setValidImage(valid); + } + }; + + if (!validImage && userXId === undefined && !loading) { + return ( + <> + <Avatar style={[styles.image, style]} uri={avatar} /> + <TouchableOpacity + accessible={true} + accessibilityLabel="ADD PROFILE PICTURE" + onPress={() => handleNewImage()}> + <PurplePlus style={styles.plus} /> + </TouchableOpacity> + </> + ); + } else { + return <Avatar style={[styles.image, style]} uri={avatar} />; + } }; const styles = StyleSheet.create({ @@ -30,6 +84,11 @@ const styles = StyleSheet.create({ width: PROFILE_DIM, borderRadius: PROFILE_DIM / 2, }, + plus: { + position: 'absolute', + bottom: 35, + right: 0, + }, }); export default TaggAvatar; diff --git a/src/components/taggs/TaggsBar.tsx b/src/components/taggs/TaggsBar.tsx index 4d567b25..a7e8fc7a 100644 --- a/src/components/taggs/TaggsBar.tsx +++ b/src/components/taggs/TaggsBar.tsx @@ -113,13 +113,11 @@ const TaggsBar: React.FC<TaggsBarProps> = ({ loadData(); } }, [taggsNeedUpdate, user]); - const paddingTopStylesProgress = useDerivedValue(() => - interpolate( - y.value, - [PROFILE_CUTOUT_BOTTOM_Y, PROFILE_CUTOUT_BOTTOM_Y + profileBodyHeight], - [0, 1], - Extrapolate.CLAMP, - ), + const paddingTopStylesProgress = interpolate( + y.value, + [PROFILE_CUTOUT_BOTTOM_Y, PROFILE_CUTOUT_BOTTOM_Y + profileBodyHeight], + [0, 1], + Extrapolate.CLAMP, ); const shadowOpacityStylesProgress = useDerivedValue(() => interpolate( @@ -134,7 +132,7 @@ const TaggsBar: React.FC<TaggsBarProps> = ({ ); const animatedStyles = useAnimatedStyle(() => ({ shadowOpacity: shadowOpacityStylesProgress.value / 5, - paddingTop: paddingTopStylesProgress.value * insetTop, + paddingTop: paddingTopStylesProgress + insetTop, })); return taggs.length > 0 ? ( diff --git a/src/utils/common.ts b/src/utils/common.ts index ce4ab7d1..95e77f64 100644 --- a/src/utils/common.ts +++ b/src/utils/common.ts @@ -180,3 +180,20 @@ const _crestIcon = (university: UniversityType) => { return require('../assets/images/bwbadges.png'); } }; + +export const validateImageLink = async (url: string | undefined) => { + if (!url) { + return false; + } + return fetch(url) + .then((res) => { + if (res.status === 200) { + return true; + } else { + return false; + } + }) + .catch((_) => { + return false; + }); +}; diff --git a/src/utils/users.ts b/src/utils/users.ts index 334cb3c0..430c843f 100644 --- a/src/utils/users.ts +++ b/src/utils/users.ts @@ -1,3 +1,4 @@ +import {Alert} from 'react-native'; import AsyncStorage from '@react-native-community/async-storage'; import {INTEGRATED_SOCIAL_LIST} from '../constants'; import {isUserBlocked, loadSocialPosts, removeBadgesService} from '../services'; @@ -24,6 +25,8 @@ import { UserType, UniversityBadge, } from './../types/types'; +import ImagePicker from 'react-native-image-crop-picker'; +import {patchEditProfile} from '../services'; const loadData = async (dispatch: AppDispatch, user: UserType) => { await Promise.all([ @@ -240,3 +243,82 @@ export const navigateToProfile = async ( screenType, }); }; + +export const patchProfile = async ( + title: 'profile' | 'header', + userId: string, +) => { + let imageSettings = {}; + let screenTitle: string; + let requestTitle: string; + let fileName: string; + switch (title) { + case 'header': + screenTitle = 'Select Header Picture'; + requestTitle = 'largeProfilePicture'; + fileName = 'large_profile_pic.jpg'; + imageSettings = { + smartAlbums: [ + 'Favorites', + 'RecentlyAdded', + 'SelfPortraits', + 'Screenshots', + 'UserLibrary', + ], + width: 580, + height: 580, + cropping: true, + cropperToolbarTitle: screenTitle, + mediaType: 'photo', + }; + break; + case 'profile': + screenTitle = 'Select Profile Picture'; + requestTitle = 'smallProfilePicture'; + fileName = 'small_profile_pic.jpg'; + imageSettings = { + smartAlbums: [ + 'Favorites', + 'RecentlyAdded', + 'SelfPortraits', + 'Screenshots', + 'UserLibrary', + ], + width: 580, + height: 580, + cropping: true, + cropperToolbarTitle: screenTitle, + mediaType: 'photo', + cropperCircleOverlay: true, + }; + break; + default: + screenTitle = ''; + requestTitle = ''; + fileName = ''; + } + + return await ImagePicker.openPicker(imageSettings) + .then((picture) => { + if ('path' in picture) { + const request = new FormData(); + request.append(requestTitle, { + uri: picture.path, + name: fileName, + type: 'image/jpg', + }); + + return patchEditProfile(request, userId) + .then((_) => { + return true; + }) + .catch((error) => { + Alert.alert(error); + return false; + }); + } + }) + .catch((_) => { + return false; + }); +}; |