BlueWallet/UnlockWith.js

150 lines
4.9 KiB
JavaScript
Raw Normal View History

2020-11-23 03:06:02 +01:00
import React, { useContext, useEffect, useState } from 'react';
2023-10-20 17:10:50 +02:00
import { View, Image, TouchableOpacity, StyleSheet, ActivityIndicator, useColorScheme, LayoutAnimation } from 'react-native';
import { Icon } from 'react-native-elements';
import Biometric from './class/biometrics';
import LottieView from 'lottie-react-native';
2020-05-27 13:12:17 +02:00
import { SafeAreaView } from 'react-native-safe-area-context';
2020-11-23 03:06:02 +01:00
import { StackActions, useNavigation, useRoute } from '@react-navigation/native';
import { BlueStorageContext } from './blue_modules/storage-context';
2021-09-14 07:36:00 +02:00
import { isHandset } from './blue_modules/environment';
import triggerHapticFeedback, { HapticFeedbackTypes } from './blue_modules/hapticFeedback';
2023-12-24 18:47:51 +01:00
const lottieJson = require('./img/bluewalletsplash.json');
const styles = StyleSheet.create({
root: {
flex: 1,
},
container: {
flex: 1,
2023-12-24 18:47:51 +01:00
justifyContent: 'center',
alignItems: 'center',
},
biometric: {
2023-12-24 18:47:51 +01:00
position: 'absolute',
bottom: 0,
left: 0,
right: 0,
alignItems: 'center',
marginBottom: 58,
},
biometricRow: {
justifyContent: 'center',
flexDirection: 'row',
},
icon: {
width: 64,
height: 64,
},
2023-12-24 18:47:51 +01:00
lottie: {
width: lottieJson.w,
height: lottieJson.h,
},
});
2020-11-23 03:06:02 +01:00
const UnlockWith = () => {
const { setWalletsInitialized, isStorageEncrypted, startAndDecrypt } = useContext(BlueStorageContext);
const { dispatch } = useNavigation();
const { unlockOnComponentMount } = useRoute().params;
const [biometricType, setBiometricType] = useState(false);
const [isStorageEncryptedEnabled, setIsStorageEncryptedEnabled] = useState(false);
const [isAuthenticating, setIsAuthenticating] = useState(false);
const [animationDidFinish, setAnimationDidFinish] = useState(false);
2020-11-23 03:06:02 +01:00
const colorScheme = useColorScheme();
2020-11-23 03:06:02 +01:00
const initialRender = async () => {
let bt = false;
2019-10-06 13:40:21 +02:00
if (await Biometric.isBiometricUseCapableAndEnabled()) {
bt = await Biometric.biometricType();
}
setBiometricType(bt);
2020-07-15 19:32:59 +02:00
};
2020-11-23 03:06:02 +01:00
useEffect(() => {
initialRender();
}, []);
const successfullyAuthenticated = () => {
setWalletsInitialized(true);
2021-09-14 07:36:00 +02:00
dispatch(StackActions.replace(isHandset ? 'Navigation' : 'DrawerRoot'));
};
2020-11-23 03:06:02 +01:00
const unlockWithBiometrics = async () => {
if (await isStorageEncrypted()) {
unlockWithKey();
}
2020-11-23 03:06:02 +01:00
setIsAuthenticating(true);
if (await Biometric.unlockWithBiometrics()) {
setIsAuthenticating(false);
await startAndDecrypt();
return successfullyAuthenticated();
}
setIsAuthenticating(false);
};
2020-11-23 03:06:02 +01:00
const unlockWithKey = async () => {
setIsAuthenticating(true);
if (await startAndDecrypt()) {
triggerHapticFeedback(HapticFeedbackTypes.NotificationSuccess);
2020-11-23 03:06:02 +01:00
successfullyAuthenticated();
} else {
setIsAuthenticating(false);
}
2019-10-06 13:40:21 +02:00
};
2020-11-23 03:06:02 +01:00
const renderUnlockOptions = () => {
if (isAuthenticating) {
2020-07-21 00:14:02 +02:00
return <ActivityIndicator />;
} else {
2020-11-23 03:06:02 +01:00
const color = colorScheme === 'dark' ? '#FFFFFF' : '#000000';
if ((biometricType === Biometric.TouchID || biometricType === Biometric.Biometrics) && !isStorageEncryptedEnabled) {
2020-07-21 00:14:02 +02:00
return (
<TouchableOpacity accessibilityRole="button" disabled={isAuthenticating} onPress={unlockWithBiometrics}>
2020-07-21 00:14:02 +02:00
<Icon name="fingerprint" size={64} type="font-awesome5" color={color} />
</TouchableOpacity>
);
2020-11-23 03:06:02 +01:00
} else if (biometricType === Biometric.FaceID && !isStorageEncryptedEnabled) {
2020-07-21 00:14:02 +02:00
return (
<TouchableOpacity accessibilityRole="button" disabled={isAuthenticating} onPress={unlockWithBiometrics}>
2020-07-21 00:14:02 +02:00
<Image
2020-11-23 03:06:02 +01:00
source={colorScheme === 'dark' ? require('./img/faceid-default.png') : require('./img/faceid-dark.png')}
2020-07-21 00:14:02 +02:00
style={styles.icon}
/>
</TouchableOpacity>
);
2020-11-23 03:06:02 +01:00
} else if (isStorageEncryptedEnabled) {
2020-07-21 00:14:02 +02:00
return (
<TouchableOpacity accessibilityRole="button" disabled={isAuthenticating} onPress={unlockWithKey}>
2020-07-21 00:14:02 +02:00
<Icon name="lock" size={64} type="font-awesome5" color={color} />
</TouchableOpacity>
);
}
}
};
const onAnimationFinish = async () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
if (unlockOnComponentMount) {
const storageIsEncrypted = await isStorageEncrypted();
setIsStorageEncryptedEnabled(storageIsEncrypted);
if (!biometricType || storageIsEncrypted) {
unlockWithKey();
} else if (typeof biometricType === 'string') unlockWithBiometrics();
}
setAnimationDidFinish(true);
};
return (
<SafeAreaView style={styles.root}>
<View style={styles.container}>
2023-12-24 18:47:51 +01:00
<LottieView source={lottieJson} autoPlay loop={false} onAnimationFinish={onAnimationFinish} style={styles.lottie} />
<View style={styles.biometric}>{animationDidFinish && <View style={styles.biometricRow}>{renderUnlockOptions()}</View>}</View>
</View>
</SafeAreaView>
);
2020-07-21 00:14:02 +02:00
};
2020-11-23 03:06:02 +01:00
export default UnlockWith;