Stash
This commit is contained in:
parent
738fabf11d
commit
94fdf44260
|
@ -0,0 +1,122 @@
|
||||||
|
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 styles from './styles';
|
||||||
|
import Button from './Button';
|
||||||
|
import Dots from './Dots';
|
||||||
|
import Title from './Title';
|
||||||
|
import Subtitle from './Subtitle';
|
||||||
|
import { TYPE } from './constants';
|
||||||
|
|
||||||
|
const PASSCODE_LENGTH = 6;
|
||||||
|
|
||||||
|
const Base = forwardRef(({
|
||||||
|
theme, type, onEndProcess, previousPasscode
|
||||||
|
}, ref) => {
|
||||||
|
const [passcode, setPasscode] = useState('');
|
||||||
|
|
||||||
|
const handleEnd = () => {
|
||||||
|
alert('END')
|
||||||
|
};
|
||||||
|
|
||||||
|
const wrongPasscode = () => {
|
||||||
|
setPasscode('');
|
||||||
|
console.log('TODO: wrong animation and vibration');
|
||||||
|
};
|
||||||
|
|
||||||
|
const onPressNumber = text => setPasscode((p) => {
|
||||||
|
const currentPasscode = p + text;
|
||||||
|
if (currentPasscode?.length === PASSCODE_LENGTH) {
|
||||||
|
switch (type) {
|
||||||
|
case TYPE.CHOOSE:
|
||||||
|
// if (this.props.validationRegex && this.props.validationRegex.test(currentPasscode)) {
|
||||||
|
// this.showError(true);
|
||||||
|
// } else {
|
||||||
|
// // this.endProcess(currentPasscode);
|
||||||
|
onEndProcess(currentPasscode);
|
||||||
|
// }
|
||||||
|
break;
|
||||||
|
case TYPE.CONFIRM:
|
||||||
|
if (currentPasscode !== previousPasscode) {
|
||||||
|
// this.showError();
|
||||||
|
alert('SHOW ERROR');
|
||||||
|
} else {
|
||||||
|
// this.endProcess(currentPasscode);
|
||||||
|
onEndProcess(currentPasscode);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TYPE.ENTER:
|
||||||
|
// this.props.endProcess(currentPasscode);
|
||||||
|
onEndProcess(currentPasscode);
|
||||||
|
// await delay(300);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return currentPasscode;
|
||||||
|
});
|
||||||
|
|
||||||
|
const onPressDelete = () => setPasscode((p) => {
|
||||||
|
if (p?.length > 0) {
|
||||||
|
const newPasscode = p.slice(0, -1);
|
||||||
|
return newPasscode;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
});
|
||||||
|
|
||||||
|
useImperativeHandle(ref, () => ({
|
||||||
|
wrongPasscode
|
||||||
|
}));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<View style={styles.container}>
|
||||||
|
<View style={styles.viewTitle}>
|
||||||
|
<Title theme={theme} />
|
||||||
|
<Subtitle theme={theme} />
|
||||||
|
</View>
|
||||||
|
<View style={styles.flexCirclePasscode}>
|
||||||
|
<Dots passcode={passcode} theme={theme} length={PASSCODE_LENGTH} />
|
||||||
|
</View>
|
||||||
|
<Grid style={styles.grid}>
|
||||||
|
<Row style={styles.row}>
|
||||||
|
{_.range(1, 4).map(i => (
|
||||||
|
<Col key={i} style={styles.colButtonCircle}>
|
||||||
|
<Button text={i} theme={theme} onPress={onPressNumber} />
|
||||||
|
</Col>
|
||||||
|
))}
|
||||||
|
</Row>
|
||||||
|
<Row style={styles.row}>
|
||||||
|
{_.range(4, 7).map(i => (
|
||||||
|
<Col key={i} style={styles.colButtonCircle}>
|
||||||
|
<Button text={i} theme={theme} onPress={onPressNumber} />
|
||||||
|
</Col>
|
||||||
|
))}
|
||||||
|
</Row>
|
||||||
|
<Row style={styles.row}>
|
||||||
|
{_.range(7, 10).map(i => (
|
||||||
|
<Col key={i} style={styles.colButtonCircle}>
|
||||||
|
<Button text={i} theme={theme} onPress={onPressNumber} />
|
||||||
|
</Col>
|
||||||
|
))}
|
||||||
|
</Row>
|
||||||
|
<Row style={styles.row}>
|
||||||
|
<Col style={styles.colButtonCircle} />
|
||||||
|
<Col style={styles.colButtonCircle}>
|
||||||
|
<Button text='0' theme={theme} onPress={onPressNumber} />
|
||||||
|
</Col>
|
||||||
|
<Col style={styles.colButtonCircle}>
|
||||||
|
<Button text='X' theme={theme} onPress={onPressDelete} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Grid>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default Base;
|
|
@ -0,0 +1,94 @@
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
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;
|
||||||
|
|
||||||
|
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'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const getLockedUntil = t => moment(t).add(TIME_TO_LOCK);
|
||||||
|
|
||||||
|
const getDiff = t => new Date(t) - new Date();
|
||||||
|
|
||||||
|
const Timer = ({ time, theme, setStatus }) => {
|
||||||
|
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();
|
||||||
|
setStatus(TYPE.ENTER);
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!timeLeft) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Text style={[styles.subtitle, { color: themes[theme].bodyText }]}>Try again in {timeLeft} seconds</Text>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
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));
|
||||||
|
};
|
||||||
|
|
||||||
|
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} setStatus={setStatus} />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Locked;
|
|
@ -0,0 +1,6 @@
|
||||||
|
export const TYPE = {
|
||||||
|
CHOOSE: 'choose',
|
||||||
|
CONFIRM: 'confirm',
|
||||||
|
ENTER: 'enter',
|
||||||
|
LOCKED: 'locked'
|
||||||
|
};
|
|
@ -1,85 +1,71 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
import { View } from 'react-native';
|
import { useAsyncStorage } from '@react-native-community/async-storage';
|
||||||
import { Col, Row, Grid } from 'react-native-easy-grid';
|
import RNUserDefaults from 'rn-user-defaults';
|
||||||
import _ from 'lodash';
|
|
||||||
|
|
||||||
import styles from './styles';
|
import Base from './Base';
|
||||||
import Button from './Button';
|
import Locked from './Locked';
|
||||||
import Dots from './Dots';
|
import { TYPE } from './constants';
|
||||||
import Title from './Title';
|
import { ATTEMPTS_KEY, LOCKED_OUT_TIMER_KEY, PASSCODE_KEY } from '../../constants/localAuthentication';
|
||||||
import Subtitle from './Subtitle';
|
console.log('LOCKED_OUT_TIMER_KEY', LOCKED_OUT_TIMER_KEY);
|
||||||
|
|
||||||
const PASSCODE_LENGTH = 6;
|
const MAX_ATTEMPTS = 2;
|
||||||
|
|
||||||
const Passcode = ({ theme }) => {
|
const PasscodeEnter = ({
|
||||||
const [passcode, setPasscode] = useState('');
|
theme, type, finishProcess
|
||||||
|
}) => {
|
||||||
|
const ref = useRef(null);
|
||||||
|
let attempts = 0;
|
||||||
|
let isLocked = 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 handleEnd = () => {
|
const fetchPasscode = async() => {
|
||||||
alert('END')
|
passcode = await RNUserDefaults.get(PASSCODE_KEY);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onPressNumber = text => setPasscode((p) => {
|
const readStorage = async() => {
|
||||||
const newPasscode = p + text;
|
isLocked = await getIsLocked();
|
||||||
if (newPasscode?.length === PASSCODE_LENGTH) {
|
attempts = await getAttempts();
|
||||||
handleEnd();
|
fetchPasscode();
|
||||||
return '';
|
};
|
||||||
}
|
|
||||||
return newPasscode;
|
|
||||||
});
|
|
||||||
|
|
||||||
const onPressDelete = () => setPasscode((p) => {
|
useEffect(() => {
|
||||||
if (p?.length > 0) {
|
readStorage();
|
||||||
const newPasscode = p.slice(0, -1);
|
}, []);
|
||||||
return newPasscode;
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
const onEndProcess = (p) => {
|
||||||
<View style={styles.container}>
|
if (p === passcode) {
|
||||||
<View style={styles.container}>
|
finishProcess();
|
||||||
<View style={styles.viewTitle}>
|
} else {
|
||||||
<Title theme={theme} />
|
attempts += 1;
|
||||||
<Subtitle theme={theme} />
|
if (attempts >= MAX_ATTEMPTS) {
|
||||||
</View>
|
setStatus(TYPE.LOCKED);
|
||||||
<View style={styles.flexCirclePasscode}>
|
setIsLocked(new Date().toISOString());
|
||||||
<Dots passcode={passcode} theme={theme} length={PASSCODE_LENGTH} />
|
} else {
|
||||||
</View>
|
ref.current.wrongPasscode();
|
||||||
<Grid style={styles.grid}>
|
setAttempts(attempts?.toString());
|
||||||
<Row style={styles.row}>
|
}
|
||||||
{_.range(1, 4).map(i => (
|
}
|
||||||
<Col key={i} style={styles.colButtonCircle}>
|
};
|
||||||
<Button text={i} theme={theme} onPress={onPressNumber} />
|
|
||||||
</Col>
|
finishProcess = () => {
|
||||||
))}
|
alert('faz submit')
|
||||||
</Row>
|
}
|
||||||
<Row style={styles.row}>
|
|
||||||
{_.range(4, 7).map(i => (
|
if (status === TYPE.LOCKED) {
|
||||||
<Col key={i} style={styles.colButtonCircle}>
|
return <Locked theme={theme} setStatus={setStatus} />;
|
||||||
<Button text={i} theme={theme} onPress={onPressNumber} />
|
}
|
||||||
</Col>
|
|
||||||
))}
|
return <Base ref={ref} theme={theme} type={TYPE.ENTER} onEndProcess={onEndProcess} />;
|
||||||
</Row>
|
|
||||||
<Row style={styles.row}>
|
|
||||||
{_.range(7, 10).map(i => (
|
|
||||||
<Col key={i} style={styles.colButtonCircle}>
|
|
||||||
<Button text={i} theme={theme} onPress={onPressNumber} />
|
|
||||||
</Col>
|
|
||||||
))}
|
|
||||||
</Row>
|
|
||||||
<Row style={styles.row}>
|
|
||||||
<Col style={styles.colButtonCircle} />
|
|
||||||
<Col style={styles.colButtonCircle}>
|
|
||||||
<Button text='0' theme={theme} onPress={onPressNumber} />
|
|
||||||
</Col>
|
|
||||||
<Col style={styles.colButtonCircle}>
|
|
||||||
<Button text='X' theme={theme} onPress={onPressDelete} />
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</Grid>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Passcode;
|
export default PasscodeEnter;
|
||||||
|
|
|
@ -24,6 +24,7 @@ import { resetAttempts } from '../utils/localAuthentication';
|
||||||
import { isTablet } from '../utils/deviceInfo';
|
import { isTablet } from '../utils/deviceInfo';
|
||||||
import Orientation from 'react-native-orientation-locker';
|
import Orientation from 'react-native-orientation-locker';
|
||||||
import Passcode from '../containers/Passcode';
|
import Passcode from '../containers/Passcode';
|
||||||
|
import { TYPE } from '../containers/Passcode/constants';
|
||||||
|
|
||||||
const MAX_ATTEMPTS = 6;
|
const MAX_ATTEMPTS = 6;
|
||||||
const TIME_TO_LOCK = 30000;
|
const TIME_TO_LOCK = 30000;
|
||||||
|
@ -201,7 +202,7 @@ const ScreenLockedView = ({ theme }) => {
|
||||||
pinAttemptsAsyncStorageName={ATTEMPTS_KEY}
|
pinAttemptsAsyncStorageName={ATTEMPTS_KEY}
|
||||||
lockedPage={<AppLocked />}
|
lockedPage={<AppLocked />}
|
||||||
/> */}
|
/> */}
|
||||||
<Passcode theme={theme} />
|
<Passcode theme={theme} type={TYPE.ENTER} />
|
||||||
</View>
|
</View>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue