aboutsummaryrefslogtreecommitdiff
path: root/src/screens
diff options
context:
space:
mode:
authorIvan Chen <ivan@tagg.id>2021-02-01 16:01:03 -0500
committerIvan Chen <ivan@tagg.id>2021-02-01 16:01:03 -0500
commit8d1013e86cf2d66671c337d49a80da157802ad86 (patch)
tree656b1656068bb6636919359d4faaf7051994ff74 /src/screens
parent951d85348acef13ec7830629205c30ad5f766bee (diff)
parent7a09cc96bf1fe468a612bb44362bbef24fccc773 (diff)
Merge branch 'master' into TMA-546-Onboarding-Page
Diffstat (limited to 'src/screens')
-rw-r--r--src/screens/main/NotificationsScreen.tsx2
-rw-r--r--src/screens/onboarding/RegistrationOne.tsx4
-rw-r--r--src/screens/profile/EditProfile.tsx48
-rw-r--r--src/screens/profile/IndividualMoment.tsx13
-rw-r--r--src/screens/profile/MomentCommentsScreen.tsx167
-rw-r--r--src/screens/profile/MomentUploadPromptScreen.tsx8
-rw-r--r--src/screens/search/SearchScreen.tsx13
7 files changed, 134 insertions, 121 deletions
diff --git a/src/screens/main/NotificationsScreen.tsx b/src/screens/main/NotificationsScreen.tsx
index 4bdee942..d9952aa8 100644
--- a/src/screens/main/NotificationsScreen.tsx
+++ b/src/screens/main/NotificationsScreen.tsx
@@ -70,7 +70,7 @@ const NotificationsScreen: React.FC = () => {
//Called when user leaves the screen
return () => resetNewNotificationFlag();
- }, [newNotificationReceived]),
+ }, [newNotificationReceived, dispatch, refreshNotifications]),
);
// handles storing and fetching the "previously viewed" information
diff --git a/src/screens/onboarding/RegistrationOne.tsx b/src/screens/onboarding/RegistrationOne.tsx
index 2a1d884d..c9822f76 100644
--- a/src/screens/onboarding/RegistrationOne.tsx
+++ b/src/screens/onboarding/RegistrationOne.tsx
@@ -146,7 +146,7 @@ const RegistrationOne: React.FC<RegistrationOneProps> = ({navigation}) => {
<Text style={styles.formHeader}>ENTER PHONE NUMBER</Text>
</View>
<TaggInput
- maxLength={12} // currently only support US phone numbers
+ maxLength={10} // currently only support US phone numbers
accessibilityHint="Enter your phone number."
accessibilityLabel="Phone number input field."
placeholder="Phone Number"
@@ -154,7 +154,7 @@ const RegistrationOne: React.FC<RegistrationOneProps> = ({navigation}) => {
textContentType="telephoneNumber"
autoCapitalize="none"
returnKeyType="next"
- keyboardType="phone-pad"
+ keyboardType="number-pad"
onChangeText={handlePhoneUpdate}
blurOnSubmit={false}
ref={phoneRef}
diff --git a/src/screens/profile/EditProfile.tsx b/src/screens/profile/EditProfile.tsx
index 3b3fa36e..7d3ca581 100644
--- a/src/screens/profile/EditProfile.tsx
+++ b/src/screens/profile/EditProfile.tsx
@@ -29,9 +29,10 @@ import {
websiteRegex,
bioRegex,
genderRegex,
+ CLASS_YEAR_LIST,
} from '../../constants';
import AsyncStorage from '@react-native-community/async-storage';
-import {ProfileStackParams} from '../../routes';
+import {MainStackParams} from '../../routes';
import Animated from 'react-native-reanimated';
import {HeaderHeight, SCREEN_HEIGHT} from '../../utils';
import {RootState} from '../../store/rootReducer';
@@ -47,12 +48,12 @@ import {
import TaggLoadingIndicator from '../../components/common/TaggLoadingIndicator';
type EditProfileNavigationProp = StackNavigationProp<
- ProfileStackParams,
+ MainStackParams,
'EditProfile'
>;
interface EditProfileProps {
- route: RouteProp<ProfileStackParams, 'EditProfile'>;
+ route: RouteProp<MainStackParams, 'EditProfile'>;
navigation: EditProfileNavigationProp;
}
@@ -65,7 +66,7 @@ const EditProfile: React.FC<EditProfileProps> = ({route, navigation}) => {
const y: Animated.Value<number> = Animated.useValue(0);
const {userId, username} = route.params;
const {
- profile: {website, biography, gender, snapchat, tiktok},
+ profile: {website, biography, gender, snapchat, tiktok, university_class},
avatar,
cover,
} = useSelector((state: RootState) => state.user);
@@ -99,6 +100,13 @@ const EditProfile: React.FC<EditProfileProps> = ({route, navigation}) => {
isValidSnapchat: true,
isValidTiktok: true,
attemptedSubmit: false,
+ classYear: university_class,
+ });
+
+ var classYearList: Array<any> = [];
+
+ CLASS_YEAR_LIST.map((value) => {
+ classYearList.push({label: value, value: value});
});
/**
@@ -254,6 +262,14 @@ const EditProfile: React.FC<EditProfileProps> = ({route, navigation}) => {
});
};
+ const handleClassYearUpdate = (value: string) => {
+ const classYear = Number.parseInt(value);
+ setForm({
+ ...form,
+ classYear,
+ });
+ };
+
const handleSubmit = useCallback(async () => {
if (!form.largePic) {
Alert.alert(ERROR_UPLOAD_LARGE_PROFILE_PIC);
@@ -297,7 +313,7 @@ const EditProfile: React.FC<EditProfileProps> = ({route, navigation}) => {
if (form.bio) {
if (form.isValidBio) {
- request.append('biography', form.bio);
+ request.append('biography', form.bio.trim());
} else {
setForm({...form, attemptedSubmit: false});
setTimeout(() => setForm({...form, attemptedSubmit: true}));
@@ -335,6 +351,15 @@ const EditProfile: React.FC<EditProfileProps> = ({route, navigation}) => {
invalidFields = true;
}
+ if (form.classYear !== university_class) {
+ if (!form.classYear) {
+ invalidFields = true;
+ Alert.alert('Please select a valid class year');
+ } else {
+ request.append('university_class', form.classYear);
+ }
+ }
+
if (invalidFields) {
return;
}
@@ -487,6 +512,19 @@ const EditProfile: React.FC<EditProfileProps> = ({route, navigation}) => {
value={form.customGenderText}
/>
)}
+
+ <TaggDropDown
+ value={form.classYear.toString()}
+ onValueChange={(value: string) =>
+ handleClassYearUpdate(value)
+ }
+ items={classYearList}
+ placeholder={{
+ label: 'Class Year',
+ value: null,
+ color: '#ddd',
+ }}
+ />
{snapchat !== '' && (
<View style={styles.row}>
<SocialIcon social={'Snapchat'} style={styles.icon} />
diff --git a/src/screens/profile/IndividualMoment.tsx b/src/screens/profile/IndividualMoment.tsx
index f13e1295..8c1dc327 100644
--- a/src/screens/profile/IndividualMoment.tsx
+++ b/src/screens/profile/IndividualMoment.tsx
@@ -4,12 +4,12 @@ import {StackNavigationProp} from '@react-navigation/stack';
import React from 'react';
import {FlatList, StyleSheet, View} from 'react-native';
import {useSelector} from 'react-redux';
-import {ProfileStackParams} from 'src/routes/main/ProfileStack';
import {
IndividualMomentTitleBar,
MomentPostContent,
MomentPostHeader,
} from '../../components';
+import {MainStackParams} from '../../routes';
import {RootState} from '../../store/rootreducer';
import {MomentType} from '../../types';
import {SCREEN_HEIGHT, SCREEN_WIDTH, StatusBarHeight} from '../../utils';
@@ -17,12 +17,9 @@ import {SCREEN_HEIGHT, SCREEN_WIDTH, StatusBarHeight} from '../../utils';
/**
* Individual moment view opened when user clicks on a moment tile
*/
-type IndividualMomentRouteProp = RouteProp<
- ProfileStackParams,
- 'IndividualMoment'
->;
+type IndividualMomentRouteProp = RouteProp<MainStackParams, 'IndividualMoment'>;
type IndividualMomentNavigationProp = StackNavigationProp<
- ProfileStackParams,
+ MainStackParams,
'IndividualMoment'
>;
interface IndividualMomentProps {
@@ -70,7 +67,7 @@ const IndividualMoment: React.FC<IndividualMomentProps> = ({
style={styles.postContent}
momentId={item.moment_id}
caption={item.caption}
- pathHash={item.path_hash}
+ pathHash={item.moment_url}
dateTime={item.date_created}
screenType={screenType}
/>
@@ -80,7 +77,7 @@ const IndividualMoment: React.FC<IndividualMomentProps> = ({
return (
<BlurView
blurType="light"
- blurAmount={10}
+ blurAmount={30}
reducedTransparencyFallbackColor="white"
style={styles.contentContainer}>
<IndividualMomentTitleBar
diff --git a/src/screens/profile/MomentCommentsScreen.tsx b/src/screens/profile/MomentCommentsScreen.tsx
index ebe4da28..5c3b8579 100644
--- a/src/screens/profile/MomentCommentsScreen.tsx
+++ b/src/screens/profile/MomentCommentsScreen.tsx
@@ -1,17 +1,15 @@
-import * as React from 'react';
import {RouteProp, useNavigation} from '@react-navigation/native';
-import {ProfileStackParams} from '../../routes/main';
-import {CenteredView, CommentTile} from '../../components';
-import {CommentType} from '../../types';
-import {ScrollView, StyleSheet, Text, View} from 'react-native';
-import {SCREEN_WIDTH} from '../../utils/screenDimensions';
-import {Button} from 'react-native-elements';
+import React, {useState} from 'react';
+import {StyleSheet, Text, TouchableOpacity, View} from 'react-native';
+import {SafeAreaView} from 'react-native-safe-area-context';
+import BackIcon from '../../assets/icons/back-arrow.svg';
+import {TabsGradient} from '../../components';
import {AddComment} from '../../components/';
-import {useEffect} from 'react';
-import AsyncStorage from '@react-native-community/async-storage';
-import {getMomentComments} from '../..//services';
-import {useDispatch} from 'react-redux';
-import {logout} from '../../store/actions';
+import CommentsContainer from '../../components/comments/CommentsContainer';
+import {ADD_COMMENT_TEXT} from '../../constants/strings';
+import {MainStackParams} from '../../routes/main';
+import {CommentType} from '../../types';
+import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils';
/**
* Comments Screen for an image uploaded
@@ -20,7 +18,7 @@ import {logout} from '../../store/actions';
*/
type MomentCommentsScreenRouteProps = RouteProp<
- ProfileStackParams,
+ MainStackParams,
'MomentCommentsScreen'
>;
@@ -30,109 +28,96 @@ interface MomentCommentsScreenProps {
const MomentCommentsScreen: React.FC<MomentCommentsScreenProps> = ({route}) => {
const navigation = useNavigation();
- const {moment_id, screenType} = route.params;
- const [commentsList, setCommentsList] = React.useState([]);
+ const {moment_id, screenType, comment_id} = route.params;
+
+ //Receives comment length from child CommentsContainer
+ const [commentsLength, setCommentsLength] = useState<number>(0);
const [newCommentsAvailable, setNewCommentsAvailable] = React.useState(true);
- const dispatch = useDispatch();
- useEffect(() => {
- const loadComments = async () => {
- const token = await AsyncStorage.getItem('token');
- if (!token) {
- dispatch(logout());
- return;
- }
- getMomentComments(moment_id, setCommentsList, token);
- setNewCommentsAvailable(false);
- };
- if (newCommentsAvailable) {
- loadComments();
- }
- }, [dispatch, moment_id, newCommentsAvailable]);
+ //Keeps track of the current comments object in focus so that the application knows which comment to post a reply to
+ const [commentObjectInFocus, setCommentObjectInFocus] = useState<
+ CommentType | undefined
+ >(undefined);
return (
- <CenteredView>
- <View style={styles.modalView}>
+ <View style={styles.background}>
+ <SafeAreaView>
<View style={styles.header}>
- <Button
- title="X"
- buttonStyle={styles.button}
- titleStyle={styles.buttonText}
+ <TouchableOpacity
+ style={styles.headerButton}
onPress={() => {
navigation.pop();
- }}
+ }}>
+ <BackIcon height={'100%'} width={'100%'} color={'white'} />
+ </TouchableOpacity>
+ <Text style={styles.headerText}>{commentsLength + ' Comments'}</Text>
+ </View>
+ <View style={styles.body}>
+ <CommentsContainer
+ objectId={moment_id}
+ commentId={comment_id}
+ screenType={screenType}
+ setCommentsLength={setCommentsLength}
+ newCommentsAvailable={newCommentsAvailable}
+ setNewCommentsAvailable={setNewCommentsAvailable}
+ setCommentObjectInFocus={setCommentObjectInFocus}
+ commentObjectInFocus={commentObjectInFocus}
+ typeOfComment={'Comment'}
+ />
+ <AddComment
+ placeholderText={
+ commentObjectInFocus
+ ? ADD_COMMENT_TEXT(commentObjectInFocus.commenter.username)
+ : ADD_COMMENT_TEXT()
+ }
+ setNewCommentsAvailable={setNewCommentsAvailable}
+ objectId={
+ commentObjectInFocus ? commentObjectInFocus.comment_id : moment_id
+ }
+ isCommentInFocus={commentObjectInFocus ? true : false}
/>
- <Text style={styles.headerText}>
- {commentsList.length + ' Comments'}
- </Text>
</View>
- <ScrollView
- style={styles.modalScrollView}
- contentContainerStyle={styles.modalScrollViewContent}>
- {commentsList &&
- commentsList.map((comment: CommentType) => (
- <CommentTile
- key={comment.comment_id}
- comment_object={comment}
- screenType={screenType}
- />
- ))}
- </ScrollView>
- <AddComment
- setNewCommentsAvailable={setNewCommentsAvailable}
- moment_id={moment_id}
- />
- </View>
- </CenteredView>
+ </SafeAreaView>
+ <TabsGradient />
+ </View>
);
};
const styles = StyleSheet.create({
- header: {flexDirection: 'row'},
+ background: {
+ backgroundColor: 'white',
+ height: '100%',
+ },
+ header: {justifyContent: 'center', padding: '3%'},
headerText: {
- position: 'relative',
- left: '180%',
+ position: 'absolute',
alignSelf: 'center',
- fontSize: 18,
- fontWeight: '500',
- },
- container: {
- position: 'relative',
- top: '5%',
- left: '5%',
- backgroundColor: 'white',
- borderRadius: 5,
- width: SCREEN_WIDTH / 1.1,
- height: '55%',
+ fontSize: 20.5,
+ fontWeight: '600',
},
- button: {
- backgroundColor: 'transparent',
+ headerButton: {
+ width: '5%',
+ aspectRatio: 1,
+ padding: 0,
+ marginLeft: '5%',
+ alignSelf: 'flex-start',
},
- buttonText: {
+ headerButtonText: {
color: 'black',
fontSize: 18,
fontWeight: '400',
},
- modalView: {
- width: '85%',
- height: '70%',
- backgroundColor: '#fff',
- shadowColor: '#000',
- shadowOpacity: 30,
- shadowOffset: {width: 0, height: 2},
- shadowRadius: 5,
- borderRadius: 8,
- paddingBottom: 15,
+ body: {
+ width: SCREEN_WIDTH * 0.9,
+ height: SCREEN_HEIGHT * 0.8,
+ paddingTop: '3%',
+ },
+ scrollView: {
paddingHorizontal: 20,
- paddingTop: 5,
- justifyContent: 'space-between',
},
- modalScrollViewContent: {
+ scrollViewContent: {
justifyContent: 'center',
},
- modalScrollView: {
- marginBottom: 10,
- },
});
export default MomentCommentsScreen;
diff --git a/src/screens/profile/MomentUploadPromptScreen.tsx b/src/screens/profile/MomentUploadPromptScreen.tsx
index 6111985d..9d46c1e9 100644
--- a/src/screens/profile/MomentUploadPromptScreen.tsx
+++ b/src/screens/profile/MomentUploadPromptScreen.tsx
@@ -6,6 +6,7 @@ import CloseIcon from '../../assets/ionicons/close-outline.svg';
import {StyleSheet, Text, View} from 'react-native';
import {Moment} from '../../components';
import {Image} from 'react-native-animatable';
+import {UPLOAD_MOMENT_PROMPT_ONE_MESSAGE} from '../../constants/strings';
type MomentUploadPromptScreenRouteProp = RouteProp<
MainStackParams,
@@ -38,10 +39,7 @@ const MomentUploadPromptScreen: React.FC<MomentUploadPromptScreenProps> = ({
}}
/>
- <Text style={styles.text}>
- Post your first moment to {'\n'} continue building your digital {'\n'}{' '}
- identity!
- </Text>
+ <Text style={styles.text}>{UPLOAD_MOMENT_PROMPT_ONE_MESSAGE}</Text>
<Image
source={require('../../assets/gifs/dotted-arrow-white.gif')}
style={styles.arrowGif}
@@ -54,6 +52,8 @@ const MomentUploadPromptScreen: React.FC<MomentUploadPromptScreenProps> = ({
screenType={screenType}
handleMomentCategoryDelete={() => {}}
shouldAllowDeletion={false}
+ showDownButton={false}
+ showUpButton={false}
externalStyles={{
container: styles.momentContainer,
titleText: styles.momentHeaderText,
diff --git a/src/screens/search/SearchScreen.tsx b/src/screens/search/SearchScreen.tsx
index 9f98b4d7..f0be7c9e 100644
--- a/src/screens/search/SearchScreen.tsx
+++ b/src/screens/search/SearchScreen.tsx
@@ -20,7 +20,7 @@ import {
SearchResultsBackground,
TabsGradient,
} from '../../components';
-import {SEARCH_ENDPOINT, TAGG_TEXT_LIGHT_BLUE} from '../../constants';
+import {SEARCH_ENDPOINT, TAGG_LIGHT_BLUE} from '../../constants';
import {loadRecentlySearched, resetScreenType} from '../../store/actions';
import {RootState} from '../../store/rootReducer';
import {ProfilePreviewType, ScreenType, UserType} from '../../types';
@@ -36,9 +36,7 @@ const NO_USER: UserType = {
*/
const SearchScreen: React.FC = () => {
- const {recentSearches, explores} = useSelector(
- (state: RootState) => state.taggUsers,
- );
+ const {recentSearches} = useSelector((state: RootState) => state.taggUsers);
const [query, setQuery] = useState<string>('');
const [results, setResults] = useState<Array<ProfilePreviewType>>([]);
const [recents, setRecents] = useState<Array<ProfilePreviewType>>(
@@ -46,7 +44,6 @@ const SearchScreen: React.FC = () => {
);
const [searching, setSearching] = useState(false);
const top = Animated.useValue(-SCREEN_HEIGHT);
- const [user, setUser] = useState<UserType>(NO_USER);
const [refreshing, setRefreshing] = useState<boolean>(false);
const dispatch = useDispatch();
@@ -69,10 +66,6 @@ const SearchScreen: React.FC = () => {
const loadResults = async (q: string) => {
try {
const token = await AsyncStorage.getItem('token');
- if (!token) {
- setUser(NO_USER);
- return;
- }
const response = await fetch(`${SEARCH_ENDPOINT}?query=${q}`, {
method: 'GET',
headers: {
@@ -213,7 +206,7 @@ const styles = StyleSheet.create({
clear: {
fontSize: 17,
fontWeight: 'bold',
- color: TAGG_TEXT_LIGHT_BLUE,
+ color: TAGG_LIGHT_BLUE,
},
image: {
width: SCREEN_WIDTH,