aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/assets/icons/findFriends/find-friends-blue-icon.svg1
-rw-r--r--src/components/friends/InviteFriendTile.tsx86
-rw-r--r--src/components/friends/index.ts1
-rw-r--r--src/components/profile/Friends.tsx162
-rw-r--r--src/constants/api.ts4
-rw-r--r--src/routes/main/MainStackNavigator.tsx3
-rw-r--r--src/routes/main/MainStackScreen.tsx14
-rw-r--r--src/screens/profile/FriendsListScreen.tsx3
-rw-r--r--src/screens/profile/InviteFriendsScreen.tsx330
-rw-r--r--src/screens/profile/index.ts1
-rw-r--r--src/store/actions/userFriends.ts21
-rw-r--r--src/utils/users.ts2
12 files changed, 601 insertions, 27 deletions
diff --git a/src/assets/icons/findFriends/find-friends-blue-icon.svg b/src/assets/icons/findFriends/find-friends-blue-icon.svg
new file mode 100644
index 00000000..26ca145d
--- /dev/null
+++ b/src/assets/icons/findFriends/find-friends-blue-icon.svg
@@ -0,0 +1 @@
+<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 216 216"><defs><style>.cls-1{fill:#08e2e2;}</style></defs><path class="cls-1" d="M104.28,135.51a58.59,58.59,0,1,0-8.85,8.86l21.79,21.26,9-8.27ZM58.62,145a46.22,46.22,0,1,1,46.21-46.21A46.23,46.23,0,0,1,58.62,145Z"/><path class="cls-1" d="M216,137.23a7.87,7.87,0,0,1-7.87,7.87H185.18v23a7.81,7.81,0,0,1-15.62,0v-23H146.62a7.87,7.87,0,0,1,0-15.73h22.94v-23a7.81,7.81,0,1,1,15.62,0v23h22.95A7.88,7.88,0,0,1,216,137.23Z"/></svg> \ No newline at end of file
diff --git a/src/components/friends/InviteFriendTile.tsx b/src/components/friends/InviteFriendTile.tsx
new file mode 100644
index 00000000..2d2b8e04
--- /dev/null
+++ b/src/components/friends/InviteFriendTile.tsx
@@ -0,0 +1,86 @@
+import React, {useState} from 'react';
+import {
+ StyleSheet,
+ Text,
+ TouchableOpacity,
+ TouchableWithoutFeedback,
+ View,
+} from 'react-native';
+import {useSelector} from 'react-redux';
+import {RootState} from '../../store/rootReducer';
+import {TAGG_LIGHT_BLUE} from '../../constants';
+import {inviteFriendService} from '../../services';
+import {normalize} from '../../utils';
+
+interface InviteFriendTileProps {
+ item: Object;
+}
+
+const InviteFriendTile: React.FC<InviteFriendTileProps> = ({item}) => {
+ const [invited, setInvited] = useState<boolean>(false);
+ const {profile} = useSelector((state: RootState) => state.user);
+ const handleInviteFriend = async () => {
+ const response = await inviteFriendService(
+ item.phoneNumber,
+ item.firstName,
+ item.lastName,
+ profile.name,
+ );
+ if (response) {
+ setInvited(response);
+ }
+ };
+
+ return (
+ <TouchableWithoutFeedback>
+ <View style={styles.container}>
+ <Text style={styles.label}>{item.firstName + ' ' + item.lastName}</Text>
+ <TouchableOpacity
+ disabled={invited}
+ style={styles.button}
+ onPress={handleInviteFriend}>
+ <Text style={styles.buttonTitle}>
+ {invited ? 'Invited' : 'Invite'}
+ </Text>
+ </TouchableOpacity>
+ </View>
+ </TouchableWithoutFeedback>
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ height: normalize(42),
+ backgroundColor: 'thistle',
+ },
+ label: {
+ fontWeight: '500',
+ fontSize: normalize(14),
+ },
+ button: {
+ alignSelf: 'center',
+ justifyContent: 'center',
+ alignItems: 'center',
+ width: 82,
+ height: 25,
+ borderColor: TAGG_LIGHT_BLUE,
+ borderWidth: 2,
+ borderRadius: 2,
+ padding: 0,
+ backgroundColor: 'transparent',
+ },
+ buttonTitle: {
+ color: TAGG_LIGHT_BLUE,
+ padding: 0,
+ fontSize: normalize(11),
+ fontWeight: '700',
+ lineHeight: normalize(13.13),
+ letterSpacing: normalize(0.6),
+ paddingHorizontal: '3.8%',
+ },
+});
+
+export default InviteFriendTile;
diff --git a/src/components/friends/index.ts b/src/components/friends/index.ts
new file mode 100644
index 00000000..42727784
--- /dev/null
+++ b/src/components/friends/index.ts
@@ -0,0 +1 @@
+export {default as InviteFriendTile} from './InviteFriendTile';
diff --git a/src/components/profile/Friends.tsx b/src/components/profile/Friends.tsx
index 7c7265c5..a1030b49 100644
--- a/src/components/profile/Friends.tsx
+++ b/src/components/profile/Friends.tsx
@@ -1,14 +1,18 @@
-import React from 'react';
-import {View, StyleSheet, ScrollView, Text} from 'react-native';
-import {ProfilePreviewType, ScreenType} from '../../types';
-import {ProfilePreview} from '../profile';
-import {normalize, SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils';
+import {useNavigation} from '@react-navigation/native';
+import React, {useEffect, useState} from 'react';
+import {ScrollView, StyleSheet, Text, View} from 'react-native';
+import {checkPermission, getAll} from 'react-native-contacts';
+import {TouchableOpacity} from 'react-native-gesture-handler';
+import {useDispatch, useSelector, useStore} from 'react-redux';
import {TAGG_LIGHT_BLUE} from '../../constants';
-import {RootState} from '../../store/rootReducer';
-import {useDispatch, useStore} from 'react-redux';
-import {handleUnfriend} from '../../utils/friends';
+import {usersFromContactsService} from '../../services';
import {NO_USER} from '../../store/initialStates';
-import {TouchableOpacity} from 'react-native-gesture-handler';
+import {RootState} from '../../store/rootReducer';
+import {ProfilePreviewType, ScreenType} from '../../types';
+import {normalize, SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils';
+import {handleAddFriend, handleUnfriend} from '../../utils/friends';
+import {ProfilePreview} from '../profile';
+import FindFriendsBlueIcon from '../../assets/icons/findFriends/find-friends-blue-icon.svg';
interface FriendsProps {
result: Array<ProfilePreviewType>;
@@ -17,16 +21,102 @@ interface FriendsProps {
}
const Friends: React.FC<FriendsProps> = ({result, screenType, userId}) => {
- const state: RootState = useStore().getState();
const dispatch = useDispatch();
+ const navigation = useNavigation();
+ const {user: loggedInUser = NO_USER} = useSelector(
+ (state: RootState) => state.user,
+ );
+ const state = useStore().getState();
+ const [usersFromContacts, setUsersFromContacts] = useState<
+ ProfilePreviewType[]
+ >([]);
+
+ const extractPhoneNumbers = async () => {
+ let phoneNumbers: Array<string> = [];
+ await getAll().then((contacts) => {
+ contacts.map((contact) => {
+ contact.phoneNumbers.map(async (phoneNumber) => {
+ phoneNumbers.push(await phoneNumber.number);
+ });
+ });
+ });
+ return phoneNumbers;
+ };
- const {user: loggedInUser = NO_USER} = state;
+ useEffect(() => {
+ const handleFindFriends = () => {
+ extractPhoneNumbers().then(async (phoneNumbers) => {
+ const permission = await checkPermission();
+ if (permission === 'authorized') {
+ let response = await usersFromContactsService(phoneNumbers);
+ await setUsersFromContacts(response.existing_tagg_users);
+ usersFromContacts.map((user) => console.log('user: ', user.username));
+ } else if (permission === 'undefined') {
+ navigation.navigate('RequestContactsAccess');
+ } else {
+ console.log('Go to settings');
+ }
+ });
+ };
+ handleFindFriends();
+ }, []);
+
+ const UsersFromContacts = () => (
+ <>
+ {usersFromContacts?.splice(0, 2).map((profilePreview) => (
+ <View key={profilePreview.id} style={styles.container}>
+ <View style={styles.friend}>
+ <ProfilePreview
+ {...{profilePreview}}
+ previewType={'Friend'}
+ screenType={screenType}
+ />
+ </View>
+ <TouchableOpacity
+ style={styles.button}
+ onPress={() => {
+ console.log('screentype: ', screenType);
+ handleAddFriend(screenType, profilePreview, dispatch, state).then(
+ (success) => {
+ if (success) {
+ let users = usersFromContacts;
+ setUsersFromContacts(
+ users.filter(
+ (user) => user.username !== profilePreview.username,
+ ),
+ );
+ }
+ },
+ );
+ }}>
+ <Text style={styles.buttonTitle}>Add Friend</Text>
+ </TouchableOpacity>
+ </View>
+ ))}
+ </>
+ );
return (
<>
<View style={styles.subheader}>
- {/* <Text style={styles.subheaderText}>Friends</Text> */}
+ <View style={styles.addFriendHeaderContainer}>
+ <Text style={[styles.subheaderText]}>Add Friends</Text>
+ <TouchableOpacity
+ style={{flexDirection: 'row'}}
+ onPress={() =>
+ navigation.navigate('InviteFriendsScreen', {
+ screenType: ScreenType.Profile,
+ })
+ }>
+ <FindFriendsBlueIcon width={20} height={20} />
+ <Text style={styles.findFriendsSubheaderText}>Find Friends</Text>
+ </TouchableOpacity>
+ </View>
+ <UsersFromContacts />
</View>
+ <Text style={[styles.subheaderText, styles.friendsSubheaderText]}>
+ Friends
+ </Text>
<ScrollView
keyboardShouldPersistTaps={'always'}
style={styles.scrollView}
@@ -41,7 +131,7 @@ const Friends: React.FC<FriendsProps> = ({result, screenType, userId}) => {
screenType={screenType}
/>
</View>
- {loggedInUser.userId === userId && (
+ {loggedInUser.userId !== userId && (
<TouchableOpacity
style={styles.button}
onPress={() =>
@@ -63,12 +153,19 @@ const styles = StyleSheet.create({
alignSelf: 'center',
width: SCREEN_WIDTH * 0.85,
},
+ firstScrollView: {},
scrollViewContent: {
alignSelf: 'center',
paddingBottom: SCREEN_HEIGHT / 7,
width: SCREEN_WIDTH * 0.85,
marginTop: '1%',
},
+ addFriendHeaderContainer: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ marginBottom: '3%',
+ marginTop: '2%',
+ },
header: {flexDirection: 'row'},
subheader: {
alignSelf: 'center',
@@ -81,6 +178,18 @@ const styles = StyleSheet.create({
fontWeight: '600',
lineHeight: normalize(14.32),
},
+ friendsSubheaderText: {
+ alignSelf: 'center',
+ width: SCREEN_WIDTH * 0.85,
+ marginVertical: '1%',
+ marginBottom: '2%',
+ },
+ findFriendsSubheaderText: {
+ color: '#08E2E2',
+ fontSize: normalize(12),
+ fontWeight: '600',
+ lineHeight: normalize(14.32),
+ },
container: {
alignSelf: 'center',
flexDirection: 'row',
@@ -94,7 +203,7 @@ const styles = StyleSheet.create({
alignSelf: 'center',
height: '100%',
},
- button: {
+ addFriendButton: {
alignSelf: 'center',
justifyContent: 'center',
alignItems: 'center',
@@ -104,10 +213,31 @@ const styles = StyleSheet.create({
borderWidth: 2,
borderRadius: 2,
padding: 0,
- backgroundColor: 'transparent',
+ backgroundColor: TAGG_LIGHT_BLUE,
+ },
+ addFriendButtonTitle: {
+ color: 'white',
+ padding: 0,
+ fontSize: normalize(11),
+ fontWeight: '700',
+ lineHeight: normalize(13.13),
+ letterSpacing: normalize(0.6),
+ paddingHorizontal: '3.8%',
+ },
+ button: {
+ alignSelf: 'center',
+ justifyContent: 'center',
+ alignItems: 'center',
+ width: 82,
+ height: '55%',
+ borderColor: TAGG_LIGHT_BLUE,
+ borderWidth: 2,
+ borderRadius: 2,
+ padding: 0,
+ backgroundColor: TAGG_LIGHT_BLUE,
},
buttonTitle: {
- color: TAGG_LIGHT_BLUE,
+ color: 'white',
padding: 0,
fontSize: normalize(11),
fontWeight: '700',
diff --git a/src/constants/api.ts b/src/constants/api.ts
index 34ef9a1c..eeac583e 100644
--- a/src/constants/api.ts
+++ b/src/constants/api.ts
@@ -33,6 +33,10 @@ export const DISCOVER_ENDPOINT: string = API_URL + 'discover/';
export const SEARCH_BUTTONS_ENDPOPINT: string = DISCOVER_ENDPOINT + 'search_buttons/';
export const WAITLIST_USER_ENDPOINT: string = API_URL + 'waitlist-user/';
export const COMMENT_THREAD_ENDPOINT: string = API_URL + 'reply/';
+export const USERS_FROM_CONTACTS_ENDPOINT: string =
+ API_URL + 'users-from-contacts/';
+export const INVITE_FRIEND_ENDPOINT: string =
+USERS_FROM_CONTACTS_ENDPOINT + 'invite_friend/';
// Suggested People
export const SP_USERS_ENDPOINT: string = API_URL + 'suggested_people/';
diff --git a/src/routes/main/MainStackNavigator.tsx b/src/routes/main/MainStackNavigator.tsx
index 142249ce..f848a5ab 100644
--- a/src/routes/main/MainStackNavigator.tsx
+++ b/src/routes/main/MainStackNavigator.tsx
@@ -84,6 +84,9 @@ export type MainStackParams = {
badge_title: string;
badge_img: string;
};
+ InviteFriendsScreen: {
+ screenType: ScreenType;
+ };
};
export const MainStack = createStackNavigator<MainStackParams>();
diff --git a/src/routes/main/MainStackScreen.tsx b/src/routes/main/MainStackScreen.tsx
index 95d45d32..4f655a64 100644
--- a/src/routes/main/MainStackScreen.tsx
+++ b/src/routes/main/MainStackScreen.tsx
@@ -15,6 +15,7 @@ import {
EditProfile,
FriendsListScreen,
IndividualMoment,
+ InviteFriendsScreen,
MomentCommentsScreen,
MomentUploadPromptScreen,
NotificationsScreen,
@@ -221,6 +222,19 @@ const MainStackScreen: React.FC<MainStackProps> = ({route}) => {
}}
/>
<MainStack.Screen
+ name="InviteFriendsScreen"
+ component={InviteFriendsScreen}
+ initialParams={{screenType}}
+ options={{
+ ...headerBarOptions('black', 'Invites'),
+ }}
+ />
+ <MainStack.Screen
+ name="RequestContactsAccess"
+ component={RequestContactsAccess}
+ initialParams={{screenType}}
+ />
+ <MainStack.Screen
name="EditProfile"
component={EditProfile}
options={{
diff --git a/src/screens/profile/FriendsListScreen.tsx b/src/screens/profile/FriendsListScreen.tsx
index 1cfef058..3016c767 100644
--- a/src/screens/profile/FriendsListScreen.tsx
+++ b/src/screens/profile/FriendsListScreen.tsx
@@ -1,6 +1,6 @@
import {RouteProp} from '@react-navigation/native';
import React from 'react';
-import {SafeAreaView, StyleSheet, View} from 'react-native';
+import {SafeAreaView, StatusBar, StyleSheet, View} from 'react-native';
import {useSelector} from 'react-redux';
import {Friends, TabsGradient} from '../../components';
import {MainStackParams} from '../../routes';
@@ -25,6 +25,7 @@ const FriendsListScreen: React.FC<FriendsListScreenProps> = ({route}) => {
return (
<>
<SafeAreaView>
+ <StatusBar barStyle="dark-content" />
<View style={styles.body}>
<Friends result={friends} screenType={screenType} userId={userXId} />
</View>
diff --git a/src/screens/profile/InviteFriendsScreen.tsx b/src/screens/profile/InviteFriendsScreen.tsx
new file mode 100644
index 00000000..8fc12a5e
--- /dev/null
+++ b/src/screens/profile/InviteFriendsScreen.tsx
@@ -0,0 +1,330 @@
+import React, {useEffect, useState} from 'react';
+import {
+ View,
+ Text,
+ TouchableOpacity,
+ SafeAreaView,
+ StyleSheet,
+ TextInput,
+ FlatList,
+ Keyboard,
+ Linking,
+ StatusBar,
+ TouchableWithoutFeedback,
+} from 'react-native';
+import {useDispatch, useStore} from 'react-redux';
+import {ProfilePreviewType, ScreenType} from '../../types';
+import {
+ handleAddFriend,
+ HeaderHeight,
+ normalize,
+ SCREEN_HEIGHT,
+ SCREEN_WIDTH,
+} from '../../utils';
+import {checkPermission, getAll} from 'react-native-contacts';
+import {usersFromContactsService} from '../../services/UserFriendsService';
+import {ProfilePreview, TabsGradient} from '../../components';
+import Animated from 'react-native-reanimated';
+import Icon from 'react-native-vector-icons/Feather';
+import {InviteFriendTile} from '../../components/friends';
+import {TAGG_LIGHT_BLUE} from '../../constants';
+const AnimatedIcon = Animated.createAnimatedComponent(Icon);
+
+interface InviteFriendsScreenProps {
+ screenType: ScreenType;
+}
+
+const InviteFriendsScreen: React.FC<InviteFriendsScreenProps> = ({
+ screenType,
+}) => {
+ const dispatch = useDispatch();
+ const state = useStore().getState();
+ const [usersFromContacts, setUsersFromContacts] = useState<
+ ProfilePreviewType[]
+ >([]);
+ const [nonUsersFromContacts, setNonUsersFromContacts] = useState<[]>([]);
+ type SearchResultType = {
+ usersFromContacts: ProfilePreviewType[];
+ nonUsersFromContacts: [];
+ };
+ const [results, setResults] = useState<SearchResultType>({
+ usersFromContacts: usersFromContacts,
+ nonUsersFromContacts: nonUsersFromContacts,
+ });
+ const [query, setQuery] = useState('');
+
+ const extractPhoneNumbers = async () => {
+ let phoneNumbers: Array<string> = [];
+ await getAll().then((contacts) => {
+ contacts.map((contact) => {
+ contact.phoneNumbers.map(async (phoneNumber) => {
+ phoneNumbers.push(await phoneNumber.number);
+ });
+ });
+ });
+ return phoneNumbers;
+ };
+
+ useEffect(() => {
+ const handleFindFriends = () => {
+ extractPhoneNumbers().then(async (phoneNumbers) => {
+ const permission = await checkPermission();
+ if (permission === 'authorized') {
+ let response = await usersFromContactsService(phoneNumbers);
+ await setUsersFromContacts(response.existing_tagg_users);
+ await setNonUsersFromContacts(response.invite_from_contacts);
+ usersFromContacts.map((user) => console.log('user: ', user.username));
+ setResults({
+ usersFromContacts: response.existing_tagg_users,
+ nonUsersFromContacts: response.invite_from_contacts,
+ });
+ } else {
+ Linking.openSettings();
+ }
+ });
+ };
+ handleFindFriends();
+ }, []);
+
+ /*
+ * Main handler for changes in query.
+ */
+ useEffect(() => {
+ const search = async () => {
+ if (query.length > 0) {
+ const searchResultsUsers = usersFromContacts.filter(
+ (item: ProfilePreviewType) => {
+ if (
+ item.first_name.includes(query) ||
+ item.last_name.includes(query) ||
+ item.username.includes(query)
+ ) {
+ return item;
+ }
+ },
+ );
+ const searchResultsNonUsers = nonUsersFromContacts.filter((item) => {
+ if (item.firstName.includes(query) || item.lastName.includes(query)) {
+ return item;
+ }
+ });
+ const sanitizedResult = {
+ usersFromContacts: searchResultsUsers,
+ nonUsersFromContacts: searchResultsNonUsers,
+ };
+ setResults(sanitizedResult);
+ } else {
+ setResults({
+ usersFromContacts: usersFromContacts,
+ nonUsersFromContacts: nonUsersFromContacts,
+ });
+ }
+ };
+ search();
+ }, [query]);
+
+ const UsersFromContacts = () => (
+ <>
+ <FlatList
+ style={{maxHeight: SCREEN_HEIGHT * 0.2}}
+ showsVerticalScrollIndicator={false}
+ data={results.usersFromContacts}
+ keyExtractor={(item) => item.username}
+ renderItem={({item}) => (
+ <View key={item.id} style={styles.ppContainer}>
+ <View style={styles.friend}>
+ <ProfilePreview
+ {...{profilePreview: item}}
+ previewType={'Friend'}
+ screenType={screenType}
+ />
+ </View>
+ <TouchableOpacity
+ style={styles.addFriendButton}
+ onPress={() => {
+ handleAddFriend(screenType, item, dispatch, state).then(
+ (success) => {
+ if (success) {
+ let users = usersFromContacts;
+ const filteredUsers = users.filter(
+ (user) => user.username !== item.username,
+ );
+ console.log('filteredUsers: ', filteredUsers);
+ setResults({
+ ...results,
+ usersFromContacts: filteredUsers,
+ });
+ }
+ },
+ );
+ }}>
+ <Text style={styles.addFriendButtonTitle}>Add Friend</Text>
+ </TouchableOpacity>
+ </View>
+ )}
+ />
+ </>
+ );
+
+ const NonUsersFromContacts = () => (
+ <>
+ <FlatList
+ showsVerticalScrollIndicator={false}
+ data={results.nonUsersFromContacts}
+ keyExtractor={(item) => item.phoneNumber}
+ renderItem={({item}) => <InviteFriendTile item={item} />}
+ />
+ </>
+ );
+
+ return (
+ <View style={{backgroundColor: 'white', height: SCREEN_HEIGHT}}>
+ <TouchableWithoutFeedback onPress={Keyboard.dismiss}>
+ <SafeAreaView>
+ <StatusBar barStyle="dark-content" />
+ <View style={styles.body}>
+ <View style={{width: 319, height: 42, alignSelf: 'center', marginBottom: '2%',}}>
+ <Text style={[styles.subheaderText, {textAlign: 'center'}]}>
+ Sharing is caring, invite friends, and create moments together!
+ </Text>
+ </View>
+ <View style={styles.container}>
+ <Animated.View style={styles.inputContainer}>
+ <AnimatedIcon
+ name="search"
+ color={'#7E7E7E'}
+ size={16}
+ style={styles.searchIcon}
+ />
+ <TextInput
+ style={[styles.input]}
+ placeholderTextColor={'#828282'}
+ clearButtonMode="while-editing"
+ autoCapitalize="none"
+ autoCorrect={false}
+ onChangeText={(text) => {
+ setQuery(text);
+ }}
+ onBlur={() => {
+ Keyboard.dismiss();
+ }}
+ onEndEditing={() => {
+ Keyboard.dismiss();
+ }}
+ value={query}
+ placeholder={'Search'}
+ />
+ </Animated.View>
+ </View>
+ <View style={styles.subheader}>
+ <Text style={[styles.subheaderText, {marginBottom: '5%'}]}>
+ Add Friends
+ </Text>
+ <UsersFromContacts />
+ </View>
+ <View style={styles.subheader}>
+ <Text style={styles.subheaderText}>Invite your friends!</Text>
+ <NonUsersFromContacts />
+ </View>
+ </View>
+ </SafeAreaView>
+ </TouchableWithoutFeedback>
+ <TabsGradient />
+ </View>
+ );
+};
+
+const styles = StyleSheet.create({
+ body: {
+ paddingTop: HeaderHeight * 1.3,
+ height: SCREEN_HEIGHT * 0.8,
+ backgroundColor: '#fff',
+ },
+ subheader: {
+ alignSelf: 'center',
+ width: SCREEN_WIDTH * 0.85,
+ marginBottom: '5%',
+ },
+ subheaderText: {
+ color: '#828282',
+ fontSize: normalize(12),
+ fontWeight: '600',
+ lineHeight: normalize(14.32),
+ },
+ container: {
+ alignSelf: 'center',
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ width: '100%',
+ height: normalize(42),
+ alignItems: 'center',
+ marginBottom: '3%',
+ marginHorizontal: 10,
+ },
+ ppContainer: {
+ alignSelf: 'center',
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ width: '100%',
+ height: normalize(42),
+ alignItems: 'center',
+ marginBottom: '5%',
+ marginHorizontal: 10,
+ },
+ inputContainer: {
+ flexGrow: 1,
+ flexDirection: 'row',
+ alignItems: 'center',
+ paddingHorizontal: 8,
+ marginHorizontal: '3%',
+ borderRadius: 20,
+ backgroundColor: '#F0F0F0',
+ height: 34,
+ },
+ searchIcon: {
+ marginRight: '5%',
+ },
+ input: {
+ flex: 1,
+ fontSize: normalize(16),
+ color: '#000',
+ letterSpacing: normalize(0.5),
+ },
+ cancelButton: {
+ height: '100%',
+ position: 'absolute',
+ justifyContent: 'center',
+ paddingHorizontal: 8,
+ },
+ cancelText: {
+ color: '#818181',
+ fontWeight: '500',
+ },
+ friend: {
+ alignSelf: 'center',
+ height: '100%',
+ },
+ addFriendButton: {
+ alignSelf: 'center',
+ justifyContent: 'center',
+ alignItems: 'center',
+ width: 82,
+ height: 25,
+ borderColor: TAGG_LIGHT_BLUE,
+ borderWidth: 2,
+ borderRadius: 2,
+ padding: 0,
+ backgroundColor: TAGG_LIGHT_BLUE,
+ },
+ addFriendButtonTitle: {
+ color: 'white',
+ padding: 0,
+ fontSize: normalize(11),
+ fontWeight: '700',
+ lineHeight: normalize(13.13),
+ letterSpacing: normalize(0.6),
+ paddingHorizontal: '3.8%',
+ },
+});
+
+export default InviteFriendsScreen;
diff --git a/src/screens/profile/index.ts b/src/screens/profile/index.ts
index 9d651729..f74946a6 100644
--- a/src/screens/profile/index.ts
+++ b/src/screens/profile/index.ts
@@ -6,3 +6,4 @@ export {default as MomentCommentsScreen} from './MomentCommentsScreen';
export {default as FriendsListScreen} from './FriendsListScreen';
export {default as EditProfile} from './EditProfile';
export {default as MomentUploadPromptScreen} from './MomentUploadPromptScreen';
+export {default as InviteFriendsScreen} from './InviteFriendsScreen';
diff --git a/src/store/actions/userFriends.ts b/src/store/actions/userFriends.ts
index 4f55acc8..9da3cb4a 100644
--- a/src/store/actions/userFriends.ts
+++ b/src/store/actions/userFriends.ts
@@ -1,4 +1,4 @@
-import {getTokenOrLogout} from '../../utils';
+import {getTokenOrLogout, userXInStore} from '../../utils';
import {RootState} from '../rootReducer';
import {
FriendshipStatusType,
@@ -90,6 +90,7 @@ export const friendUnfriendUser = (
export const addFriend = (
friend: ProfilePreviewType, // userX's profile preview
screenType: ScreenType, //screentype from content
+ state: RootState,
): ThunkAction<
Promise<boolean | undefined>,
RootState,
@@ -100,14 +101,16 @@ export const addFriend = (
const token = await getTokenOrLogout(dispatch);
const success = await addFriendService(friend.id, token);
if (success) {
- dispatch({
- type: userXFriendshipEdited.type,
- payload: {
- userId: friend.id,
- screenType,
- data: 'requested',
- },
- });
+ if (userXInStore(state, screenType, friend.id)) {
+ dispatch({
+ type: userXFriendshipEdited.type,
+ payload: {
+ userId: friend.id,
+ screen: screenType,
+ data: 'requested',
+ },
+ });
+ }
return true;
}
} catch (error) {
diff --git a/src/utils/users.ts b/src/utils/users.ts
index af4f3813..82bcb309 100644
--- a/src/utils/users.ts
+++ b/src/utils/users.ts
@@ -96,7 +96,7 @@ export const userXInStore = (
userId: string,
) => {
const userX = state.userX[screen];
- return userId in userX && userX[userId].user.userId;
+ return userX && userId in userX && userX[userId].user.userId;
};
/**