diff options
Diffstat (limited to 'src/components/profile/ProfilePreview.tsx')
-rw-r--r-- | src/components/profile/ProfilePreview.tsx | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/src/components/profile/ProfilePreview.tsx b/src/components/profile/ProfilePreview.tsx new file mode 100644 index 00000000..c527746a --- /dev/null +++ b/src/components/profile/ProfilePreview.tsx @@ -0,0 +1,216 @@ +import React, {useEffect, useState, useContext} from 'react'; +import {ProfilePreviewType} from '../../types'; +import { + View, + Text, + Image, + StyleSheet, + ViewProps, + TouchableOpacity, +} from 'react-native'; +import {useNavigation} from '@react-navigation/native'; +import RNFetchBlob from 'rn-fetch-blob'; +import AsyncStorage from '@react-native-community/async-storage'; +import {AVATAR_PHOTO_ENDPOINT} from '../../constants'; +import {UserType} from '../../types'; +import {ProfileContext} from '../../routes/viewProfile'; +const NO_USER: UserType = { + userId: '', + username: '', +}; + +/** + * This component returns user's profile picture followed by username as a touchable component. + * What happens when someone clicks on this component is partly decided by the prop isComment. + * If isComment is true then it means that we are not displaying this tile as a part of search results. + * And hence we do not cache the search results. + * On the other hand, if isComment is false, then we should update the search cache. (This cache needs to be revamped to clear outdated results.) + * In either case, we load the ProfileContext with data and set the getNewMoments flag to true (Which ensures that everything that needs to be displayed on a user's profile is set). + * Finally, We navigate to Profile if we are on the Search Stack. Else we navigate to ProfileView. + */ + +interface ProfilePreviewProps extends ViewProps { + profilePreview: ProfilePreviewType; + isComment: boolean; +} +const ProfilePreview: React.FC<ProfilePreviewProps> = ({ + profilePreview: {username, first_name, last_name, id}, + isComment, + style, +}) => { + const navigation = useNavigation(); + const {loadProfile, updateMoments} = useContext(ProfileContext); + const [avatarURI, setAvatarURI] = useState<string | null>(null); + const [user, setUser] = useState<UserType>(NO_USER); + useEffect(() => { + let mounted = true; + const loadAvatar = async () => { + try { + const token = await AsyncStorage.getItem('token'); + if (!token) { + setUser(NO_USER); + return; + } + const response = await RNFetchBlob.config({ + fileCache: true, + appendExt: 'jpg', + }).fetch('GET', AVATAR_PHOTO_ENDPOINT + `${id}/`, { + Authorization: 'Token ' + token, + }); + const status = response.info().status; + if (status === 200) { + if (mounted) { + setAvatarURI(response.path()); + } + return; + } + if (mounted) { + setAvatarURI(''); + } + } catch (error) { + console.log(error); + } + }; + loadAvatar(); + return () => { + mounted = false; + }; + }, [id]); + + /** + * Adds a searched user to the recently searched cache if they're tapped on. + * Cache maintains 10 recently searched users, popping off the oldest one if + * needed to make space. + */ + const addToRecentlyStoredAndNavigateToProfile = async () => { + let user: ProfilePreviewType = { + id, + username, + first_name, + last_name, + }; + try { + if (!isComment) { + const jsonValue = await AsyncStorage.getItem( + '@recently_searched_users', + ); + let recentlySearchedList = + jsonValue != null ? JSON.parse(jsonValue) : null; + if (recentlySearchedList) { + if (recentlySearchedList.length > 0) { + if ( + recentlySearchedList.some( + (saved_user: ProfilePreviewType) => saved_user.id === id, + ) + ) { + console.log('User already in recently searched.'); + } else { + if (recentlySearchedList.length >= 10) { + recentlySearchedList.pop(); + } + recentlySearchedList.unshift(user); + } + } + } else { + recentlySearchedList = [user]; + } + + try { + let recentlySearchedListString = JSON.stringify(recentlySearchedList); + await AsyncStorage.setItem( + '@recently_searched_users', + recentlySearchedListString, + ); + } catch (e) { + console.log(e); + } + } + + //Load user profile and set new moments to true, navigate to Profile + //Load user profile makes sure that we actually load profile of the user the logged in user want to view + //Set new moments to true makes sure that we download the moment for the user being viewed again. + loadProfile(user.id, user.username); + updateMoments(true); + if (!isComment) { + navigation.navigate('Profile', { + isProfileView: true, + }); + } else { + navigation.navigate('ProfileView', { + isProfileView: true, + }); + } + } catch (e) { + console.log(e); + } + }; + + //With @ sign if on search screen. + const usernameToDisplay = !isComment ? `@` + username : username; + const usernameStyle = isComment + ? styles.commentUsername + : styles.searchUsername; + + const avatarStyle = !isComment ? styles.searchAvatar : styles.commentAvatar; + + return ( + <TouchableOpacity + onPress={addToRecentlyStoredAndNavigateToProfile} + style={[styles.container, style]}> + <Image + style={avatarStyle} + source={ + avatarURI + ? {uri: avatarURI} + : require('../../assets/images/avatar-placeholder.png') + } + /> + <View style={styles.nameContainer}> + <Text style={usernameStyle}>{usernameToDisplay}</Text> + {first_name ? ( + <Text style={styles.name}>{first_name.concat(' ', last_name)}</Text> + ) : ( + React.Fragment + )} + </View> + </TouchableOpacity> + ); +}; + +const styles = StyleSheet.create({ + container: { + flexDirection: 'row', + alignItems: 'center', + }, + searchAvatar: { + height: 60, + width: 60, + borderRadius: 30, + marginRight: 15, + }, + commentAvatar: { + height: 40, + width: 40, + borderRadius: 20, + marginRight: 15, + marginTop: '2%', + }, + nameContainer: { + justifyContent: 'space-evenly', + alignSelf: 'stretch', + }, + searchUsername: { + fontSize: 18, + fontWeight: '500', + }, + commentUsername: { + fontSize: 16, + fontWeight: '500', + }, + name: { + fontSize: 16, + color: '#333', + }, +}); + +export default ProfilePreview; |