aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShravya Ramesh <37447613+shravyaramesh@users.noreply.github.com>2021-02-11 14:06:04 -0800
committerGitHub <noreply@github.com>2021-02-11 14:06:04 -0800
commitbcede9945a10ce7bf67aeeaf7f94e1a8984e7c0d (patch)
tree229e130c90307507e68f17b016f81cf310822ccf /src
parentda61f04d037d92fce7cf9852a3be79eb41158d5a (diff)
parent2561d20e17a697726d6b77accf79c9da2d1f6ef6 (diff)
Merge branch 'master' into tma641-animation-tutorial
Diffstat (limited to 'src')
-rw-r--r--src/assets/icons/back-arrow.svg2
-rw-r--r--src/assets/images/logo-purple.pngbin0 -> 12702 bytes
-rw-r--r--src/components/common/FriendsButton.tsx1
-rw-r--r--src/components/common/SocialIcon.tsx4
-rw-r--r--src/components/common/SocialLinkModal.tsx91
-rw-r--r--src/components/common/TaggSquareButton.tsx41
-rw-r--r--src/components/taggs/Tagg.tsx2
-rw-r--r--src/components/taggs/TaggsBar.tsx2
-rw-r--r--src/components/taggs/TwitterTaggPost.tsx11
-rw-r--r--src/constants/api.ts2
-rw-r--r--src/routes/Routes.tsx34
-rw-r--r--src/routes/main/MainStackScreen.tsx125
-rw-r--r--src/screens/main/NotificationsScreen.tsx2
-rw-r--r--src/screens/onboarding/Login.tsx24
-rw-r--r--src/screens/onboarding/ProfileOnboarding.tsx47
-rw-r--r--src/screens/onboarding/UpdateRequired.tsx84
-rw-r--r--src/screens/onboarding/WelcomeScreen.tsx5
-rw-r--r--src/screens/onboarding/index.ts1
-rw-r--r--src/screens/profile/FriendsListScreen.tsx58
-rw-r--r--src/screens/profile/MomentCommentsScreen.tsx31
-rw-r--r--src/screens/suggestedPeople/SuggestedPeopleScreen.tsx1
-rw-r--r--src/services/CommonService.ts11
-rw-r--r--src/store/actions/user.ts27
-rw-r--r--src/store/initialStates.ts1
-rw-r--r--src/store/reducers/userReducer.ts5
25 files changed, 383 insertions, 229 deletions
diff --git a/src/assets/icons/back-arrow.svg b/src/assets/icons/back-arrow.svg
index aa203dea..16beae5a 100644
--- a/src/assets/icons/back-arrow.svg
+++ b/src/assets/icons/back-arrow.svg
@@ -1 +1 @@
-<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 385.86 696.76"><defs><style>.cls-1{fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-width:77.17px;}</style></defs><polyline class="cls-1" points="347.28 38.58 38.58 351.69 347.28 658.17"/></svg> \ No newline at end of file
+<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 385.86 696.76"><defs><style>.cls-1{fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:77.17px;}</style></defs><polyline class="cls-1" points="347.28 38.58 38.58 351.69 347.28 658.17" stroke="currentColor"/></svg> \ No newline at end of file
diff --git a/src/assets/images/logo-purple.png b/src/assets/images/logo-purple.png
new file mode 100644
index 00000000..48768f67
--- /dev/null
+++ b/src/assets/images/logo-purple.png
Binary files differ
diff --git a/src/components/common/FriendsButton.tsx b/src/components/common/FriendsButton.tsx
index c7f56e2d..243a551d 100644
--- a/src/components/common/FriendsButton.tsx
+++ b/src/components/common/FriendsButton.tsx
@@ -78,7 +78,6 @@ const styles = StyleSheet.create({
borderRadius: 3,
marginRight: '2%',
marginLeft: '1%',
- padding: 0,
backgroundColor: 'transparent',
},
requestedButtonTitle: {
diff --git a/src/components/common/SocialIcon.tsx b/src/components/common/SocialIcon.tsx
index 0cd5d2a7..8216b6ff 100644
--- a/src/components/common/SocialIcon.tsx
+++ b/src/components/common/SocialIcon.tsx
@@ -17,9 +17,9 @@ const SocialIcon: React.FC<SocialIconProps> = ({
}) => {
switch (social) {
case 'Instagram':
- var icon = require('../../assets/socials/instagram-icon-white-bg.png');
+ var icon = require('../../assets/socials/instagram-icon.png');
if (screenType === ScreenType.SuggestedPeople) {
- icon = require('../../assets/socials/instagram-icon.png');
+ icon = require('../../assets/socials/instagram-icon-white-bg.png');
}
break;
case 'Facebook':
diff --git a/src/components/common/SocialLinkModal.tsx b/src/components/common/SocialLinkModal.tsx
index 0bd5a0a5..20061cd0 100644
--- a/src/components/common/SocialLinkModal.tsx
+++ b/src/components/common/SocialLinkModal.tsx
@@ -1,10 +1,11 @@
import React from 'react';
import {Modal, StyleSheet, Text, TouchableOpacity, View} from 'react-native';
import {TextInput} from 'react-native-gesture-handler';
-import { ScreenType } from '../../types';
+import {ScreenType} from '../../types';
import {SocialIcon} from '.';
import CloseIcon from '../../assets/ionicons/close-outline.svg';
import {normalize, SCREEN_WIDTH} from '../../utils';
+import CenteredView from './CenteredView';
import TaggSquareButton from './TaggSquareButton';
interface SocialLinkModalProps {
@@ -35,59 +36,51 @@ const SocialLinkModal: React.FC<SocialLinkModalProps> = ({
};
return (
- <>
- <View style={styles.centeredView}>
- <Modal
- animationType="slide"
- transparent={true}
- visible={modalVisible}
- onRequestClose={() => {}}>
- <View style={styles.centeredView}>
- <View style={styles.modalView}>
- <TouchableOpacity
- style={styles.closeButton}
- onPress={onClosePress}>
- <CloseIcon height={'100%'} width={'100%'} color={'grey'} />
- </TouchableOpacity>
- <SocialIcon
- style={styles.icon}
- social={social}
- screenType={ScreenType.Profile}
- />
- <Text style={styles.titleLabel}>{social}</Text>
- <Text style={styles.descriptionLabel}>
- Insert your {social.toLowerCase()} username to link your{' '}
- {social.toLowerCase()} account to your profile!
- </Text>
- <TextInput
- autoCapitalize={'none'}
- autoCorrect={false}
- placeholder={'Username'}
- style={styles.textInput}
- onChangeText={setUsername}
- selectionColor={'grey'}
- value={username}
- />
- <TaggSquareButton
- title={'Submit'}
- onPress={onSubmit}
- mode={'gradient'}
- color={'white'}
- />
- </View>
+ <CenteredView>
+ <Modal
+ animationType="slide"
+ transparent={true}
+ visible={modalVisible}
+ onRequestClose={() => {}}>
+ <CenteredView>
+ <View style={styles.modalView}>
+ <TouchableOpacity style={styles.closeButton} onPress={onClosePress}>
+ <CloseIcon height={'100%'} width={'100%'} color={'grey'} />
+ </TouchableOpacity>
+ <SocialIcon
+ style={styles.icon}
+ social={social}
+ screenType={ScreenType.Profile}
+ />
+ <Text style={styles.titleLabel}>{social}</Text>
+ <Text style={styles.descriptionLabel}>
+ Insert your {social.toLowerCase()} username to link your{' '}
+ {social.toLowerCase()} account to your profile!
+ </Text>
+ <TextInput
+ autoCapitalize={'none'}
+ autoCorrect={false}
+ placeholder={'Username'}
+ style={styles.textInput}
+ onChangeText={setUsername}
+ selectionColor={'grey'}
+ value={username}
+ />
+ <TaggSquareButton
+ title={'Submit'}
+ onPress={onSubmit}
+ buttonStyle={'gradient'}
+ buttonColor={'white'}
+ labelColor={'white'}
+ />
</View>
- </Modal>
- </View>
- </>
+ </CenteredView>
+ </Modal>
+ </CenteredView>
);
};
const styles = StyleSheet.create({
- centeredView: {
- flex: 1,
- justifyContent: 'center',
- alignItems: 'center',
- },
modalView: {
width: SCREEN_WIDTH * 0.8,
backgroundColor: 'white',
diff --git a/src/components/common/TaggSquareButton.tsx b/src/components/common/TaggSquareButton.tsx
index 78a90554..817a2690 100644
--- a/src/components/common/TaggSquareButton.tsx
+++ b/src/components/common/TaggSquareButton.tsx
@@ -3,6 +3,7 @@ import {
GestureResponderEvent,
StyleSheet,
Text,
+ TextStyle,
TouchableOpacity,
ViewProps,
ViewStyle,
@@ -14,14 +15,16 @@ import {normalize, SCREEN_WIDTH} from '../../utils';
interface TaggSquareButtonProps extends ViewProps {
onPress: (event: GestureResponderEvent) => void;
title: string;
- mode: 'normal' | 'large' | 'gradient';
- color: 'purple' | 'white';
+ buttonStyle: 'normal' | 'large' | 'gradient';
+ buttonColor: 'purple' | 'white';
+ labelColor: 'white' | 'blue';
style?: ViewStyle;
+ labelStyle?: TextStyle;
}
const TaggSquareButton: React.FC<TaggSquareButtonProps> = (props) => {
- const buttonStyles = (() => {
- switch (props.color) {
+ const buttonColor = (() => {
+ switch (props.buttonColor) {
case 'purple':
return {backgroundColor: TAGG_PURPLE};
case 'white':
@@ -29,24 +32,37 @@ const TaggSquareButton: React.FC<TaggSquareButtonProps> = (props) => {
return {backgroundColor: 'white'};
}
})();
- switch (props.mode) {
+ const labelColor = (() => {
+ switch (props.labelColor) {
+ case 'white':
+ return {color: 'white'};
+ case 'blue':
+ default:
+ return {color: '#78A0EF'};
+ }
+ })();
+ switch (props.buttonStyle) {
case 'large':
return (
<TouchableOpacity
onPress={props.onPress}
- style={[styles.largeButton, buttonStyles, props.style]}>
- <Text style={styles.largeLabel}>{props.title}</Text>
+ style={[styles.largeButton, buttonColor, props.style]}>
+ <Text style={[styles.largeLabel, labelColor, props.labelStyle]}>
+ {props.title}
+ </Text>
</TouchableOpacity>
);
case 'gradient':
return (
- <TouchableOpacity onPress={props.onPress}>
+ <TouchableOpacity onPress={props.onPress} style={props.style}>
<LinearGradient
style={styles.gradientButton}
colors={BACKGROUND_GRADIENT_MAP[0]}
useAngle
angle={90}>
- <Text style={styles.gradientLabel}>{props.title}</Text>
+ <Text style={[styles.gradientLabel, props.labelStyle]}>
+ {props.title}
+ </Text>
</LinearGradient>
</TouchableOpacity>
);
@@ -55,8 +71,10 @@ const TaggSquareButton: React.FC<TaggSquareButtonProps> = (props) => {
return (
<TouchableOpacity
onPress={props.onPress}
- style={[styles.normalButton, buttonStyles, props.style]}>
- <Text style={styles.normalLabel}>{props.title}</Text>
+ style={[styles.normalButton, buttonColor, props.style]}>
+ <Text style={[styles.normalLabel, labelColor, props.labelStyle]}>
+ {props.title}
+ </Text>
</TouchableOpacity>
);
}
@@ -86,7 +104,6 @@ const styles = StyleSheet.create({
normalLabel: {
fontSize: normalize(20),
fontWeight: '500',
- color: '#78A0EF',
},
gradientButton: {
marginTop: '8%',
diff --git a/src/components/taggs/Tagg.tsx b/src/components/taggs/Tagg.tsx
index 29b55786..bb450b64 100644
--- a/src/components/taggs/Tagg.tsx
+++ b/src/components/taggs/Tagg.tsx
@@ -148,7 +148,7 @@ const Tagg: React.FC<TaggProps> = ({
<SocialIcon
style={styles.icon}
social={social}
- screenType={ScreenType.Profile}
+ screenType={screenType}
/>
{pickTheRightRingHere()}
</TouchableOpacity>
diff --git a/src/components/taggs/TaggsBar.tsx b/src/components/taggs/TaggsBar.tsx
index cc0c70a7..e7bdb0f2 100644
--- a/src/components/taggs/TaggsBar.tsx
+++ b/src/components/taggs/TaggsBar.tsx
@@ -77,7 +77,7 @@ const TaggsBar: React.FC<TaggsBarProps> = ({
);
i++;
}
- if (!userXId) {
+ if (!userXId && screenType !== ScreenType.SuggestedPeople) {
for (let social of unlinkedSocials) {
new_taggs.push(
<Tagg
diff --git a/src/components/taggs/TwitterTaggPost.tsx b/src/components/taggs/TwitterTaggPost.tsx
index 0cfde857..834e32ef 100644
--- a/src/components/taggs/TwitterTaggPost.tsx
+++ b/src/components/taggs/TwitterTaggPost.tsx
@@ -3,11 +3,7 @@ import {Image, Linking, StyleSheet, View} from 'react-native';
import {Text} from 'react-native-animatable';
import Hyperlink from 'react-native-hyperlink';
import LinearGradient from 'react-native-linear-gradient';
-import {
- AVATAR_DIM,
- TAGGS_GRADIENT,
- TAGG_LIGHT_BLUE,
-} from '../../constants';
+import {AVATAR_DIM, TAGGS_GRADIENT, TAGG_LIGHT_BLUE} from '../../constants';
import {TwitterPostType} from '../../types';
import {handleOpenSocialUrlOnBrowser, SCREEN_WIDTH} from '../../utils';
import {DateLabel, PostCarousel} from '../common';
@@ -94,7 +90,10 @@ const TwitterTaggPost: React.FC<TwitterTaggPostProps> = ({
<Text
style={styles.replyHandleText}
onPress={() =>
- openTwitterProfileLink(post.in_reply_to?.handle)
+ handleOpenSocialUrlOnBrowser(
+ post.in_reply_to?.handle,
+ 'Twitter',
+ )
}>
@{post.in_reply_to.handle}
</Text>
diff --git a/src/constants/api.ts b/src/constants/api.ts
index 32631be0..165bd550 100644
--- a/src/constants/api.ts
+++ b/src/constants/api.ts
@@ -3,7 +3,7 @@ const BASE_URL: string = 'http://127.0.0.1:8000/'; // local server
const API_URL: string = BASE_URL + 'api/';
export const LOGIN_ENDPOINT: string = API_URL + 'login/';
-export const LOGOUT_ENDPOINT: string = API_URL + 'logout/';
+export const VERSION_ENDPOINT: string = API_URL + 'version/';
export const REGISTER_ENDPOINT: string = API_URL + 'register/';
export const EDIT_PROFILE_ENDPOINT: string = API_URL + 'edit-profile/';
export const SEND_OTP_ENDPOINT: string = API_URL + 'send-otp/';
diff --git a/src/routes/Routes.tsx b/src/routes/Routes.tsx
index a5383a47..1cbc9bc5 100644
--- a/src/routes/Routes.tsx
+++ b/src/routes/Routes.tsx
@@ -1,18 +1,23 @@
-import React, {useEffect} from 'react';
-import NavigationBar from './tabs';
-import Onboarding from './onboarding';
-import {useSelector, useDispatch} from 'react-redux';
+import messaging from '@react-native-firebase/messaging';
+import React, {useEffect, useState} from 'react';
+import DeviceInfo from 'react-native-device-info';
+import SplashScreen from 'react-native-splash-screen';
+import {useDispatch, useSelector} from 'react-redux';
+import {fcmService, getLiveVersion} from '../services';
+import {
+ updateNewNotificationReceived,
+ updateNewVersionAvailable,
+} from '../store/actions';
import {RootState} from '../store/rootReducer';
import {userLogin} from '../utils';
-import SplashScreen from 'react-native-splash-screen';
-import messaging from '@react-native-firebase/messaging';
-import {updateNewNotificationReceived} from '../store/actions';
-import {fcmService} from '../services';
+import Onboarding from './onboarding';
+import NavigationBar from './tabs';
const Routes: React.FC = () => {
const {
user: {userId},
} = useSelector((state: RootState) => state.user);
+ const [newVersionAvailable, setNewVersionAvailable] = useState(false);
const dispatch = useDispatch();
/**
@@ -47,7 +52,18 @@ const Routes: React.FC = () => {
}
});
- return userId ? <NavigationBar /> : <Onboarding />;
+ useEffect(() => {
+ const checkVersion = async () => {
+ const liveVersion = await getLiveVersion();
+ if (liveVersion && liveVersion !== DeviceInfo.getVersion()) {
+ setNewVersionAvailable(true);
+ dispatch(updateNewVersionAvailable(true));
+ }
+ };
+ checkVersion();
+ });
+
+ return userId && !newVersionAvailable ? <NavigationBar /> : <Onboarding />;
};
export default Routes;
diff --git a/src/routes/main/MainStackScreen.tsx b/src/routes/main/MainStackScreen.tsx
index 2531eec7..0b762dff 100644
--- a/src/routes/main/MainStackScreen.tsx
+++ b/src/routes/main/MainStackScreen.tsx
@@ -2,6 +2,9 @@ import AsyncStorage from '@react-native-community/async-storage';
import {RouteProp} from '@react-navigation/native';
import {StackNavigationOptions} from '@react-navigation/stack';
import React, {useState} from 'react';
+import {StyleSheet, Text} from 'react-native';
+import {normalize} from 'react-native-elements';
+import BackIcon from '../../assets/icons/back-arrow.svg';
import {
AnimatedTutorial,
CaptionScreen,
@@ -107,16 +110,9 @@ const MainStackScreen: React.FC<MainStackProps> = ({route}) => {
<MainStack.Screen
name="Profile"
component={ProfileScreen}
+ initialParams={{screenType}}
options={{
- headerShown: true,
- headerTransparent: true,
- headerBackTitleVisible: false,
- headerTitle: '',
- headerTintColor: 'white',
- headerStyle: {height: AvatarHeaderHeight},
- }}
- initialParams={{
- screenType,
+ ...headerBarOptions('white', ''),
}}
/>
{isSearchTab &&
@@ -158,94 +154,133 @@ const MainStackScreen: React.FC<MainStackProps> = ({route}) => {
<MainStack.Screen
name="CaptionScreen"
component={CaptionScreen}
- options={{...modalStyle, gestureEnabled: false}}
+ options={{
+ ...modalStyle,
+ gestureEnabled: false,
+ }}
/>
<MainStack.Screen
name="SocialMediaTaggs"
component={SocialMediaTaggs}
+ initialParams={{screenType}}
options={{
- headerShown: true,
- headerTransparent: true,
- headerBackTitleVisible: false,
- headerTitle: '',
- headerTintColor: 'white',
+ ...headerBarOptions('white', ''),
headerStyle: {height: AvatarHeaderHeight},
}}
- initialParams={{screenType}}
/>
<MainStack.Screen
name="CategorySelection"
component={CategorySelection}
options={{
- headerShown: true,
- headerTransparent: true,
- headerBackTitleVisible: false,
- headerTintColor: 'white',
- headerTitle: '',
+ ...headerBarOptions('white', ''),
}}
/>
<MainStack.Screen
name="CreateCustomCategory"
component={CreateCustomCategory}
options={{
- headerShown: true,
- headerTransparent: true,
- headerBackTitleVisible: false,
- headerTintColor: 'white',
- headerTitle: '',
+ ...headerBarOptions('white', ''),
}}
/>
<MainStack.Screen
name="IndividualMoment"
component={IndividualMoment}
+ initialParams={{screenType}}
options={{
+ ...modalStyle,
gestureEnabled: false,
- cardStyle: {
- backgroundColor: 'rgba(0, 0, 0, 0.6)',
- },
- cardOverlayEnabled: true,
- cardStyleInterpolator: ({current: {progress}}) => ({
- cardStyle: {
- opacity: progress.interpolate({
- inputRange: [0, 0.5, 0.9, 1],
- outputRange: [0, 0.25, 0.7, 1],
- }),
- },
- }),
}}
- initialParams={{screenType}}
/>
<MainStack.Screen
name="MomentCommentsScreen"
component={MomentCommentsScreen}
initialParams={{screenType}}
+ options={{
+ ...headerBarOptions('black', 'Comments'),
+ }}
/>
<MainStack.Screen
name="MomentUploadPrompt"
component={MomentUploadPromptScreen}
+ initialParams={{screenType}}
options={{
...modalStyle,
}}
- initialParams={{screenType}}
/>
<MainStack.Screen
name="FriendsListScreen"
component={FriendsListScreen}
initialParams={{screenType}}
+ options={{
+ ...headerBarOptions('black', 'Friends'),
+ }}
/>
<MainStack.Screen
name="EditProfile"
component={EditProfile}
options={{
- headerShown: true,
- headerTitle: 'Edit Profile',
- headerTransparent: true,
- headerBackTitleVisible: false,
- headerTintColor: 'white',
+ ...headerBarOptions('white', 'Edit Profile'),
}}
/>
</MainStack.Navigator>
);
};
+export const headerBarOptions: (
+ color: 'white' | 'black',
+ title: string,
+) => StackNavigationOptions = (color, title) => ({
+ headerShown: true,
+ headerTransparent: true,
+ headerBackTitleVisible: false,
+ headerBackImage: () => (
+ <BackIcon
+ height={normalize(18)}
+ width={normalize(18)}
+ color={color}
+ style={styles.backButton}
+ />
+ ),
+ headerTitle: () => (
+ <Text style={[styles.headerTitle, {color: color}]}>{title}</Text>
+ ),
+});
+
+const modalStyle: StackNavigationOptions = {
+ cardStyle: {backgroundColor: 'rgba(80,80,80,0.6)'},
+ 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 styles = StyleSheet.create({
+ backButton: {
+ marginLeft: 30,
+ },
+ headerTitle: {
+ fontSize: normalize(16),
+ letterSpacing: normalize(1.3),
+ fontWeight: '700',
+ },
+ whiteHeaderTitle: {
+ fontSize: normalize(16),
+ letterSpacing: normalize(1.3),
+ fontWeight: '700',
+ color: 'white',
+ },
+ blackHeaderTitle: {
+ fontSize: normalize(16),
+ letterSpacing: normalize(1.3),
+ fontWeight: '700',
+ color: 'black',
+ },
+});
+
export default MainStackScreen;
diff --git a/src/screens/main/NotificationsScreen.tsx b/src/screens/main/NotificationsScreen.tsx
index f35bb22c..266ba3f9 100644
--- a/src/screens/main/NotificationsScreen.tsx
+++ b/src/screens/main/NotificationsScreen.tsx
@@ -5,6 +5,7 @@ import React, {useCallback, useEffect, useState} from 'react';
import {
RefreshControl,
SectionList,
+ StatusBar,
StyleSheet,
Text,
View,
@@ -146,6 +147,7 @@ const NotificationsScreen: React.FC = () => {
return (
<SafeAreaView>
+ <StatusBar barStyle={'dark-content'} />
<View style={styles.header}>
<Text style={styles.headerText}>Notifications</Text>
<View style={styles.underline} />
diff --git a/src/screens/onboarding/Login.tsx b/src/screens/onboarding/Login.tsx
index 2db039c1..450c5039 100644
--- a/src/screens/onboarding/Login.tsx
+++ b/src/screens/onboarding/Login.tsx
@@ -13,7 +13,7 @@ import {
TouchableOpacity,
} from 'react-native';
import SplashScreen from 'react-native-splash-screen';
-import {useDispatch} from 'react-redux';
+import {useDispatch, useSelector} from 'react-redux';
import {Background, TaggInput, TaggSquareButton} from '../../components';
import {LOGIN_ENDPOINT, usernameRegex} from '../../constants';
import {
@@ -25,8 +25,10 @@ import {
} from '../../constants/strings';
import {OnboardingStackParams} from '../../routes/onboarding';
import {fcmService} from '../../services';
+import {RootState} from '../../store/rootReducer';
import {BackgroundGradientType, UserType} from '../../types';
import {normalize, userLogin} from '../../utils';
+import UpdateRequired from './UpdateRequired';
type VerificationScreenRouteProp = RouteProp<OnboardingStackParams, 'Login'>;
type VerificationScreenNavigationProp = StackNavigationProp<
@@ -45,11 +47,6 @@ const Login: React.FC<LoginProps> = ({navigation}: LoginProps) => {
// ref for focusing on input fields
const inputRef = useRef();
- const NO_USER: UserType = {
- userId: '',
- username: '',
- };
-
// login form state
const [form, setForm] = React.useState({
username: '',
@@ -59,7 +56,7 @@ const Login: React.FC<LoginProps> = ({navigation}: LoginProps) => {
attemptedSubmit: false,
token: '',
});
- const [user, setUser] = useState<UserType>(NO_USER);
+ const {newVersionAvailable} = useSelector((state: RootState) => state.user);
/**
* Redux Store stuff
@@ -167,7 +164,6 @@ const Login: React.FC<LoginProps> = ({navigation}: LoginProps) => {
userLogin(dispatch, {userId: data.UserID, username});
fcmService.sendFcmTokenToServer();
} catch (err) {
- setUser(NO_USER);
console.log(data);
Alert.alert(ERROR_INVALID_LOGIN);
}
@@ -216,6 +212,8 @@ const Login: React.FC<LoginProps> = ({navigation}: LoginProps) => {
style={styles.container}
gradientType={BackgroundGradientType.Light}>
<StatusBar barStyle="light-content" />
+ {/* <Modal visible={newVersionAvailable} /> */}
+ <UpdateRequired visible={newVersionAvailable} />
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={styles.keyboardAvoidingView}>
@@ -259,14 +257,16 @@ const Login: React.FC<LoginProps> = ({navigation}: LoginProps) => {
<TaggSquareButton
onPress={handleLogin}
title={'Login'}
- mode={'normal'}
- color={'white'}
+ buttonStyle={'normal'}
+ buttonColor={'white'}
+ labelColor={'blue'}
/>
<TaggSquareButton
onPress={startRegistrationProcess}
title={'Sign up'}
- mode={'normal'}
- color={'purple'}
+ buttonStyle={'normal'}
+ buttonColor={'purple'}
+ labelColor={'blue'}
/>
</KeyboardAvoidingView>
</Background>
diff --git a/src/screens/onboarding/ProfileOnboarding.tsx b/src/screens/onboarding/ProfileOnboarding.tsx
index 26ad93a7..c173c8e3 100644
--- a/src/screens/onboarding/ProfileOnboarding.tsx
+++ b/src/screens/onboarding/ProfileOnboarding.tsx
@@ -1,38 +1,34 @@
-import React from 'react';
+import AsyncStorage from '@react-native-community/async-storage';
import {RouteProp} from '@react-navigation/native';
-import moment from 'moment';
import {StackNavigationProp} from '@react-navigation/stack';
+import moment from 'moment';
+import React, {useMemo} from 'react';
import {
- Text,
+ Alert,
+ Image,
StatusBar,
StyleSheet,
- Image,
+ Text,
TouchableOpacity,
- Alert,
View,
} from 'react-native';
+import ImagePicker from 'react-native-image-crop-picker';
+import Animated from 'react-native-reanimated';
import {
Background,
+ BirthDatePicker,
TaggBigInput,
- TaggInput,
TaggDropDown,
- BirthDatePicker,
+ TaggInput,
} from '../../components';
-import {OnboardingStackParams} from '../../routes/onboarding';
-import ImagePicker from 'react-native-image-crop-picker';
import {
- EDIT_PROFILE_ENDPOINT,
- websiteRegex,
bioRegex,
- genderRegex,
CLASS_YEAR_LIST,
+ EDIT_PROFILE_ENDPOINT,
+ genderRegex,
TAGG_PURPLE,
+ websiteRegex,
} from '../../constants';
-import AsyncStorage from '@react-native-community/async-storage';
-import {BackgroundGradientType} from '../../types';
-import {PickerSelectProps} from 'react-native-picker-select';
-import Animated from 'react-native-reanimated';
-import {SCREEN_WIDTH} from '../../utils';
import {
ERROR_DOUBLE_CHECK_CONNECTION,
ERROR_PROFILE_CREATION_SHORT,
@@ -41,6 +37,9 @@ import {
ERROR_UPLOAD_LARGE_PROFILE_PIC,
ERROR_UPLOAD_SMALL_PROFILE_PIC,
} from '../../constants/strings';
+import {OnboardingStackParams} from '../../routes/onboarding';
+import {BackgroundGradientType} from '../../types';
+import {SCREEN_WIDTH} from '../../utils';
type ProfileOnboardingScreenRouteProp = RouteProp<
OnboardingStackParams,
@@ -383,6 +382,15 @@ const ProfileOnboarding: React.FC<ProfileOnboardingProps> = ({
}
};
+ const profilePics = useMemo(() => {
+ return (
+ <View style={styles.profile}>
+ <LargeProfilePic />
+ <SmallProfilePic />
+ </View>
+ );
+ }, [form.largePic, form.smallPic]);
+
return (
<Animated.ScrollView bounces={false}>
<Background
@@ -390,10 +398,7 @@ const ProfileOnboarding: React.FC<ProfileOnboardingProps> = ({
gradientType={BackgroundGradientType.Light}
style={styles.container}>
<StatusBar barStyle="light-content" />
- <View style={styles.profile}>
- <LargeProfilePic />
- <SmallProfilePic />
- </View>
+ {profilePics}
<View style={styles.contentContainer}>
<TaggInput
accessibilityHint="Enter a website."
diff --git a/src/screens/onboarding/UpdateRequired.tsx b/src/screens/onboarding/UpdateRequired.tsx
new file mode 100644
index 00000000..adf7ba71
--- /dev/null
+++ b/src/screens/onboarding/UpdateRequired.tsx
@@ -0,0 +1,84 @@
+import React from 'react';
+import {Image, Linking, Modal, StyleSheet, View} from 'react-native';
+import {Text} from 'react-native-animatable';
+import {CenteredView, TaggSquareButton} from '../../components';
+import {normalize, SCREEN_WIDTH} from '../../utils';
+
+interface UpdateRequiredProps {
+ visible: boolean;
+}
+
+const UpdateRequired: React.FC<UpdateRequiredProps> = ({visible}) => {
+ return (
+ <Modal animationType={'slide'} transparent={true} visible={visible}>
+ <CenteredView>
+ <View style={styles.contentContainer}>
+ <Image
+ style={styles.logo}
+ source={require('../../assets/images/logo-purple.png')}
+ />
+ <Text style={styles.header}>Update Required</Text>
+ <Text style={styles.body}>
+ You have to update your app to continue using Tagg, please download
+ the latest version from the app store
+ </Text>
+ <TaggSquareButton
+ title={'Update'}
+ onPress={() => {
+ Linking.openURL(
+ 'https://apps.apple.com/us/app/tagg-discover-your-community/id1537853613',
+ );
+ }}
+ buttonStyle={'normal'}
+ buttonColor={'purple'}
+ labelColor={'white'}
+ labelStyle={styles.button}
+ />
+ </View>
+ </CenteredView>
+ </Modal>
+ );
+};
+
+const styles = StyleSheet.create({
+ contentContainer: {
+ marginTop: '20%',
+ width: SCREEN_WIDTH * 0.9,
+ backgroundColor: 'white',
+ borderRadius: 5,
+ padding: '10%',
+ alignItems: 'center',
+ shadowColor: '#000',
+ shadowOffset: {
+ width: 0,
+ height: 2,
+ },
+ shadowOpacity: 0.25,
+ shadowRadius: 3.84,
+ elevation: 5,
+ },
+ logo: {
+ width: normalize(60),
+ height: normalize(60),
+ marginBottom: '10%',
+ },
+ header: {
+ fontSize: normalize(17),
+ fontWeight: '700',
+ lineHeight: 20,
+ marginBottom: '5%',
+ },
+ body: {
+ fontSize: normalize(13),
+ color: 'grey',
+ lineHeight: 20,
+ textAlign: 'center',
+ width: SCREEN_WIDTH * 0.8,
+ marginBottom: '10%',
+ },
+ button: {
+ fontWeight: '700',
+ },
+});
+
+export default UpdateRequired;
diff --git a/src/screens/onboarding/WelcomeScreen.tsx b/src/screens/onboarding/WelcomeScreen.tsx
index bfb1a127..ae31f933 100644
--- a/src/screens/onboarding/WelcomeScreen.tsx
+++ b/src/screens/onboarding/WelcomeScreen.tsx
@@ -39,8 +39,9 @@ const WelcomeScreen: React.FC<WelcomeScreenProps> = ({navigation}) => {
<TaggSquareButton
onPress={handleNext}
title={'Next'}
- mode={'large'}
- color={'purple'}
+ buttonStyle={'large'}
+ buttonColor={'purple'}
+ labelColor={'white'}
style={styles.nextButton}
/>
</Background>
diff --git a/src/screens/onboarding/index.ts b/src/screens/onboarding/index.ts
index 14d0e405..596683e5 100644
--- a/src/screens/onboarding/index.ts
+++ b/src/screens/onboarding/index.ts
@@ -14,3 +14,4 @@ export {default as CategorySelection} from './CategorySelection';
export {default as AddWaitlistUserScreen} from './AddWaitlistUserScreen';
export {default as WaitlistSuccessScreen} from './WaitlistSuccessScreen';
export {default as CreateCustomCategory} from './CreateCustomCategory';
+export {default as UpdateRequired} from './UpdateRequired';
diff --git a/src/screens/profile/FriendsListScreen.tsx b/src/screens/profile/FriendsListScreen.tsx
index b2123f44..1cfef058 100644
--- a/src/screens/profile/FriendsListScreen.tsx
+++ b/src/screens/profile/FriendsListScreen.tsx
@@ -1,21 +1,14 @@
+import {RouteProp} from '@react-navigation/native';
import React from 'react';
-import {RouteProp, useNavigation} from '@react-navigation/native';
-import {TabsGradient, Friends} from '../../components';
-import {normalize, SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils';
-import {
- SafeAreaView,
- StyleSheet,
- Text,
- TouchableOpacity,
- View,
-} from 'react-native';
-import {ProfileStackParams} from '../../routes';
+import {SafeAreaView, StyleSheet, View} from 'react-native';
import {useSelector} from 'react-redux';
+import {Friends, TabsGradient} from '../../components';
+import {MainStackParams} from '../../routes';
import {RootState} from '../../store/rootReducer';
-import BackIcon from '../../assets/icons/back-arrow.svg';
+import {HeaderHeight, SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils';
type FriendsListScreenRouteProp = RouteProp<
- ProfileStackParams,
+ MainStackParams,
'FriendsListScreen'
>;
interface FriendsListScreenProps {
@@ -24,7 +17,6 @@ interface FriendsListScreenProps {
const FriendsListScreen: React.FC<FriendsListScreenProps> = ({route}) => {
const {userXId, screenType} = route.params;
- const navigation = useNavigation();
const {friends} = userXId
? useSelector((state: RootState) => state.userX[screenType][userXId])
@@ -33,17 +25,9 @@ const FriendsListScreen: React.FC<FriendsListScreenProps> = ({route}) => {
return (
<>
<SafeAreaView>
- <View style={styles.header}>
- <TouchableOpacity
- style={styles.headerButton}
- onPress={() => {
- navigation.pop();
- }}>
- <BackIcon height={'100%'} width={'100%'} color={'white'} />
- </TouchableOpacity>
- <Text style={styles.headerText}>Friends</Text>
+ <View style={styles.body}>
+ <Friends result={friends} screenType={screenType} userId={userXId} />
</View>
- <Friends result={friends} screenType={screenType} userId={userXId} />
</SafeAreaView>
<TabsGradient />
</>
@@ -55,31 +39,11 @@ const styles = StyleSheet.create({
backgroundColor: 'white',
height: '100%',
},
- header: {
- flexDirection: 'column',
- justifyContent: 'center',
- height: SCREEN_HEIGHT * 0.05,
- padding: '3%',
- paddingBottom: 0,
- marginTop: '1%',
- },
- headerText: {
- position: 'absolute',
- alignSelf: 'center',
- fontSize: normalize(18),
- fontWeight: '700',
- lineHeight: normalize(21.48),
- letterSpacing: normalize(1.3),
- },
- headerButton: {
- width: '5%',
- aspectRatio: 1,
- padding: 0,
- marginLeft: '5%',
- alignSelf: 'flex-start',
- marginBottom: '1%',
+ backButton: {
+ marginLeft: 10,
},
body: {
+ marginTop: HeaderHeight,
width: SCREEN_WIDTH,
height: SCREEN_HEIGHT * 0.8,
},
diff --git a/src/screens/profile/MomentCommentsScreen.tsx b/src/screens/profile/MomentCommentsScreen.tsx
index ec193db5..b0208f6f 100644
--- a/src/screens/profile/MomentCommentsScreen.tsx
+++ b/src/screens/profile/MomentCommentsScreen.tsx
@@ -1,15 +1,19 @@
import {RouteProp, useNavigation} from '@react-navigation/native';
-import React, {useState} from 'react';
-import {StyleSheet, Text, TouchableOpacity, View} from 'react-native';
+import React, {useEffect, useState} from 'react';
+import {StyleSheet, 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 CommentsContainer from '../../components/comments/CommentsContainer';
import {ADD_COMMENT_TEXT} from '../../constants/strings';
-import {MainStackParams} from '../../routes/main';
+import {headerBarOptions, MainStackParams} from '../../routes/main';
import {CommentType} from '../../types';
-import {normalize, SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils';
+import {
+ HeaderHeight,
+ normalize,
+ SCREEN_HEIGHT,
+ SCREEN_WIDTH,
+} from '../../utils';
/**
* Comments Screen for an image uploaded
@@ -39,19 +43,15 @@ const MomentCommentsScreen: React.FC<MomentCommentsScreenProps> = ({route}) => {
CommentType | undefined
>(undefined);
+ useEffect(() => {
+ navigation.setOptions({
+ ...headerBarOptions('black', `${commentsLength} Comments`),
+ });
+ }, [commentsLength, navigation]);
+
return (
<View style={styles.background}>
<SafeAreaView>
- <View style={styles.header}>
- <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}
@@ -110,6 +110,7 @@ const styles = StyleSheet.create({
fontWeight: '400',
},
body: {
+ marginTop: HeaderHeight,
width: SCREEN_WIDTH * 0.9,
height: SCREEN_HEIGHT * 0.8,
paddingTop: '3%',
diff --git a/src/screens/suggestedPeople/SuggestedPeopleScreen.tsx b/src/screens/suggestedPeople/SuggestedPeopleScreen.tsx
index 80463b79..4d0a9bd5 100644
--- a/src/screens/suggestedPeople/SuggestedPeopleScreen.tsx
+++ b/src/screens/suggestedPeople/SuggestedPeopleScreen.tsx
@@ -175,5 +175,4 @@ const styles = StyleSheet.create({
},
body: {},
});
-
export default SuggestedPeopleScreen;
diff --git a/src/services/CommonService.ts b/src/services/CommonService.ts
index dfbbf70e..9fa7417f 100644
--- a/src/services/CommonService.ts
+++ b/src/services/CommonService.ts
@@ -1,4 +1,5 @@
import RNFetchBlob from 'rn-fetch-blob';
+import {VERSION_ENDPOINT} from '../constants';
export const loadImageFromURL = async (url: string) => {
try {
@@ -20,3 +21,13 @@ export const loadImageFromURL = async (url: string) => {
return undefined;
}
};
+
+export const getLiveVersion = async () => {
+ try {
+ const response = await fetch(VERSION_ENDPOINT, {method: 'GET'});
+ return response.status === 200 ? await response.json() : undefined;
+ } catch (error) {
+ console.log(error);
+ return undefined;
+ }
+};
diff --git a/src/store/actions/user.ts b/src/store/actions/user.ts
index 50f810e4..9f1855ce 100644
--- a/src/store/actions/user.ts
+++ b/src/store/actions/user.ts
@@ -8,17 +8,23 @@ import {
editSPSwipeTutorial,
} from '../../services';
import {Action, ThunkAction} from '@reduxjs/toolkit';
+import {loadAvatar, loadCover, loadProfileInfo} from '../../services';
+import {UserType} from '../../types/types';
+import {getTokenOrLogout} from '../../utils';
import {
- userLoggedIn,
- userDetailsFetched,
- socialEdited,
profileCompletionStageUpdated,
setIsOnboardedUser,
setNewNotificationReceived,
+ setNewVersionAvailable,
setReplyPosted,
+ socialEdited,
+ userDetailsFetched,
+ userLoggedIn,
} from '../reducers';
import {getTokenOrLogout} from '../../utils';
import {spSwipeTutorialUpdated} from '../reducers/userReducer';
+import {RootState} from '../rootReducer';
+import {CommentThreadType} from './../../types/types';
/**
* Entry point to our store.
@@ -104,6 +110,21 @@ export const updateIsOnboardedUser = (
}
};
+export const updateNewVersionAvailable = (
+ newVersionAvailable: boolean,
+): ThunkAction<Promise<void>, RootState, unknown, Action<string>> => async (
+ dispatch,
+) => {
+ try {
+ dispatch({
+ type: setNewVersionAvailable.type,
+ payload: {newVersionAvailable},
+ });
+ } catch (error) {
+ console.log(error);
+ }
+};
+
export const updateNewNotificationReceived = (
newNotificationReceived: boolean,
): ThunkAction<Promise<void>, RootState, unknown, Action<string>> => async (
diff --git a/src/store/initialStates.ts b/src/store/initialStates.ts
index aa391713..93b1bc6e 100644
--- a/src/store/initialStates.ts
+++ b/src/store/initialStates.ts
@@ -45,6 +45,7 @@ export const NO_USER_DATA = {
avatar: <string | null>'',
cover: <string | null>'',
isOnboardedUser: false,
+ newVersionAvailable: false,
newNotificationReceived: false,
replyPosted: <CommentThreadType | undefined>undefined,
};
diff --git a/src/store/reducers/userReducer.ts b/src/store/reducers/userReducer.ts
index b353cc60..773977db 100644
--- a/src/store/reducers/userReducer.ts
+++ b/src/store/reducers/userReducer.ts
@@ -61,6 +61,10 @@ const userDataSlice = createSlice({
setReplyPosted: (state, action) => {
state.replyPosted = action.payload.replyPosted;
},
+
+ setNewVersionAvailable: (state, action) => {
+ state.newVersionAvailable = action.payload.newVersionAvailable;
+ },
},
});
@@ -70,6 +74,7 @@ export const {
socialEdited,
profileCompletionStageUpdated,
setIsOnboardedUser,
+ setNewVersionAvailable,
setNewNotificationReceived,
setReplyPosted,
spSwipeTutorialUpdated,