Refactoring passcode
This commit is contained in:
parent
c13ea0f10f
commit
7f61529f9e
|
@ -0,0 +1,40 @@
|
|||
import React from 'react';
|
||||
import { TouchableHighlight, Text } from 'react-native';
|
||||
|
||||
import styles from './styles';
|
||||
|
||||
const ButtonNumber = ({ text }) => (
|
||||
<TouchableHighlight
|
||||
style={[
|
||||
styles.buttonCircle,
|
||||
// { backgroundColor: this.props.colorCircleButtons },
|
||||
// this.props.styleButtonCircle,
|
||||
]}
|
||||
// underlayColor={this.props.numbersButtonOverlayColor}
|
||||
// disabled={disabled}
|
||||
// onShowUnderlay={() => this.setState({ textButtonSelected: text })}
|
||||
// onHideUnderlay={() => this.setState({ textButtonSelected: "" })}
|
||||
// onPress={() => {
|
||||
// this.onPressButtonNumber(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}
|
||||
</Text>
|
||||
</TouchableHighlight>
|
||||
);
|
||||
|
||||
export default ButtonNumber;
|
|
@ -0,0 +1,62 @@
|
|||
import React from 'react';
|
||||
import { View } from 'react-native';
|
||||
import _ from 'lodash';
|
||||
|
||||
import styles from './styles';
|
||||
import { themes } from '../../constants/colors';
|
||||
|
||||
const PASSWORD_LENGTH = 6;
|
||||
const SIZE_EMPTY = 8;
|
||||
const SIZE_FULL = 12;
|
||||
|
||||
const PasscodeDots = ({
|
||||
password,
|
||||
moveData,
|
||||
showError,
|
||||
changeScreen,
|
||||
attemptFailed,
|
||||
theme
|
||||
}) => (
|
||||
<View style={[styles.topViewCirclePassword]}>
|
||||
{_.range(PASSWORD_LENGTH).map((val) => {
|
||||
const lengthSup = ((password.length >= val + 1 && !changeScreen) || showError) && !attemptFailed;
|
||||
const opacity = lengthSup ? 1 : 0.5;
|
||||
const height = lengthSup ? SIZE_FULL : SIZE_EMPTY;
|
||||
const width = lengthSup ? SIZE_FULL : SIZE_EMPTY;
|
||||
let color = '';
|
||||
if (showError) {
|
||||
color = themes[theme].dangerColor;
|
||||
} else if (lengthSup && password.length > 0) {
|
||||
color = themes[theme].titleText;
|
||||
} else {
|
||||
color = themes[theme].bodyText;
|
||||
}
|
||||
const borderRadius = lengthSup
|
||||
? SIZE_FULL / 2
|
||||
: SIZE_EMPTY / 2;
|
||||
const marginRight = lengthSup
|
||||
? 10 - (SIZE_FULL - SIZE_EMPTY) / 2
|
||||
: 10;
|
||||
const marginLeft = lengthSup
|
||||
? 10 - (SIZE_FULL - SIZE_EMPTY) / 2
|
||||
: 10;
|
||||
return (
|
||||
<View style={styles.viewCircles}>
|
||||
<View
|
||||
style={[{
|
||||
opacity,
|
||||
height,
|
||||
width,
|
||||
borderRadius,
|
||||
backgroundColor: color,
|
||||
marginRight,
|
||||
marginLeft
|
||||
}]}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
);
|
||||
|
||||
export default PasscodeDots;
|
|
@ -0,0 +1,23 @@
|
|||
import React from 'react';
|
||||
import { Text } from 'react-native';
|
||||
|
||||
import styles from './styles';
|
||||
import { themes } from '../../constants/colors';
|
||||
|
||||
const Subtitle = ({ theme }) => (
|
||||
<Text
|
||||
style={[
|
||||
styles.textSubtitle,
|
||||
{
|
||||
color: themes[theme].bodyText,
|
||||
opacity: 1 //opacityTitle
|
||||
}
|
||||
]}
|
||||
>
|
||||
{/* {attemptFailed || showError
|
||||
? this.props.subtitleError
|
||||
: this.props.subtitle} */}
|
||||
Subtitle
|
||||
</Text>
|
||||
);
|
||||
export default Subtitle;
|
|
@ -0,0 +1,24 @@
|
|||
import React from 'react';
|
||||
import { Text } from 'react-native';
|
||||
|
||||
import styles from './styles';
|
||||
import { themes } from '../../constants/colors';
|
||||
|
||||
const Title = ({ theme }) => (
|
||||
<Text
|
||||
style={[
|
||||
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>
|
||||
);
|
||||
export default Title;
|
|
@ -0,0 +1,17 @@
|
|||
const grid = {
|
||||
unit: 16,
|
||||
headline: 32,
|
||||
title: 24,
|
||||
subheader: 18,
|
||||
body: 14,
|
||||
caption: 12,
|
||||
label: 10,
|
||||
lineHeight: 1.5,
|
||||
navIcon: 20,
|
||||
border: 2,
|
||||
borderRadius: 2,
|
||||
lowOpacity: 0.4,
|
||||
mediumOpacity: 0.6,
|
||||
highOpacity: 0.8
|
||||
};
|
||||
export default grid;
|
|
@ -0,0 +1,118 @@
|
|||
import React from 'react';
|
||||
import { View } from 'react-native';
|
||||
import { Col, Row, Grid } from 'react-native-easy-grid';
|
||||
import _ from 'lodash';
|
||||
|
||||
import styles from './styles';
|
||||
import ButtonNumber from './ButtonNumber';
|
||||
import PasscodeDots from './PasscodeDots';
|
||||
import Title from './Title';
|
||||
import Subtitle from './Subtitle';
|
||||
|
||||
const Passcode = ({ theme }) => {
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
styles.container,
|
||||
// this.props.styleContainer
|
||||
]}
|
||||
>
|
||||
<View
|
||||
style={[
|
||||
styles.container,
|
||||
// this.props.styleContainer
|
||||
]}
|
||||
>
|
||||
<View
|
||||
style={[
|
||||
styles.viewTitle,
|
||||
// { opacity: opacity }
|
||||
]}
|
||||
>
|
||||
<Title theme={theme} />
|
||||
<Subtitle theme={theme} />
|
||||
</View>
|
||||
<View style={styles.flexCirclePassword}>
|
||||
<PasscodeDots password='123' theme={theme} />
|
||||
</View>
|
||||
<Grid style={styles.grid}>
|
||||
<Row
|
||||
style={[
|
||||
styles.row
|
||||
]}
|
||||
>
|
||||
{_.range(1, 4).map(i => (
|
||||
<Col
|
||||
key={i}
|
||||
style={[
|
||||
styles.colButtonCircle
|
||||
]}
|
||||
>
|
||||
<ButtonNumber text={i} />
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
<Row
|
||||
style={[
|
||||
styles.row
|
||||
]}
|
||||
>
|
||||
{_.range(4, 7).map(i => (
|
||||
<Col
|
||||
key={i}
|
||||
style={[
|
||||
styles.colButtonCircle
|
||||
]}
|
||||
>
|
||||
<ButtonNumber text={i} />
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
<Row
|
||||
style={[
|
||||
styles.row
|
||||
]}
|
||||
>
|
||||
{_.range(7, 10).map(i => (
|
||||
<Col
|
||||
key={i}
|
||||
style={[
|
||||
styles.colButtonCircle
|
||||
]}
|
||||
>
|
||||
<ButtonNumber text={i} />
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
<Row
|
||||
style={[
|
||||
styles.row
|
||||
]}
|
||||
>
|
||||
<Col
|
||||
style={[
|
||||
styles.colButtonCircle
|
||||
]}
|
||||
/>
|
||||
<Col
|
||||
style={[
|
||||
styles.colButtonCircle
|
||||
]}
|
||||
>
|
||||
<ButtonNumber text='0' />
|
||||
</Col>
|
||||
<Col
|
||||
style={[
|
||||
styles.colButtonCircle
|
||||
]}
|
||||
>
|
||||
<ButtonNumber text='X' />
|
||||
</Col>
|
||||
</Row>
|
||||
</Grid>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default Passcode;
|
|
@ -0,0 +1,95 @@
|
|||
import { StyleSheet } from 'react-native';
|
||||
|
||||
import grid from './grid';
|
||||
|
||||
export default StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
// width: '100%'
|
||||
},
|
||||
viewTitle: {
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'flex-end',
|
||||
alignItems: 'center',
|
||||
flex: 2
|
||||
},
|
||||
row: {
|
||||
flex: 0,
|
||||
flexShrink: 1,
|
||||
alignItems: 'center',
|
||||
height: grid.unit * 5.5
|
||||
},
|
||||
rowWithEmpty: {
|
||||
flexShrink: 0,
|
||||
justifyContent: 'flex-end'
|
||||
},
|
||||
colButtonCircle: {
|
||||
flex: 0,
|
||||
marginLeft: grid.unit / 2,
|
||||
marginRight: grid.unit / 2,
|
||||
alignItems: 'center',
|
||||
width: grid.unit * 4,
|
||||
height: grid.unit * 4
|
||||
},
|
||||
colEmpty: {
|
||||
flex: 0,
|
||||
marginLeft: grid.unit / 2,
|
||||
marginRight: grid.unit / 2,
|
||||
width: grid.unit * 4,
|
||||
height: grid.unit * 4
|
||||
},
|
||||
colIcon: {
|
||||
alignSelf: 'center',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
flexDirection: 'column'
|
||||
},
|
||||
text: {
|
||||
fontSize: grid.unit * 2,
|
||||
fontWeight: '200'
|
||||
},
|
||||
buttonCircle: {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
width: grid.unit * 4,
|
||||
height: grid.unit * 4,
|
||||
backgroundColor: 'rgb(242, 245, 251)',
|
||||
borderRadius: grid.unit * 2
|
||||
},
|
||||
textTitle: {
|
||||
fontSize: 20,
|
||||
fontWeight: '200',
|
||||
lineHeight: grid.unit * 2.5
|
||||
},
|
||||
textSubtitle: {
|
||||
fontSize: grid.unit,
|
||||
fontWeight: '200',
|
||||
textAlign: 'center'
|
||||
},
|
||||
flexCirclePassword: {
|
||||
flex: 2,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center'
|
||||
},
|
||||
topViewCirclePassword: {
|
||||
flexDirection: 'row',
|
||||
height: 'auto',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center'
|
||||
},
|
||||
viewCircles: {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center'
|
||||
},
|
||||
textDeleteButton: {
|
||||
fontWeight: '200',
|
||||
marginTop: 5
|
||||
},
|
||||
grid: {
|
||||
justifyContent: 'flex-start',
|
||||
width: '100%',
|
||||
flex: 7
|
||||
}
|
||||
});
|
|
@ -64,18 +64,18 @@ export const localAuthenticate = async(server) => {
|
|||
const isSupported = await LocalAuthentication.supportedAuthenticationTypesAsync();
|
||||
|
||||
// if biometry is enabled and enrolled on OS
|
||||
if (isEnrolled && isSupported) {
|
||||
// opens biometry prompt
|
||||
const authResult = await LocalAuthentication.authenticateAsync({ disableDeviceFallback: true });
|
||||
if (authResult?.success) {
|
||||
await resetAttempts();
|
||||
await saveLastLocalAuthenticationSession(server, serverRecord);
|
||||
} else {
|
||||
await localPasscode();
|
||||
}
|
||||
} else {
|
||||
await localPasscode();
|
||||
}
|
||||
// if (isEnrolled && isSupported) {
|
||||
// // opens biometry prompt
|
||||
// const authResult = await LocalAuthentication.authenticateAsync({ disableDeviceFallback: true });
|
||||
// if (authResult?.success) {
|
||||
// await resetAttempts();
|
||||
// await saveLastLocalAuthenticationSession(server, serverRecord);
|
||||
// } else {
|
||||
// await localPasscode();
|
||||
// }
|
||||
// } else {
|
||||
await localPasscode();
|
||||
// }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -23,6 +23,7 @@ import {
|
|||
import { resetAttempts } from '../utils/localAuthentication';
|
||||
import { isTablet } from '../utils/deviceInfo';
|
||||
import Orientation from 'react-native-orientation-locker';
|
||||
import Passcode from '../containers/Passcode';
|
||||
|
||||
const MAX_ATTEMPTS = 6;
|
||||
const TIME_TO_LOCK = 30000;
|
||||
|
@ -169,7 +170,7 @@ const ScreenLockedView = ({ theme }) => {
|
|||
style={{ margin: 0 }}
|
||||
>
|
||||
<View style={[styles.container, { backgroundColor: themes[theme].auxiliaryBackground }]}>
|
||||
<PINCode
|
||||
{/* <PINCode
|
||||
status={PinStatus.enter}
|
||||
passwordLength={PASSCODE_LENGTH}
|
||||
customBackSpaceIcon={() => null}
|
||||
|
@ -199,7 +200,8 @@ const ScreenLockedView = ({ theme }) => {
|
|||
timePinLockedAsyncStorageName={LOCKED_OUT_TIMER_KEY}
|
||||
pinAttemptsAsyncStorageName={ATTEMPTS_KEY}
|
||||
lockedPage={<AppLocked />}
|
||||
/>
|
||||
/> */}
|
||||
<Passcode theme={theme} />
|
||||
</View>
|
||||
</Modal>
|
||||
);
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
"react-native-console-time-polyfill": "^1.2.1",
|
||||
"react-native-device-info": "^2.3.0",
|
||||
"react-native-document-picker": "^3.2.4",
|
||||
"react-native-easy-grid": "^0.2.2",
|
||||
"react-native-easy-toast": "^1.2.0",
|
||||
"react-native-fast-image": "^7.0.2",
|
||||
"react-native-firebase": "^5.5.5",
|
||||
|
|
Loading…
Reference in New Issue