aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAshm Walia <40498934+ashmgarv@users.noreply.github.com>2020-12-14 16:02:09 -0800
committerGitHub <noreply@github.com>2020-12-14 19:02:09 -0500
commit3b7bf256d83e1898642c2aab9072ffbeec8cc032 (patch)
tree9b48ff57f61414321e2c78124bd6a63101a04602
parent410d9224f4e198ab0b8ecae35fa05c240a2439bf (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>
-rw-r--r--src/components/moments/Moment.tsx2
-rw-r--r--src/components/moments/MomentTile.tsx2
-rw-r--r--src/components/profile/Avatar.tsx2
-rw-r--r--src/components/profile/Content.tsx67
-rw-r--r--src/components/profile/Cover.tsx25
-rw-r--r--src/components/profile/FollowCount.tsx4
-rw-r--r--src/components/profile/ProfileBody.tsx18
-rw-r--r--src/components/profile/ProfileHeader.tsx2
-rw-r--r--src/components/profile/ProfilePreview.tsx11
-rw-r--r--src/components/search/SearchResults.tsx18
-rw-r--r--src/components/taggs/Tagg.tsx2
-rw-r--r--src/components/taggs/TaggsBar.tsx2
-rw-r--r--src/constants/constants.ts3
-rw-r--r--src/routes/profile/Profile.tsx15
-rw-r--r--src/screens/profile/ProfileScreen.tsx6
-rw-r--r--src/utils/users.ts18
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 = (