BlueWallet/screen/wallets/ImportWallet.tsx

241 lines
8.2 KiB
TypeScript
Raw Normal View History

2024-11-10 20:07:17 +00:00
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { RouteProp, useRoute } from '@react-navigation/native';
import Clipboard from '@react-native-clipboard/clipboard';
import { Keyboard, Platform, ScrollView, StyleSheet, TouchableWithoutFeedback, View } from 'react-native';
import { disallowScreenshot } from 'react-native-screen-capture';
2024-09-15 11:23:51 -04:00
import { BlueButtonLink, BlueFormLabel, BlueFormMultiInput, BlueSpacing20 } from '../../BlueComponents';
2023-11-15 08:54:04 -04:00
import Button from '../../components/Button';
2024-08-24 14:06:17 -04:00
import {
DoneAndDismissKeyboardInputAccessory,
DoneAndDismissKeyboardInputAccessoryViewID,
} from '../../components/DoneAndDismissKeyboardInputAccessory';
2024-09-27 08:39:31 -04:00
import HeaderMenuButton from '../../components/HeaderMenuButton';
2024-11-10 20:07:17 +00:00
import { useTheme } from '../../components/themes';
import { scanQrHelper } from '../../helpers/scan-qr';
2024-11-08 22:38:05 -04:00
import { useSettings } from '../../hooks/context/useSettings';
2024-11-10 20:07:17 +00:00
import { useExtendedNavigation } from '../../hooks/useExtendedNavigation';
import { useKeyboard } from '../../hooks/useKeyboard';
import loc from '../../loc';
import { CommonToolTipActions } from '../../typings/CommonToolTipActions';
import { AddWalletStackParamList } from '../../navigation/AddWalletStack';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
2024-11-10 20:07:17 +00:00
type RouteProps = RouteProp<AddWalletStackParamList, 'ImportWallet'>;
type NavigationProps = NativeStackNavigationProp<AddWalletStackParamList, 'ImportWallet'>;
const ImportWallet = () => {
const navigation = useExtendedNavigation<NavigationProps>();
2020-07-15 13:32:59 -04:00
const { colors } = useTheme();
2024-11-10 20:07:17 +00:00
const route = useRoute<RouteProps>();
const label = route?.params?.label ?? '';
const triggerImport = route?.params?.triggerImport ?? false;
2024-07-22 23:19:32 -04:00
const scannedData = route?.params?.scannedData ?? '';
2024-11-10 20:07:17 +00:00
const [importText, setImportText] = useState<string>(label);
const [isToolbarVisibleForAndroid, setIsToolbarVisibleForAndroid] = useState<boolean>(false);
const [, setSpeedBackdoor] = useState<number>(0);
const [searchAccountsMenuState, setSearchAccountsMenuState] = useState<boolean>(false);
const [askPassphraseMenuState, setAskPassphraseMenuState] = useState<boolean>(false);
const [clearClipboardMenuState, setClearClipboardMenuState] = useState<boolean>(true);
2024-11-08 22:38:05 -04:00
const { isPrivacyBlurEnabled } = useSettings();
// Styles
2020-07-15 13:32:59 -04:00
const styles = StyleSheet.create({
root: {
paddingTop: 10,
2020-07-15 13:32:59 -04:00
backgroundColor: colors.elevated,
flex: 1,
2020-07-15 13:32:59 -04:00
},
center: {
flex: 1,
marginHorizontal: 16,
2020-07-15 13:32:59 -04:00
backgroundColor: colors.elevated,
},
});
2024-11-10 20:07:17 +00:00
const onBlur = useCallback(() => {
2021-11-16 11:18:58 -05:00
const valueWithSingleWhitespace = importText.replace(/^\s+|\s+$|\s+(?=\s)/g, '');
2021-11-10 15:17:43 -05:00
setImportText(valueWithSingleWhitespace);
2021-11-14 10:57:48 -05:00
return valueWithSingleWhitespace;
2024-11-10 20:07:17 +00:00
}, [importText]);
2021-11-10 15:17:43 -05:00
useKeyboard({
onKeyboardDidShow: () => {
setIsToolbarVisibleForAndroid(true);
},
onKeyboardDidHide: () => {
setIsToolbarVisibleForAndroid(false);
},
});
2024-11-10 20:07:17 +00:00
const importMnemonic = useCallback(
async (text: string) => {
if (clearClipboardMenuState) {
try {
if (await Clipboard.hasString()) {
Clipboard.setString('');
}
} catch (error) {
console.error('Failed to clear clipboard:', error);
}
}
navigation.navigate('ImportWalletDiscovery', {
importText: text,
askPassphrase: askPassphraseMenuState,
searchAccounts: searchAccountsMenuState,
});
},
[askPassphraseMenuState, clearClipboardMenuState, navigation, searchAccountsMenuState],
);
2024-11-10 20:07:17 +00:00
const handleImport = useCallback(() => {
2021-11-14 10:57:48 -05:00
const textToImport = onBlur();
if (textToImport.trim().length === 0) {
2019-12-26 20:21:07 -06:00
return;
}
2021-11-14 10:57:48 -05:00
importMnemonic(textToImport);
2024-11-10 20:07:17 +00:00
}, [importMnemonic, onBlur]);
const onBarScanned = useCallback(
(value: string | { data: any }) => {
// no objects here, only strings
const newValue: string = typeof value !== 'string' ? value.data + '' : value;
setImportText(newValue);
setTimeout(() => importMnemonic(newValue), 500);
},
[importMnemonic],
);
2024-11-10 20:07:17 +00:00
const importScan = useCallback(async () => {
const data = await scanQrHelper(route.name, true);
2024-10-02 22:55:01 -04:00
if (data) {
onBarScanned(data);
}
2024-11-10 20:07:17 +00:00
}, [route.name, onBarScanned]);
const speedBackdoorTap = () => {
setSpeedBackdoor(v => {
v += 1;
if (v < 5) return v;
2024-05-08 17:41:13 -04:00
navigation.navigate('ImportSpeed');
return 0;
});
};
const toolTipOnPressMenuItem = useCallback(
2024-11-10 20:07:17 +00:00
(menuItem: string) => {
2024-10-06 17:49:52 -04:00
Keyboard.dismiss();
if (menuItem === CommonToolTipActions.Passphrase.id) {
2024-10-06 17:49:52 -04:00
setAskPassphraseMenuState(!askPassphraseMenuState);
} else if (menuItem === CommonToolTipActions.SearchAccount.id) {
2024-10-06 17:49:52 -04:00
setSearchAccountsMenuState(!searchAccountsMenuState);
} else if (menuItem === CommonToolTipActions.ClearClipboard.id) {
setClearClipboardMenuState(!clearClipboardMenuState);
}
},
2024-10-06 17:49:52 -04:00
[askPassphraseMenuState, clearClipboardMenuState, searchAccountsMenuState],
);
// ToolTipMenu actions for advanced options
const toolTipActions = useMemo(() => {
2024-11-10 20:07:17 +00:00
return [
{ ...CommonToolTipActions.Passphrase, menuState: askPassphraseMenuState },
{ ...CommonToolTipActions.SearchAccount, menuState: searchAccountsMenuState },
{ ...CommonToolTipActions.ClearClipboard, menuState: clearClipboardMenuState },
];
2024-10-06 17:49:52 -04:00
}, [askPassphraseMenuState, clearClipboardMenuState, searchAccountsMenuState]);
const HeaderRight = useMemo(
2024-09-27 08:39:31 -04:00
() => <HeaderMenuButton onPressMenuItem={toolTipOnPressMenuItem} actions={toolTipActions} />,
[toolTipOnPressMenuItem, toolTipActions],
);
2024-11-10 20:07:17 +00:00
useEffect(() => {
disallowScreenshot(isPrivacyBlurEnabled);
return () => {
disallowScreenshot(false);
};
}, [isPrivacyBlurEnabled]);
useEffect(() => {
if (triggerImport) handleImport();
}, [triggerImport, handleImport]);
useEffect(() => {
if (scannedData) {
onBarScanned(scannedData);
}
}, [scannedData, onBarScanned]);
// Adding the ToolTipMenu to the header
useEffect(() => {
navigation.setOptions({
headerRight: () => HeaderRight,
});
2024-10-06 17:49:52 -04:00
}, [colors.foregroundColor, navigation, toolTipActions, HeaderRight]);
const renderOptionsAndImportButton = (
<>
2020-04-27 03:11:33 -04:00
<BlueSpacing20 />
<View style={styles.center}>
<>
2024-11-10 20:07:17 +00:00
<Button disabled={importText.trim().length === 0} title={loc.wallets.import_do_import} testID="DoImport" onPress={handleImport} />
<BlueSpacing20 />
<BlueButtonLink title={loc.wallets.import_scan_qr} onPress={importScan} testID="ScanImport" />
</>
2020-04-27 03:11:33 -04:00
</View>
</>
);
return (
<ScrollView
contentContainerStyle={styles.root}
automaticallyAdjustContentInsets
automaticallyAdjustsScrollIndicatorInsets
2024-09-13 18:30:01 -04:00
keyboardShouldPersistTaps="always"
automaticallyAdjustKeyboardInsets
contentInsetAdjustmentBehavior="automatic"
>
<BlueSpacing20 />
<TouchableWithoutFeedback accessibilityRole="button" onPress={speedBackdoorTap} testID="SpeedBackdoor">
<BlueFormLabel>{loc.wallets.import_explanation}</BlueFormLabel>
</TouchableWithoutFeedback>
<BlueSpacing20 />
<BlueFormMultiInput
value={importText}
2021-11-14 10:51:39 -05:00
onBlur={onBlur}
onChangeText={setImportText}
testID="MnemonicInput"
2024-08-24 14:06:17 -04:00
inputAccessoryViewID={DoneAndDismissKeyboardInputAccessoryViewID}
/>
{Platform.select({ android: !isToolbarVisibleForAndroid && renderOptionsAndImportButton, default: renderOptionsAndImportButton })}
2020-04-27 03:11:33 -04:00
{Platform.select({
ios: (
2024-08-24 14:06:17 -04:00
<DoneAndDismissKeyboardInputAccessory
2020-04-27 03:11:33 -04:00
onClearTapped={() => {
2021-11-14 10:51:39 -05:00
setImportText('');
2020-04-27 03:11:33 -04:00
}}
onPasteTapped={text => {
setImportText(text);
Keyboard.dismiss();
}}
/>
2020-04-27 03:11:33 -04:00
),
android: isToolbarVisibleForAndroid && (
2024-08-24 14:06:17 -04:00
<DoneAndDismissKeyboardInputAccessory
2020-04-27 03:11:33 -04:00
onClearTapped={() => {
2021-11-14 10:51:39 -05:00
setImportText('');
2020-04-27 03:11:33 -04:00
Keyboard.dismiss();
}}
onPasteTapped={text => {
2021-11-14 10:51:39 -05:00
setImportText(text);
2020-04-27 03:11:33 -04:00
Keyboard.dismiss();
}}
/>
2020-04-27 03:11:33 -04:00
),
})}
</ScrollView>
2019-12-26 20:21:07 -06:00
);
};
2024-11-10 20:07:17 +00:00
export default ImportWallet;