mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-22 22:49:45 +01:00
combine login & signup in one page
This commit is contained in:
@@ -1,137 +1,192 @@
|
|||||||
import React, {createRef} from 'react';
|
import React, {createRef, useState} from 'react';
|
||||||
import {Modal, TouchableOpacity, View} from 'react-native';
|
import {
|
||||||
|
ActivityIndicator,
|
||||||
|
Clipboard,
|
||||||
|
Linking,
|
||||||
|
Modal,
|
||||||
|
Text,
|
||||||
|
TouchableOpacity,
|
||||||
|
View,
|
||||||
|
} from 'react-native';
|
||||||
import * as Animatable from 'react-native-animatable';
|
import * as Animatable from 'react-native-animatable';
|
||||||
import {normalize} from '../../common/common';
|
import {TextInput} from 'react-native-gesture-handler';
|
||||||
|
import QRCode from 'react-native-qrcode-generator';
|
||||||
|
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||||
|
import {opacity, ph, pv, SIZE, WEIGHT} from '../../common/common';
|
||||||
|
import {Button} from '../../components/Button';
|
||||||
|
import Seperator from '../../components/Seperator';
|
||||||
|
import {Toast} from '../../components/Toast';
|
||||||
import {ACTIONS} from '../../provider/actions';
|
import {ACTIONS} from '../../provider/actions';
|
||||||
|
import {useTracked} from '../../provider/index';
|
||||||
import {eSendEvent} from '../../services/eventManager';
|
import {eSendEvent} from '../../services/eventManager';
|
||||||
import {eLoginDialogNavigateBack, eSetModalNavigator} from '../../services/events';
|
import {eCloseLoginDialog} from '../../services/events';
|
||||||
import {getElevation, DDS} from '../../utils/utils';
|
import {
|
||||||
import ForgotPassword from '../../views/ForgotPassword';
|
validateEmail,
|
||||||
import Login from '../../views/Login';
|
validatePass,
|
||||||
import Signup from '../../views/Signup';
|
validateUsername,
|
||||||
import {updateEvent} from '../DialogManager/recievers';
|
} from '../../services/validation';
|
||||||
import {NavigationContainer} from '@react-navigation/native';
|
import {db, DDS, getElevation, ToastEvent} from '../../utils/utils';
|
||||||
import {createStackNavigator} from '@react-navigation/stack';
|
import CheckBox from '@react-native-community/checkbox';
|
||||||
import Container from '../Container';
|
|
||||||
|
|
||||||
const Stack = createStackNavigator();
|
const LoginDialog = () => {
|
||||||
const modalNavigatorRef2 = createRef();
|
const [state, dispatch] = useTracked();
|
||||||
|
const colors = state.colors;
|
||||||
|
const [visible, setVisible] = useState(true);
|
||||||
|
const [animated, setAnimated] = useState(false);
|
||||||
|
const [status, setStatus] = useState('');
|
||||||
|
const [loggingIn, setLoggingIn] = useState(false);
|
||||||
|
const [email, setEmail] = useState(null);
|
||||||
|
const [password, setPassword] = useState(null);
|
||||||
|
const [invalidEmail, setInvalidEmail] = useState(false);
|
||||||
|
const [invalidPassword, setInvalidPassword] = useState(false);
|
||||||
|
const [username, setUsername] = useState(null);
|
||||||
|
const [invalidUsername, setInvalidUsername] = useState(false);
|
||||||
|
const [secureEntry, setSecureEntry] = useState(true);
|
||||||
|
const [confirmPassword, setConfirmPassword] = useState(false);
|
||||||
|
const [key, setKey] = useState('');
|
||||||
|
const [passwordReEnter, setPasswordReEnter] = useState(null);
|
||||||
|
const [failed, setFailed] = useState(false);
|
||||||
|
const [signingIn, setSigningIn] = useState(false);
|
||||||
|
const [login, setLogin] = useState(true);
|
||||||
|
const [modalVisible, setModalVisible] = useState(false);
|
||||||
|
const [userConsent, setUserConsent] = useState(false);
|
||||||
|
const _email = createRef();
|
||||||
|
const _pass = createRef();
|
||||||
|
const _username = createRef();
|
||||||
|
const _passConfirm = createRef();
|
||||||
|
const _passContainer = createRef();
|
||||||
|
|
||||||
|
function open() {
|
||||||
|
setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
setVisible(false);
|
||||||
|
setAnimated(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const loginUser = async () => {
|
||||||
|
if (
|
||||||
|
!password ||
|
||||||
|
password.length < 8 ||
|
||||||
|
!username ||
|
||||||
|
invalidPassword ||
|
||||||
|
invalidUsername
|
||||||
|
) {
|
||||||
|
ToastEvent.show('username or password is invalid', 'error');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setLoggingIn(true);
|
||||||
|
_username.current.blur();
|
||||||
|
_pass.current.blur();
|
||||||
|
setStatus('Logging in...');
|
||||||
|
|
||||||
|
try {
|
||||||
|
let res = await db.user.login(username.toLowerCase(), password);
|
||||||
|
console.log(res, username, password);
|
||||||
|
if (res) {
|
||||||
|
setStatus('Fetching data...');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
setTimeout(() => {
|
||||||
|
ToastEvent.show(e.message, 'error');
|
||||||
|
setLoggingIn(false);
|
||||||
|
}, 500);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let user;
|
||||||
|
|
||||||
|
try {
|
||||||
|
user = await db.user.get();
|
||||||
|
if (!user) throw new Error('Username or password incorrect');
|
||||||
|
dispatch({type: ACTIONS.USER, user: user});
|
||||||
|
dispatch({type: ACTIONS.SYNCING, syncing: true});
|
||||||
|
setStatus('Syncing your notes...');
|
||||||
|
await db.sync();
|
||||||
|
eSendEvent(eStartSyncer);
|
||||||
|
navigation.goBack();
|
||||||
|
dispatch({type: ACTIONS.ALL});
|
||||||
|
eSendEvent(refreshNotesPage);
|
||||||
|
dispatch({type: ACTIONS.SYNCING, syncing: false});
|
||||||
|
ToastEvent.show(`Logged in as ${username}`, 'success');
|
||||||
|
} catch (e) {
|
||||||
|
dispatch({type: ACTIONS.SYNCING, syncing: false});
|
||||||
|
setLoggingIn(false);
|
||||||
|
ToastEvent.show(e.message, 'error', 'local');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const signupUser = async () => {
|
||||||
|
if (!validateInfo) return;
|
||||||
|
|
||||||
|
setSigningIn(true);
|
||||||
|
setStatus('Creating your account...');
|
||||||
|
try {
|
||||||
|
await db.user.signup(username, email, password);
|
||||||
|
} catch (e) {
|
||||||
|
setSigningIn(false);
|
||||||
|
setFailed(true);
|
||||||
|
ToastEvent.show('Signup failed, Network Error', 'error', 'local');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let user;
|
||||||
|
try {
|
||||||
|
user = await db.user.user.get();
|
||||||
|
setStatus('Logging you in...');
|
||||||
|
let k = await db.user.key();
|
||||||
|
setKey(k.key);
|
||||||
|
setStatus('Setting up crenditials...');
|
||||||
|
dispatch({type: ACTIONS.USER, user: user});
|
||||||
|
eSendEvent(eStartSyncer);
|
||||||
|
setTimeout(() => {
|
||||||
|
setModalVisible(true);
|
||||||
|
}, 500);
|
||||||
|
} catch (e) {
|
||||||
|
setSigningIn(false);
|
||||||
|
setFailed(true);
|
||||||
|
ToastEvent.show('Login Failed, try again', 'error', 'local');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const ModalNavigator = ({onStateChange}) => {
|
|
||||||
return (
|
return (
|
||||||
<NavigationContainer
|
<Modal
|
||||||
onStateChange={onStateChange}
|
animated={true}
|
||||||
independent={true}
|
animationType="fade"
|
||||||
ref={modalNavigatorRef2}>
|
onShow={() => {
|
||||||
<Stack.Navigator
|
setAnimated(true);
|
||||||
initialRouteName="Login"
|
}}
|
||||||
screenOptions={{
|
onRequestClose={close}
|
||||||
headerShown: false,
|
visible={visible}
|
||||||
animationEnabled: false,
|
transparent={true}>
|
||||||
gestureEnabled: false,
|
<Animatable.View
|
||||||
cardOverlayEnabled: false,
|
transition={['opacity', 'scaleX', 'scaleY']}
|
||||||
cardShadowEnabled: false,
|
useNativeDriver={true}
|
||||||
|
duration={300}
|
||||||
|
iterationCount={1}
|
||||||
|
style={{
|
||||||
|
opacity: animated ? 1 : 0,
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: DDS.isTab ? 'rgba(0,0,0,0.3)' : colors.bg,
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
alignSelf: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
transform: [
|
||||||
|
{
|
||||||
|
scaleX: animated ? 1 : 0.95,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scaleY: animated ? 1 : 0.95,
|
||||||
|
},
|
||||||
|
],
|
||||||
}}>
|
}}>
|
||||||
<Stack.Screen
|
{DDS.isTab ? (
|
||||||
initialParams={{
|
|
||||||
root: false,
|
|
||||||
}}
|
|
||||||
name="Login"
|
|
||||||
component={Login}
|
|
||||||
/>
|
|
||||||
<Stack.Screen
|
|
||||||
initialParams={{
|
|
||||||
root: false,
|
|
||||||
}}
|
|
||||||
name="Signup"
|
|
||||||
component={Signup}
|
|
||||||
/>
|
|
||||||
<Stack.Screen
|
|
||||||
initialParams={{
|
|
||||||
root: false,
|
|
||||||
}}
|
|
||||||
name="ForgotPassword"
|
|
||||||
component={ForgotPassword}
|
|
||||||
/>
|
|
||||||
</Stack.Navigator>
|
|
||||||
</NavigationContainer>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
class LoginDialog extends React.Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
visible: false,
|
|
||||||
animated: false,
|
|
||||||
};
|
|
||||||
this.routeIndex = 0;
|
|
||||||
this.count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
open() {
|
|
||||||
updateEvent({type: ACTIONS.LOGIN_NAVIGATOR, enabled: true});
|
|
||||||
this.setState({
|
|
||||||
visible: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
close() {
|
|
||||||
this.setState({
|
|
||||||
visible: false,
|
|
||||||
animated: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {visible, animated} = this.state;
|
|
||||||
const {colors} = this.props;
|
|
||||||
return (
|
|
||||||
<Modal
|
|
||||||
animated={true}
|
|
||||||
animationType="fade"
|
|
||||||
onShow={() => {
|
|
||||||
eSendEvent(eSetModalNavigator, true);
|
|
||||||
this.setState({
|
|
||||||
animated: true,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
onRequestClose={() => {
|
|
||||||
if (!this.routeIndex || this.routeIndex === 0) {
|
|
||||||
updateEvent({type: ACTIONS.LOGIN_NAVIGATOR, enabled: false});
|
|
||||||
eSendEvent(eSetModalNavigator, false);
|
|
||||||
this.close();
|
|
||||||
} else {
|
|
||||||
eSendEvent(eLoginDialogNavigateBack);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
visible={visible}
|
|
||||||
transparent={true}>
|
|
||||||
<Animatable.View
|
|
||||||
transition={['opacity', 'scaleX', 'scaleY']}
|
|
||||||
useNativeDriver={true}
|
|
||||||
duration={300}
|
|
||||||
iterationCount={1}
|
|
||||||
style={{
|
|
||||||
opacity: animated ? 1 : 0,
|
|
||||||
flex: 1,
|
|
||||||
backgroundColor: DDS.isTab ? 'rgba(0,0,0,0.3)' : colors.bg,
|
|
||||||
width: '100%',
|
|
||||||
height: '100%',
|
|
||||||
alignSelf: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center',
|
|
||||||
transform: [
|
|
||||||
{
|
|
||||||
scaleX: animated ? 1 : 0.95,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scaleY: animated ? 1 : 0.95,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}}>
|
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
onPress={() => this.close()}
|
onPress={close}
|
||||||
style={{
|
style={{
|
||||||
width: '100%',
|
width: '100%',
|
||||||
height: '100%',
|
height: '100%',
|
||||||
@@ -139,30 +194,656 @@ class LoginDialog extends React.Component {
|
|||||||
zIndex: 1,
|
zIndex: 1,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
) : null}
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
height: '100%',
|
||||||
|
width: '100%',
|
||||||
|
backgroundColor: colors.bg,
|
||||||
|
}}>
|
||||||
|
<Modal
|
||||||
|
animated={true}
|
||||||
|
animationType="fade"
|
||||||
|
visible={modalVisible}
|
||||||
|
transparent={true}>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
backgroundColor: 'rgba(0,0,0,0.3)',
|
||||||
|
}}>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
backgroundColor: colors.bg,
|
||||||
|
paddingHorizontal: DDS.isTab ? '20%' : '0%',
|
||||||
|
height: '100%',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
}}>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontFamily: WEIGHT.bold,
|
||||||
|
fontSize: SIZE.xl,
|
||||||
|
color: colors.accent,
|
||||||
|
marginBottom: 25,
|
||||||
|
}}>
|
||||||
|
Hi there!
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontFamily: WEIGHT.regular,
|
||||||
|
fontSize: SIZE.sm,
|
||||||
|
maxWidth: '85%',
|
||||||
|
textAlign: 'center',
|
||||||
|
color: colors.pri,
|
||||||
|
}}>
|
||||||
|
All your data is encrypted. This means that we cannot read
|
||||||
|
your data or recover your password.{' '}
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
color: colors.errorText,
|
||||||
|
}}>
|
||||||
|
If you lose your password, you can recover your data only
|
||||||
|
using your recovery key.{' '}
|
||||||
|
</Text>
|
||||||
|
</Text>
|
||||||
|
|
||||||
<View
|
<Text
|
||||||
style={{
|
style={{
|
||||||
...getElevation(DDS.isTab ? 10 : 0),
|
fontFamily: WEIGHT.regular,
|
||||||
width: DDS.isTab ? normalize(600) : '100%',
|
fontSize: SIZE.sm,
|
||||||
height: DDS.isTab ? normalize(500) : '100%',
|
maxWidth: '85%',
|
||||||
borderRadius: DDS.isTab ? 5 : 0,
|
textAlign: 'center',
|
||||||
backgroundColor: colors.bg,
|
marginTop: 25,
|
||||||
padding: 8,
|
marginBottom: 10,
|
||||||
paddingVertical: 16,
|
color: colors.pri,
|
||||||
zIndex: 10,
|
}}>
|
||||||
}}>
|
Take a Sceenshot of QR-Code
|
||||||
<Container root={false}>
|
</Text>
|
||||||
<ModalNavigator
|
|
||||||
onStateChange={event => {
|
<QRCode
|
||||||
this.routeIndex = event.index;
|
value={key}
|
||||||
|
size={200}
|
||||||
|
bgColor="black"
|
||||||
|
fgColor="white"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TouchableOpacity
|
||||||
|
activeOpacity={0.6}
|
||||||
|
onPress={() => {
|
||||||
|
Clipboard.setString(key);
|
||||||
|
ToastEvent.show('Recovery key copied!', 'success', 'local');
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
flexDirection: 'row',
|
||||||
|
borderWidth: 1,
|
||||||
|
borderRadius: 5,
|
||||||
|
paddingVertical: 8,
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
marginTop: 15,
|
||||||
|
alignItems: 'center',
|
||||||
|
borderColor: colors.nav,
|
||||||
|
}}>
|
||||||
|
<Text
|
||||||
|
numberOfLines={2}
|
||||||
|
style={{
|
||||||
|
fontFamily: WEIGHT.regular,
|
||||||
|
fontSize: SIZE.sm,
|
||||||
|
width: '85%',
|
||||||
|
maxWidth: '85%',
|
||||||
|
paddingRight: 10,
|
||||||
|
color: colors.pri,
|
||||||
|
}}>
|
||||||
|
{key}
|
||||||
|
</Text>
|
||||||
|
<Icon color={colors.accent} size={SIZE.lg} name="clipboard" />
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
color: colors.pri,
|
||||||
|
fontSize: 10,
|
||||||
|
width: '85%',
|
||||||
|
maxWidth: '85%',
|
||||||
|
}}>
|
||||||
|
You can also save your recovery key from app settings on any
|
||||||
|
device.
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={() => {
|
||||||
|
DDS.isTab
|
||||||
|
? eSendEvent(eCloseLoginDialog)
|
||||||
|
: navigation.navigate('Home');
|
||||||
|
setModalVisible(false);
|
||||||
|
}}
|
||||||
|
activeOpacity={opacity}
|
||||||
|
style={{
|
||||||
|
...getElevation(5),
|
||||||
|
paddingVertical: pv + 5,
|
||||||
|
paddingHorizontal: ph,
|
||||||
|
borderRadius: 5,
|
||||||
|
width: '90%',
|
||||||
|
marginTop: 20,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
backgroundColor: colors.accent,
|
||||||
|
}}>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontFamily: WEIGHT.medium,
|
||||||
|
color: 'white',
|
||||||
|
fontSize: SIZE.sm,
|
||||||
|
}}>
|
||||||
|
I have saved the key
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<Toast context="local" />
|
||||||
|
</Modal>
|
||||||
|
|
||||||
|
<>
|
||||||
|
<Icon
|
||||||
|
name="arrow-left"
|
||||||
|
size={SIZE.xxxl}
|
||||||
|
onPress={() => {
|
||||||
|
setVisible(false);
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
marginLeft: 12,
|
||||||
|
position: 'absolute',
|
||||||
|
textAlignVertical: 'center',
|
||||||
|
marginBottom: 15,
|
||||||
|
}}
|
||||||
|
color={colors.heading}
|
||||||
|
/>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
justifyContent: 'center',
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
alignSelf: 'center',
|
||||||
|
paddingHorizontal: 12,
|
||||||
|
}}>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
marginBottom: 25,
|
||||||
|
}}>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
color: colors.accent,
|
||||||
|
fontFamily: WEIGHT.bold,
|
||||||
|
fontSize: SIZE.xxxl,
|
||||||
|
}}>
|
||||||
|
{login ? 'Login' : 'Sign up'}
|
||||||
|
{'\n'}
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
color: colors.icon,
|
||||||
|
fontSize: SIZE.md,
|
||||||
|
fontFamily: WEIGHT.regular,
|
||||||
|
}}>
|
||||||
|
{login
|
||||||
|
? 'Get all your notes from other devices'
|
||||||
|
: 'Create an account to access notes anywhere.'}
|
||||||
|
{}
|
||||||
|
</Text>
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{login ? null : (
|
||||||
|
<>
|
||||||
|
<TextInput
|
||||||
|
ref={_username}
|
||||||
|
onFocus={() => {
|
||||||
|
if (!invalidUsername) {
|
||||||
|
_username.current.setNativeProps({
|
||||||
|
style: {
|
||||||
|
borderColor: colors.accent,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
defaultValue={username}
|
||||||
|
onBlur={() => {
|
||||||
|
if (!validateUsername(username) && username?.length > 0) {
|
||||||
|
setInvalidUsername(true);
|
||||||
|
_username.current.setNativeProps({
|
||||||
|
style: {
|
||||||
|
color: colors.errorText,
|
||||||
|
borderColor: colors.errorText,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setInvalidUsername(false);
|
||||||
|
_username.current.setNativeProps({
|
||||||
|
style: {
|
||||||
|
borderColor: colors.nav,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
textContentType="username"
|
||||||
|
onChangeText={(value) => {
|
||||||
|
setUsername(value);
|
||||||
|
|
||||||
|
if (invalidUsername && validateUsername(username)) {
|
||||||
|
setInvalidUsername(false);
|
||||||
|
_username.current.setNativeProps({
|
||||||
|
style: {
|
||||||
|
color: colors.pri,
|
||||||
|
borderColor: colors.accent,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onSubmitEditing={() => {
|
||||||
|
if (!validateUsername(username)) {
|
||||||
|
setInvalidUsername(true);
|
||||||
|
_username.current.setNativeProps({
|
||||||
|
style: {
|
||||||
|
color: colors.errorText,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
paddingHorizontal: pv,
|
||||||
|
height: 50,
|
||||||
|
borderWidth: 1.5,
|
||||||
|
borderColor: colors.nav,
|
||||||
|
borderRadius: 5,
|
||||||
|
fontSize: SIZE.sm,
|
||||||
|
fontFamily: WEIGHT.regular,
|
||||||
|
}}
|
||||||
|
placeholder="Username (a-z _- 0-9)"
|
||||||
|
placeholderTextColor={colors.icon}
|
||||||
|
/>
|
||||||
|
{invalidUsername ? (
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
textAlign: 'right',
|
||||||
|
fontFamily: WEIGHT.regular,
|
||||||
|
textAlignVertical: 'bottom',
|
||||||
|
fontSize: SIZE.xs,
|
||||||
|
marginTop: 2.5,
|
||||||
|
}}>
|
||||||
|
<Icon
|
||||||
|
name="alert-circle-outline"
|
||||||
|
size={SIZE.xs}
|
||||||
|
color={colors.errorText}
|
||||||
|
/>{' '}
|
||||||
|
Username is invalid
|
||||||
|
</Text>
|
||||||
|
) : null}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Seperator />
|
||||||
|
|
||||||
|
<TextInput
|
||||||
|
ref={_email}
|
||||||
|
onFocus={() => {
|
||||||
|
if (!invalidEmail) {
|
||||||
|
_email.current.setNativeProps({
|
||||||
|
style: {
|
||||||
|
borderColor: colors.accent,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
|
defaultValue={email}
|
||||||
|
onBlur={() => {
|
||||||
|
if (!validateEmail(email) && email?.length > 0) {
|
||||||
|
setInvalidEmail(true);
|
||||||
|
_email.current.setNativeProps({
|
||||||
|
style: {
|
||||||
|
color: colors.errorText,
|
||||||
|
borderColor: colors.errorText,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setInvalidEmail(false);
|
||||||
|
_email.current.setNativeProps({
|
||||||
|
style: {
|
||||||
|
borderColor: colors.nav,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
textContentType="emailAddress"
|
||||||
|
onChangeText={(value) => {
|
||||||
|
setEmail(value);
|
||||||
|
if (invalidEmail && validateEmail(email)) {
|
||||||
|
setInvalidEmail(false);
|
||||||
|
_email.current.setNativeProps({
|
||||||
|
style: {
|
||||||
|
color: colors.pri,
|
||||||
|
borderColor: colors.accent,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onSubmitEditing={() => {
|
||||||
|
if (!validateEmail(email)) {
|
||||||
|
setInvalidEmail(true);
|
||||||
|
_email.current.setNativeProps({
|
||||||
|
style: {
|
||||||
|
color: colors.errorText,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
paddingHorizontal: pv,
|
||||||
|
height: 50,
|
||||||
|
borderWidth: 1.5,
|
||||||
|
borderColor: colors.nav,
|
||||||
|
borderRadius: 5,
|
||||||
|
fontSize: SIZE.sm,
|
||||||
|
fontFamily: WEIGHT.regular,
|
||||||
|
}}
|
||||||
|
placeholder="Email"
|
||||||
|
placeholderTextColor={colors.icon}
|
||||||
/>
|
/>
|
||||||
</Container>
|
|
||||||
</View>
|
{invalidEmail ? (
|
||||||
</Animatable.View>
|
<Text
|
||||||
</Modal>
|
style={{
|
||||||
);
|
textAlign: 'right',
|
||||||
}
|
fontFamily: WEIGHT.regular,
|
||||||
}
|
textAlignVertical: 'bottom',
|
||||||
|
fontSize: SIZE.xs,
|
||||||
|
marginTop: 2.5,
|
||||||
|
}}>
|
||||||
|
<Icon
|
||||||
|
name="alert-circle-outline"
|
||||||
|
size={SIZE.xs}
|
||||||
|
color={colors.errorText}
|
||||||
|
/>{' '}
|
||||||
|
Password is invalid
|
||||||
|
</Text>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
<Seperator />
|
||||||
|
|
||||||
|
<View
|
||||||
|
ref={_passContainer}
|
||||||
|
style={{
|
||||||
|
borderWidth: 1.5,
|
||||||
|
borderColor: colors.nav,
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
borderRadius: 5,
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
alignItems: 'center',
|
||||||
|
}}>
|
||||||
|
<TextInput
|
||||||
|
ref={_pass}
|
||||||
|
onFocus={() => {
|
||||||
|
if (!invalidPassword) {
|
||||||
|
_passContainer.current?.setNativeProps({
|
||||||
|
style: {
|
||||||
|
borderColor: colors.accent,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
defaultValue={password}
|
||||||
|
onBlur={() => {
|
||||||
|
if (!validatePass(password) && password?.length > 0) {
|
||||||
|
setInvalidPassword(true);
|
||||||
|
_pass.current.setNativeProps({
|
||||||
|
style: {
|
||||||
|
color: colors.errorText,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
_passContainer.current?.setNativeProps({
|
||||||
|
style: {
|
||||||
|
borderColor: colors.errorText,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setInvalidPassword(false);
|
||||||
|
_passContainer.current?.setNativeProps({
|
||||||
|
style: {
|
||||||
|
borderColor: colors.nav,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onChangeText={(value) => {
|
||||||
|
setPassword(value);
|
||||||
|
if (invalidPassword && validatePass(password)) {
|
||||||
|
setInvalidPassword(false);
|
||||||
|
_pass.current.setNativeProps({
|
||||||
|
style: {
|
||||||
|
color: colors.pri,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onSubmitEditing={() => {
|
||||||
|
if (!validatePass(password)) {
|
||||||
|
setInvalidPassword(true);
|
||||||
|
_pass.current.setNativeProps({
|
||||||
|
style: {
|
||||||
|
color: colors.errorText,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
paddingHorizontal: 0,
|
||||||
|
height: 50,
|
||||||
|
fontSize: SIZE.sm,
|
||||||
|
fontFamily: WEIGHT.regular,
|
||||||
|
width: '85%',
|
||||||
|
maxWidth: '85%',
|
||||||
|
}}
|
||||||
|
secureTextEntry={secureEntry}
|
||||||
|
placeholder="Password (6+ characters)"
|
||||||
|
placeholderTextColor={colors.icon}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Icon
|
||||||
|
name="eye"
|
||||||
|
size={20}
|
||||||
|
onPress={() => {
|
||||||
|
setSecureEntry(!secureEntry);
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
width: 25,
|
||||||
|
}}
|
||||||
|
color={secureEntry ? colors.icon : colors.accent}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
{invalidPassword ? (
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
textAlign: 'right',
|
||||||
|
fontFamily: WEIGHT.regular,
|
||||||
|
textAlignVertical: 'bottom',
|
||||||
|
fontSize: SIZE.xs,
|
||||||
|
marginTop: 2.5,
|
||||||
|
}}>
|
||||||
|
<Icon
|
||||||
|
name="alert-circle-outline"
|
||||||
|
size={SIZE.xs}
|
||||||
|
color={colors.errorText}
|
||||||
|
/>{' '}
|
||||||
|
Password is invalid
|
||||||
|
</Text>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
<Seperator />
|
||||||
|
|
||||||
|
{login ? null : (
|
||||||
|
<>
|
||||||
|
<TextInput
|
||||||
|
ref={_passConfirm}
|
||||||
|
editable={password && !invalidPassword ? true : false}
|
||||||
|
defaultValue={passwordReEnter}
|
||||||
|
onChangeText={(value) => {
|
||||||
|
setPasswordReEnter(value);
|
||||||
|
if (value !== password) {
|
||||||
|
setConfirmPassword(false);
|
||||||
|
_passConfirm.current.setNativeProps({
|
||||||
|
style: {
|
||||||
|
borderColor: colors.errorText,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
_pass.current.setNativeProps({
|
||||||
|
style: {
|
||||||
|
borderColor: colors.errorText,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setConfirmPassword(true);
|
||||||
|
_passConfirm.current.setNativeProps({
|
||||||
|
style: {
|
||||||
|
borderColor: colors.accent,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
_pass.current.setNativeProps({
|
||||||
|
style: {
|
||||||
|
borderColor: colors.accent,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onFocus={() => {
|
||||||
|
_passConfirm.current.setNativeProps({
|
||||||
|
style: {
|
||||||
|
borderColor: colors.accent,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
paddingHorizontal: pv,
|
||||||
|
borderWidth: 1.5,
|
||||||
|
height: 50,
|
||||||
|
borderColor: colors.nav,
|
||||||
|
borderRadius: 5,
|
||||||
|
fontSize: SIZE.sm,
|
||||||
|
fontFamily: WEIGHT.regular,
|
||||||
|
}}
|
||||||
|
secureTextEntry={secureEntry}
|
||||||
|
placeholder="Confirm Password"
|
||||||
|
placeholderTextColor={colors.icon}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{password && !invalidPassword && !confirmPassword ? (
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
textAlign: 'right',
|
||||||
|
fontFamily: WEIGHT.regular,
|
||||||
|
textAlignVertical: 'bottom',
|
||||||
|
fontSize: SIZE.xs,
|
||||||
|
marginTop: 2.5,
|
||||||
|
}}>
|
||||||
|
<Icon
|
||||||
|
name="alert-circle-outline"
|
||||||
|
size={SIZE.xs}
|
||||||
|
color={colors.errorText}
|
||||||
|
/>{' '}
|
||||||
|
Passwords do not match
|
||||||
|
</Text>
|
||||||
|
) : null}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{login ? null : (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: 'row',
|
||||||
|
width: '100%',
|
||||||
|
}}>
|
||||||
|
<CheckBox
|
||||||
|
onValueChange={(value) => {
|
||||||
|
setUserConsent(value);
|
||||||
|
}}
|
||||||
|
boxType="circle"
|
||||||
|
tintColors={{true: colors.accent, false: colors.icon}}
|
||||||
|
value={userConsent}
|
||||||
|
/>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: SIZE.xs + 1,
|
||||||
|
fontFamily: WEIGHT.regular,
|
||||||
|
color: colors.pri,
|
||||||
|
maxWidth: '90%',
|
||||||
|
}}>
|
||||||
|
By signing up you agree to our{' '}
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
color: colors.accent,
|
||||||
|
}}>
|
||||||
|
terms of service{' '}
|
||||||
|
</Text>
|
||||||
|
and{' '}
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
color: colors.accent,
|
||||||
|
}}>
|
||||||
|
privacy policy.
|
||||||
|
</Text>
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Seperator />
|
||||||
|
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
}}>
|
||||||
|
<Button
|
||||||
|
title={login ? 'Login' : 'Create Account'}
|
||||||
|
onPress={login ? loginUser : signupUser}
|
||||||
|
width="100%"
|
||||||
|
height={50}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={() => {
|
||||||
|
setLogin(!login);
|
||||||
|
}}
|
||||||
|
activeOpacity={opacity}
|
||||||
|
style={{
|
||||||
|
alignSelf: 'center',
|
||||||
|
marginTop: 70,
|
||||||
|
height: 50,
|
||||||
|
}}>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: SIZE.xs + 1,
|
||||||
|
fontFamily: WEIGHT.regular,
|
||||||
|
color: colors.pri,
|
||||||
|
height: 25,
|
||||||
|
}}>
|
||||||
|
{!login
|
||||||
|
? 'Already have an account? '
|
||||||
|
: "Don't have an account? "}
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
color: colors.accent,
|
||||||
|
}}>
|
||||||
|
{!login ? 'Login' : 'Sign up now'}
|
||||||
|
</Text>
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</>
|
||||||
|
</View>
|
||||||
|
<Toast context="local" />
|
||||||
|
</Animatable.View>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default LoginDialog;
|
export default LoginDialog;
|
||||||
|
|||||||
Reference in New Issue
Block a user