2020-10-24 13:20:59 -04:00
|
|
|
import { useNavigation } from '@react-navigation/native';
|
2024-05-20 10:54:13 +01:00
|
|
|
import React, { useCallback, useEffect, useState } from 'react';
|
|
|
|
import { Alert, Platform, ScrollView, StyleSheet, Text, TouchableOpacity, TouchableWithoutFeedback, View } from 'react-native';
|
|
|
|
|
|
|
|
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
2024-05-17 18:34:39 -04:00
|
|
|
import { useStorage } from '../../blue_modules/storage-context';
|
2024-05-20 10:54:13 +01:00
|
|
|
import { BlueCard, BlueLoading, BlueSpacing20, BlueText } from '../../BlueComponents';
|
2024-02-07 15:24:24 -04:00
|
|
|
import presentAlert from '../../components/Alert';
|
2023-12-16 17:44:35 -04:00
|
|
|
import ListItem from '../../components/ListItem';
|
2023-12-29 07:52:12 -04:00
|
|
|
import { useTheme } from '../../components/themes';
|
2024-03-31 20:59:14 +01:00
|
|
|
import prompt from '../../helpers/prompt';
|
2024-05-17 18:34:39 -04:00
|
|
|
import { useBiometrics } from '../../hooks/useBiometrics';
|
2024-05-20 10:54:13 +01:00
|
|
|
import loc from '../../loc';
|
2018-09-30 04:31:09 -04:00
|
|
|
|
2020-07-15 13:32:59 -04:00
|
|
|
const EncryptStorage = () => {
|
2024-05-17 18:34:39 -04:00
|
|
|
const { isStorageEncrypted, encryptStorage, decryptStorage, saveToDisk } = useStorage();
|
2024-03-02 12:50:26 -04:00
|
|
|
const [isLoading, setIsLoading] = useState(true);
|
2024-05-17 18:34:39 -04:00
|
|
|
const { isDeviceBiometricCapable, biometricEnabled, setBiometricUseEnabled, deviceBiometricType, unlockWithBiometrics } = useBiometrics();
|
2020-10-24 13:20:59 -04:00
|
|
|
const [storageIsEncryptedSwitchEnabled, setStorageIsEncryptedSwitchEnabled] = useState(false);
|
2024-05-17 18:45:51 -04:00
|
|
|
const [deviceBiometricCapable, setDeviceBiometricCapable] = useState(false);
|
2020-10-24 13:20:59 -04:00
|
|
|
const { navigate, popToTop } = useNavigation();
|
2023-12-29 07:52:12 -04:00
|
|
|
const { colors } = useTheme();
|
2024-01-21 16:07:29 -04:00
|
|
|
const styleHooks = StyleSheet.create({
|
2020-07-15 13:32:59 -04:00
|
|
|
root: {
|
|
|
|
backgroundColor: colors.background,
|
|
|
|
},
|
2024-01-21 16:07:29 -04:00
|
|
|
headerText: {
|
|
|
|
color: colors.foregroundColor,
|
|
|
|
},
|
2018-10-29 18:11:48 -04:00
|
|
|
});
|
2018-09-30 04:31:09 -04:00
|
|
|
|
2024-03-02 12:50:26 -04:00
|
|
|
const initialState = useCallback(async () => {
|
2020-10-24 13:20:59 -04:00
|
|
|
const isStorageEncryptedSwitchEnabled = await isStorageEncrypted();
|
2024-05-17 18:45:51 -04:00
|
|
|
const isDeviceBiometricCapableSync = await isDeviceBiometricCapable();
|
2020-10-24 13:20:59 -04:00
|
|
|
setStorageIsEncryptedSwitchEnabled(isStorageEncryptedSwitchEnabled);
|
2024-05-17 18:45:51 -04:00
|
|
|
setDeviceBiometricCapable(isDeviceBiometricCapableSync);
|
2024-03-02 12:50:26 -04:00
|
|
|
setIsLoading(false);
|
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
}, []);
|
2020-07-15 13:32:59 -04:00
|
|
|
useEffect(() => {
|
|
|
|
initialState();
|
2020-10-24 13:20:59 -04:00
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
}, []);
|
2018-09-30 04:31:09 -04:00
|
|
|
|
2020-10-24 13:20:59 -04:00
|
|
|
const handleDecryptStorage = async () => {
|
2019-08-23 03:04:23 -04:00
|
|
|
const password = await prompt(loc.settings.password, loc._.storage_is_encrypted).catch(() => {
|
2020-07-15 13:32:59 -04:00
|
|
|
setIsLoading(false);
|
2019-08-23 03:04:23 -04:00
|
|
|
});
|
|
|
|
try {
|
2020-10-24 13:20:59 -04:00
|
|
|
await decryptStorage(password);
|
2020-11-02 08:11:28 -05:00
|
|
|
await saveToDisk();
|
2020-10-24 13:20:59 -04:00
|
|
|
popToTop();
|
2019-08-23 03:04:23 -04:00
|
|
|
} catch (e) {
|
2019-08-23 03:25:12 -04:00
|
|
|
if (password) {
|
2023-12-29 07:52:12 -04:00
|
|
|
triggerHapticFeedback(HapticFeedbackTypes.NotificationError);
|
2024-02-15 15:43:46 -04:00
|
|
|
presentAlert({ message: loc._.bad_password });
|
2019-08-23 03:25:12 -04:00
|
|
|
}
|
2020-07-15 13:32:59 -04:00
|
|
|
|
|
|
|
setIsLoading(false);
|
2020-10-24 13:20:59 -04:00
|
|
|
setStorageIsEncryptedSwitchEnabled(await isStorageEncrypted());
|
2019-08-23 03:04:23 -04:00
|
|
|
}
|
2020-10-24 13:20:59 -04:00
|
|
|
};
|
2019-08-23 03:04:23 -04:00
|
|
|
|
2020-10-24 13:20:59 -04:00
|
|
|
const onEncryptStorageSwitch = async value => {
|
2024-03-02 12:50:26 -04:00
|
|
|
setIsLoading(true);
|
2020-10-24 13:20:59 -04:00
|
|
|
if (value === true) {
|
|
|
|
let p1 = await prompt(loc.settings.password, loc.settings.password_explain).catch(() => {
|
2024-03-02 12:50:26 -04:00
|
|
|
setIsLoading(false);
|
2020-10-24 13:20:59 -04:00
|
|
|
p1 = undefined;
|
|
|
|
});
|
|
|
|
if (!p1) {
|
2024-03-02 12:50:26 -04:00
|
|
|
setIsLoading(false);
|
2020-10-24 13:20:59 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
const p2 = await prompt(loc.settings.password, loc.settings.retype_password).catch(() => {
|
2024-03-02 12:50:26 -04:00
|
|
|
setIsLoading(false);
|
2020-10-24 13:20:59 -04:00
|
|
|
});
|
|
|
|
if (p1 === p2) {
|
|
|
|
await encryptStorage(p1);
|
2024-03-02 12:50:26 -04:00
|
|
|
setIsLoading(false);
|
2020-10-24 13:20:59 -04:00
|
|
|
setStorageIsEncryptedSwitchEnabled(await isStorageEncrypted());
|
2020-11-02 08:11:28 -05:00
|
|
|
saveToDisk();
|
2019-08-23 03:04:23 -04:00
|
|
|
} else {
|
2024-03-02 12:50:26 -04:00
|
|
|
setIsLoading(false);
|
2024-02-09 12:25:09 -04:00
|
|
|
triggerHapticFeedback(HapticFeedbackTypes.NotificationError);
|
2024-02-07 15:24:24 -04:00
|
|
|
presentAlert({ message: loc.settings.passwords_do_not_match });
|
2019-08-23 03:04:23 -04:00
|
|
|
}
|
2020-10-24 13:20:59 -04:00
|
|
|
} else {
|
|
|
|
Alert.alert(
|
|
|
|
loc.settings.encrypt_decrypt,
|
|
|
|
loc.settings.encrypt_decrypt_q,
|
|
|
|
[
|
|
|
|
{
|
|
|
|
text: loc._.cancel,
|
|
|
|
style: 'cancel',
|
2024-03-02 12:50:26 -04:00
|
|
|
onPress: () => setIsLoading(false),
|
2020-10-24 13:20:59 -04:00
|
|
|
},
|
|
|
|
{
|
|
|
|
text: loc._.ok,
|
|
|
|
style: 'destructive',
|
|
|
|
onPress: handleDecryptStorage,
|
|
|
|
},
|
|
|
|
],
|
|
|
|
{ cancelable: false },
|
|
|
|
);
|
|
|
|
}
|
|
|
|
};
|
2019-08-23 03:04:23 -04:00
|
|
|
|
2020-10-24 13:20:59 -04:00
|
|
|
const onUseBiometricSwitch = async value => {
|
2024-05-17 18:34:39 -04:00
|
|
|
if (await unlockWithBiometrics()) {
|
|
|
|
setBiometricUseEnabled(value);
|
2020-10-24 13:20:59 -04:00
|
|
|
}
|
|
|
|
};
|
2019-11-10 06:43:41 -05:00
|
|
|
|
2020-07-15 13:32:59 -04:00
|
|
|
const navigateToPlausibleDeniability = () => {
|
|
|
|
navigate('PlausibleDeniability');
|
|
|
|
};
|
2018-09-30 04:31:09 -04:00
|
|
|
|
2024-02-25 23:09:18 -04:00
|
|
|
const renderPasscodeExplanation = () => {
|
|
|
|
let isCapable = true;
|
2024-03-02 12:50:26 -04:00
|
|
|
|
2024-02-25 23:09:18 -04:00
|
|
|
if (Platform.OS === 'android') {
|
|
|
|
if (Platform.Version < 30) {
|
|
|
|
isCapable = false;
|
|
|
|
}
|
|
|
|
}
|
2024-03-02 12:50:26 -04:00
|
|
|
|
2024-02-26 18:46:13 -04:00
|
|
|
return isCapable ? (
|
|
|
|
<>
|
|
|
|
<BlueText />
|
2024-05-17 18:34:39 -04:00
|
|
|
<BlueText>{loc.formatString(loc.settings.biometrics_fail, { type: deviceBiometricType })}</BlueText>
|
2024-02-26 18:46:13 -04:00
|
|
|
</>
|
|
|
|
) : null;
|
2024-02-25 23:09:18 -04:00
|
|
|
};
|
|
|
|
|
2024-03-02 12:50:26 -04:00
|
|
|
return isLoading ? (
|
|
|
|
<ScrollView centerContent>
|
|
|
|
<BlueLoading />
|
|
|
|
</ScrollView>
|
|
|
|
) : (
|
|
|
|
<ScrollView contentContainerStyle={styles.root} automaticallyAdjustContentInsets contentInsetAdjustmentBehavior="automatic">
|
2024-02-26 18:38:28 -04:00
|
|
|
<View style={styles.paddingTop} />
|
2024-05-17 18:45:51 -04:00
|
|
|
{deviceBiometricCapable && (
|
2024-01-13 10:56:29 -04:00
|
|
|
<>
|
2024-01-21 16:07:29 -04:00
|
|
|
<Text adjustsFontSizeToFit style={[styles.headerText, styleHooks.headerText]}>
|
2024-02-26 18:38:28 -04:00
|
|
|
{loc.settings.biometrics}
|
2024-01-21 16:07:29 -04:00
|
|
|
</Text>
|
2023-12-16 17:44:35 -04:00
|
|
|
<ListItem
|
2024-05-17 18:34:39 -04:00
|
|
|
title={loc.formatString(loc.settings.encrypt_use, { type: deviceBiometricType })}
|
2024-01-13 10:56:29 -04:00
|
|
|
Component={TouchableWithoutFeedback}
|
2024-05-17 18:34:39 -04:00
|
|
|
switch={{ value: biometricEnabled, onValueChange: onUseBiometricSwitch }}
|
2020-07-15 13:32:59 -04:00
|
|
|
/>
|
2024-02-26 18:38:28 -04:00
|
|
|
<BlueCard>
|
2024-05-17 18:34:39 -04:00
|
|
|
<BlueText>{loc.formatString(loc.settings.encrypt_use_expl, { type: deviceBiometricType })}</BlueText>
|
2024-02-26 18:38:28 -04:00
|
|
|
{renderPasscodeExplanation()}
|
|
|
|
</BlueCard>
|
|
|
|
<BlueSpacing20 />
|
2024-01-13 10:56:29 -04:00
|
|
|
</>
|
|
|
|
)}
|
2024-02-26 18:38:28 -04:00
|
|
|
<Text adjustsFontSizeToFit style={[styles.headerText, styleHooks.headerText]}>
|
|
|
|
{loc.settings.encrypt_tstorage}
|
|
|
|
</Text>
|
|
|
|
<ListItem
|
2024-03-02 12:50:26 -04:00
|
|
|
testID="EncyptedAndPasswordProtected"
|
2024-02-26 18:38:28 -04:00
|
|
|
hideChevron
|
|
|
|
title={loc.settings.encrypt_enc_and_pass}
|
|
|
|
Component={TouchableWithoutFeedback}
|
2024-03-02 12:50:26 -04:00
|
|
|
switch={{ onValueChange: onEncryptStorageSwitch, value: storageIsEncryptedSwitchEnabled }}
|
2024-02-26 18:38:28 -04:00
|
|
|
/>
|
|
|
|
{storageIsEncryptedSwitchEnabled && (
|
|
|
|
<ListItem
|
|
|
|
onPress={navigateToPlausibleDeniability}
|
|
|
|
title={loc.settings.plausible_deniability}
|
|
|
|
chevron
|
|
|
|
testID="PlausibleDeniabilityButton"
|
|
|
|
Component={TouchableOpacity}
|
|
|
|
/>
|
|
|
|
)}
|
2024-01-13 10:56:29 -04:00
|
|
|
</ScrollView>
|
2020-07-15 13:32:59 -04:00
|
|
|
);
|
2018-09-30 04:31:09 -04:00
|
|
|
};
|
2020-07-15 13:32:59 -04:00
|
|
|
|
2024-01-21 16:07:29 -04:00
|
|
|
const styles = StyleSheet.create({
|
2024-03-02 12:50:26 -04:00
|
|
|
root: {
|
|
|
|
flex: 1,
|
|
|
|
},
|
|
|
|
paddingTop: { paddingTop: 19 },
|
2024-01-21 16:07:29 -04:00
|
|
|
headerText: {
|
|
|
|
fontWeight: 'bold',
|
|
|
|
fontSize: 30,
|
|
|
|
marginLeft: 17,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2020-07-15 13:32:59 -04:00
|
|
|
export default EncryptStorage;
|