aboutsummaryrefslogtreecommitdiff
path: root/src/screens
diff options
context:
space:
mode:
Diffstat (limited to 'src/screens')
-rw-r--r--src/screens/main/NotificationsScreen.tsx9
-rw-r--r--src/screens/onboarding/AddWaitlistUserScreen.tsx238
-rw-r--r--src/screens/onboarding/CategorySelection.tsx202
-rw-r--r--src/screens/onboarding/CreateCustomCategory.tsx123
-rw-r--r--src/screens/onboarding/InvitationCodeVerification.tsx29
-rw-r--r--src/screens/onboarding/Login.tsx15
-rw-r--r--src/screens/onboarding/ProfileOnboarding.tsx52
-rw-r--r--src/screens/onboarding/SocialMedia.tsx8
-rw-r--r--src/screens/onboarding/WaitlistSuccessScreen.tsx156
-rw-r--r--src/screens/onboarding/index.ts3
-rw-r--r--src/screens/profile/CaptionScreen.tsx64
-rw-r--r--src/screens/profile/EditProfile.tsx52
-rw-r--r--src/screens/profile/MomentUploadPromptScreen.tsx114
-rw-r--r--src/screens/profile/ProfileScreen.tsx4
-rw-r--r--src/screens/profile/index.ts1
-rw-r--r--src/screens/search/SearchScreen.tsx51
16 files changed, 945 insertions, 176 deletions
diff --git a/src/screens/main/NotificationsScreen.tsx b/src/screens/main/NotificationsScreen.tsx
index d6d47b02..8aa47299 100644
--- a/src/screens/main/NotificationsScreen.tsx
+++ b/src/screens/main/NotificationsScreen.tsx
@@ -17,6 +17,7 @@ import {NotificationType, ScreenType} from '../../types';
import {getDateAge, SCREEN_HEIGHT} from '../../utils';
const NotificationsScreen: React.FC = () => {
+ const {user: loggedInUser} = useSelector((state: RootState) => state.user);
const [refreshing, setRefreshing] = useState(false);
// used for figuring out which ones are unread
const [lastViewed, setLastViewed] = useState<moment.Moment | undefined>(
@@ -95,7 +96,13 @@ const NotificationsScreen: React.FC = () => {
}, [lastViewed, notifications]);
const renderNotification = ({item}: {item: NotificationType}) => (
- <Notification item={item} screenType={ScreenType.Notifications} />
+ <Notification
+ item={item}
+ userXId={
+ item.actor.id === loggedInUser.userId ? undefined : item.actor.id
+ }
+ screenType={ScreenType.Notifications}
+ />
);
const renderSectionHeader = ({section: {title, data}}) =>
diff --git a/src/screens/onboarding/AddWaitlistUserScreen.tsx b/src/screens/onboarding/AddWaitlistUserScreen.tsx
new file mode 100644
index 00000000..1c13ffb5
--- /dev/null
+++ b/src/screens/onboarding/AddWaitlistUserScreen.tsx
@@ -0,0 +1,238 @@
+import {StackNavigationProp} from '@react-navigation/stack';
+import * as React from 'react';
+import {
+ KeyboardAvoidingView,
+ Platform,
+ StatusBar,
+ StyleSheet,
+ Text,
+ TouchableOpacity,
+ View,
+} from 'react-native';
+import {
+ ArrowButton,
+ Background,
+ LoadingIndicator,
+ SubmitButton,
+ TaggInput,
+} from '../../components';
+import {nameRegex, phoneRegex} from '../../constants';
+import {OnboardingStackParams} from '../../routes';
+import {adduserToWaitlist} from '../../services';
+import {BackgroundGradientType} from '../../types';
+import {SCREEN_HEIGHT} from '../../utils';
+
+type AddWaitlistUserScreenProp = StackNavigationProp<
+ OnboardingStackParams,
+ 'AddWaitlistUser'
+>;
+
+interface AddWaitlistUserScreenProps {
+ navigation: AddWaitlistUserScreenProp;
+}
+
+const AddWaitlistUserScreen: React.FC<AddWaitlistUserScreenProps> = ({
+ navigation,
+}) => {
+ const phoneRef = React.useRef();
+ const lnameRef = React.useRef();
+
+ const [form, setForm] = React.useState({
+ phone_number: {value: '', isValid: false},
+ first_name: {value: '', isValid: false},
+ last_name: {value: '', isValid: false},
+ attemptedSubmit: false,
+ });
+
+ //Handlers
+ const handleFocusChange = (field: string): void => {
+ switch (field) {
+ case 'last_name':
+ const lnameField: any = lnameRef.current;
+ lnameField.focus();
+ break;
+ case 'phone_number':
+ const phoneField: any = phoneRef.current;
+ phoneField.focus();
+ break;
+ default:
+ return;
+ }
+ };
+
+ const validate = (value: string, type: string) => {
+ let isValid: boolean = false;
+ switch (type) {
+ case 'phone_number':
+ isValid = phoneRegex.test(value);
+ break;
+ default:
+ isValid = nameRegex.test(value);
+ break;
+ }
+ return isValid;
+ };
+
+ const handleUpdate = (value: string, type: string) => {
+ value = value.trim();
+ const isValid = validate(value, type);
+ setForm({
+ ...form,
+ [type]: {value, isValid},
+ });
+ };
+
+ const handleAddUser = async () => {
+ if (!form.attemptedSubmit) {
+ setForm({
+ ...form,
+ attemptedSubmit: true,
+ });
+ }
+ try {
+ const {phone_number, first_name, last_name} = form;
+ if (phone_number.isValid && first_name.isValid && last_name.isValid) {
+ const success = await adduserToWaitlist(
+ phone_number.value,
+ first_name.value,
+ last_name.value,
+ );
+ if (success) {
+ navigation.navigate('WaitlistSuccess');
+ }
+ } else {
+ setForm({...form, attemptedSubmit: false});
+ setTimeout(() => setForm({...form, attemptedSubmit: true}));
+ }
+ } catch (err) {
+ console.log(err);
+ }
+ };
+
+ //Components
+ const Footer = () => (
+ <View style={styles.footer}>
+ <ArrowButton
+ direction="backward"
+ onPress={() => navigation.navigate('InvitationCodeVerification')}
+ />
+ </View>
+ );
+
+ const {phone_number, first_name, last_name} = form;
+
+ return (
+ <Background
+ style={styles.container}
+ gradientType={BackgroundGradientType.Light}>
+ <StatusBar barStyle="light-content" />
+ <KeyboardAvoidingView
+ behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
+ style={styles.container}>
+ <View>
+ <Text style={styles.formHeader}>JOIN WAITLIST</Text>
+ </View>
+ <TaggInput
+ accessibilityHint="Enter your first name."
+ accessibilityLabel="First name input field."
+ placeholder="First Name"
+ autoCompleteType="name"
+ textContentType="name"
+ returnKeyType="next"
+ onChangeText={(text) => handleUpdate(text, 'first_name')}
+ onSubmitEditing={() => handleFocusChange('first_name')}
+ blurOnSubmit={false}
+ valid={first_name.isValid}
+ invalidWarning="Please enter a valid first name."
+ attemptedSubmit={form.attemptedSubmit}
+ width={280}
+ />
+ <TaggInput
+ accessibilityHint="Enter your last name."
+ accessibilityLabel="Last name input field."
+ placeholder="Last Name"
+ autoCompleteType="name"
+ textContentType="name"
+ returnKeyType="next"
+ onChangeText={(text) => handleUpdate(text, 'last_name')}
+ blurOnSubmit={false}
+ ref={lnameRef}
+ valid={last_name.isValid}
+ invalidWarning="Please enter a valid last name."
+ onSubmitEditing={() => handleFocusChange('phone_number')}
+ attemptedSubmit={form.attemptedSubmit}
+ width={280}
+ />
+ <TaggInput
+ maxLength={12}
+ accessibilityHint="Enter your phone number."
+ accessibilityLabel="Phone number input field."
+ placeholder="Phone Number"
+ autoCompleteType="tel"
+ textContentType="telephoneNumber"
+ autoCapitalize="none"
+ returnKeyType="next"
+ keyboardType="phone-pad"
+ onChangeText={(text) => handleUpdate(text, 'phone_number')}
+ blurOnSubmit={false}
+ ref={phoneRef}
+ valid={phone_number.isValid}
+ invalidWarning="Please enter a valid 10 digit number."
+ onSubmitEditing={handleAddUser}
+ attemptedSubmit={form.attemptedSubmit}
+ width={280}
+ />
+ <TouchableOpacity onPress={handleAddUser} style={styles.finalAction}>
+ <Text style={styles.finalActionLabel}>Submit</Text>
+ </TouchableOpacity>
+ <LoadingIndicator />
+ </KeyboardAvoidingView>
+ <Footer />
+ </Background>
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ finalAction: {
+ backgroundColor: 'white',
+ justifyContent: 'center',
+ alignItems: 'center',
+ width: 150,
+ height: 40,
+ borderRadius: 5,
+ borderWidth: 1,
+ borderColor: '#fff',
+ marginVertical: SCREEN_HEIGHT / 20,
+ },
+ finalActionLabel: {
+ fontSize: 16,
+ fontWeight: '500',
+ color: 'black',
+ },
+ formHeader: {
+ color: '#fff',
+ fontSize: 30,
+ fontWeight: '600',
+ marginBottom: '16%',
+ },
+ footer: {
+ width: '100%',
+ flexDirection: 'row',
+ justifyContent: 'space-around',
+ ...Platform.select({
+ ios: {
+ bottom: '20%',
+ },
+ android: {
+ bottom: '10%',
+ },
+ }),
+ },
+});
+
+export default AddWaitlistUserScreen;
diff --git a/src/screens/onboarding/CategorySelection.tsx b/src/screens/onboarding/CategorySelection.tsx
index b9677ed4..5589ea9e 100644
--- a/src/screens/onboarding/CategorySelection.tsx
+++ b/src/screens/onboarding/CategorySelection.tsx
@@ -1,8 +1,8 @@
import {RouteProp} from '@react-navigation/native';
-import React, {useCallback, useEffect, useState} from 'react';
+import {StackNavigationProp} from '@react-navigation/stack';
+import React, {useEffect, useState} from 'react';
import {
Alert,
- KeyboardAvoidingView,
Platform,
StatusBar,
StyleSheet,
@@ -10,20 +10,20 @@ import {
TouchableOpacity,
View,
} from 'react-native';
-import {useDispatch} from 'react-redux';
-import {
- BackgroundGradientType,
- CategorySelectionScreenType,
- MomentCategoryType,
-} from '../../types';
+import {ScrollView} from 'react-native-gesture-handler';
+import {useDispatch, useSelector} from 'react-redux';
+import PlusIcon from '../../assets/icons/plus_icon-01.svg';
import {Background, MomentCategory} from '../../components';
import {MOMENT_CATEGORIES} from '../../constants';
import {OnboardingStackParams} from '../../routes';
-import {StackNavigationProp} from '@react-navigation/stack';
-import {getTokenOrLogout, userLogin} from '../../utils';
import {fcmService, postMomentCategories} from '../../services';
-import {updateMomentCategories} from '../../store/actions/momentCategories';
-import {ScrollView} from 'react-native-gesture-handler';
+import {
+ updateMomentCategories,
+ updateIsOnboardedUser,
+} from '../../store/actions/';
+import {RootState} from '../../store/rootReducer';
+import {BackgroundGradientType, CategorySelectionScreenType} from '../../types';
+import {getTokenOrLogout, SCREEN_WIDTH, userLogin} from '../../utils';
type CategorySelectionRouteProps = RouteProp<
OnboardingStackParams,
@@ -47,17 +47,47 @@ const CategorySelection: React.FC<CategorySelectionProps> = ({
/**
* Same component to be used for category selection while onboarding and while on profile
*/
- const {categories, screenType, user} = route.params;
+ const {screenType, user} = route.params;
const isOnBoarding: boolean =
screenType === CategorySelectionScreenType.Onboarding;
const {userId, username} = user;
- const [selectedCategories, setSelectedCategories] = useState<
- Array<MomentCategoryType>
+ // During onboarding this will fail and default to []
+ const {momentCategories = []} = useSelector(
+ (state: RootState) => state.momentCategories,
+ );
+
+ // Stores all the categories that will be saved to the store
+ const [selectedCategories, setSelectedCategories] = useState<string[]>([]);
+
+ /**
+ * Stores all the custom categories for the UI, allow easier logic for
+ * unchecking a custom category.
+ *
+ * Each uncommited custom category should also have a copy in selectedCategories
+ * since that's the final value that will be stored in the store.
+ */
+ const [uncommitedCustomCategories, setUncommitedCustomCategories] = useState<
+ string[]
>([]);
+ const customCategories = momentCategories.filter(
+ (mc) => !MOMENT_CATEGORIES.includes(mc),
+ );
+
const dispatch = useDispatch();
+ useEffect(() => {
+ const newCustomCategory = route.params.newCustomCategory;
+ if (newCustomCategory) {
+ setUncommitedCustomCategories([
+ ...uncommitedCustomCategories,
+ newCustomCategory,
+ ]);
+ selectedCategories.push(newCustomCategory);
+ }
+ }, [route.params?.newCustomCategory]);
+
/**
* Show the tutorial if a new user is OnBoarding
*/
@@ -67,13 +97,8 @@ const CategorySelection: React.FC<CategorySelectionProps> = ({
popupProps: {
messageHeader: 'Category And Moments',
messageBody:
- 'Use pictures and videos to share different aspects of you',
- next: {
- messageHeader: 'Select Categories',
- messageBody:
- 'Select between 2 - 6 categories to begin creating moments!',
- next: undefined,
- },
+ 'Use pictures and videos to share \ndifferent aspects of you',
+ next: undefined,
},
});
}
@@ -89,11 +114,13 @@ const CategorySelection: React.FC<CategorySelectionProps> = ({
* Remove from the selected categories
*/
const onSelect = (
- category: MomentCategoryType,
+ category: string,
isSelected: boolean,
isAdded: boolean,
) => {
- if (isAdded) return;
+ if (isAdded) {
+ return;
+ }
if (isSelected) {
setSelectedCategories((prev) => [...prev, category]);
} else {
@@ -104,40 +131,51 @@ const CategorySelection: React.FC<CategorySelectionProps> = ({
};
/**
- * if onboarding
- * Count of already added categories will always be 0
- * else
- * Calculate number of selected categories by iterating through the user's pre-selected categories
+ * Handle deselection of custom category.
+ *
+ * Custom categories is "added" and "selected" by CreateCustomCategory screen.
+ * User can only "deselect" an uncommited custom category.
+ *
+ * case isAdded || isSelected:
+ * Return without doing anything
+ * default:
+ * Remove from selected categories AND uncommitedCustomCategories
*/
- const addedLength = !isOnBoarding
- ? Object.keys(categories).filter((key) => {
- return categories[key as MomentCategoryType] === true;
- }).length
- : 0;
+ const onDeselectCustomCategory = (
+ category: string,
+ isSelected: boolean,
+ isAdded: boolean,
+ ) => {
+ if (isAdded || isSelected) {
+ return;
+ }
+ setSelectedCategories(
+ selectedCategories.filter((item) => item !== category),
+ );
+ setUncommitedCustomCategories(
+ uncommitedCustomCategories.filter((item) => item !== category),
+ );
+ };
const handleButtonPress = async () => {
- /**
- * Check for lower and upper bound before creating new categories
- */
- const totalCategories = addedLength + selectedCategories.length;
- if (totalCategories < 2) {
- Alert.alert('Please select atleast 2 categories');
- return;
- } else if (totalCategories > 6) {
- Alert.alert('You may not add more than 6 categories');
- return;
- } else if (selectedCategories.length === 0) {
- Alert.alert('Please select some categories!');
+ if (momentCategories.length + selectedCategories.length === 0) {
+ Alert.alert('Please select at least 1 category');
return;
}
try {
if (isOnBoarding) {
+ dispatch(updateIsOnboardedUser(true));
const token = await getTokenOrLogout(dispatch);
await postMomentCategories(selectedCategories, token);
userLogin(dispatch, {userId: userId, username: username});
fcmService.sendFcmTokenToServer();
} else {
- dispatch(updateMomentCategories(selectedCategories, true, userId));
+ dispatch(
+ updateMomentCategories(
+ momentCategories.concat(selectedCategories),
+ true,
+ ),
+ );
navigation.goBack();
}
} catch (error) {
@@ -155,15 +193,55 @@ const CategorySelection: React.FC<CategorySelectionProps> = ({
style={styles.container}
gradientType={BackgroundGradientType.Dark}>
<StatusBar barStyle="light-content" />
- <Text style={styles.subtext}>Create new categories</Text>
+ <Text style={styles.subtext}>Create Categories</Text>
<View style={styles.container}>
+ {!isOnBoarding && (
+ <TouchableOpacity
+ style={styles.createCategory}
+ onPress={() => {
+ navigation.push('CreateCustomCategory', {
+ screenType,
+ user,
+ existingCategories: momentCategories.concat(
+ selectedCategories,
+ ),
+ });
+ }}>
+ <PlusIcon width={30} height={30} color="white" />
+ <Text style={styles.createCategoryLabel}>
+ Create your own category
+ </Text>
+ </TouchableOpacity>
+ )}
<View style={styles.linkerContainer}>
+ {/* commited custom categories */}
+ {customCategories.map((category, index) => (
+ <MomentCategory
+ key={index}
+ categoryType={category}
+ isSelected={false}
+ isAdded={true}
+ onSelect={onDeselectCustomCategory}
+ />
+ ))}
+ {/* uncommited custom categroies */}
+ {uncommitedCustomCategories.map((category, index) => (
+ <MomentCategory
+ key={index}
+ categoryType={category}
+ isSelected={selectedCategories.includes(category)}
+ isAdded={false}
+ onSelect={onDeselectCustomCategory}
+ />
+ ))}
+ {customCategories.length + uncommitedCustomCategories.length !==
+ 0 && <View style={styles.divider} />}
{MOMENT_CATEGORIES.map((category, index) => (
<MomentCategory
key={index}
categoryType={category}
isSelected={selectedCategories.includes(category)}
- isAdded={categories[category]}
+ isAdded={momentCategories.includes(category)}
onSelect={onSelect}
/>
))}
@@ -215,11 +293,12 @@ const styles = StyleSheet.create({
},
subtext: {
color: '#fff',
- fontSize: 16,
+ fontSize: 20,
fontWeight: '600',
textAlign: 'center',
marginVertical: '8%',
marginHorizontal: '10%',
+ marginTop: '15%',
},
finalAction: {
backgroundColor: 'white',
@@ -237,6 +316,31 @@ const styles = StyleSheet.create({
fontWeight: '500',
color: 'black',
},
+ createCategory: {
+ backgroundColor: '#53329B',
+ width: SCREEN_WIDTH * 0.9,
+ height: 70,
+ alignItems: 'center',
+ justifyContent: 'center',
+ borderRadius: 10,
+ flexDirection: 'row',
+ marginBottom: '5%',
+ },
+ createCategoryLabel: {
+ color: 'white',
+ marginLeft: '3%',
+ fontSize: 18,
+ fontWeight: '500',
+ },
+ plusIcon: {
+ color: 'white',
+ },
+ divider: {
+ borderColor: 'white',
+ borderBottomWidth: 1,
+ width: SCREEN_WIDTH * 0.9,
+ marginVertical: '2%',
+ },
});
export default CategorySelection;
diff --git a/src/screens/onboarding/CreateCustomCategory.tsx b/src/screens/onboarding/CreateCustomCategory.tsx
new file mode 100644
index 00000000..eab72c7d
--- /dev/null
+++ b/src/screens/onboarding/CreateCustomCategory.tsx
@@ -0,0 +1,123 @@
+import {RouteProp} from '@react-navigation/native';
+import {StackNavigationProp} from '@react-navigation/stack';
+import React, {useState} from 'react';
+import {
+ Alert,
+ KeyboardAvoidingView,
+ StatusBar,
+ StyleSheet,
+ Text,
+ TextInput,
+ TouchableOpacity,
+} from 'react-native';
+import {Background} from '../../components';
+import {OnboardingStackParams} from '../../routes';
+import {BackgroundGradientType} from '../../types';
+import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils';
+
+type CreateCustomCategoryRouteProps = RouteProp<
+ OnboardingStackParams,
+ 'CreateCustomCategory'
+>;
+
+type CreateCustomCategoryNavigationProps = StackNavigationProp<
+ OnboardingStackParams,
+ 'CreateCustomCategory'
+>;
+
+interface CreateCustomCategoryProps {
+ route: CreateCustomCategoryRouteProps;
+ navigation: CreateCustomCategoryNavigationProps;
+}
+
+const CreateCustomCategory: React.FC<CreateCustomCategoryProps> = ({
+ route,
+ navigation,
+}) => {
+ /**
+ * Same component to be used for category selection while onboarding and while on profile
+ */
+ const {existingCategories} = route.params;
+ const [newCategory, setNewCategory] = useState('');
+
+ const handleButtonPress = () => {
+ if (existingCategories.includes(newCategory)) {
+ Alert.alert('Looks like you already have that one created!');
+ } else {
+ navigation.navigate('CategorySelection', {
+ screenType: route.params.screenType,
+ user: route.params.user,
+ newCustomCategory: newCategory,
+ });
+ }
+ };
+
+ return (
+ <>
+ <StatusBar barStyle="light-content" />
+ <Background
+ style={styles.container}
+ gradientType={BackgroundGradientType.Dark}>
+ <KeyboardAvoidingView
+ style={styles.innerContainer}
+ behavior={'padding'}>
+ <Text style={styles.title}>Give your category a name</Text>
+ <TextInput
+ style={styles.input}
+ selectionColor={'white'}
+ onChangeText={setNewCategory}
+ autoFocus={true}
+ />
+ <TouchableOpacity
+ onPress={handleButtonPress}
+ style={styles.finalAction}>
+ <Text style={styles.finalActionLabel}>{'Create'}</Text>
+ </TouchableOpacity>
+ </KeyboardAvoidingView>
+ </Background>
+ </>
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ alignItems: 'center',
+ minHeight: SCREEN_HEIGHT,
+ },
+ innerContainer: {
+ height: '40%',
+ top: '20%',
+ justifyContent: 'space-around',
+ alignItems: 'center',
+ },
+ title: {
+ color: 'white',
+ fontSize: 20,
+ fontWeight: '600',
+ },
+ input: {
+ width: SCREEN_WIDTH * 0.75,
+ fontSize: 30,
+ color: 'white',
+ textAlign: 'center',
+ borderBottomWidth: 1,
+ borderBottomColor: 'white',
+ },
+ finalAction: {
+ backgroundColor: 'white',
+ justifyContent: 'center',
+ alignItems: 'center',
+ width: 150,
+ height: 40,
+ borderRadius: 5,
+ borderWidth: 1,
+ borderColor: '#8F01FF',
+ },
+ finalActionLabel: {
+ fontSize: 16,
+ fontWeight: '500',
+ color: 'black',
+ },
+});
+
+export default CreateCustomCategory;
diff --git a/src/screens/onboarding/InvitationCodeVerification.tsx b/src/screens/onboarding/InvitationCodeVerification.tsx
index a9d1c12e..cc7cd678 100644
--- a/src/screens/onboarding/InvitationCodeVerification.tsx
+++ b/src/screens/onboarding/InvitationCodeVerification.tsx
@@ -10,7 +10,10 @@ import {
LoadingIndicator,
} from '../../components';
-import {VERIFY_INVITATION_CODE_ENDPOUNT} from '../../constants';
+import {
+ TAGG_LIGHT_PURPLE,
+ VERIFY_INVITATION_CODE_ENDPOUNT,
+} from '../../constants';
import {Text} from 'react-native-animatable';
import {
@@ -83,6 +86,10 @@ const InvitationCodeVerification: React.FC<InvitationCodeVerificationProps> = ({
}
};
+ const navigateToAddWaitList = () => {
+ navigation.navigate('AddWaitlistUser');
+ };
+
const Footer = () => (
<View style={styles.footer}>
<ArrowButton
@@ -131,6 +138,13 @@ const InvitationCodeVerification: React.FC<InvitationCodeVerificationProps> = ({
accessibilityHint="Select this after entering your invitation code"
onPress={handleInvitationCodeVerification}
/>
+ <View style={styles.noInviteCode}>
+ <Text style={styles.inviteCodeText}>Don't have an invite? </Text>
+ <Text style={styles.inviteCodeLink} onPress={navigateToAddWaitList}>
+ {' '}
+ Join the Waitlist
+ </Text>
+ </View>
<LoadingIndicator />
</KeyboardAvoidingView>
<Footer />
@@ -206,6 +220,19 @@ const styles = StyleSheet.create({
},
}),
},
+ noInviteCode: {
+ flexDirection: 'row',
+ justifyContent: 'center',
+ },
+ inviteCodeText: {
+ color: TAGG_LIGHT_PURPLE,
+ fontSize: 18,
+ },
+ inviteCodeLink: {
+ color: 'white',
+ fontSize: 18,
+ textDecorationLine: 'underline',
+ },
});
export default InvitationCodeVerification;
diff --git a/src/screens/onboarding/Login.tsx b/src/screens/onboarding/Login.tsx
index 3e59b00e..d1717fc1 100644
--- a/src/screens/onboarding/Login.tsx
+++ b/src/screens/onboarding/Login.tsx
@@ -15,17 +15,16 @@ import {
import {fcmService} from '../../services';
import {OnboardingStackParams} from '../../routes/onboarding';
import {Background, TaggInput, SubmitButton} from '../../components';
-import {usernameRegex, LOGIN_ENDPOINT} from '../../constants';
-import AsyncStorage from '@react-native-community/async-storage';
import {
- BackgroundGradientType,
- CategorySelectionScreenType,
- UserType,
-} from '../../types';
+ usernameRegex,
+ LOGIN_ENDPOINT,
+ TAGG_LIGHT_PURPLE,
+} from '../../constants';
+import AsyncStorage from '@react-native-community/async-storage';
+import {BackgroundGradientType, UserType} from '../../types';
import {useDispatch} from 'react-redux';
import {userLogin} from '../../utils';
import SplashScreen from 'react-native-splash-screen';
-import {MOMENT_CATEGORIES_MAP} from '../../store/initialStates';
type VerificationScreenRouteProp = RouteProp<OnboardingStackParams, 'Login'>;
type VerificationScreenNavigationProp = StackNavigationProp<
@@ -356,7 +355,7 @@ const styles = StyleSheet.create({
},
newUser: {
fontSize: 14,
- color: '#f4ddff',
+ color: TAGG_LIGHT_PURPLE,
},
getStarted: {
fontSize: 14,
diff --git a/src/screens/onboarding/ProfileOnboarding.tsx b/src/screens/onboarding/ProfileOnboarding.tsx
index 70550f36..1f8e58da 100644
--- a/src/screens/onboarding/ProfileOnboarding.tsx
+++ b/src/screens/onboarding/ProfileOnboarding.tsx
@@ -147,43 +147,51 @@ const ProfileOnboarding: React.FC<ProfileOnboardingProps> = ({
const goToGalleryLargePic = () => {
ImagePicker.openPicker({
- smartAlbums: ['Favorites', 'RecentlyAdded', 'SelfPortraits', 'Screenshots', 'UserLibrary'],
+ smartAlbums: [
+ 'Favorites',
+ 'RecentlyAdded',
+ 'SelfPortraits',
+ 'Screenshots',
+ 'UserLibrary',
+ ],
width: 580,
height: 580,
cropping: true,
cropperToolbarTitle: 'Select Header',
mediaType: 'photo',
- })
- .then((picture) => {
- if ('path' in picture) {
- setForm({
- ...form,
- largePic: picture.path,
- });
- }
- })
- .catch(() => {});
+ }).then((picture) => {
+ if ('path' in picture) {
+ setForm({
+ ...form,
+ largePic: picture.path,
+ });
+ }
+ });
};
const goToGallerySmallPic = () => {
ImagePicker.openPicker({
- smartAlbums: ['Favorites', 'RecentlyAdded', 'SelfPortraits', 'Screenshots', 'UserLibrary'],
+ smartAlbums: [
+ 'Favorites',
+ 'RecentlyAdded',
+ 'SelfPortraits',
+ 'Screenshots',
+ 'UserLibrary',
+ ],
width: 580,
height: 580,
cropping: true,
cropperToolbarTitle: 'Select Profile Picture',
mediaType: 'photo',
cropperCircleOverlay: true,
- })
- .then((picture) => {
- if ('path' in picture) {
- setForm({
- ...form,
- smallPic: picture.path,
- });
- }
- })
- .catch(() => {});
+ }).then((picture) => {
+ if ('path' in picture) {
+ setForm({
+ ...form,
+ smallPic: picture.path,
+ });
+ }
+ });
};
/*
diff --git a/src/screens/onboarding/SocialMedia.tsx b/src/screens/onboarding/SocialMedia.tsx
index d2a43e7a..2a978f94 100644
--- a/src/screens/onboarding/SocialMedia.tsx
+++ b/src/screens/onboarding/SocialMedia.tsx
@@ -2,7 +2,6 @@ import {RouteProp} from '@react-navigation/native';
import {StackNavigationProp} from '@react-navigation/stack';
import React from 'react';
import {
- Alert,
KeyboardAvoidingView,
Platform,
StatusBar,
@@ -22,9 +21,8 @@ import {
LinkSocialMedia,
RegistrationWizard,
} from '../../components';
-import {SOCIAL_LIST} from '../../constants/';
+import {SOCIAL_LIST, MOMENT_CATEGORIES} from '../../constants/';
import {OnboardingStackParams} from '../../routes';
-import {MOMENT_CATEGORIES_MAP} from '../../store/initialStates';
/**
* Social Media Screen for displaying social media linkers
@@ -55,8 +53,6 @@ const SocialMedia: React.FC<SocialMediaProps> = ({route, navigation}) => {
linkers.push(linker);
}
- const dispatch = useDispatch();
-
/**
* Just commenting this out, in case we need it in the future
*/
@@ -69,9 +65,9 @@ const SocialMedia: React.FC<SocialMediaProps> = ({route, navigation}) => {
const handleNext = () => {
navigation.navigate('CategorySelection', {
- categories: MOMENT_CATEGORIES_MAP,
screenType: CategorySelectionScreenType.Onboarding,
user: {userId: userId, username: username},
+ newCustomCategory: undefined,
});
};
diff --git a/src/screens/onboarding/WaitlistSuccessScreen.tsx b/src/screens/onboarding/WaitlistSuccessScreen.tsx
new file mode 100644
index 00000000..1f603e3a
--- /dev/null
+++ b/src/screens/onboarding/WaitlistSuccessScreen.tsx
@@ -0,0 +1,156 @@
+import {StackNavigationProp} from '@react-navigation/stack';
+import * as React from 'react';
+import {
+ KeyboardAvoidingView,
+ Linking,
+ Platform,
+ StatusBar,
+ StyleSheet,
+ Text,
+ TouchableOpacity,
+ View,
+} from 'react-native';
+import {ArrowButton, Background, SubmitButton} from '../../components';
+import {OnboardingStackParams} from '../../routes';
+import {BackgroundGradientType} from '../../types';
+import CelebrationLogo from '../../assets/icons/celebration-logo.svg';
+import {SCREEN_HEIGHT} from '../../utils';
+import {TAGG_WEBSITE} from '../../constants';
+
+type WaitlistSuccessScreenProp = StackNavigationProp<
+ OnboardingStackParams,
+ 'WaitlistSuccess'
+>;
+
+interface WaitlistSuccessScreenProps {
+ navigation: WaitlistSuccessScreenProp;
+}
+
+const WaitlistSuccessScreen: React.FC<WaitlistSuccessScreenProps> = ({
+ navigation,
+}) => {
+ const handleSignIn = () => {
+ navigation.navigate('InvitationCodeVerification');
+ };
+
+ const Footer = () => (
+ <View style={styles.footer}>
+ <ArrowButton
+ direction="backward"
+ onPress={() => navigation.navigate('AddWaitlistUser')}
+ />
+ </View>
+ );
+ return (
+ <Background
+ style={styles.container}
+ gradientType={BackgroundGradientType.Light}>
+ <KeyboardAvoidingView
+ behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
+ style={styles.container}>
+ <StatusBar barStyle="light-content" />
+ <CelebrationLogo width={100} height={100} />
+ <Text style={styles.heading}>
+ You've successfully joined{'\n'}
+ the waitlist, we'll let you know{'\n'}
+ as soon as your invite is{'\n'}ready!
+ </Text>
+ <Text style={[styles.subHeading, styles.subHeadOneMargin]}>
+ To learn more about Tagg you can visit our{'\n'}{' '}
+ <Text
+ style={styles.link}
+ onPress={() => {
+ Linking.openURL(TAGG_WEBSITE);
+ }}>
+ website
+ </Text>
+ . Thank you!
+ </Text>
+ <Text style={[styles.subHeading, styles.subHeadTwoMargin]}>
+ Got your invite text?
+ </Text>
+ <TouchableOpacity onPress={handleSignIn} style={styles.finalAction}>
+ <Text style={styles.finalActionLabel}>Sign In</Text>
+ </TouchableOpacity>
+ </KeyboardAvoidingView>
+ <Footer />
+ </Background>
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ flexDirection: 'column',
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ wizard: {
+ ...Platform.select({
+ ios: {
+ top: 50,
+ },
+ android: {
+ bottom: 40,
+ },
+ }),
+ },
+ link: {
+ textDecorationLine: 'underline',
+ },
+ finalAction: {
+ backgroundColor: 'white',
+ justifyContent: 'center',
+ alignItems: 'center',
+ width: 150,
+ height: 40,
+ borderRadius: 5,
+ borderWidth: 1,
+ borderColor: '#fff',
+ marginBottom: SCREEN_HEIGHT / 20,
+ marginTop: SCREEN_HEIGHT / 45,
+ },
+ finalActionLabel: {
+ fontSize: 16,
+ fontWeight: '500',
+ color: 'black',
+ },
+ formHeader: {
+ color: '#fff',
+ fontSize: 30,
+ fontWeight: '600',
+ marginBottom: '16%',
+ },
+ footer: {
+ width: '100%',
+ flexDirection: 'row',
+ justifyContent: 'space-around',
+ ...Platform.select({
+ ios: {
+ bottom: '20%',
+ },
+ android: {
+ bottom: '10%',
+ },
+ }),
+ },
+ heading: {
+ fontSize: 25,
+ fontWeight: 'bold',
+ color: 'white',
+ marginTop: SCREEN_HEIGHT / 25,
+ textAlign: 'center',
+ },
+ subHeading: {
+ color: 'white',
+ textAlign: 'center',
+ },
+ subHeadOneMargin: {
+ marginTop: SCREEN_HEIGHT / 30,
+ },
+ subHeadTwoMargin: {
+ marginTop: SCREEN_HEIGHT / 10,
+ },
+});
+
+export default WaitlistSuccessScreen;
diff --git a/src/screens/onboarding/index.ts b/src/screens/onboarding/index.ts
index ec833929..14d0e405 100644
--- a/src/screens/onboarding/index.ts
+++ b/src/screens/onboarding/index.ts
@@ -11,3 +11,6 @@ export {default as PasswordResetRequest} from './PasswordResetRequest';
export {default as PasswordReset} from './PasswordReset';
export {default as WelcomeScreen} from './WelcomeScreen';
export {default as CategorySelection} from './CategorySelection';
+export {default as AddWaitlistUserScreen} from './AddWaitlistUserScreen';
+export {default as WaitlistSuccessScreen} from './WaitlistSuccessScreen';
+export {default as CreateCustomCategory} from './CreateCustomCategory';
diff --git a/src/screens/profile/CaptionScreen.tsx b/src/screens/profile/CaptionScreen.tsx
index e9eed668..5537d6bf 100644
--- a/src/screens/profile/CaptionScreen.tsx
+++ b/src/screens/profile/CaptionScreen.tsx
@@ -14,20 +14,24 @@ import {SearchBackground, TaggBigInput} from '../../components';
import {SCREEN_WIDTH, StatusBarHeight} from '../../utils';
import AsyncStorage from '@react-native-community/async-storage';
import {RouteProp} from '@react-navigation/native';
-import {ProfileStackParams} from 'src/routes';
+import {MainStackParams} from 'src/routes';
import {StackNavigationProp} from '@react-navigation/stack';
import {CaptionScreenHeader} from '../../components/';
import {MOMENTS_ENDPOINT} from '../../constants';
import {useDispatch, useSelector} from 'react-redux';
-import {loadUserMoments} from '../../store/actions';
+import {
+ loadUserMoments,
+ updateProfileCompletionStage,
+} from '../../store/actions';
import {RootState} from '../../store/rootReducer';
+import {postMoment} from '../../services';
/**
* Upload Screen to allow users to upload posts to Tagg
*/
-type CaptionScreenRouteProp = RouteProp<ProfileStackParams, 'CaptionScreen'>;
+type CaptionScreenRouteProp = RouteProp<MainStackParams, 'CaptionScreen'>;
type CaptionScreenNavigationProp = StackNavigationProp<
- ProfileStackParams,
+ MainStackParams,
'CaptionScreen'
>;
interface CaptionScreenProps {
@@ -47,15 +51,6 @@ const CaptionScreen: React.FC<CaptionScreenProps> = ({route, navigation}) => {
setCaption(caption);
};
- const checkImageUploadStatus = (statusMap: object) => {
- for (let [key, value] of Object.entries(statusMap)) {
- if (value != 'Success') {
- return false;
- }
- }
- return true;
- };
-
const navigateToProfile = () => {
//Since the logged In User is navigating to own profile, useXId is not required
navigation.navigate('Profile', {
@@ -66,43 +61,20 @@ const CaptionScreen: React.FC<CaptionScreenProps> = ({route, navigation}) => {
const handleShare = async () => {
try {
- const request = new FormData();
- const uri = image.path;
- var fileName = image.filename;
-
- //Manipulating filename to end with .jpg instead of .heic
- if (fileName.endsWith('.heic') || fileName.endsWith('.HEIC')) {
- fileName = fileName.split('.')[0] + '.jpg';
- }
- request.append('image', {
- uri: uri,
- name: fileName,
- type: 'image/jpg',
- });
- request.append('moment', title);
- request.append('user_id', userId);
- request.append('captions', JSON.stringify({image: caption}));
-
- const token = await AsyncStorage.getItem('token');
- let response = await fetch(MOMENTS_ENDPOINT, {
- method: 'POST',
- headers: {
- 'Content-Type': 'multipart/form-data',
- Authorization: 'Token ' + token,
- },
- body: request,
- });
- let statusCode = response.status;
- let data = await response.json();
- if (statusCode === 200 && checkImageUploadStatus(data)) {
- Alert.alert('The picture was uploaded successfully!');
+ const data = await postMoment(
+ image.filename,
+ image.path,
+ caption,
+ title,
+ userId,
+ );
+ if (data) {
dispatch(loadUserMoments(userId));
+ dispatch(updateProfileCompletionStage(data));
navigateToProfile();
- } else {
- Alert.alert('An error occured while uploading. Please try again!');
}
} catch (err) {
- Alert.alert('An error occured during authenticaion. Please login again!');
+ console.log(err);
}
};
diff --git a/src/screens/profile/EditProfile.tsx b/src/screens/profile/EditProfile.tsx
index ed012313..a6849c7a 100644
--- a/src/screens/profile/EditProfile.tsx
+++ b/src/screens/profile/EditProfile.tsx
@@ -131,43 +131,51 @@ const EditProfile: React.FC<EditProfileProps> = ({route, navigation}) => {
const goToGalleryLargePic = () => {
ImagePicker.openPicker({
- smartAlbums: ['Favorites', 'RecentlyAdded', 'SelfPortraits', 'Screenshots', 'UserLibrary'],
+ smartAlbums: [
+ 'Favorites',
+ 'RecentlyAdded',
+ 'SelfPortraits',
+ 'Screenshots',
+ 'UserLibrary',
+ ],
width: 580,
height: 580,
cropping: true,
cropperToolbarTitle: 'Select Header',
mediaType: 'photo',
- })
- .then((picture) => {
- if ('path' in picture) {
- setForm({
- ...form,
- largePic: picture.path,
- });
- }
- })
- .catch(() => {});
+ }).then((picture) => {
+ if ('path' in picture) {
+ setForm({
+ ...form,
+ largePic: picture.path,
+ });
+ }
+ });
};
const goToGallerySmallPic = () => {
ImagePicker.openPicker({
- smartAlbums: ['Favorites', 'RecentlyAdded', 'SelfPortraits', 'Screenshots', 'UserLibrary'],
+ smartAlbums: [
+ 'Favorites',
+ 'RecentlyAdded',
+ 'SelfPortraits',
+ 'Screenshots',
+ 'UserLibrary',
+ ],
width: 580,
height: 580,
cropping: true,
cropperToolbarTitle: 'Select Profile Picture',
mediaType: 'photo',
cropperCircleOverlay: true,
- })
- .then((picture) => {
- if ('path' in picture) {
- setForm({
- ...form,
- smallPic: picture.path,
- });
- }
- })
- .catch(() => {});
+ }).then((picture) => {
+ if ('path' in picture) {
+ setForm({
+ ...form,
+ smallPic: picture.path,
+ });
+ }
+ });
};
/*
diff --git a/src/screens/profile/MomentUploadPromptScreen.tsx b/src/screens/profile/MomentUploadPromptScreen.tsx
new file mode 100644
index 00000000..6111985d
--- /dev/null
+++ b/src/screens/profile/MomentUploadPromptScreen.tsx
@@ -0,0 +1,114 @@
+import * as React from 'react';
+import {RouteProp} from '@react-navigation/native';
+import {StackNavigationProp} from '@react-navigation/stack';
+import {MainStackParams} from '../../routes';
+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';
+
+type MomentUploadPromptScreenRouteProp = RouteProp<
+ MainStackParams,
+ 'MomentUploadPrompt'
+>;
+type MomentUploadPromptScreenNavigationProp = StackNavigationProp<
+ MainStackParams,
+ 'MomentUploadPrompt'
+>;
+
+interface MomentUploadPromptScreenProps {
+ route: MomentUploadPromptScreenRouteProp;
+ navigation: MomentUploadPromptScreenNavigationProp;
+}
+
+const MomentUploadPromptScreen: React.FC<MomentUploadPromptScreenProps> = ({
+ route,
+ navigation,
+}) => {
+ const {screenType, momentCategory} = route.params;
+ return (
+ <View style={styles.container}>
+ <CloseIcon
+ height={'10%'}
+ width={'10%'}
+ color={'white'}
+ style={styles.closeButton}
+ onPress={() => {
+ navigation.goBack();
+ }}
+ />
+
+ <Text style={styles.text}>
+ Post your first moment to {'\n'} continue building your digital {'\n'}{' '}
+ identity!
+ </Text>
+ <Image
+ source={require('../../assets/gifs/dotted-arrow-white.gif')}
+ style={styles.arrowGif}
+ />
+ <Moment
+ key={1}
+ title={momentCategory}
+ images={[]}
+ userXId={undefined}
+ screenType={screenType}
+ handleMomentCategoryDelete={() => {}}
+ shouldAllowDeletion={false}
+ externalStyles={{
+ container: styles.momentContainer,
+ titleText: styles.momentHeaderText,
+ header: styles.momentHeader,
+ scrollContainer: styles.momentScrollContainer,
+ }}
+ />
+ </View>
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flexDirection: 'column',
+ justifyContent: 'center',
+ },
+ closeButton: {
+ position: 'relative',
+ height: '48%',
+ aspectRatio: 1,
+ top: 20,
+ },
+ text: {
+ justifyContent: 'center',
+ color: '#fff',
+ fontWeight: 'bold',
+ fontSize: 20,
+ textAlign: 'center',
+ position: 'relative',
+ top: '40%',
+ },
+ arrowGif: {
+ position: 'relative',
+ width: '25%',
+ height: '40%',
+ left: '40%',
+ aspectRatio: 1.2,
+ top: '50%',
+ transform: [{scaleX: -1}, {rotate: '15deg'}],
+ },
+
+ //Styles to adjust moment container
+ momentScrollContainer: {
+ backgroundColor: 'transparent',
+ },
+ momentContainer: {
+ top: '62%',
+ backgroundColor: 'transparent',
+ },
+ momentHeaderText: {
+ paddingBottom: '5%',
+ },
+ momentHeader: {
+ backgroundColor: 'transparent',
+ },
+});
+
+export default MomentUploadPromptScreen;
diff --git a/src/screens/profile/ProfileScreen.tsx b/src/screens/profile/ProfileScreen.tsx
index 1b9a1049..0ea96cd2 100644
--- a/src/screens/profile/ProfileScreen.tsx
+++ b/src/screens/profile/ProfileScreen.tsx
@@ -3,7 +3,7 @@ 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} from '../../routes/';
+import {MainStackParams} from '../../routes/';
import {resetScreenType} from '../../store/actions';
import {useDispatch, useStore} from 'react-redux';
import {DUMMY_USERID} from '../../store/initialStates';
@@ -13,7 +13,7 @@ import {DUMMY_USERID} from '../../store/initialStates';
* including posts, messaging, and settings
*/
-type ProfileScreenRouteProps = RouteProp<ProfileStackParams, 'Profile'>;
+type ProfileScreenRouteProps = RouteProp<MainStackParams, 'Profile'>;
interface ProfileOnboardingProps {
route: ProfileScreenRouteProps;
diff --git a/src/screens/profile/index.ts b/src/screens/profile/index.ts
index b6a13144..9d651729 100644
--- a/src/screens/profile/index.ts
+++ b/src/screens/profile/index.ts
@@ -5,3 +5,4 @@ export {default as IndividualMoment} from './IndividualMoment';
export {default as MomentCommentsScreen} from './MomentCommentsScreen';
export {default as FriendsListScreen} from './FriendsListScreen';
export {default as EditProfile} from './EditProfile';
+export {default as MomentUploadPromptScreen} from './MomentUploadPromptScreen';
diff --git a/src/screens/search/SearchScreen.tsx b/src/screens/search/SearchScreen.tsx
index 78c0c5cc..4505163c 100644
--- a/src/screens/search/SearchScreen.tsx
+++ b/src/screens/search/SearchScreen.tsx
@@ -1,9 +1,17 @@
import AsyncStorage from '@react-native-community/async-storage';
-import React, {useEffect, useState} from 'react';
-import {Keyboard, ScrollView, StatusBar, StyleSheet} from 'react-native';
+import {useFocusEffect} from '@react-navigation/native';
+import React, {useCallback, useEffect, useState} from 'react';
+import {
+ Keyboard,
+ RefreshControl,
+ ScrollView,
+ StatusBar,
+ StyleSheet,
+} from 'react-native';
import Animated, {Easing, timing} from 'react-native-reanimated';
+import {useDispatch, useSelector} from 'react-redux';
import {
- DiscoverUsers,
+ Explore,
RecentSearches,
SearchBackground,
SearchBar,
@@ -13,6 +21,8 @@ import {
TabsGradient,
} from '../../components';
import {SEARCH_ENDPOINT, TAGG_TEXT_LIGHT_BLUE} from '../../constants';
+import {loadRecentlySearched, resetScreenType} from '../../store/actions';
+import {RootState} from '../../store/rootReducer';
import {ProfilePreviewType, ScreenType, UserType} from '../../types';
import {SCREEN_HEIGHT, SCREEN_WIDTH, StatusBarHeight} from '../../utils';
const NO_USER: UserType = {
@@ -20,18 +30,13 @@ const NO_USER: UserType = {
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} = useSelector(
+ const {recentSearches, explores} = useSelector(
(state: RootState) => state.taggUsers,
);
const [query, setQuery] = useState<string>('');
@@ -42,6 +47,19 @@ 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();
+
+ const onRefresh = useCallback(() => {
+ const refrestState = async () => {
+ dispatch(loadRecentlySearched());
+ };
+ setRefreshing(true);
+ refrestState().then(() => {
+ setRefreshing(false);
+ });
+ }, []);
useEffect(() => {
if (query.length < 3) {
@@ -76,8 +94,6 @@ 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.
@@ -135,7 +151,10 @@ const SearchScreen: React.FC = () => {
keyboardShouldPersistTaps={'always'}
stickyHeaderIndices={[4]}
contentContainerStyle={styles.contentContainer}
- showsVerticalScrollIndicator={false}>
+ showsVerticalScrollIndicator={false}
+ refreshControl={
+ <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
+ }>
<SearchHeader style={styles.header} {...{top}} />
<SearchBar
style={styles.searchBar}
@@ -146,13 +165,7 @@ const SearchScreen: React.FC = () => {
value={query}
{...{top, searching}}
/>
- {/* Removed for Alpha for now */}
- {/* <Explore /> */}
- <DiscoverUsers
- sectionTitle="Discover Users"
- users={taggUsers}
- screenType={ScreenType.Search}
- />
+ <Explore />
<SearchResultsBackground {...{top}}>
{results.length === 0 && recents.length !== 0 ? (
<RecentSearches