diff options
Diffstat (limited to 'src')
21 files changed, 77 insertions, 134 deletions
diff --git a/src/components/comments/AddComment.tsx b/src/components/comments/AddComment.tsx index 3b195a2b..2a8c773e 100644 --- a/src/components/comments/AddComment.tsx +++ b/src/components/comments/AddComment.tsx @@ -1,6 +1,5 @@ import React, {useEffect, useRef} from 'react'; import { - Image, Keyboard, KeyboardAvoidingView, Platform, @@ -15,6 +14,7 @@ import {postComment} from '../../services'; import {updateReplyPosted} from '../../store/actions'; import {RootState} from '../../store/rootreducer'; import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; +import {Avatar} from '../common'; /** * This file provides the add comment view for a user. @@ -101,14 +101,7 @@ const AddComment: React.FC<AddCommentProps> = ({ keyboardVisible ? styles.whiteBackround : {}, ]}> <View style={styles.textContainer}> - <Image - style={styles.avatar} - source={ - avatar - ? {uri: avatar} - : require('../../assets/images/avatar-placeholder.png') - } - /> + <Avatar style={styles.avatar} uri={avatar} /> <TextInput style={styles.text} placeholder={placeholderText} diff --git a/src/components/common/Avatar.tsx b/src/components/common/Avatar.tsx new file mode 100644 index 00000000..831cf906 --- /dev/null +++ b/src/components/common/Avatar.tsx @@ -0,0 +1,18 @@ +import React, {FC} from 'react'; +import {Image, ImageStyle, StyleProp} from 'react-native'; + +type AvatarProps = { + style: StyleProp<ImageStyle>; + uri: string | undefined; +}; +const Avatar: FC<AvatarProps> = ({style, uri}) => { + return ( + <Image + style={style} + defaultSource={require('../../assets/images/avatar-placeholder.png')} + source={{uri, cache: 'reload'}} + /> + ); +}; + +export default Avatar; diff --git a/src/components/common/AvatarTitle.tsx b/src/components/common/AvatarTitle.tsx index 81351327..a2a7c0aa 100644 --- a/src/components/common/AvatarTitle.tsx +++ b/src/components/common/AvatarTitle.tsx @@ -1,10 +1,11 @@ import React from 'react'; -import {Image, StyleSheet, View} from 'react-native'; +import {StyleSheet, View} from 'react-native'; import LinearGradient from 'react-native-linear-gradient'; import {TAGGS_GRADIENT} from '../../constants'; +import Avatar from './Avatar'; type AvatarTitleProps = { - avatar: string | null; + avatar: string | undefined; }; const AvatarTitle: React.FC<AvatarTitleProps> = ({avatar}) => { return ( @@ -16,14 +17,7 @@ const AvatarTitle: React.FC<AvatarTitleProps> = ({avatar}) => { angleCenter={{x: 0.5, y: 0.5}} style={styles.gradient} /> - <Image - style={styles.avatar} - source={ - avatar - ? {uri: avatar} - : require('../../assets/images/avatar-placeholder.png') - } - /> + <Avatar style={styles.avatar} uri={avatar} /> </View> ); }; diff --git a/src/components/common/index.ts b/src/components/common/index.ts index 5a601f1d..802cf505 100644 --- a/src/components/common/index.ts +++ b/src/components/common/index.ts @@ -23,3 +23,4 @@ export {default as FriendsButton} from './FriendsButton'; export {default as TaggSquareButton} from './TaggSquareButton'; export {default as GradientBorderButton} from './GradientBorderButton'; export {default as BasicButton} from './BasicButton'; +export {default as Avatar} from './Avatar'; diff --git a/src/components/messages/ChannelPreview.tsx b/src/components/messages/ChannelPreview.tsx index 3d31d42a..878e5a6b 100644 --- a/src/components/messages/ChannelPreview.tsx +++ b/src/components/messages/ChannelPreview.tsx @@ -22,6 +22,7 @@ import { } from '../../types'; import {normalize, SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; import {getMember, isOnline} from '../../utils/messages'; +import {Avatar} from '../common'; const ChannelPreview: React.FC< ChannelPreviewMessengerProps< @@ -87,13 +88,9 @@ const ChannelPreview: React.FC< navigation.navigate('Chat'); }}> <View> - <Image + <Avatar style={styles.avatar} - source={ - member - ? {uri: member.user?.thumbnail_url} - : require('../../assets/images/avatar-placeholder.png') - } + uri={member?.user?.thumbnail_url as string} /> {online && <View style={styles.online} />} </View> diff --git a/src/components/messages/ChatHeader.tsx b/src/components/messages/ChatHeader.tsx index 7ddaa7e6..37dab0fd 100644 --- a/src/components/messages/ChatHeader.tsx +++ b/src/components/messages/ChatHeader.tsx @@ -1,6 +1,6 @@ import {useNavigation} from '@react-navigation/native'; import React, {useContext} from 'react'; -import {Image, StyleSheet, View} from 'react-native'; +import {StyleSheet, View} from 'react-native'; import {Text} from 'react-native-animatable'; import {TouchableOpacity} from 'react-native-gesture-handler'; import {useDispatch, useStore} from 'react-redux'; @@ -15,6 +15,7 @@ import { userXInStore, } from '../../utils'; import {formatLastSeenText, getMember, isOnline} from '../../utils/messages'; +import {Avatar} from '../common'; type ChatHeaderProps = { screenType: ScreenType; @@ -50,13 +51,9 @@ const ChatHeader: React.FC<ChatHeaderProps> = (props) => { <View style={styles.container}> <TouchableOpacity style={styles.tappables} onPress={toProfile}> <View> - <Image + <Avatar style={styles.avatar} - source={ - member - ? {uri: member.user?.thumbnail_url} - : require('../../assets/images/avatar-placeholder.png') - } + uri={member?.user?.thumbnail_url as string} /> {online && <View style={styles.online} />} </View> diff --git a/src/components/messages/ChatInput.tsx b/src/components/messages/ChatInput.tsx index a6e5c458..5585d246 100644 --- a/src/components/messages/ChatInput.tsx +++ b/src/components/messages/ChatInput.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import {Image, StyleSheet, View} from 'react-native'; +import {StyleSheet, View} from 'react-native'; import {useStore} from 'react-redux'; import { AutoCompleteInput, @@ -17,6 +17,7 @@ import { LocalUserType, } from '../../types'; import {normalize} from '../../utils'; +import {Avatar} from '../common'; import {ChatInputSubmit} from '../messages'; const ChatInput: React.FC< @@ -65,14 +66,7 @@ const ChatInput: React.FC< return ( <View style={styles.container}> <View style={styles.textContainer}> - <Image - style={styles.avatar} - source={ - avatar - ? {uri: avatar} - : require('../../assets/images/avatar-placeholder.png') - } - /> + <Avatar style={styles.avatar} uri={avatar} /> <AutoCompleteInput /> <View style={styles.actionButtons}> {/* TODO: Not working, toggled off for now */} diff --git a/src/components/messages/MessageAvatar.tsx b/src/components/messages/MessageAvatar.tsx index d275eae5..bcd4e7a8 100644 --- a/src/components/messages/MessageAvatar.tsx +++ b/src/components/messages/MessageAvatar.tsx @@ -1,9 +1,10 @@ import React, {useContext} from 'react'; -import {Image, StyleSheet, View} from 'react-native'; -import {getMember, normalize} from '../../utils'; -import {useMessageContext} from 'stream-chat-react-native-core'; +import {StyleSheet, View} from 'react-native'; import {useStore} from 'react-redux'; +import {useMessageContext} from 'stream-chat-react-native-core'; import {ChatContext} from '../../App'; +import {getMember, normalize} from '../../utils'; +import {Avatar} from '../common'; const MessageAvatar: React.FC = () => { const {channel} = useContext(ChatContext); @@ -14,13 +15,9 @@ const MessageAvatar: React.FC = () => { return ( <View style={styles.messageAvatarContainer}> {message.lastGroupMessage === true && ( - <Image + <Avatar style={styles.messageAvatar} - source={ - member - ? {uri: member.user?.thumbnail_url} - : require('../../assets/images/avatar-placeholder.png') - } + uri={member?.user?.thumbnail_url as string} /> )} </View> diff --git a/src/components/moments/MomentPostHeader.tsx b/src/components/moments/MomentPostHeader.tsx index 8cf509ab..20d9150a 100644 --- a/src/components/moments/MomentPostHeader.tsx +++ b/src/components/moments/MomentPostHeader.tsx @@ -10,7 +10,7 @@ import {MomentMoreInfoDrawer} from '../profile'; import {loadUserMoments} from '../../store/actions'; import {useDispatch, useSelector, useStore} from 'react-redux'; import {ScreenType} from '../../types'; -import Avatar from '../profile/Avatar'; +import TaggAvatar from '../profile/TaggAvatar'; import {useNavigation} from '@react-navigation/native'; import {RootState} from '../../store/rootReducer'; import {fetchUserX, userXInStore} from '../../utils'; @@ -54,7 +54,7 @@ const MomentPostHeader: React.FC<MomentPostHeaderProps> = ({ return ( <View style={[styles.container, style]}> <TouchableOpacity onPress={navigateToProfile} style={styles.header}> - <Avatar + <TaggAvatar style={styles.avatar} userXId={userXId} screenType={screenType} diff --git a/src/components/notifications/Notification.tsx b/src/components/notifications/Notification.tsx index 3cc1c7f1..a74480b4 100644 --- a/src/components/notifications/Notification.tsx +++ b/src/components/notifications/Notification.tsx @@ -30,6 +30,7 @@ import { SCREEN_WIDTH, userXInStore, } from '../../utils'; +import {Avatar} from '../common'; import AcceptDeclineButtons from '../common/AcceptDeclineButtons'; interface NotificationProps { @@ -225,14 +226,7 @@ const Notification: React.FC<NotificationProps> = (props) => { <TouchableWithoutFeedback onPress={navigateToProfile} style={styles.avatarContainer}> - <Image - style={styles.avatar} - source={ - avatar - ? {uri: avatar, cache: 'reload'} - : require('../../assets/images/avatar-placeholder.png') - } - /> + <Avatar style={styles.avatar} uri={avatar} /> </TouchableWithoutFeedback> {notification_type === 'SYSTEM_MSG' ? ( // Only verbage diff --git a/src/components/profile/ProfileHeader.tsx b/src/components/profile/ProfileHeader.tsx index 62c2e1e3..3102937b 100644 --- a/src/components/profile/ProfileHeader.tsx +++ b/src/components/profile/ProfileHeader.tsx @@ -8,7 +8,7 @@ import {RootState} from '../../store/rootreducer'; import {ScreenType} from '../../types'; import {hasSeenBadgeTutorial, normalize} from '../../utils'; import BadgeDetailView from '../common/BadgeDetailView'; -import Avatar from './Avatar'; +import TaggAvatar from './TaggAvatar'; import BadgeTutorial from './BadgeTutorial'; import FriendsCount from './FriendsCount'; import ProfileMoreInfoDrawer from './ProfileMoreInfoDrawer'; @@ -106,7 +106,7 @@ const ProfileHeader: React.FC<ProfileHeaderProps> = ({ /> )} <View style={styles.row}> - <Avatar + <TaggAvatar style={styles.avatar} userXId={userXId} screenType={screenType} diff --git a/src/components/profile/ProfilePreview.tsx b/src/components/profile/ProfilePreview.tsx index bea989d9..66d68d8f 100644 --- a/src/components/profile/ProfilePreview.tsx +++ b/src/components/profile/ProfilePreview.tsx @@ -2,7 +2,6 @@ import {useNavigation} from '@react-navigation/native'; import React, {useEffect, useState} from 'react'; import { Alert, - Image, StyleSheet, Text, TouchableOpacity, @@ -23,6 +22,7 @@ import { userXInStore, } from '../../utils'; import {addUserToRecentlySearched} from '../../utils/search'; +import {Avatar} from '../common'; /** * This component returns user's profile picture friended by username as a touchable component. @@ -48,7 +48,7 @@ const ProfilePreview: React.FC<ProfilePreviewProps> = ({ }) => { const navigation = useNavigation(); const {user: loggedInUser} = useSelector((state: RootState) => state.user); - const [avatar, setAvatar] = useState<string | null>(null); + const [avatar, setAvatar] = useState<string>(); const dispatch = useDispatch(); useEffect(() => { @@ -187,14 +187,7 @@ const ProfilePreview: React.FC<ProfilePreviewProps> = ({ <TouchableOpacity onPress={addToRecentlyStoredAndNavigateToProfile} style={containerStyle}> - <Image - style={avatarStyle} - source={ - avatar - ? {uri: avatar} - : require('../../assets/images/avatar-placeholder.png') - } - /> + <Avatar style={avatarStyle} uri={avatar} /> <View style={nameContainerStyle}> {(previewType === 'Search' || previewType === 'Recent') && ( <> diff --git a/src/components/profile/Avatar.tsx b/src/components/profile/TaggAvatar.tsx index e57a56a3..ea0bdb65 100644 --- a/src/components/profile/Avatar.tsx +++ b/src/components/profile/TaggAvatar.tsx @@ -1,28 +1,27 @@ import React from 'react'; -import {Image, StyleSheet} from 'react-native'; +import {StyleSheet} from 'react-native'; import {useSelector} from 'react-redux'; import {RootState} from '../../store/rootreducer'; import {ScreenType} from '../../types'; +import {Avatar} from '../common'; const PROFILE_DIM = 100; -interface AvatarProps { +interface TaggAvatarProps { style?: object; userXId: string | undefined; screenType: ScreenType; } -const Avatar: React.FC<AvatarProps> = ({style, screenType, userXId}) => { +const TaggAvatar: React.FC<TaggAvatarProps> = ({ + style, + screenType, + userXId, +}) => { const {avatar} = useSelector((state: RootState) => userXId ? state.userX[screenType][userXId] : state.user, ); - return ( - <Image - style={[styles.image, style]} - defaultSource={require('../../assets/images/avatar-placeholder.png')} - source={{uri: avatar, cache: 'reload'}} - /> - ); + return <Avatar style={[styles.image, style]} uri={avatar} />; }; const styles = StyleSheet.create({ @@ -33,4 +32,4 @@ const styles = StyleSheet.create({ }, }); -export default Avatar; +export default TaggAvatar; diff --git a/src/components/profile/index.ts b/src/components/profile/index.ts index 260f4217..c544c3f2 100644 --- a/src/components/profile/index.ts +++ b/src/components/profile/index.ts @@ -8,3 +8,4 @@ export {default as Friends} from './Friends'; export {default as ProfileMoreInfoDrawer} from './ProfileMoreInfoDrawer'; export {default as MomentMoreInfoDrawer} from './MomentMoreInfoDrawer'; export {default as UniversityIcon} from './UniversityIcon'; +export {default as TaggAvatar} from './TaggAvatar'; diff --git a/src/components/search/ExploreSectionUser.tsx b/src/components/search/ExploreSectionUser.tsx index d8c92be2..c949acd4 100644 --- a/src/components/search/ExploreSectionUser.tsx +++ b/src/components/search/ExploreSectionUser.tsx @@ -1,13 +1,13 @@ import {useNavigation} from '@react-navigation/native'; import React, {useEffect, useState} from 'react'; -import {TextStyle, ViewStyle} from 'react-native'; import { - Image, StyleProp, StyleSheet, Text, + TextStyle, TouchableOpacity, ViewProps, + ViewStyle, } from 'react-native'; import LinearGradient from 'react-native-linear-gradient'; import {useDispatch, useSelector, useStore} from 'react-redux'; @@ -15,6 +15,7 @@ import {loadImageFromURL} from '../../services'; import {RootState} from '../../store/rootReducer'; import {ProfilePreviewType, ScreenType} from '../../types'; import {fetchUserX, normalize, userXInStore} from '../../utils'; +import {Avatar} from '../common'; /** * Search Screen for user recommendations and a search @@ -30,7 +31,7 @@ const ExploreSectionUser: React.FC<ExploreSectionUserProps> = ({ externalStyles, }) => { const {id, username, first_name, last_name} = user; - const [avatar, setAvatar] = useState<string | null>(null); + const [avatar, setAvatar] = useState<string>(); const navigation = useNavigation(); const {user: loggedInUser} = useSelector((state: RootState) => state.user); const state: RootState = useStore().getState(); @@ -71,14 +72,7 @@ const ExploreSectionUser: React.FC<ExploreSectionUserProps> = ({ angle={90} angleCenter={{x: 0.5, y: 0.5}} style={styles.gradient}> - <Image - source={ - avatar - ? {uri: avatar} - : require('../../assets/images/avatar-placeholder.png') - } - style={styles.profile} - /> + <Avatar style={styles.profile} uri={avatar} /> </LinearGradient> <Text style={[styles.name, externalStyles?.name]} numberOfLines={2}> {first_name} {last_name} diff --git a/src/components/search/SearchResultCell.tsx b/src/components/search/SearchResultCell.tsx index 5a6ea110..16e62a53 100644 --- a/src/components/search/SearchResultCell.tsx +++ b/src/components/search/SearchResultCell.tsx @@ -22,10 +22,10 @@ import { } from '../../utils'; import { checkIfUserIsBlocked, - defaultUserProfile, fetchUserX, userXInStore, } from '../../utils/users'; +import {Avatar} from '../common'; interface SearchResults { profileData: ProfilePreviewType; @@ -129,11 +129,7 @@ const SearchResultsCell: React.FC<SearchResults> = ({ <TouchableOpacity onPress={addToRecentlyStoredAndNavigateToProfile} style={styles.cellContainer}> - <Image - defaultSource={defaultUserProfile()} - source={{uri: avatar}} - style={styles.imageContainer} - /> + <Avatar style={styles.imageContainer} uri={avatar} /> <View style={[styles.initialTextContainer, styles.multiText]}> <Text style={styles.initialTextStyle}>{`@${username}`}</Text> <Text style={styles.secondaryTextStyle}> diff --git a/src/components/taggs/TwitterTaggPost.tsx b/src/components/taggs/TwitterTaggPost.tsx index 0a6f53d8..db07ba66 100644 --- a/src/components/taggs/TwitterTaggPost.tsx +++ b/src/components/taggs/TwitterTaggPost.tsx @@ -11,7 +11,7 @@ import { } from '../../constants'; import {TwitterPostType} from '../../types'; import {handleOpenSocialUrlOnBrowser, SCREEN_WIDTH} from '../../utils'; -import {DateLabel, PostCarousel} from '../common'; +import {Avatar, DateLabel, PostCarousel} from '../common'; interface TwitterTaggPostProps { ownerHandle: string; @@ -31,14 +31,7 @@ const TwitterTaggPost: React.FC<TwitterTaggPostProps> = ({ )} {/* Post header (avatar and handle) */} <View style={styles.header}> - <Image - style={styles.avatar} - source={ - post.profile_pic - ? {uri: post.profile_pic} - : require('../../assets/images/avatar-placeholder.png') - } - /> + <Avatar style={styles.avatar} uri={post.profile_pic} /> <Text style={styles.headerText} onPress={() => handleOpenSocialUrlOnBrowser(post.handle, 'Twitter')}> @@ -84,13 +77,9 @@ const TwitterTaggPost: React.FC<TwitterTaggPostProps> = ({ <View style={styles.replyHeader}> {post.in_reply_to.text !== 'This tweet is unavailable' && ( <> - <Image - style={styles.replyAvatar} - source={ - post.in_reply_to.profile_pic - ? {uri: post.in_reply_to.profile_pic} - : require('../../assets/images/avatar-placeholder.png') - } + <Avatar + style={styles.avatar} + uri={post.in_reply_to.profile_pic} /> <Text style={styles.replyHandleText} diff --git a/src/screens/chat/ChatResultsCell.tsx b/src/screens/chat/ChatResultsCell.tsx index e1eb97dd..14062810 100644 --- a/src/screens/chat/ChatResultsCell.tsx +++ b/src/screens/chat/ChatResultsCell.tsx @@ -1,13 +1,13 @@ import {useNavigation} from '@react-navigation/native'; import React, {useContext, useEffect, useState} from 'react'; -import {Alert, Image, StyleSheet, Text, View} from 'react-native'; +import {Alert, StyleSheet, Text, View} from 'react-native'; import {TouchableOpacity} from 'react-native-gesture-handler'; import {ChatContext} from '../../App'; +import {Avatar} from '../../components'; import {ERROR_FAILED_TO_CREATE_CHANNEL} from '../../constants/strings'; import {loadImageFromURL} from '../../services'; import {ProfilePreviewType, UserType} from '../../types'; import {createChannel, normalize, SCREEN_WIDTH} from '../../utils'; -import {defaultUserProfile} from '../../utils/users'; interface ChatResults { profileData: ProfilePreviewType; @@ -58,11 +58,7 @@ const ChatResultsCell: React.FC<ChatResults> = ({ <TouchableOpacity onPress={createChannelIfNotPresentAndNavigate} style={styles.cellContainer}> - <Image - defaultSource={defaultUserProfile()} - source={{uri: avatar}} - style={styles.imageContainer} - /> + <Avatar style={styles.imageContainer} uri={avatar} /> <View style={[styles.initialTextContainer, styles.multiText]}> <Text style={styles.initialTextStyle}>{`@${username}`}</Text> <Text style={styles.secondaryTextStyle}> diff --git a/src/screens/onboarding/OnboardingStepThree.tsx b/src/screens/onboarding/OnboardingStepThree.tsx index 638f0889..34173b39 100644 --- a/src/screens/onboarding/OnboardingStepThree.tsx +++ b/src/screens/onboarding/OnboardingStepThree.tsx @@ -27,7 +27,6 @@ import { ERROR_SELECT_CLASS_YEAR, ERROR_SELECT_GENDER, ERROR_SELECT_UNIVERSITY, - ERROR_UPLOAD_SMALL_PROFILE_PIC, } from '../../constants/strings'; import {OnboardingStackParams} from '../../routes/onboarding'; import {patchEditProfile} from '../../services'; @@ -160,10 +159,6 @@ const OnboardingStepThree: React.FC<OnboardingStepThreeProps> = ({ }; const handleSubmit = async () => { - if (!form.smallPic) { - Alert.alert(ERROR_UPLOAD_SMALL_PROFILE_PIC); - return; - } if (form.classYear === -1) { Alert.alert(ERROR_SELECT_CLASS_YEAR); return; diff --git a/src/screens/profile/SocialMediaTaggs.tsx b/src/screens/profile/SocialMediaTaggs.tsx index 9186f187..52d20683 100644 --- a/src/screens/profile/SocialMediaTaggs.tsx +++ b/src/screens/profile/SocialMediaTaggs.tsx @@ -59,7 +59,7 @@ const SocialMediaTaggs: React.FC<SocialMediaTaggsProps> = ({ useEffect(() => { navigation.setOptions({ headerTitle: () => { - return <AvatarTitle avatar={avatar ?? null} />; + return <AvatarTitle avatar={avatar} />; }, }); }, [avatar, navigation]); diff --git a/src/utils/users.ts b/src/utils/users.ts index 7148eb79..abadaf6e 100644 --- a/src/utils/users.ts +++ b/src/utils/users.ts @@ -168,11 +168,6 @@ export const checkIfUserIsBlocked = async ( return await isUserBlocked(userId, loggedInUser.userId, token); }; -export const defaultUserProfile = () => { - const defaultImage = require('../assets/images/avatar-placeholder.png'); - return defaultImage; -}; - /** * Used to determine whether the logged-in user is able to view userX's private * information or not. |