Merge pull request #6188 from BlueWallet/passcodeexp

ADD: If OS supports passcode, provide explanation
This commit is contained in:
GLaDOS 2024-02-29 10:43:23 +00:00 committed by GitHub
commit 0d293c47d9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 57 additions and 26 deletions

View file

@ -1640,7 +1640,7 @@
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match Development io.bluewallet.bluewallet";
"PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "match AppStore io.bluewallet.bluewallet catalyst";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = YES;
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_OBJC_BRIDGING_HEADER = "BlueWallet-Bridging-Header.h";
@ -1695,7 +1695,7 @@
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore io.bluewallet.bluewallet";
"PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "match AppStore io.bluewallet.bluewallet catalyst";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = YES;
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_OBJC_BRIDGING_HEADER = "BlueWallet-Bridging-Header.h";

View file

@ -271,6 +271,7 @@
"encrypt_tstorage": "Storage",
"encrypt_use": "Use {type}",
"encrypt_use_expl": "{type} will be used to confirm your identity before making a transaction, unlocking, exporting, or deleting a wallet. {type} will not be used to unlock encrypted storage.",
"biometrics_fail": "If {type} is not enabled, or fails to unlock, you can use your device passcode as an alternative.",
"general": "General",
"general_adv_mode": "Advanced Mode",
"general_adv_mode_e": "When enabled, you will see advanced options such as different wallet types, the ability to specify the LNDHub instance you wish to connect to, and custom entropy during wallet creation.",

View file

@ -1,8 +1,8 @@
import React, { useEffect, useState, useCallback, useContext } from 'react';
import { View, ScrollView, Alert, TouchableOpacity, TouchableWithoutFeedback, Text, StyleSheet } from 'react-native';
import { View, ScrollView, Alert, TouchableOpacity, TouchableWithoutFeedback, Text, StyleSheet, Platform } from 'react-native';
import { useNavigation } from '@react-navigation/native';
import navigationStyle from '../../components/navigationStyle';
import { BlueLoading, BlueSpacing20, BlueCard, BlueText } from '../../BlueComponents';
import { BlueSpacing20, BlueCard, BlueText } from '../../BlueComponents';
import Biometric from '../../class/biometrics';
import loc from '../../loc';
import { BlueStorageContext } from '../../blue_modules/storage-context';
@ -14,11 +14,11 @@ const prompt = require('../../helpers/prompt');
const EncryptStorage = () => {
const { isStorageEncrypted, encryptStorage, decryptStorage, saveToDisk } = useContext(BlueStorageContext);
const [isLoading, setIsLoading] = useState(true);
const [biometrics, setBiometrics] = useState({ isDeviceBiometricCapable: false, isBiometricsEnabled: false, biometricsType: '' });
const [storageIsEncryptedSwitchEnabled, setStorageIsEncryptedSwitchEnabled] = useState(false);
const { navigate, popToTop } = useNavigation();
const { colors } = useTheme();
const [isLoading, setIsLoading] = useState({ encryptStorage: false, biometrics: false });
const styleHooks = StyleSheet.create({
root: {
backgroundColor: colors.background,
@ -35,7 +35,6 @@ const EncryptStorage = () => {
const isStorageEncryptedSwitchEnabled = await isStorageEncrypted();
setStorageIsEncryptedSwitchEnabled(isStorageEncryptedSwitchEnabled);
setBiometrics({ isBiometricsEnabled, isDeviceBiometricCapable, biometricsType });
setIsLoading(false);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
@ -63,26 +62,26 @@ const EncryptStorage = () => {
};
const onEncryptStorageSwitch = async value => {
setIsLoading(true);
setIsLoading(prev => ({ ...prev, encryptStorage: true }));
if (value === true) {
let p1 = await prompt(loc.settings.password, loc.settings.password_explain).catch(() => {
setIsLoading(false);
setIsLoading(prev => ({ ...prev, encryptStorage: false }));
p1 = undefined;
});
if (!p1) {
setIsLoading(false);
setIsLoading(prev => ({ ...prev, encryptStorage: false }));
return;
}
const p2 = await prompt(loc.settings.password, loc.settings.retype_password).catch(() => {
setIsLoading(false);
setIsLoading(prev => ({ ...prev, encryptStorage: false }));
});
if (p1 === p2) {
await encryptStorage(p1);
setIsLoading(false);
setStorageIsEncryptedSwitchEnabled(await isStorageEncrypted());
saveToDisk();
setIsLoading(prev => ({ ...prev, encryptStorage: false }));
} else {
setIsLoading(false);
setIsLoading(prev => ({ ...prev, encryptStorage: false }));
triggerHapticFeedback(HapticFeedbackTypes.NotificationError);
presentAlert({ message: loc.settings.passwords_do_not_match });
}
@ -94,7 +93,7 @@ const EncryptStorage = () => {
{
text: loc._.cancel,
style: 'cancel',
onPress: () => setIsLoading(false),
onPress: () => setIsLoading(prev => ({ ...prev, encryptStorage: false })),
},
{
text: loc._.ok,
@ -108,6 +107,7 @@ const EncryptStorage = () => {
};
const onUseBiometricSwitch = async value => {
setIsLoading(prev => ({ ...prev, biometrics: true }));
const isBiometricsEnabled = {
isDeviceBiometricCapable: biometrics.isDeviceBiometricCapable,
isBiometricsEnabled: biometrics.isBiometricsEnabled,
@ -118,18 +118,35 @@ const EncryptStorage = () => {
await Biometric.setBiometricUseEnabled(value);
setBiometrics(isBiometricsEnabled);
}
setIsLoading(prev => ({ ...prev, biometrics: false }));
};
const navigateToPlausibleDeniability = () => {
navigate('PlausibleDeniability');
};
return isLoading ? (
<ScrollView centerContent>
<BlueLoading />
</ScrollView>
) : (
<ScrollView contentContainerStyle={styles.root} automaticallyAdjustContentInsets contentInsetAdjustmentBehavior="automatic">
const renderPasscodeExplanation = () => {
let isCapable = true;
if (Platform.OS === 'android') {
if (Platform.Version < 30) {
isCapable = false;
}
}
return isCapable ? (
<>
<BlueText />
<BlueText>{loc.formatString(loc.settings.biometrics_fail, { type: biometrics.biometricsType })}</BlueText>
</>
) : null;
};
return (
<ScrollView
contentContainerStyle={styleHooks.root}
automaticallyAdjustContentInsets
contentInsetAdjustmentBehavior="automatic"
centerContent={isLoading}
>
<View style={styles.paddingTop} />
{biometrics.isDeviceBiometricCapable && (
<>
@ -139,10 +156,17 @@ const EncryptStorage = () => {
<ListItem
title={loc.formatString(loc.settings.encrypt_use, { type: biometrics.biometricsType })}
Component={TouchableWithoutFeedback}
switch={{ value: biometrics.isBiometricsEnabled, onValueChange: onUseBiometricSwitch }}
isLoading={isLoading.biometrics}
containerStyle={[styles.rowItemContainerStyle, styleHooks.root]}
switch={{
value: biometrics.isBiometricsEnabled,
onValueChange: onUseBiometricSwitch,
disabled: isLoading.encryptStorage || isLoading.biometrics,
}}
/>
<BlueCard>
<BlueText>{loc.formatString(loc.settings.encrypt_use_expl, { type: biometrics.biometricsType })}</BlueText>
{renderPasscodeExplanation()}
</BlueCard>
<BlueSpacing20 />
</>
@ -151,11 +175,17 @@ const EncryptStorage = () => {
{loc.settings.encrypt_tstorage}
</Text>
<ListItem
testID="EncyptedAndPasswordProtected"
testID="EncryptedAndPasswordProtected"
hideChevron
isLoading={isLoading.encryptStorage}
title={loc.settings.encrypt_enc_and_pass}
Component={TouchableWithoutFeedback}
switch={{ onValueChange: onEncryptStorageSwitch, value: storageIsEncryptedSwitchEnabled }}
containerStyle={[styles.rowItemContainerStyle, styleHooks.root]}
switch={{
onValueChange: onEncryptStorageSwitch,
value: storageIsEncryptedSwitchEnabled,
disabled: isLoading.encryptStorage || isLoading.biometrics,
}}
/>
{storageIsEncryptedSwitchEnabled && (
<ListItem
@ -171,15 +201,15 @@ const EncryptStorage = () => {
};
const styles = StyleSheet.create({
root: {
flex: 1,
},
paddingTop: { paddingTop: 19 },
paddingTop: { paddingTop: 36 },
headerText: {
fontWeight: 'bold',
fontSize: 30,
marginLeft: 17,
},
rowItemContainerStyle: {
minHeight: 60,
},
});
export default EncryptStorage;