diff options
author | Ashm Walia <40498934+ashmgarv@users.noreply.github.com> | 2020-12-14 16:02:09 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-14 19:02:09 -0500 |
commit | 3b7bf256d83e1898642c2aab9072ffbeec8cc032 (patch) | |
tree | 9b48ff57f61414321e2c78124bd6a63101a04602 /src | |
parent | 410d9224f4e198ab0b8ecae35fa05c240a2439bf (diff) |
[TMA - 426] Fix recent search + Add refresh control (#138)
* Got rid of small lint errors before start
* Final push
* Final
* disable scroll first try / logic
* small change
* Try to make the cover photo consistent with different screen sizes
* Final change
* added RefreshControl
* removed scale effect
* Fix misorientation of cover
* remove more scale stuff
* fix userIDs for different views
* Mend refresh control
* white bg
Co-authored-by: hsalhab <husam_salhab@brown.edu>
Diffstat (limited to 'src')
-rw-r--r-- | src/components/moments/Moment.tsx | 2 | ||||
-rw-r--r-- | src/components/moments/MomentTile.tsx | 2 | ||||
-rw-r--r-- | src/components/profile/Avatar.tsx | 2 | ||||
-rw-r--r-- | src/components/profile/Content.tsx | 67 | ||||
-rw-r--r-- | src/components/profile/Cover.tsx | 25 | ||||
-rw-r--r-- | src/components/profile/FollowCount.tsx | 4 | ||||
-rw-r--r-- | src/components/profile/ProfileBody.tsx | 18 | ||||
-rw-r--r-- | src/components/profile/ProfileHeader.tsx | 2 | ||||
-rw-r--r-- | src/components/profile/ProfilePreview.tsx | 11 | ||||
-rw-r--r-- | src/components/search/SearchResults.tsx | 18 | ||||
-rw-r--r-- | src/components/taggs/Tagg.tsx | 2 | ||||
-rw-r--r-- | src/components/taggs/TaggsBar.tsx | 2 | ||||
-rw-r--r-- | src/constants/constants.ts | 3 | ||||
-rw-r--r-- | src/routes/profile/Profile.tsx | 15 | ||||
-rw-r--r-- | src/screens/profile/ProfileScreen.tsx | 6 | ||||
-rw-r--r-- | src/utils/users.ts | 18 |
16 files changed, 143 insertions, 54 deletions
diff --git a/src/components/moments/Moment.tsx b/src/components/moments/Moment.tsx index e928f7e0..940b519c 100644 --- a/src/components/moments/Moment.tsx +++ b/src/components/moments/Moment.tsx @@ -15,7 +15,7 @@ import {MomentType, ScreenType} from 'src/types'; interface MomentProps { title: string; images: MomentType[] | undefined; - userXId: string; + userXId: string | undefined; screenType: ScreenType; } diff --git a/src/components/moments/MomentTile.tsx b/src/components/moments/MomentTile.tsx index 05ccfa15..16e91c82 100644 --- a/src/components/moments/MomentTile.tsx +++ b/src/components/moments/MomentTile.tsx @@ -5,7 +5,7 @@ import {MomentType, ScreenType} from 'src/types'; interface MomentTileProps { moment: MomentType; - userXId: string; + userXId: string | undefined; screenType: ScreenType; } const MomentTile: React.FC<MomentTileProps> = ({ diff --git a/src/components/profile/Avatar.tsx b/src/components/profile/Avatar.tsx index 903d0d18..d3c53043 100644 --- a/src/components/profile/Avatar.tsx +++ b/src/components/profile/Avatar.tsx @@ -7,7 +7,7 @@ import {ScreenType} from '../../types'; const PROFILE_DIM = 100; interface AvatarProps { style: object; - userXId: string; + userXId: string | undefined; screenType: ScreenType; } const Avatar: React.FC<AvatarProps> = ({style, screenType, userXId}) => { diff --git a/src/components/profile/Content.tsx b/src/components/profile/Content.tsx index 73f6fad3..f2e0db0a 100644 --- a/src/components/profile/Content.tsx +++ b/src/components/profile/Content.tsx @@ -1,5 +1,12 @@ -import React, {useCallback, useEffect, useState, useContext} from 'react'; -import {LayoutChangeEvent, StyleSheet, View} from 'react-native'; +import React, {useCallback, useEffect, useState} from 'react'; +import { + LayoutChangeEvent, + NativeScrollEvent, + NativeSyntheticEvent, + RefreshControl, + StyleSheet, + View, +} from 'react-native'; import Animated from 'react-native-reanimated'; import { MomentType, @@ -8,8 +15,8 @@ import { ScreenType, UserType, } from '../../types'; -import {defaultMoments} from '../../constants'; -import {SCREEN_HEIGHT} from '../../utils'; +import {COVER_HEIGHT, defaultMoments} from '../../constants'; +import {fetchUserX, SCREEN_HEIGHT, userLogin} from '../../utils'; import TaggsBar from '../taggs/TaggsBar'; import {Moment} from '../moments'; import ProfileBody from './ProfileBody'; @@ -29,10 +36,12 @@ import { EMPTY_PROFILE_PREVIEW_LIST, EMPTY_MOMENTS_LIST, } from '../../store/initialStates'; +import {Cover} from '.'; +import {Background} from '../onboarding'; interface ContentProps { y: Animated.Value<number>; - userXId: string; + userXId: string | undefined; screenType: ScreenType; } @@ -68,6 +77,22 @@ const Content: React.FC<ContentProps> = ({y, userXId, screenType}) => { const [isFollowed, setIsFollowed] = useState<boolean>(false); const [isBlocked, setIsBlocked] = useState<boolean>(false); const [profileBodyHeight, setProfileBodyHeight] = useState(0); + const [shouldBounce, setShouldBounce] = useState<boolean>(true); + const [refreshing, setRefreshing] = useState<boolean>(false); + + const onRefresh = useCallback(() => { + const refrestState = async () => { + if (!userXId) { + await userLogin(dispatch, loggedInUser); + } else { + await fetchUserX(dispatch, user, screenType); + } + }; + setRefreshing(true); + refrestState().then(() => { + setRefreshing(false); + }); + }, []); /** * If own profile is being viewed then do not show the follow button. @@ -169,12 +194,35 @@ const Content: React.FC<ContentProps> = ({y, userXId, screenType}) => { await dispatch(updateUserXFollowersAndFollowing(user.userId, state)); }; + const handleScroll = (e: NativeSyntheticEvent<NativeScrollEvent>) => { + /** + * Set the new y position + */ + const newY = e.nativeEvent.contentOffset.y; + y.setValue(newY); + + /** + * Do not allow overflow of scroll on bottom of the screen + * SCREEN_HEIGHT - COVER_HEIGHT = Height of the scroll view + */ + if (newY >= SCREEN_HEIGHT - COVER_HEIGHT) { + setShouldBounce(false); + } else if (newY === 0) { + setShouldBounce(true); + } + }; + return ( <Animated.ScrollView style={styles.container} - onScroll={(e) => y.setValue(e.nativeEvent.contentOffset.y)} + onScroll={(e) => handleScroll(e)} + bounces={shouldBounce} showsVerticalScrollIndicator={false} - scrollEventThrottle={1}> + scrollEventThrottle={1} + refreshControl={ + <RefreshControl refreshing={refreshing} onRefresh={onRefresh} /> + }> + <Cover {...{userXId, screenType}} /> <ProfileCutout /> <ProfileHeader {...{userXId, screenType}} /> <ProfileBody @@ -206,6 +254,11 @@ const Content: React.FC<ContentProps> = ({y, userXId, screenType}) => { }; const styles = StyleSheet.create({ + refreshControlContainer: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + }, container: { flex: 1, }, diff --git a/src/components/profile/Cover.tsx b/src/components/profile/Cover.tsx index 3c0f7045..a03ef123 100644 --- a/src/components/profile/Cover.tsx +++ b/src/components/profile/Cover.tsx @@ -1,30 +1,21 @@ -import React, {useContext} from 'react'; -import {Image, StyleSheet} from 'react-native'; -import Animated from 'react-native-reanimated'; +import React from 'react'; +import {Image, StyleSheet, View} from 'react-native'; import {IMAGE_WIDTH, COVER_HEIGHT, IMAGE_HEIGHT} from '../../constants'; -import {useSelector, useStore} from 'react-redux'; +import {useSelector} from 'react-redux'; import {RootState} from '../../store/rootreducer'; import {ScreenType} from '../../types'; -import {DUMMY_USERID, NO_USER_DATA} from '../../store/initialStates'; -const {interpolate, Extrapolate} = Animated; interface CoverProps { - y: Animated.Value<number>; - userXId: string; + userXId: string | undefined; screenType: ScreenType; } -const Cover: React.FC<CoverProps> = ({y, userXId, screenType}) => { +const Cover: React.FC<CoverProps> = ({userXId, screenType}) => { const {cover = ''} = userXId ? useSelector((state: RootState) => state.userX[screenType][userXId]) : useSelector((state: RootState) => state.user); - const scale: Animated.Node<number> = interpolate(y, { - inputRange: [-COVER_HEIGHT, 0], - outputRange: [1.5, 1.25], - extrapolateRight: Extrapolate.CLAMP, - }); return ( - <Animated.View style={[styles.container, {transform: [{scale}]}]}> + <View style={[styles.container]}> <Image style={styles.image} source={ @@ -33,7 +24,7 @@ const Cover: React.FC<CoverProps> = ({y, userXId, screenType}) => { : require('../../assets/images/cover-placeholder.png') } /> - </Animated.View> + </View> ); }; @@ -43,7 +34,7 @@ const styles = StyleSheet.create({ }, image: { width: IMAGE_WIDTH, - height: IMAGE_HEIGHT, + height: COVER_HEIGHT, }, }); export default Cover; diff --git a/src/components/profile/FollowCount.tsx b/src/components/profile/FollowCount.tsx index a23a3533..95b953dc 100644 --- a/src/components/profile/FollowCount.tsx +++ b/src/components/profile/FollowCount.tsx @@ -1,4 +1,4 @@ -import React, {useContext} from 'react'; +import React from 'react'; import {View, Text, StyleSheet, ViewProps} from 'react-native'; import {TouchableOpacity} from 'react-native-gesture-handler'; import {useNavigation} from '@react-navigation/native'; @@ -9,7 +9,7 @@ import {EMPTY_PROFILE_PREVIEW_LIST} from '../../store/initialStates'; interface FollowCountProps extends ViewProps { mode: 'followers' | 'following'; - userXId: string; + userXId: string | undefined; screenType: ScreenType; } diff --git a/src/components/profile/ProfileBody.tsx b/src/components/profile/ProfileBody.tsx index 57800578..49ee74ee 100644 --- a/src/components/profile/ProfileBody.tsx +++ b/src/components/profile/ProfileBody.tsx @@ -14,7 +14,7 @@ interface ProfileBodyProps { isOwnProfile: boolean; handleFollowUnfollow: Function; handleBlockUnblock: Function; - userXId: string; + userXId: string | undefined; screenType: ScreenType; } const ProfileBody: React.FC<ProfileBodyProps> = ({ @@ -33,7 +33,7 @@ const ProfileBody: React.FC<ProfileBodyProps> = ({ } = userXId ? useSelector((state: RootState) => state.userX[screenType][userXId]) : useSelector((state: RootState) => state.user); - + const {biography, website} = profile; return ( <View onLayout={onLayout} style={styles.container}> @@ -41,11 +41,15 @@ const ProfileBody: React.FC<ProfileBodyProps> = ({ {biography.length > 0 && ( <Text style={styles.biography}>{`${biography}`}</Text> )} - {website.length > 0 && <Text style={styles.website} onPress={() => { - Linking.openURL( - website.startsWith('http') ? website : 'http://' + website, - ); - }}>{`${website}`}</Text>} + {website.length > 0 && ( + <Text + style={styles.website} + onPress={() => { + Linking.openURL( + website.startsWith('http') ? website : 'http://' + website, + ); + }}>{`${website}`}</Text> + )} {userXId && !isOwnProfile ? ( <View style={styles.toggleButtonContainer}> {!isBlocked && ( diff --git a/src/components/profile/ProfileHeader.tsx b/src/components/profile/ProfileHeader.tsx index b622510e..0eb2d469 100644 --- a/src/components/profile/ProfileHeader.tsx +++ b/src/components/profile/ProfileHeader.tsx @@ -9,7 +9,7 @@ import FollowCount from './FollowCount'; import ProfileMoreInfoDrawer from './ProfileMoreInfoDrawer'; type ProfileHeaderProps = { - userXId: string; + userXId: string | undefined; screenType: ScreenType; }; diff --git a/src/components/profile/ProfilePreview.tsx b/src/components/profile/ProfilePreview.tsx index 93d1f415..9dd03c54 100644 --- a/src/components/profile/ProfilePreview.tsx +++ b/src/components/profile/ProfilePreview.tsx @@ -17,8 +17,8 @@ import {UserType, PreviewType} from '../../types'; import {isUserBlocked} from '../../services'; import {useSelector, useDispatch, useStore} from 'react-redux'; import {RootState} from '../../store/rootreducer'; -import {loadUserX, logout} from '../../store/actions'; -import {userXInStore} from '../../utils'; +import {logout} from '../../store/actions'; +import {fetchUserX, userXInStore} from '../../utils'; const NO_USER: UserType = { userId: '', username: '', @@ -157,8 +157,10 @@ const ProfilePreview: React.FC<ProfilePreviewProps> = ({ * Finally, Navigate to profile of the user selected */ if (!userXInStore(state, screenType, user.id)) { - dispatch( - loadUserX({userId: user.id, username: user.username}, screenType), + await fetchUserX( + dispatch, + {userId: user.id, username: user.username}, + screenType, ); } navigation.push('Profile', { @@ -244,7 +246,6 @@ const ProfilePreview: React.FC<ProfilePreviewProps> = ({ )} {previewType === 'Discover Users' && ( <> - <Text style={nameStyle}>{first_name.concat(' ', last_name)}</Text> <Text style={usernameStyle}>{usernameToDisplay}</Text> </> )} diff --git a/src/components/search/SearchResults.tsx b/src/components/search/SearchResults.tsx index 001c7968..9d95593a 100644 --- a/src/components/search/SearchResults.tsx +++ b/src/components/search/SearchResults.tsx @@ -12,8 +12,23 @@ const SearchResults: React.FC<SearchResultsProps> = ({ previewType, screenType, }) => { + /** + * Added the following swicth case to make Results on Search and Recents screen a list + * Flex is love + */ + var containerStyle; + switch (previewType) { + case 'Search': + containerStyle = styles.containerSearch; + break; + case 'Recent': + containerStyle = styles.containerSearch; + break; + default: + containerStyle = styles.container; + } return ( - <View style={styles.container}> + <View style={containerStyle}> {results.map((profilePreview) => ( <ProfilePreview style={styles.result} @@ -28,6 +43,7 @@ const SearchResults: React.FC<SearchResultsProps> = ({ }; const styles = StyleSheet.create({ + containerSearch: {flexDirection: 'column', flexWrap: 'wrap'}, container: {flexDirection: 'row', flexWrap: 'wrap'}, result: { marginVertical: 10, diff --git a/src/components/taggs/Tagg.tsx b/src/components/taggs/Tagg.tsx index 4c8f8226..12172df9 100644 --- a/src/components/taggs/Tagg.tsx +++ b/src/components/taggs/Tagg.tsx @@ -24,7 +24,7 @@ interface TaggProps { isIntegrated: boolean; setTaggsNeedUpdate: (_: boolean) => void; setSocialDataNeedUpdate: (social: string, username: string) => void; - userXId: string; + userXId: string | undefined; user: UserType; } diff --git a/src/components/taggs/TaggsBar.tsx b/src/components/taggs/TaggsBar.tsx index 68061e03..795797ef 100644 --- a/src/components/taggs/TaggsBar.tsx +++ b/src/components/taggs/TaggsBar.tsx @@ -17,7 +17,7 @@ const {View, ScrollView, interpolate, Extrapolate} = Animated; interface TaggsBarProps { y: Animated.Value<number>; profileBodyHeight: number; - userXId: string; + userXId: string | undefined; screenType: ScreenType; } const TaggsBar: React.FC<TaggsBarProps> = ({ diff --git a/src/constants/constants.ts b/src/constants/constants.ts index 8832cec3..3fed8fe6 100644 --- a/src/constants/constants.ts +++ b/src/constants/constants.ts @@ -11,7 +11,7 @@ export const PROFILE_CUTOUT_CORNER_Y = SCREEN_HEIGHT / 1.95; export const IMAGE_WIDTH = SCREEN_WIDTH; export const IMAGE_HEIGHT = SCREEN_WIDTH; -export const COVER_HEIGHT = SCREEN_WIDTH * (7 / 5); +export const COVER_HEIGHT = SCREEN_HEIGHT * 0.55; export const AVATAR_DIM = 44; export const AVATAR_GRADIENT_DIM = 50; @@ -102,4 +102,3 @@ export const BROWSABLE_SOCIAL_URLS: Record<string, string> = { Instagram: 'https://instagram.com/', Twitter: 'https://twitter.com/', }; - diff --git a/src/routes/profile/Profile.tsx b/src/routes/profile/Profile.tsx index f47d25c4..3cb928e5 100644 --- a/src/routes/profile/Profile.tsx +++ b/src/routes/profile/Profile.tsx @@ -41,7 +41,7 @@ const Profile: React.FC<ProfileStackProps> = ({route}) => { <ProfileStack.Navigator screenOptions={{ headerShown: false, - cardStyle: {backgroundColor: 'transparent'}, + cardStyle: {backgroundColor: 'white'}, cardOverlayEnabled: true, cardStyleInterpolator: ({current: {progress}}) => ({ cardStyle: { @@ -98,18 +98,27 @@ const Profile: React.FC<ProfileStackProps> = ({route}) => { <ProfileStack.Screen name="IndividualMoment" component={IndividualMoment} - options={{headerShown: false}} + options={{ + headerShown: false, + cardStyle: {backgroundColor: 'transparent'}, + }} initialParams={{screenType}} /> <ProfileStack.Screen name="MomentCommentsScreen" component={MomentCommentsScreen} - options={{headerShown: false}} + options={{ + headerShown: false, + cardStyle: {backgroundColor: 'transparent'}, + }} initialParams={{screenType}} /> <ProfileStack.Screen name="FollowersListScreen" component={FollowersListScreen} + options={{ + cardStyle: {backgroundColor: 'transparent'}, + }} initialParams={{screenType}} /> <ProfileStack.Screen diff --git a/src/screens/profile/ProfileScreen.tsx b/src/screens/profile/ProfileScreen.tsx index a2a1b5bd..1b9a1049 100644 --- a/src/screens/profile/ProfileScreen.tsx +++ b/src/screens/profile/ProfileScreen.tsx @@ -1,12 +1,11 @@ -import React, {useContext, useEffect, useState} from 'react'; +import React from 'react'; import {StatusBar} from 'react-native'; import Animated from 'react-native-reanimated'; import {Content, Cover, TabsGradient} from '../../components'; import {RouteProp, useFocusEffect} from '@react-navigation/native'; -import {ProfileStackParams, ProfileProvider} from '../../routes/'; +import {ProfileStackParams} from '../../routes/'; import {resetScreenType} from '../../store/actions'; import {useDispatch, useStore} from 'react-redux'; -import {ScreenType} from '../../types'; import {DUMMY_USERID} from '../../store/initialStates'; /**r @@ -48,7 +47,6 @@ const ProfileScreen: React.FC<ProfileOnboardingProps> = ({route}) => { return ( <> <StatusBar /> - <Cover {...{y, userXId, screenType}} /> <Content {...{y, userXId, screenType}} /> <TabsGradient /> </> diff --git a/src/utils/users.ts b/src/utils/users.ts index 30b9d77b..0ed490c7 100644 --- a/src/utils/users.ts +++ b/src/utils/users.ts @@ -1,3 +1,4 @@ +import {loadUserX} from './../store/actions/userX'; import {RootState} from './../store/rootReducer'; import AsyncStorage from '@react-native-community/async-storage'; import {AppDispatch} from './../store/configureStore'; @@ -54,6 +55,23 @@ export const userLogin = async (dispatch: AppDispatch, user: UserType) => { }; /** + * This tries to load data userX passed in + * @param dispatch This is the dispatch object from the redux store + * @param user The user + */ +export const fetchUserX = async ( + dispatch: AppDispatch, + user: UserType, + screenType: ScreenType, +) => { + try { + await Promise.all([dispatch(loadUserX(user, screenType))]); + } catch (error) { + console.log(error); + } +}; + +/** * This function checks if the userX slice of our store contains the given user for the provided Screen */ export const userXInStore = ( |