Refactor
This commit is contained in:
parent
94fdf44260
commit
b13a88e9dc
|
@ -5,3 +5,5 @@ export const ATTEMPTS_KEY = 'kAttempts';
|
|||
export const LOCAL_AUTHENTICATE_EMITTER = 'LOCAL_AUTHENTICATE';
|
||||
|
||||
export const PASSCODE_LENGTH = 6;
|
||||
export const MAX_ATTEMPTS = 6;
|
||||
export const TIME_TO_LOCK = 10000;
|
||||
|
|
|
@ -2,6 +2,7 @@ import React, { useState, forwardRef, useImperativeHandle } from 'react';
|
|||
import { View } from 'react-native';
|
||||
import { Col, Row, Grid } from 'react-native-easy-grid';
|
||||
import _ from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import styles from './styles';
|
||||
import Button from './Button';
|
||||
|
@ -17,10 +18,6 @@ const Base = forwardRef(({
|
|||
}, ref) => {
|
||||
const [passcode, setPasscode] = useState('');
|
||||
|
||||
const handleEnd = () => {
|
||||
alert('END')
|
||||
};
|
||||
|
||||
const wrongPasscode = () => {
|
||||
setPasscode('');
|
||||
console.log('TODO: wrong animation and vibration');
|
||||
|
@ -119,4 +116,11 @@ const Base = forwardRef(({
|
|||
);
|
||||
});
|
||||
|
||||
Base.propTypes = {
|
||||
theme: PropTypes.string,
|
||||
type: PropTypes.string,
|
||||
previousPasscode: PropTypes.string,
|
||||
onEndProcess: PropTypes.string
|
||||
};
|
||||
|
||||
export default Base;
|
||||
|
|
|
@ -1,44 +1,31 @@
|
|||
import React from 'react';
|
||||
import { TouchableHighlight, Text } from 'react-native';
|
||||
import { Text } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import styles from './styles';
|
||||
import { themes } from '../../constants/colors';
|
||||
import Touch from '../../utils/touch';
|
||||
|
||||
const ButtonNumber = ({
|
||||
const Button = ({
|
||||
text, disabled, theme, onPress
|
||||
}) => (
|
||||
<TouchableHighlight
|
||||
style={[
|
||||
styles.buttonCircle,
|
||||
{ backgroundColor: themes[theme].backgroundColor },
|
||||
// this.props.styleButtonCircle,
|
||||
]}
|
||||
// underlayColor={this.props.numbersButtonOverlayColor}
|
||||
<Touch
|
||||
style={[styles.buttonCircle, { backgroundColor: themes[theme].backgroundColor, borderColor: themes[theme].borderColor }]}
|
||||
disabled={disabled}
|
||||
// onShowUnderlay={() => this.setState({ textButtonSelected: text })}
|
||||
// onHideUnderlay={() => this.setState({ textButtonSelected: "" })}
|
||||
// onPress={() => {
|
||||
// this.onPressButtonNumber(text);
|
||||
// }}
|
||||
theme={theme}
|
||||
onPress={() => onPress && onPress(text)}
|
||||
// accessible
|
||||
// accessibilityLabel={text}
|
||||
>
|
||||
<Text
|
||||
style={[
|
||||
styles.text,
|
||||
// this.props.styleTextButton,
|
||||
// {
|
||||
// opacity: opacity,
|
||||
// color: this.state.textButtonSelected === text
|
||||
// ? this.props.styleColorButtonTitleSelected
|
||||
// : this.props.styleColorButtonTitle
|
||||
// }
|
||||
]}
|
||||
>
|
||||
<Text style={[styles.text, { color: themes[theme].titleText }]}>
|
||||
{text}
|
||||
</Text>
|
||||
</TouchableHighlight>
|
||||
</Touch>
|
||||
);
|
||||
|
||||
export default ButtonNumber;
|
||||
Button.propTypes = {
|
||||
text: PropTypes.string,
|
||||
theme: PropTypes.string,
|
||||
disabled: PropTypes.bool,
|
||||
onPress: PropTypes.func
|
||||
};
|
||||
|
||||
export default Button;
|
||||
|
|
|
@ -10,7 +10,6 @@ const SIZE_FULL = 12;
|
|||
|
||||
const Dots = ({
|
||||
passcode,
|
||||
moveData,
|
||||
showError,
|
||||
changeScreen,
|
||||
attemptFailed,
|
||||
|
|
|
@ -3,18 +3,12 @@ import {
|
|||
View, StyleSheet, Text
|
||||
} from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
import moment from 'moment';
|
||||
import { useAsyncStorage } from '@react-native-community/async-storage';
|
||||
|
||||
import sharedStyles from '../../views/Styles';
|
||||
import { themes } from '../../constants/colors';
|
||||
import {
|
||||
PASSCODE_KEY, PASSCODE_LENGTH, LOCAL_AUTHENTICATE_EMITTER, LOCKED_OUT_TIMER_KEY, ATTEMPTS_KEY
|
||||
} from '../../constants/localAuthentication';
|
||||
import { resetAttempts } from '../../utils/localAuthentication';
|
||||
import { TYPE } from './constants';
|
||||
|
||||
const TIME_TO_LOCK = 10000;
|
||||
import { getLockedUntil } from './utils';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
@ -37,8 +31,6 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
const getLockedUntil = t => moment(t).add(TIME_TO_LOCK);
|
||||
|
||||
const getDiff = t => new Date(t) - new Date();
|
||||
|
||||
const Timer = ({ time, theme, setStatus }) => {
|
||||
|
@ -72,11 +64,10 @@ const Timer = ({ time, theme, setStatus }) => {
|
|||
|
||||
const Locked = ({ theme, setStatus }) => {
|
||||
const [lockedUntil, setLockedUntil] = useState(null);
|
||||
const { getItem } = useAsyncStorage(LOCKED_OUT_TIMER_KEY);
|
||||
|
||||
const readItemFromStorage = async() => {
|
||||
const item = await getItem();
|
||||
setLockedUntil(getLockedUntil(item));
|
||||
const l = await getLockedUntil();
|
||||
setLockedUntil(l);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -91,4 +82,15 @@ const Locked = ({ theme, setStatus }) => {
|
|||
);
|
||||
};
|
||||
|
||||
Locked.propTypes = {
|
||||
theme: PropTypes.string,
|
||||
setStatus: PropTypes.func
|
||||
};
|
||||
|
||||
Timer.propTypes = {
|
||||
time: PropTypes.string,
|
||||
theme: PropTypes.string,
|
||||
setStatus: PropTypes.func
|
||||
};
|
||||
|
||||
export default Locked;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React from 'react';
|
||||
import { Text } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import styles from './styles';
|
||||
import { themes } from '../../constants/colors';
|
||||
|
@ -9,15 +10,16 @@ const Subtitle = ({ theme }) => (
|
|||
style={[
|
||||
styles.textSubtitle,
|
||||
{
|
||||
color: themes[theme].bodyText,
|
||||
opacity: 1 //opacityTitle
|
||||
color: themes[theme].bodyText
|
||||
}
|
||||
]}
|
||||
>
|
||||
{/* {attemptFailed || showError
|
||||
? this.props.subtitleError
|
||||
: this.props.subtitle} */}
|
||||
Subtitle
|
||||
</Text>
|
||||
);
|
||||
|
||||
Subtitle.propTypes = {
|
||||
theme: PropTypes.string
|
||||
};
|
||||
|
||||
export default Subtitle;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React from 'react';
|
||||
import { Text } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import styles from './styles';
|
||||
import { themes } from '../../constants/colors';
|
||||
|
@ -10,15 +11,15 @@ const Title = ({ theme }) => (
|
|||
styles.textTitle,
|
||||
{
|
||||
color: themes[theme].titleText,
|
||||
opacity: 1 //opacityTitle
|
||||
}
|
||||
]}
|
||||
>
|
||||
{/* {(attemptFailed && this.props.titleAttemptFailed) ||
|
||||
(showError && this.props.titleConfirmFailed) ||
|
||||
(showError && this.props.titleValidationFailed) ||
|
||||
this.props.sentenceTitle} */}
|
||||
Title
|
||||
</Text>
|
||||
);
|
||||
|
||||
Title.propTypes = {
|
||||
theme: PropTypes.string
|
||||
};
|
||||
|
||||
export default Title;
|
||||
|
|
|
@ -1,40 +1,43 @@
|
|||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { useAsyncStorage } from '@react-native-community/async-storage';
|
||||
import RNUserDefaults from 'rn-user-defaults';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Base from './Base';
|
||||
import Locked from './Locked';
|
||||
import { TYPE } from './constants';
|
||||
import { ATTEMPTS_KEY, LOCKED_OUT_TIMER_KEY, PASSCODE_KEY } from '../../constants/localAuthentication';
|
||||
console.log('LOCKED_OUT_TIMER_KEY', LOCKED_OUT_TIMER_KEY);
|
||||
|
||||
const MAX_ATTEMPTS = 2;
|
||||
import {
|
||||
ATTEMPTS_KEY, LOCKED_OUT_TIMER_KEY, PASSCODE_KEY, MAX_ATTEMPTS
|
||||
} from '../../constants/localAuthentication';
|
||||
import { resetAttempts } from '../../utils/localAuthentication';
|
||||
import { getLockedUntil, getDiff } from './utils';
|
||||
|
||||
const PasscodeEnter = ({
|
||||
theme, type, finishProcess
|
||||
}) => {
|
||||
const ref = useRef(null);
|
||||
let attempts = 0;
|
||||
let isLocked = false;
|
||||
let lockedUntil = false;
|
||||
let passcode = null;
|
||||
const [status, setStatus] = useState(type);
|
||||
console.log('status', status);
|
||||
// const [attempts, setAttempts] = useState(null);
|
||||
// console.log('PasscodeEnter -> attempts', attempts);
|
||||
// const [isLocked, setIsLocked] = useState(null);
|
||||
// console.log('PasscodeEnter -> isLocked', isLocked);
|
||||
// const [passcode, setPasscode] = useState('');
|
||||
// console.log('passcode', passcode);
|
||||
const { getItem: getAttempts, setItem: setAttempts } = useAsyncStorage(ATTEMPTS_KEY);
|
||||
const { getItem: getIsLocked, setItem: setIsLocked } = useAsyncStorage(LOCKED_OUT_TIMER_KEY);
|
||||
const { setItem: setLockedUntil } = useAsyncStorage(LOCKED_OUT_TIMER_KEY);
|
||||
|
||||
const fetchPasscode = async() => {
|
||||
passcode = await RNUserDefaults.get(PASSCODE_KEY);
|
||||
};
|
||||
|
||||
const readStorage = async() => {
|
||||
isLocked = await getIsLocked();
|
||||
attempts = await getAttempts();
|
||||
lockedUntil = await getLockedUntil();
|
||||
if (lockedUntil) {
|
||||
const diff = getDiff(lockedUntil);
|
||||
if (diff <= 1) {
|
||||
resetAttempts();
|
||||
} else {
|
||||
attempts = await getAttempts();
|
||||
setStatus(TYPE.LOCKED);
|
||||
}
|
||||
}
|
||||
fetchPasscode();
|
||||
};
|
||||
|
||||
|
@ -49,7 +52,7 @@ const PasscodeEnter = ({
|
|||
attempts += 1;
|
||||
if (attempts >= MAX_ATTEMPTS) {
|
||||
setStatus(TYPE.LOCKED);
|
||||
setIsLocked(new Date().toISOString());
|
||||
setLockedUntil(new Date().toISOString());
|
||||
} else {
|
||||
ref.current.wrongPasscode();
|
||||
setAttempts(attempts?.toString());
|
||||
|
@ -57,10 +60,6 @@ const PasscodeEnter = ({
|
|||
}
|
||||
};
|
||||
|
||||
finishProcess = () => {
|
||||
alert('faz submit')
|
||||
}
|
||||
|
||||
if (status === TYPE.LOCKED) {
|
||||
return <Locked theme={theme} setStatus={setStatus} />;
|
||||
}
|
||||
|
@ -68,4 +67,10 @@ const PasscodeEnter = ({
|
|||
return <Base ref={ref} theme={theme} type={TYPE.ENTER} onEndProcess={onEndProcess} />;
|
||||
};
|
||||
|
||||
PasscodeEnter.propTypes = {
|
||||
theme: PropTypes.string,
|
||||
type: PropTypes.string,
|
||||
finishProcess: PropTypes.func
|
||||
};
|
||||
|
||||
export default PasscodeEnter;
|
||||
|
|
|
@ -56,7 +56,8 @@ export default StyleSheet.create({
|
|||
width: grid.unit * 4,
|
||||
height: grid.unit * 4,
|
||||
backgroundColor: 'rgb(242, 245, 251)',
|
||||
borderRadius: grid.unit * 2
|
||||
borderRadius: grid.unit * 2,
|
||||
borderWidth: 1
|
||||
},
|
||||
textTitle: {
|
||||
fontSize: 20,
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
import AsyncStorage from '@react-native-community/async-storage';
|
||||
import moment from 'moment';
|
||||
|
||||
import { LOCKED_OUT_TIMER_KEY, TIME_TO_LOCK } from '../../constants/localAuthentication';
|
||||
|
||||
export const getLockedUntil = async() => {
|
||||
const t = await AsyncStorage.getItem(LOCKED_OUT_TIMER_KEY);
|
||||
if (t) {
|
||||
return moment(t).add(TIME_TO_LOCK);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export const getDiff = t => new Date(t) - new Date();
|
|
@ -3,120 +3,34 @@ import {
|
|||
View, StyleSheet, Text
|
||||
} from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
import PINCode, { PinStatus } from '@haskkor/react-native-pincode';
|
||||
// import PINCode, { PinStatus } from '@haskkor/react-native-pincode';
|
||||
import Modal from 'react-native-modal';
|
||||
import useDeepCompareEffect from 'use-deep-compare-effect';
|
||||
import _ from 'lodash';
|
||||
import RNUserDefaults from 'rn-user-defaults';
|
||||
import { useAsyncStorage } from '@react-native-community/async-storage';
|
||||
import moment from 'moment';
|
||||
import Orientation from 'react-native-orientation-locker';
|
||||
|
||||
import I18n from '../i18n';
|
||||
// import I18n from '../i18n';
|
||||
import { withTheme } from '../theme';
|
||||
import { themes } from '../constants/colors';
|
||||
import EventEmitter from '../utils/events';
|
||||
import sharedStyles from './Styles';
|
||||
// import sharedStyles from './Styles';
|
||||
import { withSplit } from '../split';
|
||||
import {
|
||||
PASSCODE_KEY, PASSCODE_LENGTH, LOCAL_AUTHENTICATE_EMITTER, LOCKED_OUT_TIMER_KEY, ATTEMPTS_KEY
|
||||
} from '../constants/localAuthentication';
|
||||
import { resetAttempts } from '../utils/localAuthentication';
|
||||
import { LOCAL_AUTHENTICATE_EMITTER } from '../constants/localAuthentication';
|
||||
import { isTablet } from '../utils/deviceInfo';
|
||||
import Orientation from 'react-native-orientation-locker';
|
||||
import Passcode from '../containers/Passcode';
|
||||
import { TYPE } from '../containers/Passcode/constants';
|
||||
|
||||
const MAX_ATTEMPTS = 6;
|
||||
const TIME_TO_LOCK = 30000;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
width: '100%'
|
||||
},
|
||||
title: {
|
||||
...sharedStyles.textRegular,
|
||||
fontSize: 20,
|
||||
fontWeight: '400',
|
||||
marginBottom: 10,
|
||||
textAlign: 'center'
|
||||
},
|
||||
subtitle: {
|
||||
...sharedStyles.textRegular,
|
||||
fontSize: 16,
|
||||
fontWeight: '400',
|
||||
textAlign: 'center'
|
||||
},
|
||||
circleButtonText: {
|
||||
...sharedStyles.textRegular,
|
||||
fontWeight: '100'
|
||||
},
|
||||
circleButton: {
|
||||
borderWidth: 1
|
||||
}
|
||||
});
|
||||
|
||||
const getLockedUntil = t => moment(t).add(TIME_TO_LOCK);
|
||||
|
||||
const getDiff = t => new Date(t) - new Date();
|
||||
|
||||
const Timer = ({ time, theme, changeStatus }) => {
|
||||
const calcTimeLeft = () => {
|
||||
const diff = getDiff(time);
|
||||
if (diff > 0) {
|
||||
return Math.floor((diff / 1000) % 60);
|
||||
}
|
||||
};
|
||||
|
||||
const [timeLeft, setTimeLeft] = useState(calcTimeLeft());
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
setTimeLeft(calcTimeLeft());
|
||||
if (timeLeft <= 1) {
|
||||
resetAttempts();
|
||||
changeStatus(PinStatus.initial);
|
||||
}
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
if (!timeLeft) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Text style={[styles.subtitle, { color: themes[theme].bodyText }]}>Try again in {timeLeft} seconds</Text>
|
||||
);
|
||||
};
|
||||
|
||||
// `changeStatus` prop is injected from react-native-pincode
|
||||
const AppLocked = withTheme(({ theme, changeStatus }) => {
|
||||
const [lockedUntil, setLockedUntil] = useState(null);
|
||||
const { getItem } = useAsyncStorage(LOCKED_OUT_TIMER_KEY);
|
||||
|
||||
const readItemFromStorage = async() => {
|
||||
const item = await getItem();
|
||||
setLockedUntil(getLockedUntil(item));
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
readItemFromStorage();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<View style={[styles.container, { backgroundColor: themes[theme].auxiliaryBackground }]}>
|
||||
<Text style={[styles.title, { color: themes[theme].titleText }]}>App locked</Text>
|
||||
<Timer theme={theme} time={lockedUntil} changeStatus={changeStatus} />
|
||||
</View>
|
||||
);
|
||||
});
|
||||
|
||||
const ScreenLockedView = ({ theme }) => {
|
||||
const [passcode, setPasscode] = useState('');
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [data, setData] = useState({});
|
||||
const { getItem } = useAsyncStorage(LOCKED_OUT_TIMER_KEY);
|
||||
|
||||
useDeepCompareEffect(() => {
|
||||
if (!_.isEmpty(data)) {
|
||||
|
@ -126,32 +40,15 @@ const ScreenLockedView = ({ theme }) => {
|
|||
}
|
||||
}, [data]);
|
||||
|
||||
const fetchPasscode = async() => {
|
||||
const storedPin = await RNUserDefaults.get(PASSCODE_KEY);
|
||||
setPasscode(storedPin);
|
||||
};
|
||||
|
||||
const showScreenLock = (args) => {
|
||||
setData(args);
|
||||
fetchPasscode();
|
||||
if (!isTablet) {
|
||||
Orientation.lockToPortrait();
|
||||
}
|
||||
};
|
||||
|
||||
const checkOldSession = async() => {
|
||||
const time = await getItem();
|
||||
const lockedUntil = getLockedUntil(time);
|
||||
const diff = getDiff(lockedUntil);
|
||||
if (diff <= 1) {
|
||||
resetAttempts();
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
EventEmitter.addEventListener(LOCAL_AUTHENTICATE_EMITTER, showScreenLock);
|
||||
fetchPasscode();
|
||||
checkOldSession();
|
||||
return () => EventEmitter.removeListener(LOCAL_AUTHENTICATE_EMITTER);
|
||||
}, []);
|
||||
|
||||
|
@ -202,23 +99,12 @@ const ScreenLockedView = ({ theme }) => {
|
|||
pinAttemptsAsyncStorageName={ATTEMPTS_KEY}
|
||||
lockedPage={<AppLocked />}
|
||||
/> */}
|
||||
<Passcode theme={theme} type={TYPE.ENTER} />
|
||||
<Passcode theme={theme} type={TYPE.ENTER} finishProcess={onSubmit} />
|
||||
</View>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
Timer.propTypes = {
|
||||
time: PropTypes.string,
|
||||
theme: PropTypes.string,
|
||||
changeStatus: PropTypes.func
|
||||
};
|
||||
|
||||
AppLocked.propTypes = {
|
||||
theme: PropTypes.string,
|
||||
changeStatus: PropTypes.func
|
||||
};
|
||||
|
||||
ScreenLockedView.propTypes = {
|
||||
theme: PropTypes.string,
|
||||
// eslint-disable-next-line react/no-unused-prop-types
|
||||
|
|
Loading…
Reference in New Issue