mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-03-12 18:51:21 +01:00
wip
This commit is contained in:
parent
27116f851c
commit
8a9127d22e
2 changed files with 119 additions and 71 deletions
|
@ -18,7 +18,6 @@ interface PromptPasswordConfirmationModalProps {
|
||||||
modalType: ModalType;
|
modalType: ModalType;
|
||||||
onConfirmationSuccess: (password: string) => Promise<boolean>;
|
onConfirmationSuccess: (password: string) => Promise<boolean>;
|
||||||
onConfirmationFailure: () => void;
|
onConfirmationFailure: () => void;
|
||||||
onDismiss?: () => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PromptPasswordConfirmationModalHandle {
|
export interface PromptPasswordConfirmationModalHandle {
|
||||||
|
@ -27,16 +26,18 @@ export interface PromptPasswordConfirmationModalHandle {
|
||||||
}
|
}
|
||||||
|
|
||||||
const PromptPasswordConfirmationModal = forwardRef<PromptPasswordConfirmationModalHandle, PromptPasswordConfirmationModalProps>(
|
const PromptPasswordConfirmationModal = forwardRef<PromptPasswordConfirmationModalHandle, PromptPasswordConfirmationModalProps>(
|
||||||
({ modalType, onConfirmationSuccess, onConfirmationFailure, onDismiss }, ref) => {
|
({ modalType, onConfirmationSuccess, onConfirmationFailure }, ref) => {
|
||||||
const [password, setPassword] = useState('');
|
const [password, setPassword] = useState('');
|
||||||
const [confirmPassword, setConfirmPassword] = useState('');
|
const [confirmPassword, setConfirmPassword] = useState('');
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [isSuccess, setIsSuccess] = useState(false);
|
const [isSuccess, setIsSuccess] = useState(false);
|
||||||
|
const [showExplanation, setShowExplanation] = useState(true); // State to toggle between explanation and password input for CREATE_PASSWORD
|
||||||
const modalRef = useRef<BottomModalHandle>(null);
|
const modalRef = useRef<BottomModalHandle>(null);
|
||||||
const fadeOutAnimation = useRef(new Animated.Value(1)).current;
|
const fadeOutAnimation = useRef(new Animated.Value(1)).current;
|
||||||
const fadeInAnimation = useRef(new Animated.Value(0)).current;
|
const fadeInAnimation = useRef(new Animated.Value(0)).current;
|
||||||
const scaleAnimation = useRef(new Animated.Value(1)).current;
|
const scaleAnimation = useRef(new Animated.Value(1)).current;
|
||||||
const shakeAnimation = useRef(new Animated.Value(0)).current;
|
const shakeAnimation = useRef(new Animated.Value(0)).current;
|
||||||
|
const explanationOpacity = useRef(new Animated.Value(1)).current; // New animated value for opacity
|
||||||
const { colors } = useTheme();
|
const { colors } = useTheme();
|
||||||
const passwordInputRef = useRef<TextInput>(null);
|
const passwordInputRef = useRef<TextInput>(null);
|
||||||
const confirmPasswordInputRef = useRef<TextInput>(null);
|
const confirmPasswordInputRef = useRef<TextInput>(null);
|
||||||
|
@ -64,7 +65,7 @@ const PromptPasswordConfirmationModal = forwardRef<PromptPasswordConfirmationMod
|
||||||
present: async () => {
|
present: async () => {
|
||||||
resetState();
|
resetState();
|
||||||
modalRef.current?.present();
|
modalRef.current?.present();
|
||||||
if (modalType === MODAL_TYPES.CREATE_PASSWORD) {
|
if (modalType === MODAL_TYPES.CREATE_PASSWORD && !showExplanation) {
|
||||||
passwordInputRef.current?.focus();
|
passwordInputRef.current?.focus();
|
||||||
} else if (modalType === MODAL_TYPES.ENTER_PASSWORD) {
|
} else if (modalType === MODAL_TYPES.ENTER_PASSWORD) {
|
||||||
passwordInputRef.current?.focus();
|
passwordInputRef.current?.focus();
|
||||||
|
@ -72,7 +73,7 @@ const PromptPasswordConfirmationModal = forwardRef<PromptPasswordConfirmationMod
|
||||||
},
|
},
|
||||||
dismiss: async () => {
|
dismiss: async () => {
|
||||||
await modalRef.current?.dismiss();
|
await modalRef.current?.dismiss();
|
||||||
onDismiss?.(); // Call onDismiss if provided after modal dismisses
|
resetState();
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -85,26 +86,46 @@ const PromptPasswordConfirmationModal = forwardRef<PromptPasswordConfirmationMod
|
||||||
fadeInAnimation.setValue(0);
|
fadeInAnimation.setValue(0);
|
||||||
scaleAnimation.setValue(1);
|
scaleAnimation.setValue(1);
|
||||||
shakeAnimation.setValue(0);
|
shakeAnimation.setValue(0);
|
||||||
|
explanationOpacity.setValue(1);
|
||||||
|
if (modalType === MODAL_TYPES.CREATE_PASSWORD) {
|
||||||
|
setShowExplanation(true);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
resetState();
|
||||||
|
}, [modalType]);
|
||||||
|
|
||||||
const handleShakeAnimation = () => {
|
const handleShakeAnimation = () => {
|
||||||
Animated.sequence([
|
Animated.sequence([
|
||||||
Animated.timing(shakeAnimation, {
|
Animated.timing(shakeAnimation, {
|
||||||
toValue: 10,
|
toValue: 10,
|
||||||
duration: 100,
|
duration: 150,
|
||||||
easing: Easing.bounce,
|
easing: Easing.inOut(Easing.ease),
|
||||||
useNativeDriver: true,
|
useNativeDriver: true,
|
||||||
}),
|
}),
|
||||||
Animated.timing(shakeAnimation, {
|
Animated.timing(shakeAnimation, {
|
||||||
toValue: -10,
|
toValue: -10,
|
||||||
|
duration: 150,
|
||||||
|
easing: Easing.inOut(Easing.ease),
|
||||||
|
useNativeDriver: true,
|
||||||
|
}),
|
||||||
|
Animated.timing(shakeAnimation, {
|
||||||
|
toValue: 5,
|
||||||
duration: 100,
|
duration: 100,
|
||||||
easing: Easing.bounce,
|
easing: Easing.inOut(Easing.ease),
|
||||||
|
useNativeDriver: true,
|
||||||
|
}),
|
||||||
|
Animated.timing(shakeAnimation, {
|
||||||
|
toValue: -5,
|
||||||
|
duration: 100,
|
||||||
|
easing: Easing.inOut(Easing.ease),
|
||||||
useNativeDriver: true,
|
useNativeDriver: true,
|
||||||
}),
|
}),
|
||||||
Animated.timing(shakeAnimation, {
|
Animated.timing(shakeAnimation, {
|
||||||
toValue: 0,
|
toValue: 0,
|
||||||
duration: 100,
|
duration: 100,
|
||||||
easing: Easing.bounce,
|
easing: Easing.inOut(Easing.ease),
|
||||||
useNativeDriver: true,
|
useNativeDriver: true,
|
||||||
}),
|
}),
|
||||||
]).start(() => {
|
]).start(() => {
|
||||||
|
@ -175,22 +196,23 @@ const PromptPasswordConfirmationModal = forwardRef<PromptPasswordConfirmationMod
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleTransitionToCreatePassword = () => {
|
||||||
|
Animated.timing(explanationOpacity, {
|
||||||
|
toValue: 0,
|
||||||
|
duration: 300,
|
||||||
|
useNativeDriver: true,
|
||||||
|
}).start(() => {
|
||||||
|
setShowExplanation(false);
|
||||||
|
explanationOpacity.setValue(1); // Reset opacity for when transitioning back
|
||||||
|
passwordInputRef.current?.focus();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const handleCancel = async () => {
|
const handleCancel = async () => {
|
||||||
resetState();
|
|
||||||
onConfirmationFailure();
|
onConfirmationFailure();
|
||||||
await modalRef.current?.dismiss();
|
await modalRef.current?.dismiss();
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
resetState();
|
|
||||||
if (modalType === MODAL_TYPES.CREATE_PASSWORD) {
|
|
||||||
passwordInputRef.current?.focus();
|
|
||||||
} else if (modalType === MODAL_TYPES.ENTER_PASSWORD) {
|
|
||||||
passwordInputRef.current?.focus();
|
|
||||||
}
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [modalType]);
|
|
||||||
|
|
||||||
const animatedViewStyle: Animated.WithAnimatedObject<ViewStyle> = {
|
const animatedViewStyle: Animated.WithAnimatedObject<ViewStyle> = {
|
||||||
opacity: fadeOutAnimation,
|
opacity: fadeOutAnimation,
|
||||||
transform: [{ scale: scaleAnimation }],
|
transform: [{ scale: scaleAnimation }],
|
||||||
|
@ -201,13 +223,14 @@ const PromptPasswordConfirmationModal = forwardRef<PromptPasswordConfirmationMod
|
||||||
<BottomModal
|
<BottomModal
|
||||||
ref={modalRef}
|
ref={modalRef}
|
||||||
showCloseButton={false}
|
showCloseButton={false}
|
||||||
onDismiss={onDismiss || handleCancel}
|
onDismiss={resetState}
|
||||||
grabber={false}
|
grabber={false}
|
||||||
sizes={[350]}
|
sizes={[370]}
|
||||||
backgroundColor={colors.modal}
|
backgroundColor={colors.modal}
|
||||||
contentContainerStyle={styles.modalContent}
|
contentContainerStyle={styles.modalContent}
|
||||||
footer={
|
footer={
|
||||||
!isSuccess && (
|
!isSuccess ? (
|
||||||
|
showExplanation && modalType === MODAL_TYPES.CREATE_PASSWORD ? null : (
|
||||||
<Animated.View style={{ opacity: fadeOutAnimation, transform: [{ scale: scaleAnimation }] }}>
|
<Animated.View style={{ opacity: fadeOutAnimation, transform: [{ scale: scaleAnimation }] }}>
|
||||||
<View style={styles.feeModalFooter}>
|
<View style={styles.feeModalFooter}>
|
||||||
<SecondButton testID="CancelButton" title={loc._.cancel} onPress={handleCancel} disabled={isLoading} />
|
<SecondButton testID="CancelButton" title={loc._.cancel} onPress={handleCancel} disabled={isLoading} />
|
||||||
|
@ -221,11 +244,27 @@ const PromptPasswordConfirmationModal = forwardRef<PromptPasswordConfirmationMod
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
) || undefined
|
)
|
||||||
|
) : null
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{!isSuccess && modalType !== MODAL_TYPES.SUCCESS && (
|
{!isSuccess && (
|
||||||
<Animated.View style={animatedViewStyle}>
|
<Animated.View style={animatedViewStyle}>
|
||||||
|
{modalType === MODAL_TYPES.CREATE_PASSWORD && showExplanation && (
|
||||||
|
<Animated.View style={{ opacity: explanationOpacity }}>
|
||||||
|
<Text style={[styles.textLabel, stylesHook.feeModalLabel]}>{loc.settings.encrypt_storage_explanation_headline}</Text>
|
||||||
|
<Text style={[styles.description, stylesHook.feeModalCustomText]}>
|
||||||
|
{loc.settings.encrypt_storage_explanation_description_line1}
|
||||||
|
</Text>
|
||||||
|
<Text style={[styles.description, stylesHook.feeModalCustomText]}>
|
||||||
|
{loc.settings.encrypt_storage_explanation_description_line2}
|
||||||
|
</Text>
|
||||||
|
<View style={styles.feeModalFooter} />
|
||||||
|
<SecondButton title={loc.settings.i_understand} onPress={handleTransitionToCreatePassword} disabled={isLoading} />
|
||||||
|
</Animated.View>
|
||||||
|
)}
|
||||||
|
{(modalType === MODAL_TYPES.ENTER_PASSWORD || (modalType === MODAL_TYPES.CREATE_PASSWORD && !showExplanation)) && (
|
||||||
|
<>
|
||||||
<Text style={[styles.textLabel, stylesHook.feeModalLabel]}>
|
<Text style={[styles.textLabel, stylesHook.feeModalLabel]}>
|
||||||
{modalType === MODAL_TYPES.CREATE_PASSWORD ? loc.settings.password_explain : loc._.enter_password}
|
{modalType === MODAL_TYPES.CREATE_PASSWORD ? loc.settings.password_explain : loc._.enter_password}
|
||||||
</Text>
|
</Text>
|
||||||
|
@ -237,7 +276,6 @@ const PromptPasswordConfirmationModal = forwardRef<PromptPasswordConfirmationMod
|
||||||
secureTextEntry
|
secureTextEntry
|
||||||
placeholder="Password"
|
placeholder="Password"
|
||||||
value={password}
|
value={password}
|
||||||
selectTextOnFocus
|
|
||||||
onChangeText={setPassword}
|
onChangeText={setPassword}
|
||||||
style={[styles.input, stylesHook.input]}
|
style={[styles.input, stylesHook.input]}
|
||||||
autoFocus
|
autoFocus
|
||||||
|
@ -252,7 +290,6 @@ const PromptPasswordConfirmationModal = forwardRef<PromptPasswordConfirmationMod
|
||||||
secureTextEntry
|
secureTextEntry
|
||||||
placeholder="Confirm Password"
|
placeholder="Confirm Password"
|
||||||
value={confirmPassword}
|
value={confirmPassword}
|
||||||
selectTextOnFocus
|
|
||||||
onChangeText={setConfirmPassword}
|
onChangeText={setConfirmPassword}
|
||||||
style={[styles.input, stylesHook.input]}
|
style={[styles.input, stylesHook.input]}
|
||||||
onSubmitEditing={handleSubmit} // Handle Enter key as OK
|
onSubmitEditing={handleSubmit} // Handle Enter key as OK
|
||||||
|
@ -260,6 +297,8 @@ const PromptPasswordConfirmationModal = forwardRef<PromptPasswordConfirmationMod
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
)}
|
)}
|
||||||
{isSuccess && (
|
{isSuccess && (
|
||||||
|
@ -278,7 +317,7 @@ const PromptPasswordConfirmationModal = forwardRef<PromptPasswordConfirmationMod
|
||||||
transform: [
|
transform: [
|
||||||
{
|
{
|
||||||
scale: scaleAnimation.interpolate({
|
scale: scaleAnimation.interpolate({
|
||||||
inputRange: [0, 1],
|
inputRange: [0.8, 1],
|
||||||
outputRange: [0.8, 1],
|
outputRange: [0.8, 1],
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
@ -333,6 +372,11 @@ const styles = StyleSheet.create({
|
||||||
marginBottom: 16,
|
marginBottom: 16,
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
},
|
},
|
||||||
|
description: {
|
||||||
|
fontSize: 16,
|
||||||
|
marginBottom: 12,
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
successContainer: {
|
successContainer: {
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
|
|
@ -264,6 +264,10 @@
|
||||||
"encrypt_decrypt": "Decrypt Storage",
|
"encrypt_decrypt": "Decrypt Storage",
|
||||||
"encrypt_decrypt_q": "Are you sure you want to decrypt your storage? This will allow your wallets to be accessed without a password.",
|
"encrypt_decrypt_q": "Are you sure you want to decrypt your storage? This will allow your wallets to be accessed without a password.",
|
||||||
"encrypt_enc_and_pass": "Encrypted and Password Protected",
|
"encrypt_enc_and_pass": "Encrypted and Password Protected",
|
||||||
|
"encrypt_storage_explanation_headline": "Enable Storage Encryption",
|
||||||
|
"encrypt_storage_explanation_description_line1": "Enabling Storage Encryption adds an extra layer of protection to your app by securing the way your data is stored on your device. This makes it harder for anyone to access your information without permission.",
|
||||||
|
"encrypt_storage_explanation_description_line2": "However, it's important to know that this encryption only protects the access to your wallets stored on the device's keychain. It doesn't put a password or any extra protection on the wallets themselves.",
|
||||||
|
"i_understand": "I understand",
|
||||||
"encrypt_title": "Security",
|
"encrypt_title": "Security",
|
||||||
"encrypt_tstorage": "Storage",
|
"encrypt_tstorage": "Storage",
|
||||||
"encrypt_use": "Use {type}",
|
"encrypt_use": "Use {type}",
|
||||||
|
|
Loading…
Add table
Reference in a new issue