aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIvan Chen <ivan@thetaggid.com>2021-02-11 17:27:30 -0500
committerGitHub <noreply@github.com>2021-02-11 17:27:30 -0500
commitd494b27509066f4d1b61078f1fe6457f20d5f449 (patch)
tree2418b7e9ff40fbb6d51124644065ead0a6f24e8b /src
parent2561d20e17a697726d6b77accf79c9da2d1f6ef6 (diff)
parenteeac3efd296656a0ef0a1e5797fec7c9955c7a12 (diff)
Merge pull request #239 from shravyaramesh/tma641-animation-tutorial
[TMA-641] Suggested People: Swipe Up Animation Tutorial
Diffstat (limited to 'src')
-rw-r--r--src/assets/gifs/swipe-animation.gifbin0 -> 160536 bytes
-rw-r--r--src/routes/main/MainStackNavigator.tsx3
-rw-r--r--src/routes/main/MainStackScreen.tsx37
-rw-r--r--src/screens/suggestedPeople/AnimatedTutorial.tsx92
-rw-r--r--src/screens/suggestedPeople/SuggestedPeopleScreen.tsx40
-rw-r--r--src/screens/suggestedPeople/index.ts1
-rw-r--r--src/services/UserProfileService.ts33
-rw-r--r--src/store/actions/user.ts29
-rw-r--r--src/store/initialStates.ts1
-rw-r--r--src/store/reducers/userReducer.ts7
-rw-r--r--src/types/types.ts1
11 files changed, 229 insertions, 15 deletions
diff --git a/src/assets/gifs/swipe-animation.gif b/src/assets/gifs/swipe-animation.gif
new file mode 100644
index 00000000..b3b203d0
--- /dev/null
+++ b/src/assets/gifs/swipe-animation.gif
Binary files differ
diff --git a/src/routes/main/MainStackNavigator.tsx b/src/routes/main/MainStackNavigator.tsx
index f3aa7fc6..9771c1e6 100644
--- a/src/routes/main/MainStackNavigator.tsx
+++ b/src/routes/main/MainStackNavigator.tsx
@@ -66,6 +66,9 @@ export type MainStackParams = {
screenType: ScreenType;
momentCategory: string;
};
+ AnimatedTutorial: {
+ screenType: ScreenType;
+ };
};
export const MainStack = createStackNavigator<MainStackParams>();
diff --git a/src/routes/main/MainStackScreen.tsx b/src/routes/main/MainStackScreen.tsx
index 99446432..0b762dff 100644
--- a/src/routes/main/MainStackScreen.tsx
+++ b/src/routes/main/MainStackScreen.tsx
@@ -6,6 +6,7 @@ import {StyleSheet, Text} from 'react-native';
import {normalize} from 'react-native-elements';
import BackIcon from '../../assets/icons/back-arrow.svg';
import {
+ AnimatedTutorial,
CaptionScreen,
CategorySelection,
CreateCustomCategory,
@@ -70,6 +71,34 @@ const MainStackScreen: React.FC<MainStackProps> = ({route}) => {
}
})();
+ const modalStyle: StackNavigationOptions = {
+ cardStyle: {backgroundColor: 'rgba(80,80,80,0.9)'},
+ gestureDirection: 'vertical',
+ cardOverlayEnabled: true,
+ cardStyleInterpolator: ({current: {progress}}) => ({
+ cardStyle: {
+ opacity: progress.interpolate({
+ inputRange: [0, 0.5, 0.9, 1],
+ outputRange: [0, 0.25, 0.7, 1],
+ }),
+ },
+ }),
+ };
+
+ const tutorialModalStyle: StackNavigationOptions = {
+ cardStyle: {backgroundColor: 'rgba(0, 0, 0, 0.5)'},
+ gestureDirection: 'vertical',
+ cardOverlayEnabled: true,
+ cardStyleInterpolator: ({current: {progress}}) => ({
+ cardStyle: {
+ opacity: progress.interpolate({
+ inputRange: [0, 0.5, 0.9, 1],
+ outputRange: [0, 0.25, 0.7, 1],
+ }),
+ },
+ }),
+ };
+
return (
<MainStack.Navigator
screenOptions={{
@@ -115,6 +144,14 @@ const MainStackScreen: React.FC<MainStackProps> = ({route}) => {
/>
)}
<MainStack.Screen
+ name="AnimatedTutorial"
+ component={AnimatedTutorial}
+ options={{
+ ...tutorialModalStyle,
+ }}
+ initialParams={{screenType}}
+ />
+ <MainStack.Screen
name="CaptionScreen"
component={CaptionScreen}
options={{
diff --git a/src/screens/suggestedPeople/AnimatedTutorial.tsx b/src/screens/suggestedPeople/AnimatedTutorial.tsx
new file mode 100644
index 00000000..8ebdaea6
--- /dev/null
+++ b/src/screens/suggestedPeople/AnimatedTutorial.tsx
@@ -0,0 +1,92 @@
+import * as React from 'react';
+import CloseIcon from '../../assets/ionicons/close-outline.svg';
+import {StyleSheet, Text, View} from 'react-native';
+import {Image} from 'react-native-animatable';
+import {isIPhoneX, SCREEN_WIDTH} from '../../utils';
+import {SafeAreaView} from 'react-native-safe-area-context';
+import {useNavigation} from '@react-navigation/native';
+import {useDispatch, useSelector} from 'react-redux';
+import {RootState} from '../../store/rootReducer';
+import {updateSPSwipeTutorial} from '../../store/actions/user';
+
+const AnimatedTutorial: React.FC = () => {
+ const navigation = useNavigation();
+ const dispatch = useDispatch();
+ const {user} = useSelector((state: RootState) => state.user);
+
+ const handleCloseAnimationTutorial = async () => {
+ /* In user's store, check if profile.sp_swipe_tutorial === 0
+ * Make call to edit profile endpoint with suggested people === 1
+ */
+ const data = 1;
+ dispatch(updateSPSwipeTutorial(user, data));
+ navigation.pop();
+ };
+ return (
+ <SafeAreaView>
+ <View style={styles.container}>
+ <CloseIcon
+ height={'10%'}
+ width={'10%'}
+ color={'white'}
+ style={styles.closeButton}
+ onPress={handleCloseAnimationTutorial}
+ />
+ <View style={styles.textContainer}>
+ <Text style={styles.text}>{'Swipe up to discover more people!'}</Text>
+ </View>
+ <Image
+ source={require('../../assets/gifs/swipe-animation.gif')}
+ style={styles.swipeGif}
+ />
+ </View>
+ </SafeAreaView>
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flexDirection: 'column',
+ },
+ closeButton: {
+ top: '2.55%',
+ left: '5%',
+ },
+ text: {
+ justifyContent: 'center',
+ color: '#fff',
+ fontWeight: 'bold',
+ fontSize: 20,
+ textAlign: 'center',
+ position: 'relative',
+ top: '100%',
+ },
+ textContainer: {
+ width: isIPhoneX() ? SCREEN_WIDTH * 0.5 : SCREEN_WIDTH * 0.6,
+ alignSelf: 'center',
+ top: isIPhoneX() ? '65%' : '45%',
+ },
+ swipeGif: {
+ width: 333,
+ height: 250,
+ left: '22.5%',
+ top: isIPhoneX() ? '75%' : '45%',
+ },
+
+ //Styles to adjust moment container
+ momentScrollContainer: {
+ backgroundColor: 'transparent',
+ },
+ momentContainer: {
+ top: '62%',
+ backgroundColor: 'transparent',
+ },
+ momentHeaderText: {
+ paddingBottom: '5%',
+ },
+ momentHeader: {
+ backgroundColor: 'transparent',
+ },
+});
+
+export default AnimatedTutorial;
diff --git a/src/screens/suggestedPeople/SuggestedPeopleScreen.tsx b/src/screens/suggestedPeople/SuggestedPeopleScreen.tsx
index fffaf715..4d0a9bd5 100644
--- a/src/screens/suggestedPeople/SuggestedPeopleScreen.tsx
+++ b/src/screens/suggestedPeople/SuggestedPeopleScreen.tsx
@@ -1,4 +1,4 @@
-import React, { useEffect } from 'react';
+import React, {useCallback} from 'react';
import {
StatusBar,
StyleSheet,
@@ -7,20 +7,15 @@ import {
View,
} from 'react-native';
import {Image} from 'react-native-animatable';
-import {
- fetchUserX,
- isIPhoneX,
- SCREEN_HEIGHT,
- SCREEN_WIDTH,
- userXInStore,
-} from '../../utils';
+import {isIPhoneX, SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils';
import {TabsGradient, TaggsBar} from '../../components';
import {SafeAreaView} from 'react-native-safe-area-context';
import {normalize} from '../../utils';
import Animated from 'react-native-reanimated';
import {ScreenType} from '../../types';
-import {useDispatch, useStore} from 'react-redux';
+import {useSelector} from 'react-redux';
import {RootState} from '../../store/rootReducer';
+import {useFocusEffect, useNavigation} from '@react-navigation/native';
/**
* Bare bones for suggested people consisting of:
@@ -33,6 +28,25 @@ const SuggestedPeopleScreen: React.FC = () => {
// Adviced to maintain username as a variable here to append @ symbol for maintainability
const username = '@' + 'sarahmiller';
+ const navigation = useNavigation();
+ const screenType = ScreenType.SuggestedPeople;
+ const {
+ profile: {sp_swipe_tutorial},
+ } = useSelector((state: RootState) => state.user);
+
+ useFocusEffect(
+ useCallback(() => {
+ const navigateToAnimatedTutorial = () => {
+ /* In user's store, check if profile.sp_swipe_tutorial === 0
+ * If, true show tutorial.
+ */
+ if (sp_swipe_tutorial === 0) {
+ navigation.navigate('AnimatedTutorial');
+ }
+ };
+ navigateToAnimatedTutorial();
+ }, [sp_swipe_tutorial, navigation]),
+ );
return (
<>
@@ -46,7 +60,7 @@ const SuggestedPeopleScreen: React.FC = () => {
<View style={styles.mainContainer}>
<Text style={styles.title}>Suggested People</Text>
<View style={styles.body}>
- {/* Added first row contaning name, username, add button (w/o functionality) */}
+ {/* First row contaning name, username, add button (w/o functionality) */}
<View style={styles.addUserContainer}>
<View style={styles.nameInfoContainer}>
<Text style={styles.firstName}>{firstName}</Text>
@@ -54,18 +68,20 @@ const SuggestedPeopleScreen: React.FC = () => {
</View>
<TouchableOpacity
activeOpacity={0.5}
+ // TODO: Call function to Add Friend
onPress={() => console.log('Call add friend function')}>
<View style={styles.addButton}>
<Text style={styles.addButtonTitle}>{'Add Friend'}</Text>
</View>
</TouchableOpacity>
</View>
- {/* TODO: Add TaggsBar here */}
+ {/* Taggs Bar. Displays only linked profiles for user while viewing their own profile. */}
<TaggsBar
y={Animated.useValue(0)}
+ // :: For testing purposes, to view user's own profile, pass userXId=''
userXId={''}
profileBodyHeight={0}
- screenType={ScreenType.SuggestedPeople}
+ screenType={screenType}
/>
{/* TODO: Add MutualFriends here */}
</View>
diff --git a/src/screens/suggestedPeople/index.ts b/src/screens/suggestedPeople/index.ts
index a42d9c52..8c06d81e 100644
--- a/src/screens/suggestedPeople/index.ts
+++ b/src/screens/suggestedPeople/index.ts
@@ -1 +1,2 @@
export {default as SuggestedPeopleScreen} from './SuggestedPeopleScreen';
+export {default as AnimatedTutorial} from './AnimatedTutorial';
diff --git a/src/services/UserProfileService.ts b/src/services/UserProfileService.ts
index d0610714..3bca66f3 100644
--- a/src/services/UserProfileService.ts
+++ b/src/services/UserProfileService.ts
@@ -2,7 +2,7 @@ import AsyncStorage from '@react-native-community/async-storage';
import moment from 'moment';
import {Alert} from 'react-native';
import RNFetchBlob from 'rn-fetch-blob';
-import {SocialAccountType} from '../types';
+import {SocialAccountType, UserType} from '../types';
import {
PROFILE_PHOTO_ENDPOINT,
HEADER_PHOTO_ENDPOINT,
@@ -15,6 +15,7 @@ import {
VERIFY_OTP_ENDPOINT,
SEND_OTP_ENDPOINT,
PROFILE_PHOTO_THUMBNAIL_ENDPOINT,
+ EDIT_PROFILE_ENDPOINT,
} from '../constants';
import {
ERROR_DOUBLE_CHECK_CONNECTION,
@@ -49,10 +50,15 @@ export const loadProfileInfo = async (token: string, userId: string) => {
tiktok,
university_class,
profile_completion_stage,
+ sp_swipe_tutorial,
friendship_status,
friendship_requester_id,
} = info;
birthday = birthday && moment(birthday).format('YYYY-MM-DD');
+ console.log(
+ 'Suggested People loaded from backend for logged in user: ',
+ sp_swipe_tutorial,
+ );
return {
name,
biography,
@@ -63,6 +69,7 @@ export const loadProfileInfo = async (token: string, userId: string) => {
tiktok,
university_class,
profile_completion_stage,
+ sp_swipe_tutorial,
friendship_status,
friendship_requester_id,
};
@@ -313,3 +320,27 @@ export const sendOtp = async (phone: string) => {
return false;
}
};
+
+export const editSPSwipeTutorial = async (user: UserType) => {
+ try {
+ const request = new FormData();
+ request.append('sp_swipe_tutorial', 1);
+ const endpoint = EDIT_PROFILE_ENDPOINT + `${user.userId}/`;
+ const token = await AsyncStorage.getItem('token');
+ let response = await fetch(endpoint, {
+ method: 'PATCH',
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ Authorization: 'Token ' + token,
+ },
+ body: request,
+ });
+ if (response.status === 200) {
+ return true;
+ } else {
+ return false;
+ }
+ } catch (error) {
+ console.log('Error updating animated tutorial close button press');
+ }
+};
diff --git a/src/store/actions/user.ts b/src/store/actions/user.ts
index 589e6f0d..990f9260 100644
--- a/src/store/actions/user.ts
+++ b/src/store/actions/user.ts
@@ -1,5 +1,10 @@
import {Action, ThunkAction} from '@reduxjs/toolkit';
-import {loadAvatar, loadCover, loadProfileInfo} from '../../services';
+import {
+ editSPSwipeTutorial,
+ loadAvatar,
+ loadCover,
+ loadProfileInfo,
+} from '../../services';
import {UserType} from '../../types/types';
import {getTokenOrLogout} from '../../utils';
import {
@@ -12,6 +17,7 @@ import {
userDetailsFetched,
userLoggedIn,
} from '../reducers';
+import {spSwipeTutorialUpdated} from '../reducers/userReducer';
import {RootState} from '../rootReducer';
import {CommentThreadType} from './../../types/types';
@@ -156,3 +162,24 @@ export const logout = (): ThunkAction<
console.log(error);
}
};
+
+export const updateSPSwipeTutorial = (
+ user: UserType,
+ data: number,
+): ThunkAction<
+ Promise<boolean | undefined>,
+ RootState,
+ unknown,
+ Action<string>
+> => async (dispatch) => {
+ try {
+ // update store first, assume success
+ dispatch({
+ type: spSwipeTutorialUpdated.type,
+ payload: {sp_swipe_tutorial: data},
+ });
+ return await editSPSwipeTutorial(user);
+ } catch (error) {
+ console.log('Error while updating suggested people linked state: ', error);
+ }
+};
diff --git a/src/store/initialStates.ts b/src/store/initialStates.ts
index 6ca133e0..93b1bc6e 100644
--- a/src/store/initialStates.ts
+++ b/src/store/initialStates.ts
@@ -21,6 +21,7 @@ export const NO_PROFILE: ProfileType = {
//Default to an invalid value and ignore it gracefully while showing tutorials / popups.
profile_completion_stage: -1,
+ sp_swipe_tutorial: 0,
snapchat: '',
tiktok: '',
friendship_status: 'no_record',
diff --git a/src/store/reducers/userReducer.ts b/src/store/reducers/userReducer.ts
index 29ec38cc..773977db 100644
--- a/src/store/reducers/userReducer.ts
+++ b/src/store/reducers/userReducer.ts
@@ -1,4 +1,4 @@
-import {createSlice, Action} from '@reduxjs/toolkit';
+import {createSlice} from '@reduxjs/toolkit';
import {NO_USER_DATA} from '../initialStates';
/**
@@ -46,6 +46,10 @@ const userDataSlice = createSlice({
state.profile.profile_completion_stage = action.payload.stage;
},
+ spSwipeTutorialUpdated: (state, action) => {
+ state.profile.sp_swipe_tutorial = action.payload.sp_swipe_tutorial;
+ },
+
setIsOnboardedUser: (state, action) => {
state.isOnboardedUser = action.payload.isOnboardedUser;
},
@@ -73,5 +77,6 @@ export const {
setNewVersionAvailable,
setNewNotificationReceived,
setReplyPosted,
+ spSwipeTutorialUpdated,
} = userDataSlice.actions;
export const userDataReducer = userDataSlice.reducer;
diff --git a/src/types/types.ts b/src/types/types.ts
index 7fccaa44..fe16fb8e 100644
--- a/src/types/types.ts
+++ b/src/types/types.ts
@@ -23,6 +23,7 @@ export interface ProfileType {
gender: string;
university_class: number;
profile_completion_stage: number;
+ sp_swipe_tutorial: number;
birthday: Date | undefined;
snapchat: string;
tiktok: string;