Merge branch 'master' into navc

This commit is contained in:
Overtorment 2025-01-14 17:01:11 +00:00 committed by GitHub
commit 756f37eeb4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 148 additions and 142 deletions

View file

@ -3,8 +3,8 @@ import { Animated, SafeAreaView, StatusBar, StyleSheet, TouchableOpacity, View }
import { Camera, CameraApi, CameraType, Orientation } from 'react-native-camera-kit';
import loc from '../loc';
import { Icon } from '@rneui/base';
const AnimatedIcon = Animated.createAnimatedComponent(Icon);
import { OnOrientationChangeData, OnReadCodeData } from 'react-native-camera-kit/dist/CameraProps';
import { triggerSelectionHapticFeedback } from '../blue_modules/hapticFeedback';
interface CameraScreenProps {
onCancelButtonPress: () => void;
@ -12,8 +12,7 @@ interface CameraScreenProps {
showFilePickerButton?: boolean;
onImagePickerButtonPress?: () => void;
onFilePickerButtonPress?: () => void;
onReadCode?: (event: any) => void;
onReadCode?: (event: OnReadCodeData) => void;
}
const CameraScreen: React.FC<CameraScreenProps> = ({
@ -22,7 +21,6 @@ const CameraScreen: React.FC<CameraScreenProps> = ({
showFilePickerButton,
onImagePickerButtonPress,
onFilePickerButtonPress,
onReadCode,
}) => {
const cameraRef = useRef<CameraApi>(null);
@ -35,10 +33,12 @@ const CameraScreen: React.FC<CameraScreenProps> = ({
const direction = cameraType === CameraType.Back ? CameraType.Front : CameraType.Back;
setCameraType(direction);
setZoom(1); // When changing camera type, reset to default zoom for that camera
triggerSelectionHapticFeedback();
};
const onSetTorch = () => {
setTorchMode(!torchMode);
triggerSelectionHapticFeedback();
};
// Counter-rotate the icons to indicate the actual orientation of the captured photo.
@ -60,17 +60,47 @@ const CameraScreen: React.FC<CameraScreenProps> = ({
}).start();
}
const handleZoom = (e: { nativeEvent: { zoom: number } }) => {
console.debug('zoom', e.nativeEvent.zoom);
setZoom(e.nativeEvent.zoom);
};
const handleOrientationChange = (e: OnOrientationChangeData) => {
switch (e.nativeEvent.orientation) {
case Orientation.PORTRAIT_UPSIDE_DOWN:
console.debug('orientationChange', 'PORTRAIT_UPSIDE_DOWN');
rotateUiTo(1);
break;
case Orientation.LANDSCAPE_LEFT:
console.debug('orientationChange', 'LANDSCAPE_LEFT');
rotateUiTo(2);
break;
case Orientation.PORTRAIT:
console.debug('orientationChange', 'PORTRAIT');
rotateUiTo(3);
break;
case Orientation.LANDSCAPE_RIGHT:
console.debug('orientationChange', 'LANDSCAPE_RIGHT');
rotateUiTo(4);
break;
default:
console.debug('orientationChange', e.nativeEvent);
break;
}
};
const handleReadCode = (event: OnReadCodeData) => {
onReadCode?.(event);
};
return (
<View style={styles.screen}>
<StatusBar hidden />
<SafeAreaView style={styles.topButtons}>
<TouchableOpacity style={styles.topButton} onPress={onSetTorch}>
<AnimatedIcon
name={torchMode ? 'flashlight-on' : 'flashlight-off'}
type="font-awesome-6"
color="#ffffff"
style={{ ...styles.topButtonImg, ...uiRotationStyle }}
/>
<Animated.View style={[styles.topButtonImg, uiRotationStyle]}>
<Icon name={torchMode ? 'flashlight-on' : 'flashlight-off'} type="font-awesome-6" color="#ffffff" />
</Animated.View>
</TouchableOpacity>
<View style={styles.rightButtonsContainer}>
{showImagePickerButton && (
@ -80,7 +110,9 @@ const CameraScreen: React.FC<CameraScreenProps> = ({
style={[styles.topButton, styles.spacing, uiRotationStyle]}
onPress={onImagePickerButtonPress}
>
<AnimatedIcon name="image" type="font-awesome" color="#ffffff" style={{ ...styles.topButtonImg, ...uiRotationStyle }} />
<Animated.View style={[styles.topButtonImg, uiRotationStyle]}>
<Icon name="image" type="font-awesome" color="#ffffff" />
</Animated.View>
</TouchableOpacity>
)}
{showFilePickerButton && (
@ -90,12 +122,9 @@ const CameraScreen: React.FC<CameraScreenProps> = ({
style={[styles.topButton, styles.spacing, uiRotationStyle]}
onPress={onFilePickerButtonPress}
>
<AnimatedIcon
name="file-import"
type="font-awesome-5"
color="#ffffff"
style={{ ...styles.topButtonImg, ...uiRotationStyle }}
/>
<Animated.View style={[styles.topButtonImg, uiRotationStyle]}>
<Icon name="file-import" type="font-awesome-5" color="#ffffff" />
</Animated.View>
</TouchableOpacity>
)}
</View>
@ -109,40 +138,14 @@ const CameraScreen: React.FC<CameraScreenProps> = ({
resetFocusWhenMotionDetected
zoom={zoom}
maxZoom={10}
onZoom={e => {
console.debug('zoom', e.nativeEvent.zoom);
setZoom(e.nativeEvent.zoom);
}}
onReadCode={onReadCode}
scanBarcode
resizeMode="cover"
onZoom={handleZoom}
onReadCode={handleReadCode}
torchMode={torchMode ? 'on' : 'off'}
shutterPhotoSound
maxPhotoQualityPrioritization="quality"
onOrientationChange={e => {
// We recommend locking the camera UI to portrait (using a different library)
// and rotating the UI elements counter to the orientation
// However, we include onOrientationChange so you can match your UI to what the camera does
switch (e.nativeEvent.orientation) {
case Orientation.PORTRAIT_UPSIDE_DOWN:
console.debug('orientationChange', 'PORTRAIT_UPSIDE_DOWN');
rotateUiTo(1);
break;
case Orientation.LANDSCAPE_LEFT:
console.debug('orientationChange', 'LANDSCAPE_LEFT');
rotateUiTo(2);
break;
case Orientation.PORTRAIT:
console.debug('orientationChange', 'PORTRAIT');
rotateUiTo(3);
break;
case Orientation.LANDSCAPE_RIGHT:
console.debug('orientationChange', 'LANDSCAPE_RIGHT');
rotateUiTo(4);
break;
default:
console.debug('orientationChange', e.nativeEvent);
break;
}
}}
onOrientationChange={handleOrientationChange}
/>
</View>
@ -151,7 +154,9 @@ const CameraScreen: React.FC<CameraScreenProps> = ({
<Animated.Text style={[styles.backTextStyle, uiRotationStyle]}>{loc._.cancel}</Animated.Text>
</TouchableOpacity>
<TouchableOpacity style={styles.bottomButton} onPress={onSwitchCameraPressed}>
<AnimatedIcon name="cameraswitch" type="font-awesome-6" color="#ffffff" style={{ ...styles.topButtonImg, ...uiRotationStyle }} />
<Animated.View style={[styles.topButtonImg, uiRotationStyle]}>
<Icon name="cameraswitch" type="font-awesome-6" color="#ffffff" />
</Animated.View>
</TouchableOpacity>
</SafeAreaView>
</View>

View file

@ -13,7 +13,7 @@ PODS:
- hermes-engine/Pre-built (= 0.75.4)
- hermes-engine/Pre-built (0.75.4)
- lottie-ios (4.5.0)
- lottie-react-native (7.1.0):
- lottie-react-native (7.2.1):
- DoubleConversion
- glog
- hermes-engine
@ -1613,7 +1613,7 @@ PODS:
- React
- RNCAsyncStorage (2.1.0):
- React-Core
- RNCClipboard (1.15.0):
- RNCClipboard (1.16.0):
- React-Core
- RNCPushNotificationIOS (1.11.0):
- React-Core
@ -2209,7 +2209,7 @@ SPEC CHECKSUMS:
glog: 69ef571f3de08433d766d614c73a9838a06bf7eb
hermes-engine: ea92f60f37dba025e293cbe4b4a548fd26b610a0
lottie-ios: a881093fab623c467d3bce374367755c272bdd59
lottie-react-native: 015e84640c4b8dd47049a8c981996fd203001ddf
lottie-react-native: 816fb00189b309b3eee7c152ddfc8d37f56d1865
RCT-Folly: 34124ae2e667a0e5f0ea378db071d27548124321
RCTDeprecation: 726d24248aeab6d7180dac71a936bbca6a994ed1
RCTRequired: a94e7febda6db0345d207e854323c37e3a31d93b
@ -2280,7 +2280,7 @@ SPEC CHECKSUMS:
ReactNativeCameraKit: e72b838dac4ea2da19b7eb5d00b23125072790fd
RealmJS: 9fd51c849eb552ade9f7b11db42a319b4f6cab4c
RNCAsyncStorage: c91d753ede6dc21862c4922cd13f98f7cfde578e
RNCClipboard: dbcf25b8f666b4685c02eeb65be981d30198e505
RNCClipboard: d05e3f409b80d63c6507fd5753846e5992057799
RNCPushNotificationIOS: 6c4ca3388c7434e4a662b92e4dfeeee858e6f440
RNDefaultPreference: 8a089ee8ce829a66c5453e3c5434f0785499d1c3
RNDeviceInfo: ae26ae45db3f9937f038a284bcd0a1db8d70db96

View file

@ -28,6 +28,8 @@
"enter_amount": "Wprowadź kwotę",
"qr_custom_input_button": "Stuknij 10 razy, aby wprowadzić niestandardowe dane",
"unlock": "Odblokuj",
"port": "Port",
"ssl_port": "Port SSL",
"suggested": "Sugerowane"
},
"azteco": {
@ -74,6 +76,7 @@
"please_pay": "Proszę zapłać",
"preimage": "Obraz pierwotny",
"sats": "satoshi.",
"date_time": "Data i czas",
"wasnt_paid_and_expired": "Ta faktura nie została opłacona i przeterminowała się."
},
"plausibledeniability": {
@ -190,7 +193,7 @@
"outdated_rate": "Ostatnia aktualizacja kursu: {date}",
"psbt_tx_open": "Otwórz podpisaną transakcję",
"psbt_tx_scan": "Skanuj Podpisane Transakcje",
"qr_error_no_qrcode": "Nie udało nam się znaleźć kodu QR na wybranym obrazie. Upewnij się, że obraz zawiera tylko kod QR bez dodatkowych treści, takich jak tekst czy przyciski.",
"qr_error_no_qrcode": "Nie udało nam się znaleźć prawidłowego kodu QR w wybranym obrazie. Upewnij się, że obraz zawiera tylko kod QR i nie ma dodatkowych elementów, takich jak tekst lub przyciski.",
"reset_amount": "Resetuj ilość",
"reset_amount_confirm": "Czy chcesz zresetować ilość?",
"success_done": "Zrobione",
@ -250,15 +253,10 @@
"electrum_status": "Status",
"electrum_preferred_server": "Preferowany serwer",
"electrum_preferred_server_description": "Wprowadź serwer, którego ma używać twój portfel do wszystkich operacji związanych z Bitcoinem. Po zapisaniu ustawień, portfel będzie korzystał wyłącznie z tego serwera do sprawdzania sald, wysyłania transakcji oraz pobierania danych z sieci. Upewnij się, że masz zaufanie do tego serwera przed jego wyborem.",
"electrum_clear_alert_title": "Wyczyścić historię?",
"electrum_clear_alert_message": "Czy chcesz wyczyścić historię serwerów Electrum?",
"electrum_clear_alert_cancel": "Anuluj",
"electrum_clear_alert_ok": "Ok",
"electrum_reset": "Ustaw wartości domyślne",
"electrum_unable_to_connect": "Nie można się połączyć z {server}.",
"electrum_history": "Historia",
"electrum_reset_to_default": "Czy na pewno ustawić domyślne ustawienia Electrum?",
"electrum_clear": "Wyczyść historię",
"electrum_reset_to_default": "To pozwoli BlueWallet losowo wybrać serwer z sugerowanej listy i historii. Historia Twoich serwerów pozostanie niezmieniona.",
"electrum_reset": "Ustaw wartości domyślne",
"encrypt_decrypt": "Odszyfruj Magazyn Danych",
"encrypt_decrypt_q": "Czy jesteś pewien, że chcesz odszyfrować schowek? To pozwoli na dostęp do twoich portfeli bez hasła.",
"encrypt_enc_and_pass": "Szyfrowany i chroniony hasłem",
@ -272,6 +270,8 @@
"encrypt_title": "Zabezpieczenia",
"encrypt_tstorage": "Dane",
"encrypt_use": "Użyj {type}",
"set_as_preferred": "Ustaw jako preferowany",
"set_as_preferred_electrum": "Ustawienie {host}:{port} jako preferowanego serwera wyłączy losowe łączenie się z sugerowanym serwerem.",
"encrypted_feature_disabled": "Ta funkcja nie może być używana z włączonym szyfrowaniem pamięci.",
"encrypt_use_expl": "{type} będzie użyty w celu potwierdzenia twojej tożsamości przed wykonaniem transakcji, odblokowaniem, eksportem lub usunięciem portfela. {type} nie będzie użyty do odblokowania danych zaszyfrowanych.",
"biometrics_fail": "Jeśli {type} nie jest włączony lub nie udaje się odblokować, możesz alternatywnie użyć kodu dostępu swojego urządzenia.",
@ -291,6 +291,7 @@
"network": "Sieć",
"network_broadcast": "Rozgłoś transakcję",
"network_electrum": "Serwer Electrum",
"electrum_suggested_description": "Gdy preferowany serwer nie jest ustawiony, sugerowany serwer zostanie wybrany losowo do użycia.",
"not_a_valid_uri": "Nieprawidłowy adres",
"notifications": "Powiadomienia",
"open_link_in_explorer": "Otwórz link w eksploratorze bloków",
@ -654,6 +655,8 @@
"bip47": {
"payment_code": "Kod płatności",
"contacts": "Kontakty",
"bip47_explain": "Kod wielokrotnego użytku i do udostępnienia.",
"bip47_explain_subtitle": "BIP47",
"purpose": "Kod wielokrotnego użytku możliwy do udostępnienia (BIP47)",
"pay_this_contact": "Zapłać temu kontaktowi",
"rename_contact": "Zmień nazwę kontaktu",
@ -667,7 +670,7 @@
"notification_tx_unconfirmed": "Transakcja powiadomienia nie została jeszcze potwierdzona, proszę czekać",
"failed_create_notif_tx": "Nie udało się utworzyć transakcji on-chain",
"onchain_tx_needed": "Wymagana transakcja on-chain",
"notif_tx_sent": "Transakcja powiadomienia wysłana. Proszę czekać na jej potwierdzenie",
"notif_tx_sent" : "Transakcja powiadomienia wysłana. Proszę czekać na jej potwierdzenie",
"notif_tx": "Transakcja powiadomienia",
"not_found": "Kod płatności nie znaleziony"
}

35
package-lock.json generated
View file

@ -70,7 +70,7 @@
"react-native-document-picker": "9.3.1",
"react-native-draglist": "github:BlueWallet/react-native-draglist#a4af02f",
"react-native-fs": "2.20.0",
"react-native-gesture-handler": "2.21.2",
"react-native-gesture-handler": "2.22.0",
"react-native-handoff": "github:BlueWallet/react-native-handoff#v0.0.4",
"react-native-haptic-feedback": "2.3.3",
"react-native-image-picker": "7.2.2",
@ -78,20 +78,20 @@
"react-native-keychain": "9.1.0",
"react-native-linear-gradient": "2.8.3",
"react-native-localize": "3.4.1",
"react-native-permissions": "5.2.2",
"react-native-permissions": "5.2.3",
"react-native-prompt-android": "github:BlueWallet/react-native-prompt-android#ed168d66fed556bc2ed07cf498770f058b78a376",
"react-native-push-notification": "8.1.1",
"react-native-qrcode-svg": "6.3.2",
"react-native-quick-actions": "0.3.13",
"react-native-randombytes": "3.6.1",
"react-native-rate": "1.2.12",
"react-native-reanimated": "3.16.6",
"react-native-reanimated": "3.16.7",
"react-native-safe-area-context": "4.14.1",
"react-native-screen-capture": "github:BlueWallet/react-native-screen-capture#18cb79f",
"react-native-screens": "3.35.0",
"react-native-secure-key-store": "github:BlueWallet/react-native-secure-key-store#2076b4849e88aa0a78e08bfbb4ce3923e0925cbc",
"react-native-share": "11.1.0",
"react-native-svg": "15.10.1",
"react-native-svg": "15.11.1",
"react-native-tcp-socket": "6.2.0",
"react-native-vector-icons": "10.2.0",
"react-native-watch-connectivity": "1.1.0",
@ -22019,15 +22019,14 @@
}
},
"node_modules/react-native-gesture-handler": {
"version": "2.21.2",
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.21.2.tgz",
"integrity": "sha512-HcwB225K9aeZ8e/B8nFzEh+2T4EPWTeamO1l/y3PcQ9cyCDYO2zja/G31ITpYRIqkip7XzGs6wI/gnHOQn1LDQ==",
"version": "2.22.0",
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.22.0.tgz",
"integrity": "sha512-m5Ps1cOSxSiMP4re+XsbeWcC9DNJuIEjMSmtUxBdyfYEJtdu5iAAiX7KlHHrf2mnK4I/56Ncy4PvPKWBwSpWpQ==",
"license": "MIT",
"dependencies": {
"@egjs/hammerjs": "^2.0.17",
"hoist-non-react-statics": "^3.3.0",
"invariant": "^2.2.4",
"prop-types": "^15.7.2"
"invariant": "^2.2.4"
},
"peerDependencies": {
"react": "*",
@ -22118,9 +22117,9 @@
}
},
"node_modules/react-native-permissions": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/react-native-permissions/-/react-native-permissions-5.2.2.tgz",
"integrity": "sha512-Mae5VKT8bjliksONZ+jMYTPf90wxuhn1H1FiH/kRfw0Y5tW5WIV1P8t/KiEHKZRvimnrInimuCr+EpRzK0IPWQ==",
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/react-native-permissions/-/react-native-permissions-5.2.3.tgz",
"integrity": "sha512-HGcMxGkfPUhhnWnQRkeihqiUdF5FrXVYbvwduyzeqsDLDfEJcQqVF6vPvNkVx74XhN5XgrcjPQh1RV8Owf9hhg==",
"license": "MIT",
"peerDependencies": {
"react": ">=18.1.0",
@ -22218,9 +22217,9 @@
}
},
"node_modules/react-native-reanimated": {
"version": "3.16.6",
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.16.6.tgz",
"integrity": "sha512-jPbAfLF5t8+UCKFTO+LeOY+OmAcDP5SsAfqINvNQz5GFGvoO7UebxujjtY58CmpZNH6c3SQ514FF9//mZDpo/g==",
"version": "3.16.7",
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.16.7.tgz",
"integrity": "sha512-qoUUQOwE1pHlmQ9cXTJ2MX9FQ9eHllopCLiWOkDkp6CER95ZWeXhJCP4cSm6AD4jigL5jHcZf/SkWrg8ttZUsw==",
"license": "MIT",
"dependencies": {
"@babel/plugin-transform-arrow-functions": "^7.0.0-0",
@ -22299,9 +22298,9 @@
}
},
"node_modules/react-native-svg": {
"version": "15.10.1",
"resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.10.1.tgz",
"integrity": "sha512-Hqz/doQciVFK/Df2v+wsW96oY5jxlta7rZ31KQYo78dlgvAHEaGr6paEOAMvlIruw7EHNQ0Vc1ZmJPJF2kfIPQ==",
"version": "15.11.1",
"resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.11.1.tgz",
"integrity": "sha512-Qmwx/yJKt+AHUr4zjxx/Q69qwKtRfr1+uIfFMQoq3WFRhqU76aL9db1DyvPiY632DAsVGba1pHf92OZPkpjrdQ==",
"license": "MIT",
"dependencies": {
"css-select": "^5.1.0",

View file

@ -134,7 +134,7 @@
"react-native-document-picker": "9.3.1",
"react-native-draglist": "github:BlueWallet/react-native-draglist#a4af02f",
"react-native-fs": "2.20.0",
"react-native-gesture-handler": "2.21.2",
"react-native-gesture-handler": "2.22.0",
"react-native-handoff": "github:BlueWallet/react-native-handoff#v0.0.4",
"react-native-haptic-feedback": "2.3.3",
"react-native-image-picker": "7.2.2",
@ -142,20 +142,20 @@
"react-native-keychain": "9.1.0",
"react-native-linear-gradient": "2.8.3",
"react-native-localize": "3.4.1",
"react-native-permissions": "5.2.2",
"react-native-permissions": "5.2.3",
"react-native-prompt-android": "github:BlueWallet/react-native-prompt-android#ed168d66fed556bc2ed07cf498770f058b78a376",
"react-native-push-notification": "8.1.1",
"react-native-qrcode-svg": "6.3.2",
"react-native-quick-actions": "0.3.13",
"react-native-randombytes": "3.6.1",
"react-native-rate": "1.2.12",
"react-native-reanimated": "3.16.6",
"react-native-reanimated": "3.16.7",
"react-native-safe-area-context": "4.14.1",
"react-native-screen-capture": "github:BlueWallet/react-native-screen-capture#18cb79f",
"react-native-screens": "3.35.0",
"react-native-secure-key-store": "github:BlueWallet/react-native-secure-key-store#2076b4849e88aa0a78e08bfbb4ce3923e0925cbc",
"react-native-share": "11.1.0",
"react-native-svg": "15.10.1",
"react-native-svg": "15.11.1",
"react-native-tcp-socket": "6.2.0",
"react-native-vector-icons": "10.2.0",
"react-native-watch-connectivity": "1.1.0",

View file

@ -2,7 +2,7 @@ import { useFocusEffect, useIsFocused, useNavigation, useRoute } from '@react-na
import * as bitcoin from 'bitcoinjs-lib';
import createHash from 'create-hash';
import React, { useCallback, useEffect, useState } from 'react';
import { Alert, Platform, StyleSheet, TextInput, TouchableOpacity, View } from 'react-native';
import { Platform, StyleSheet, TextInput, TouchableOpacity, View } from 'react-native';
import Base43 from '../../blue_modules/base43';
import * as fs from '../../blue_modules/fs';
import { BlueURDecoder, decodeUR, extractSingleWorkload } from '../../blue_modules/ur';
@ -14,6 +14,8 @@ import { isCameraAuthorizationStatusGranted } from '../../helpers/scan-qr';
import loc from '../../loc';
import { useSettings } from '../../hooks/context/useSettings';
import CameraScreen from '../../components/CameraScreen';
import SafeArea from '../../components/SafeArea';
import presentAlert from '../../components/Alert';
let decoder = false;
@ -120,20 +122,13 @@ const ScanQRCode = () => {
} catch (error) {
console.warn(error);
setIsLoading(true);
Alert.alert(
loc.send.scan_error,
loc._.invalid_animated_qr_code_fragment,
[
{
text: loc._.ok,
onPress: () => {
setIsLoading(false);
},
style: 'default',
},
],
{ cancelabe: false },
);
presentAlert({
title: loc.send.scan_error,
message: loc._.invalid_animated_qr_code_fragment,
onPress: () => {
setIsLoading(false);
},
});
}
};
@ -170,20 +165,14 @@ const ScanQRCode = () => {
} catch (error) {
console.warn(error);
setIsLoading(true);
Alert.alert(
loc.send.scan_error,
loc._.invalid_animated_qr_code_fragment,
[
{
text: loc._.ok,
onPress: () => {
setIsLoading(false);
},
style: 'default',
},
],
{ cancelabe: false },
);
presentAlert({
title: loc.send.scan_error,
message: loc._.invalid_animated_qr_code_fragment,
onPress: () => {
setIsLoading(false);
},
});
}
};
@ -272,22 +261,45 @@ const ScanQRCode = () => {
navigation.goBack();
};
const handleReadCode = event => {
onBarCodeRead({ data: event?.nativeEvent?.codeStringValue });
};
const handleBackdoorOkPress = () => {
setBackdoorVisible(false);
setBackdoorText('');
if (backdoorText) onBarCodeRead({ data: backdoorText });
};
// this is an invisible backdoor button on bottom left screen corner
// tapping it 10 times fires prompt dialog asking for a string thats gona be passed to onBarCodeRead.
// this allows to mock and test QR scanning in e2e tests
const handleInvisibleBackdoorPress = async () => {
setBackdoorPressed(backdoorPressed + 1);
if (backdoorPressed < 5) return;
setBackdoorPressed(0);
setBackdoorVisible(true);
};
const render = isLoading ? (
<BlueLoading />
) : (
<>
<SafeArea>
{!cameraStatusGranted ? (
<View style={[styles.openSettingsContainer, stylesHook.openSettingsContainer]}>
<BlueText>{loc.send.permission_camera_message}</BlueText>
<BlueSpacing40 />
<Button title={loc.send.open_settings} onPress={openPrivacyDesktopSettings} />
<BlueSpacing40 />
{showFileImportButton && <Button title={loc.wallets.import_file} onPress={showFilePicker} />}
<BlueSpacing40 />
<Button title={loc.wallets.list_long_choose} onPress={showFilePicker} />
<BlueSpacing40 />
<Button title={loc._.cancel} onPress={dismiss} />
</View>
) : isFocused ? (
<CameraScreen
scanBarcode
onReadCode={event => onBarCodeRead({ data: event?.nativeEvent?.codeStringValue })}
onReadCode={handleReadCode}
showFrame={false}
showFilePickerButton={showFileImportButton}
showImagePickerButton={true}
@ -320,16 +332,7 @@ const ScanQRCode = () => {
value={backdoorText}
onChangeText={setBackdoorText}
/>
<Button
title="OK"
testID="scanQrBackdoorOkButton"
onPress={() => {
setBackdoorVisible(false);
setBackdoorText('');
if (backdoorText) onBarCodeRead({ data: backdoorText });
}}
/>
<Button title="OK" testID="scanQrBackdoorOkButton" onPress={handleBackdoorOkPress} />
</View>
)}
<TouchableOpacity
@ -337,17 +340,9 @@ const ScanQRCode = () => {
accessibilityLabel={loc._.qr_custom_input_button}
testID="ScanQrBackdoorButton"
style={styles.backdoorButton}
onPress={async () => {
// this is an invisible backdoor button on bottom left screen corner
// tapping it 10 times fires prompt dialog asking for a string thats gona be passed to onBarCodeRead.
// this allows to mock and test QR scanning in e2e tests
setBackdoorPressed(backdoorPressed + 1);
if (backdoorPressed < 5) return;
setBackdoorPressed(0);
setBackdoorVisible(true);
}}
onPress={handleInvisibleBackdoorPress}
/>
</>
</SafeArea>
);
return <View style={styles.root}>{render}</View>;

View file

@ -1,6 +1,6 @@
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { RouteProp, useRoute } from '@react-navigation/native';
import { ActivityIndicator, FlatList, LayoutAnimation, StyleSheet, View } from 'react-native';
import { ActivityIndicator, FlatList, LayoutAnimation, Platform, StyleSheet, UIManager, View } from 'react-native';
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
import { BlueButtonLink, BlueFormLabel, BlueSpacing10, BlueSpacing20, BlueSpacing40, BlueText } from '../../BlueComponents';
import { HDSegwitBech32Wallet, WatchOnlyWallet } from '../../class';
@ -17,7 +17,6 @@ import { useStorage } from '../../hooks/context/useStorage';
import { AddWalletStackParamList } from '../../navigation/AddWalletStack';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { THDWalletForWatchOnly, TWallet } from '../../class/wallets/types';
import { navigate } from '../../NavigationService';
import { keepAwake, disallowScreenshot } from 'react-native-screen-capture';
import { useSettings } from '../../hooks/context/useSettings';
import { isDesktop } from '../../blue_modules/environment';
@ -31,6 +30,10 @@ type WalletEntry = {
id: string;
};
if (Platform.OS === 'android' && UIManager.setLayoutAnimationEnabledExperimental) {
UIManager.setLayoutAnimationEnabledExperimental(true);
}
const ImportWalletDiscovery: React.FC = () => {
const navigation = useExtendedNavigation<NavigationProp>();
const { colors } = useTheme();
@ -65,9 +68,9 @@ const ImportWalletDiscovery: React.FC = () => {
if (importing.current) return;
importing.current = true;
addAndSaveWallet(wallet);
navigate('WalletsList');
navigation.getParent()?.goBack();
},
[addAndSaveWallet],
[addAndSaveWallet, navigation],
);
const handleSave = () => {
@ -139,8 +142,9 @@ const ImportWalletDiscovery: React.FC = () => {
task.current?.stop();
};
// ignoring "navigation" here, because it is constantly mutating
// removed all deps as they were leading to a rerender and retask loop
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [askPassphrase, importText, isElectrumDisabled, saveWallet, searchAccounts]);
}, []);
const handleCustomDerivation = () => {
task.current?.stop();