diff --git a/apps/mobile/src/components/LoginDialog/index.js b/apps/mobile/src/components/LoginDialog/index.js
index e6ff596a5..c0249304a 100644
--- a/apps/mobile/src/components/LoginDialog/index.js
+++ b/apps/mobile/src/components/LoginDialog/index.js
@@ -1,137 +1,192 @@
-import React, {createRef} from 'react';
-import {Modal, TouchableOpacity, View} from 'react-native';
+import React, {createRef, useState} from 'react';
+import {
+ ActivityIndicator,
+ Clipboard,
+ Linking,
+ Modal,
+ Text,
+ TouchableOpacity,
+ View,
+} from 'react-native';
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 {useTracked} from '../../provider/index';
import {eSendEvent} from '../../services/eventManager';
-import {eLoginDialogNavigateBack, eSetModalNavigator} from '../../services/events';
-import {getElevation, DDS} from '../../utils/utils';
-import ForgotPassword from '../../views/ForgotPassword';
-import Login from '../../views/Login';
-import Signup from '../../views/Signup';
-import {updateEvent} from '../DialogManager/recievers';
-import {NavigationContainer} from '@react-navigation/native';
-import {createStackNavigator} from '@react-navigation/stack';
-import Container from '../Container';
+import {eCloseLoginDialog} from '../../services/events';
+import {
+ validateEmail,
+ validatePass,
+ validateUsername,
+} from '../../services/validation';
+import {db, DDS, getElevation, ToastEvent} from '../../utils/utils';
+import CheckBox from '@react-native-community/checkbox';
-const Stack = createStackNavigator();
-const modalNavigatorRef2 = createRef();
+const LoginDialog = () => {
+ 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 (
-
- {
+ setAnimated(true);
+ }}
+ onRequestClose={close}
+ visible={visible}
+ transparent={true}>
+
-
-
-
-
-
- );
-};
-
-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 (
- {
- 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}>
-
+ {DDS.isTab ? (
this.close()}
+ onPress={close}
style={{
width: '100%',
height: '100%',
@@ -139,30 +194,656 @@ class LoginDialog extends React.Component {
zIndex: 1,
}}
/>
+ ) : null}
+
+
+
+
+
+ Hi there!
+
+
+ All your data is encrypted. This means that we cannot read
+ your data or recover your password.{' '}
+
+ If you lose your password, you can recover your data only
+ using your recovery key.{' '}
+
+
-
-
- {
- this.routeIndex = event.index;
+
+ Take a Sceenshot of QR-Code
+
+
+
+
+ {
+ 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,
+ }}>
+
+ {key}
+
+
+
+
+
+ You can also save your recovery key from app settings on any
+ device.
+
+
+ {
+ 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,
+ }}>
+
+ I have saved the key
+
+
+
+
+
+
+
+ <>
+ {
+ setVisible(false);
+ }}
+ style={{
+ width: 50,
+ height: 50,
+ marginLeft: 12,
+ position: 'absolute',
+ textAlignVertical: 'center',
+ marginBottom: 15,
+ }}
+ color={colors.heading}
+ />
+
+
+
+ {login ? 'Login' : 'Sign up'}
+ {'\n'}
+
+ {login
+ ? 'Get all your notes from other devices'
+ : 'Create an account to access notes anywhere.'}
+ {}
+
+
+
+
+ {login ? null : (
+ <>
+ {
+ 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 ? (
+
+ {' '}
+ Username is invalid
+
+ ) : null}
+ >
+ )}
+
+
+
+ {
+ 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}
/>
-
-
-
-
- );
- }
-}
+
+ {invalidEmail ? (
+
+ {' '}
+ Password is invalid
+
+ ) : null}
+
+
+
+
+ {
+ 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}
+ />
+
+ {
+ setSecureEntry(!secureEntry);
+ }}
+ style={{
+ width: 25,
+ }}
+ color={secureEntry ? colors.icon : colors.accent}
+ />
+
+ {invalidPassword ? (
+
+ {' '}
+ Password is invalid
+
+ ) : null}
+
+
+
+ {login ? null : (
+ <>
+ {
+ 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 ? (
+
+ {' '}
+ Passwords do not match
+
+ ) : null}
+ >
+ )}
+ {login ? null : (
+
+ {
+ setUserConsent(value);
+ }}
+ boxType="circle"
+ tintColors={{true: colors.accent, false: colors.icon}}
+ value={userConsent}
+ />
+
+ By signing up you agree to our{' '}
+
+ terms of service{' '}
+
+ and{' '}
+
+ privacy policy.
+
+
+
+ )}
+
+
+
+
+
+
+
+ {
+ setLogin(!login);
+ }}
+ activeOpacity={opacity}
+ style={{
+ alignSelf: 'center',
+ marginTop: 70,
+ height: 50,
+ }}>
+
+ {!login
+ ? 'Already have an account? '
+ : "Don't have an account? "}
+
+ {!login ? 'Login' : 'Sign up now'}
+
+
+
+
+ >
+
+
+
+
+ );
+};
export default LoginDialog;