import React, { Component } from 'react'; import { View, Image, TouchableOpacity, StyleSheet, Appearance, StatusBar, ActivityIndicator } from 'react-native'; import { Icon } from 'react-native-elements'; import Biometric from './class/biometrics'; import { SafeAreaView } from 'react-native-safe-area-context'; import * as NavigationService from './NavigationService'; import { StackActions } from '@react-navigation/native'; import PropTypes from 'prop-types'; import { BlueStorageContext } from './blue_modules/storage-context'; /** @type {AppStorage} */ const styles = StyleSheet.create({ root: { flex: 1, }, container: { flex: 2, justifyContent: 'space-between', alignItems: 'center', }, qrCode: { flex: 1, justifyContent: 'center', alignItems: 'center', }, qrCodeImage: { width: 120, height: 120, }, biometric: { flex: 0.2, justifyContent: 'flex-end', marginBottom: 58, }, biometricRow: { justifyContent: 'center', flexDirection: 'row', }, icon: { width: 64, height: 64, }, encrypted: { width: 0.5, height: 20, }, }); export default class UnlockWith extends Component { state = { biometricType: false, isStorageEncrypted: false, isAuthenticating: false, appearance: Appearance.getColorScheme() }; static contextType = BlueStorageContext; async componentDidMount() { Appearance.addChangeListener(this.appearanceChanged); let biometricType = false; if (await Biometric.isBiometricUseCapableAndEnabled()) { biometricType = await Biometric.biometricType(); } const storageIsEncrypted = await this.context.isStorageEncrypted(); this.setState({ biometricType, isStorageEncrypted: storageIsEncrypted }, async () => { if (this.props.route.params.unlockOnComponentMount) { if (!biometricType || storageIsEncrypted) { this.unlockWithKey(); } else if (typeof biometricType === 'string') this.unlockWithBiometrics(); } }); } componentWillUnmount() { Appearance.removeChangeListener(); } appearanceChanged = () => { const appearance = Appearance.getColorScheme(); if (appearance) { this.setState({ appearance }); } }; successfullyAuthenticated = () => { this.context.setWalletsInitialized(true); NavigationService.dispatch(StackActions.replace('DrawerRoot')); }; unlockWithBiometrics = async () => { if (await this.context.isStorageEncrypted()) { this.unlockWithKey(); } this.setState({ isAuthenticating: true }, async () => { if (await Biometric.unlockWithBiometrics()) { this.setState({ isAuthenticating: false }); await this.context.startAndDecrypt(); return this.successfullyAuthenticated(); } this.setState({ isAuthenticating: false }); }); }; unlockWithKey = () => { this.setState({ isAuthenticating: true }, async () => { if (await this.context.startAndDecrypt()) { this.successfullyAuthenticated(); } else { this.setState({ isAuthenticating: false }); } }); }; renderUnlockOptions = () => { if (this.state.isAuthenticating) { return ; } else { const color = this.state.appearance === 'dark' ? '#FFFFFF' : '#000000'; if ( (this.state.biometricType === Biometric.TouchID || this.state.biometricType === Biometric.Biometrics) && !this.state.isStorageEncrypted ) { return ( ); } else if (this.state.biometricType === Biometric.FaceID && !this.state.isStorageEncrypted) { return ( ); } else if (this.state.isStorageEncrypted) { return ( ); } } }; render() { if (!this.state.biometricType && !this.state.isStorageEncrypted) { return ; } return ( {this.renderUnlockOptions()} ); } } UnlockWith.propTypes = { route: PropTypes.shape({ params: PropTypes.shape({ unlockOnComponentMount: PropTypes.bool, }), }), };