diff options
author | Ashm Walia <40498934+ashmgarv@users.noreply.github.com> | 2020-12-04 08:50:24 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-04 11:50:24 -0500 |
commit | 0fd892ad288f2e1eaaa4fdf5e1fd6f15dbd45860 (patch) | |
tree | d7d53d94c6c4026ac9b325508ebce4706d412ac4 /src/screens | |
parent | f620102190629e0b6f180d3ce056d850b1db5aaa (diff) |
[TMA - 398 AND TMA-430] Replace Providers with Redux Store (#125)
* First
* WIP
* Thunk
* Some more comments
* sc
* recent searches and follounfollow
* Edit profile dummy
* Block / unblock and some cleanup
* Replace auth provider
* Sc
* Delete AP after rebase
* Discover users
* Cleanup
* More cleanup
* Replace profile provider
* Fixed build failure
* Fixed a bug reported
* Prevent app crash when backend server is down
Diffstat (limited to 'src/screens')
-rw-r--r-- | src/screens/onboarding/Checkpoint.tsx | 1 | ||||
-rw-r--r-- | src/screens/onboarding/Login.tsx | 15 | ||||
-rw-r--r-- | src/screens/onboarding/SocialMedia.tsx | 14 | ||||
-rw-r--r-- | src/screens/profile/CaptionScreen.tsx | 26 | ||||
-rw-r--r-- | src/screens/profile/EditProfile.tsx | 13 | ||||
-rw-r--r-- | src/screens/profile/FollowersListScreen.tsx | 21 | ||||
-rw-r--r-- | src/screens/profile/IndividualMoment.tsx | 25 | ||||
-rw-r--r-- | src/screens/profile/MomentCommentsScreen.tsx | 15 | ||||
-rw-r--r-- | src/screens/profile/ProfileScreen.tsx | 74 | ||||
-rw-r--r-- | src/screens/profile/SocialMediaTaggs.tsx | 100 | ||||
-rw-r--r-- | src/screens/search/SearchScreen.tsx | 37 |
11 files changed, 220 insertions, 121 deletions
diff --git a/src/screens/onboarding/Checkpoint.tsx b/src/screens/onboarding/Checkpoint.tsx index 0be1e831..83a8a2bc 100644 --- a/src/screens/onboarding/Checkpoint.tsx +++ b/src/screens/onboarding/Checkpoint.tsx @@ -11,7 +11,6 @@ import { } from 'react-native'; import {OnboardingStackParams} from '../../routes'; -import {AuthContext} from '../../routes/authentication'; import {RegistrationWizard, Background} from '../../components'; type CheckpointRouteProp = RouteProp<OnboardingStackParams, 'Checkpoint'>; diff --git a/src/screens/onboarding/Login.tsx b/src/screens/onboarding/Login.tsx index 8f19ec3d..2ddae403 100644 --- a/src/screens/onboarding/Login.tsx +++ b/src/screens/onboarding/Login.tsx @@ -14,11 +14,12 @@ import { } from 'react-native'; import {OnboardingStackParams} from '../../routes/onboarding'; -import {AuthContext} from '../../routes/authentication'; import {Background, TaggInput, SubmitButton} from '../../components'; import {usernameRegex, LOGIN_ENDPOINT} from '../../constants'; import AsyncStorage from '@react-native-community/async-storage'; import {UserType} from '../../types'; +import {useDispatch} from 'react-redux'; +import {userLogin} from '../../utils'; type VerificationScreenRouteProp = RouteProp<OnboardingStackParams, 'Login'>; type VerificationScreenNavigationProp = StackNavigationProp< @@ -51,9 +52,15 @@ const Login: React.FC<LoginProps> = ({navigation}: LoginProps) => { attemptedSubmit: false, token: '', }); - // determines if user is logged in - const {login} = React.useContext(AuthContext); const [user, setUser] = useState<UserType>(NO_USER); + + /** + * Redux Store stuff + * Get the dispatch reference + */ + + const dispatch = useDispatch(); + /** * Updates the state of username. Also verifies the input of the username field by ensuring proper length and appropriate characters. */ @@ -140,7 +147,7 @@ const Login: React.FC<LoginProps> = ({navigation}: LoginProps) => { await AsyncStorage.setItem('token', data.token); await AsyncStorage.setItem('userId', data.UserID); await AsyncStorage.setItem('username', username); - login(data.UserID, username); + userLogin(dispatch, {userId: data.UserID, username}); } catch (err) { setUser(NO_USER); console.log(data); diff --git a/src/screens/onboarding/SocialMedia.tsx b/src/screens/onboarding/SocialMedia.tsx index 57270e4e..ee2bed10 100644 --- a/src/screens/onboarding/SocialMedia.tsx +++ b/src/screens/onboarding/SocialMedia.tsx @@ -10,6 +10,7 @@ import { TouchableOpacity, View, } from 'react-native'; +import {useDispatch} from 'react-redux'; import {LinkerType} from 'src/types'; import { Background, @@ -17,7 +18,8 @@ import { RegistrationWizard, } from '../../components'; import {SOCIAL_LIST} from '../../constants/'; -import {AuthContext, OnboardingStackParams} from '../../routes'; +import {OnboardingStackParams} from '../../routes'; +import {userLogin} from '../../utils'; /** * Social Media Screen for displaying social media linkers @@ -33,12 +35,6 @@ const SocialMedia: React.FC<SocialMediaProps> = ({route}) => { const {userId, username} = route.params; const linkers: Array<LinkerType> = []; - /** - * login: determines if user successully created an account to - * navigate to home and display main tab navigation bar - */ - const {login} = React.useContext(AuthContext); - // let numSocials: Number = state.showMore ? 9 : 3; for (let i = 0; i < SOCIAL_LIST.length; i++) { @@ -48,6 +44,8 @@ const SocialMedia: React.FC<SocialMediaProps> = ({route}) => { linkers.push(linker); } + const dispatch = useDispatch(); + /** * Just commenting this out, in case we need it in the future */ @@ -60,7 +58,7 @@ const SocialMedia: React.FC<SocialMediaProps> = ({route}) => { const handleLogin = () => { try { - login(userId, username); + userLogin(dispatch, {userId: userId, username: username}); } catch (error) { console.log(error); Alert.alert('There was a problem logging you in'); diff --git a/src/screens/profile/CaptionScreen.tsx b/src/screens/profile/CaptionScreen.tsx index 08dd8e5b..e9eed668 100644 --- a/src/screens/profile/CaptionScreen.tsx +++ b/src/screens/profile/CaptionScreen.tsx @@ -18,7 +18,9 @@ import {ProfileStackParams} from 'src/routes'; import {StackNavigationProp} from '@react-navigation/stack'; import {CaptionScreenHeader} from '../../components/'; import {MOMENTS_ENDPOINT} from '../../constants'; -import {AuthContext} from '../../routes/authentication'; +import {useDispatch, useSelector} from 'react-redux'; +import {loadUserMoments} from '../../store/actions'; +import {RootState} from '../../store/rootReducer'; /** * Upload Screen to allow users to upload posts to Tagg @@ -34,11 +36,11 @@ interface CaptionScreenProps { } const CaptionScreen: React.FC<CaptionScreenProps> = ({route, navigation}) => { - const {title, image} = route.params; + const {title, image, screenType} = route.params; const { user: {userId}, - updateMoments, - } = React.useContext(AuthContext); + } = useSelector((state: RootState) => state.user); + const dispatch = useDispatch(); const [caption, setCaption] = React.useState(''); const handleCaptionUpdate = (caption: string) => { @@ -54,6 +56,14 @@ const CaptionScreen: React.FC<CaptionScreenProps> = ({route, navigation}) => { return true; }; + const navigateToProfile = () => { + //Since the logged In User is navigating to own profile, useXId is not required + navigation.navigate('Profile', { + screenType, + userXId: undefined, + }); + }; + const handleShare = async () => { try { const request = new FormData(); @@ -86,8 +96,8 @@ const CaptionScreen: React.FC<CaptionScreenProps> = ({route, navigation}) => { let data = await response.json(); if (statusCode === 200 && checkImageUploadStatus(data)) { Alert.alert('The picture was uploaded successfully!'); - updateMoments(true); - navigation.navigate('Profile', {isProfileView: false}); + dispatch(loadUserMoments(userId)); + navigateToProfile(); } else { Alert.alert('An error occured while uploading. Please try again!'); } @@ -107,9 +117,7 @@ const CaptionScreen: React.FC<CaptionScreenProps> = ({route, navigation}) => { <Button title="Cancel" buttonStyle={styles.button} - onPress={() => { - navigation.navigate('Profile', {isProfileView: false}); - }} + onPress={() => navigateToProfile()} /> <Button title="Share" diff --git a/src/screens/profile/EditProfile.tsx b/src/screens/profile/EditProfile.tsx index 01b67155..44d99b82 100644 --- a/src/screens/profile/EditProfile.tsx +++ b/src/screens/profile/EditProfile.tsx @@ -30,9 +30,11 @@ import { genderRegex, } from '../../constants'; import AsyncStorage from '@react-native-community/async-storage'; -import {AuthContext} from '../../routes'; import Animated from 'react-native-reanimated'; import {SCREEN_HEIGHT} from '../../utils'; +import {RootState} from '../../store/rootReducer'; +import {useDispatch, useSelector} from 'react-redux'; +import {loadUserData} from '../../store/actions'; type ProfileOnboardingScreenRouteProp = RouteProp< OnboardingStackParams, @@ -62,13 +64,14 @@ const ProfileOnboarding: React.FC<ProfileOnboardingProps> = ({ profile: {website, biography, birthday, gender}, avatar, cover, - updateIsEditedProfile, - } = React.useContext(AuthContext); + } = useSelector((state: RootState) => state.user); + const [needsUpdate, setNeedsUpdate] = useState(false); + const dispatch = useDispatch(); useEffect(() => { - updateIsEditedProfile(needsUpdate); - }, [needsUpdate, updateIsEditedProfile]); + if (needsUpdate) dispatch(loadUserData({userId, username})); + }, [loadUserData, needsUpdate]); const [isCustomGender, setIsCustomGender] = React.useState<boolean>( gender !== '' && gender !== 'female' && gender !== 'male', diff --git a/src/screens/profile/FollowersListScreen.tsx b/src/screens/profile/FollowersListScreen.tsx index bad264a1..874dd01b 100644 --- a/src/screens/profile/FollowersListScreen.tsx +++ b/src/screens/profile/FollowersListScreen.tsx @@ -1,10 +1,14 @@ -import React from 'react'; +import React, {useEffect, useState} from 'react'; import {RouteProp} from '@react-navigation/native'; import {TabsGradient, Followers, CenteredView} from '../../components'; import {ScrollView} from 'react-native-gesture-handler'; import {SCREEN_HEIGHT} from '../../utils'; import {StyleSheet, View} from 'react-native'; import {ProfileStackParams} from '../../routes'; +import {ProfilePreviewType} from '../../types'; +import {EMPTY_PROFILE_PREVIEW_LIST} from '../../store/initialStates'; +import {useSelector} from 'react-redux'; +import {RootState} from '../../store/rootReducer'; type FollowersListScreenRouteProp = RouteProp< ProfileStackParams, @@ -15,7 +19,19 @@ interface FollowersListScreenProps { } const FollowersListScreen: React.FC<FollowersListScreenProps> = ({route}) => { - const {isFollowers, list} = route.params; + const {isFollowers, userXId, screenType} = route.params; + + const {followers, following} = userXId + ? useSelector((state: RootState) => state.userX[screenType][userXId]) + : useSelector((state: RootState) => state.follow); + + const [list, setList] = useState<ProfilePreviewType[]>( + EMPTY_PROFILE_PREVIEW_LIST, + ); + + useEffect(() => { + setList(isFollowers ? followers : following); + }, [followers, following, setList]); return ( <CenteredView> @@ -28,6 +44,7 @@ const FollowersListScreen: React.FC<FollowersListScreenProps> = ({route}) => { <Followers result={list} sectionTitle={isFollowers ? 'Followers' : 'Following'} + screenType={screenType} /> </ScrollView> <TabsGradient /> diff --git a/src/screens/profile/IndividualMoment.tsx b/src/screens/profile/IndividualMoment.tsx index 29a624cf..2739324e 100644 --- a/src/screens/profile/IndividualMoment.tsx +++ b/src/screens/profile/IndividualMoment.tsx @@ -12,7 +12,6 @@ import {UserType} from '../../types'; import {RouteProp} from '@react-navigation/native'; import {StackNavigationProp} from '@react-navigation/stack'; import {CaptionScreenHeader} from '../../components'; -import {AuthContext, ProfileContext} from '../../routes/'; import {ProfileStackParams} from 'src/routes/profile/ProfileStack'; import Animated from 'react-native-reanimated'; import {CommentsCount} from '../../components'; @@ -21,6 +20,10 @@ import {getMomentCommentsCount} from '../../services'; import {TouchableOpacity} from 'react-native-gesture-handler'; import {Alert} from 'react-native'; import {sendReport} from '../../services/ReportingService'; +import {logout} from '../../store/actions'; +import {useDispatch, useSelector} from 'react-redux'; +import {RootState} from '../../store/rootreducer'; +import {DUMMY_USERNAME} from '../../store/initialStates'; const NO_USER: UserType = { userId: '', @@ -53,17 +56,25 @@ const IndividualMoment: React.FC<IndividualMomentProps> = ({ date_time, moment_id, } = route.params.moment; - const {isProfileView, username} = route.params; + const {userXId, screenType} = route.params; + const { user: {userId: loggedInUserId, username: loggedInusername}, - logout, - } = React.useContext(AuthContext); + } = useSelector((state: RootState) => state.user); + + const { + user: {username}, + } = userXId + ? useSelector((state: RootState) => state.userX[screenType][userXId]) + : {user: {username: DUMMY_USERNAME}}; + const isOwnProfile = username === loggedInusername; const [user, setUser] = useState<UserType>(NO_USER); const [caption, setCaption] = React.useState(route.params.moment.caption); const [elapsedTime, setElapsedTime] = React.useState<string>(); const [comments_count, setCommentsCount] = React.useState(''); const [isReporting, setIsReporting] = React.useState(false); + const dispatch = useDispatch(); const handleCaptionUpdate = (caption: string) => { setCaption(caption); @@ -80,7 +91,7 @@ const IndividualMoment: React.FC<IndividualMomentProps> = ({ const loadComments = async () => { const token = await AsyncStorage.getItem('token'); if (!token) { - logout(); + dispatch(logout()); return; } getMomentCommentsCount(moment_id, setCommentsCount, token); @@ -155,13 +166,13 @@ const IndividualMoment: React.FC<IndividualMomentProps> = ({ <View style={styles.bodyContainer}> <CommentsCount comments_count={comments_count} - isProfileView={isProfileView} moment_id={moment_id} + screenType={screenType} /> <Animated.Text style={styles.text}>{elapsedTime}</Animated.Text> </View> <Animated.Text style={styles.captionText}>{caption}</Animated.Text> - {isProfileView && !isOwnProfile && !isReporting && ( + {userXId && !isOwnProfile && !isReporting && ( <TouchableOpacity onPress={sendReportAlert}> <Animated.Text style={styles.reportIssue}> {'Report an issue'} diff --git a/src/screens/profile/MomentCommentsScreen.tsx b/src/screens/profile/MomentCommentsScreen.tsx index 7a0bfa66..34f85c28 100644 --- a/src/screens/profile/MomentCommentsScreen.tsx +++ b/src/screens/profile/MomentCommentsScreen.tsx @@ -9,8 +9,9 @@ import {Button} from 'react-native-elements'; import {AddComment} from '../../components/'; import {useEffect} from 'react'; import AsyncStorage from '@react-native-community/async-storage'; -import {AuthContext} from '../../routes/authentication'; import {getMomentComments} from '../..//services'; +import {useDispatch} from 'react-redux'; +import {logout} from '../../store/actions'; /** * Comments Screen for an image uploaded @@ -29,16 +30,16 @@ interface MomentCommentsScreenProps { const MomentCommentsScreen: React.FC<MomentCommentsScreenProps> = ({route}) => { const navigation = useNavigation(); - const {isProfileView, moment_id} = route.params; + const {moment_id, screenType} = route.params; const [commentsList, setCommentsList] = React.useState([]); const [newCommentsAvailable, setNewCommentsAvailable] = React.useState(true); - const {logout} = React.useContext(AuthContext); + const dispatch = useDispatch(); useEffect(() => { const loadComments = async () => { const token = await AsyncStorage.getItem('token'); if (!token) { - logout(); + dispatch(logout()); return; } getMomentComments(moment_id, setCommentsList, token); @@ -70,7 +71,11 @@ const MomentCommentsScreen: React.FC<MomentCommentsScreenProps> = ({route}) => { contentContainerStyle={styles.modalScrollViewContent}> {commentsList && commentsList.map((comment: CommentType) => ( - <CommentTile key={comment.comment_id} comment_object={comment} /> + <CommentTile + key={comment.comment_id} + comment_object={comment} + screenType={screenType} + /> ))} </ScrollView> <AddComment diff --git a/src/screens/profile/ProfileScreen.tsx b/src/screens/profile/ProfileScreen.tsx index d32eca98..a2a1b5bd 100644 --- a/src/screens/profile/ProfileScreen.tsx +++ b/src/screens/profile/ProfileScreen.tsx @@ -1,11 +1,15 @@ -import React, {useContext, useEffect} from 'react'; +import React, {useContext, useEffect, useState} from 'react'; import {StatusBar} from 'react-native'; import Animated from 'react-native-reanimated'; import {Content, Cover, TabsGradient} from '../../components'; -import {RouteProp} from '@react-navigation/native'; -import {ProfileStackParams, ProfileProvider, AuthContext} from '../../routes/'; - -/** +import {RouteProp, useFocusEffect} from '@react-navigation/native'; +import {ProfileStackParams, ProfileProvider} from '../../routes/'; +import {resetScreenType} from '../../store/actions'; +import {useDispatch, useStore} from 'react-redux'; +import {ScreenType} from '../../types'; +import {DUMMY_USERID} from '../../store/initialStates'; + +/**r * Profile Screen for a user's profile * including posts, messaging, and settings */ @@ -17,45 +21,37 @@ interface ProfileOnboardingProps { } const ProfileScreen: React.FC<ProfileOnboardingProps> = ({route}) => { - const {isProfileView, username, userId} = route.params; + const {screenType} = route.params; + let {userXId} = route.params; const y = Animated.useValue(0); - const {updateIsEditedProfile} = useContext(AuthContext); - - useEffect(() => { - updateIsEditedProfile(false); - }); + const dispatch = useDispatch(); - const profileView = () => { - return ( - <> - <StatusBar /> - <Cover {...{y, isProfileView}} /> - <Content {...{y, isProfileView}} /> - <TabsGradient /> - </> - ); - }; + /** + * This is a double safety check to avoid app crash. + * Checks if the required userXId is present in the store, if not userXId is set to dummy id + */ + if (userXId && !(userXId in useStore().getState().userX[screenType])) { + userXId = DUMMY_USERID; + } /** - * Every profile to have it's own ProfileContext if a profile is being visited by the logged in user. - * Pass userid and username of the user whose profile needs to be viewed and the information gets loaded to the ProfileContext. - * Now this profile context is local to every user being viewed. - * This comes with BENEFITS and CAVEATS - * BENEFITS : - * 1 - The app now remembers which user was visited last. - * 2 - The Search and Profile stacks (and potentially more stacks in the future) now have totally unrelated stacks of profiles being visited. - * 3 - This will help us manage the navigation stack better if we introduce a feature to go back to the last profile visited. - * CAVEATS : - * 1 - Since the ProfileContext is not global, whenever we navigate to some component that is not in the child tree of the ProfileProvider, we would not be able to use anything in the context (It would basically have default values). - * 2 - For example, the followers list (FollowersListScreen) and profile picture on the Taggs screen (AvatarTile) now no longer have access to the ProfileContext. - * 3 - Components like these now have to have data passed in via props, instead of using the context. + * Code under useFocusEffect gets executed every time the screen comes under focus / is being viewed by the user. + * This is done to reset the users stored in our store for the Search screen. + * Read more about useFocusEffect here : https://reactnavigation.org/docs/function-after-focusing-screen/ */ - return isProfileView ? ( - <ProfileProvider uId={userId} uname={username}> - {profileView()} - </ProfileProvider> - ) : ( - profileView() + useFocusEffect(() => { + if (!userXId) { + dispatch(resetScreenType(screenType)); + } + }); + + return ( + <> + <StatusBar /> + <Cover {...{y, userXId, screenType}} /> + <Content {...{y, userXId, screenType}} /> + <TabsGradient /> + </> ); }; diff --git a/src/screens/profile/SocialMediaTaggs.tsx b/src/screens/profile/SocialMediaTaggs.tsx index d67f3a1a..5634c251 100644 --- a/src/screens/profile/SocialMediaTaggs.tsx +++ b/src/screens/profile/SocialMediaTaggs.tsx @@ -1,7 +1,13 @@ import {RouteProp} from '@react-navigation/native'; import {StackNavigationProp} from '@react-navigation/stack'; -import React, {useEffect} from 'react'; -import {ScrollView, StatusBar, StyleSheet, View} from 'react-native'; +import React, {useEffect, useState} from 'react'; +import { + ActivityIndicator, + ScrollView, + StatusBar, + StyleSheet, + View, +} from 'react-native'; import LinearGradient from 'react-native-linear-gradient'; import { AvatarTitle, @@ -10,10 +16,13 @@ import { TaggPost, TwitterTaggPost, } from '../../components'; -import {AVATAR_GRADIENT} from '../../constants'; +import {AVATAR_GRADIENT, TAGG_DARK_BLUE} from '../../constants'; import {ProfileStackParams} from '../../routes'; -import {SimplePostType, TwitterPostType} from '../../types'; +import {SimplePostType, TwitterPostType, SocialAccountType} from '../../types'; import {AvatarHeaderHeight, SCREEN_HEIGHT} from '../../utils'; +import {useSelector} from 'react-redux'; +import {RootState} from '../../store/rootReducer'; +import TaggLoadingIndicator from '../../components/common/TaggLoadingIndicator'; type SocialMediaTaggsRouteProp = RouteProp< ProfileStackParams, @@ -34,12 +43,27 @@ const SocialMediaTaggs: React.FC<SocialMediaTaggsProps> = ({ route, navigation, }) => { + const [accountData, setAccountData] = useState<SocialAccountType>({ + posts: [], + }); + const {socialMediaType, userXId, screenType} = route.params; + const { + avatar, + profile: {name}, + } = userXId + ? useSelector((state: RootState) => state.userX[screenType][userXId]) + : useSelector((state: RootState) => state.user); + + const {socialAccounts} = userXId + ? useSelector((state: RootState) => state.userX[screenType][userXId]) + : useSelector((state: RootState) => state.socialAccounts); - /** - * Since access to the loaded context is lost, we need the previous screen to pass in a whole lot of data to this screen. - * This calls for a better state management system such as Redux which allows to have a central repo for the app state. - */ - const {socialMediaType, name, accountData, avatar} = route.params; + useEffect(() => { + const currentSocialData = {...socialAccounts[socialMediaType]}; + if (currentSocialData) { + setAccountData(currentSocialData); + } + }, [socialAccounts, setAccountData]); useEffect(() => { navigation.setOptions({ @@ -58,33 +82,37 @@ const SocialMediaTaggs: React.FC<SocialMediaTaggsProps> = ({ colors={[AVATAR_GRADIENT.start, AVATAR_GRADIENT.end]}> <StatusBar barStyle={'light-content'} /> {/* Cropping the scroll view to mimic the presence of a header while preserving the gradient background */} - <View - // we want a slightly bigger header here for the avatar image - style={[styles.flex, {marginTop: AvatarHeaderHeight}]}> - <ScrollView - showsVerticalScrollIndicator={false} - contentContainerStyle={styles.contentContainer}> - <SocialMediaInfo - fullname={name} - type={socialMediaType} - handle={accountData?.handle} - /> - {(accountData?.posts as Array< - SimplePostType | TwitterPostType - >).map((post, index) => - socialMediaType === 'Twitter' ? ( - <TwitterTaggPost - key={index} - ownerHandle={accountData?.handle || '_'} - post={post as TwitterPostType} - /> - ) : ( - <TaggPost key={index} post={post as SimplePostType} /> - ), - )} - </ScrollView> - <TabsGradient /> - </View> + {accountData?.posts && accountData.posts.length > 0 ? ( + <View + // we want a slightly bigger header here for the avatar image + style={[styles.flex, {marginTop: AvatarHeaderHeight}]}> + <ScrollView + showsVerticalScrollIndicator={false} + contentContainerStyle={styles.contentContainer}> + <SocialMediaInfo + fullname={name} + type={socialMediaType} + handle={accountData?.handle} + /> + {(accountData?.posts as Array< + SimplePostType | TwitterPostType + >).map((post, index) => + socialMediaType === 'Twitter' ? ( + <TwitterTaggPost + key={index} + ownerHandle={accountData?.handle || '_'} + post={post as TwitterPostType} + /> + ) : ( + <TaggPost key={index} post={post as SimplePostType} /> + ), + )} + </ScrollView> + <TabsGradient /> + </View> + ) : ( + <TaggLoadingIndicator color="white" /> + )} </LinearGradient> ); }; diff --git a/src/screens/search/SearchScreen.tsx b/src/screens/search/SearchScreen.tsx index 535b964c..b11f6a1a 100644 --- a/src/screens/search/SearchScreen.tsx +++ b/src/screens/search/SearchScreen.tsx @@ -13,21 +13,27 @@ import { TabsGradient, } from '../../components'; import {SEARCH_ENDPOINT, TAGG_TEXT_LIGHT_BLUE} from '../../constants'; -import {AuthContext} from '../../routes/authentication'; -import {ProfilePreviewType, UserType} from '../../types'; +import {ProfilePreviewType, ScreenType, UserType} from '../../types'; import {SCREEN_HEIGHT, SCREEN_WIDTH, StatusBarHeight} from '../../utils'; const NO_USER: UserType = { userId: '', username: '', }; +import {RootState} from '../../store/rootReducer'; +import {useSelector, useDispatch} from 'react-redux'; +import {resetScreenType} from '../../store/actions'; +import {useFocusEffect} from '@react-navigation/native'; + /** * Search Screen for user recommendations and a search * tool to allow user to find other users */ const SearchScreen: React.FC = () => { - const {recentSearches, taggUsers} = React.useContext(AuthContext); + const {recentSearches, taggUsers} = useSelector( + (state: RootState) => state.taggUsers, + ); const [query, setQuery] = useState<string>(''); const [results, setResults] = useState<Array<ProfilePreviewType>>([]); const [recents, setRecents] = useState<Array<ProfilePreviewType>>( @@ -36,6 +42,7 @@ const SearchScreen: React.FC = () => { const [searching, setSearching] = useState(false); const top = Animated.useValue(-SCREEN_HEIGHT); const [user, setUser] = useState<UserType>(NO_USER); + useEffect(() => { if (query.length < 3) { setResults([]); @@ -69,6 +76,17 @@ const SearchScreen: React.FC = () => { loadResults(query); }, [query]); + const dispatch = useDispatch(); + + /** + * Code under useFocusEffect gets executed every time the screen comes under focus / is being viewed by the user. + * This is done to reset the users stored in our store for the Search screen. + * Read more here : https://reactnavigation.org/docs/function-after-focusing-screen/ + */ + useFocusEffect(() => { + dispatch(resetScreenType(ScreenType.Search)); + }); + const handleFocus = () => { const topInConfig = { duration: 180, @@ -130,7 +148,11 @@ const SearchScreen: React.FC = () => { /> {/* Removed for Alpha for now */} {/* <Explore /> */} - <DiscoverUsers sectionTitle="Discover Users" users={taggUsers} /> + <DiscoverUsers + sectionTitle="Discover Users" + users={taggUsers} + screenType={ScreenType.Search} + /> <SearchResultsBackground {...{top}}> {results.length === 0 && recents.length !== 0 ? ( <RecentSearches @@ -138,9 +160,14 @@ const SearchScreen: React.FC = () => { sectionButtonTitle="Clear all" onPress={clearRecentlySearched} recents={recents} + screenType={ScreenType.Search} /> ) : ( - <SearchResults {...{results}} previewType={'Search'} /> + <SearchResults + {...{results}} + previewType={'Search'} + screenType={ScreenType.Search} + /> )} </SearchResultsBackground> </ScrollView> |