Merge branch 'master' into modal

This commit is contained in:
Marcos Rodriguez Velez 2024-07-25 11:58:45 -04:00
commit a544f5c324
No known key found for this signature in database
GPG Key ID: 6030B2F48CCE86D7
10 changed files with 103 additions and 115 deletions

View File

@ -288,7 +288,6 @@ interface WalletsCarouselProps extends Partial<FlatListProps<any>> {
handleLongPress?: () => void; handleLongPress?: () => void;
data: TWallet[]; data: TWallet[];
scrollEnabled?: boolean; scrollEnabled?: boolean;
showNewWalletPanel?: boolean; // New prop
} }
type FlatListRefType = FlatList<any> & { type FlatListRefType = FlatList<any> & {
@ -317,7 +316,7 @@ const cStyles = StyleSheet.create({
const ListHeaderComponent: React.FC = () => <View style={cStyles.separatorStyle} />; const ListHeaderComponent: React.FC = () => <View style={cStyles.separatorStyle} />;
const WalletsCarousel = forwardRef<FlatListRefType, WalletsCarouselProps>((props, ref) => { const WalletsCarousel = forwardRef<FlatListRefType, WalletsCarouselProps>((props, ref) => {
const { horizontal, data, handleLongPress, onPress, selectedWallet, scrollEnabled, showNewWalletPanel, onNewWalletPress } = props; const { horizontal, data, handleLongPress, onPress, selectedWallet, scrollEnabled, onNewWalletPress } = props;
const renderItem = useCallback( const renderItem = useCallback(
({ item, index }: ListRenderItemInfo<TWallet>) => ({ item, index }: ListRenderItemInfo<TWallet>) =>
item ? ( item ? (
@ -357,8 +356,8 @@ const WalletsCarousel = forwardRef<FlatListRefType, WalletsCarouselProps>((props
}, []); }, []);
const onScrollToIndexFailed = (error: { averageItemLength: number; index: number }): void => { const onScrollToIndexFailed = (error: { averageItemLength: number; index: number }): void => {
console.log('onScrollToIndexFailed'); console.debug('onScrollToIndexFailed');
console.log(error); console.debug(error);
flatListRef.current?.scrollToOffset({ offset: error.averageItemLength * error.index, animated: true }); flatListRef.current?.scrollToOffset({ offset: error.averageItemLength * error.index, animated: true });
setTimeout(() => { setTimeout(() => {
if (data.length !== 0 && flatListRef.current !== null) { if (data.length !== 0 && flatListRef.current !== null) {
@ -390,7 +389,7 @@ const WalletsCarousel = forwardRef<FlatListRefType, WalletsCarouselProps>((props
ListHeaderComponent={ListHeaderComponent} ListHeaderComponent={ListHeaderComponent}
style={{ minHeight: sliderHeight + 12 }} style={{ minHeight: sliderHeight + 12 }}
onScrollToIndexFailed={onScrollToIndexFailed} onScrollToIndexFailed={onScrollToIndexFailed}
ListFooterComponent={showNewWalletPanel && onNewWalletPress ? <NewWalletPanel onPress={onNewWalletPress} /> : null} ListFooterComponent={onNewWalletPress ? <NewWalletPanel onPress={onNewWalletPress} /> : null}
{...props} {...props}
/> />
) : ( ) : (
@ -406,7 +405,7 @@ const WalletsCarousel = forwardRef<FlatListRefType, WalletsCarouselProps>((props
/> />
) : null, ) : null,
)} )}
{showNewWalletPanel && onNewWalletPress && <NewWalletPanel onPress={onNewWalletPress} />} {onNewWalletPress && <NewWalletPanel onPress={onNewWalletPress} />}
</View> </View>
); );
}); });

View File

@ -10,53 +10,42 @@ import { navigationRef } from '../NavigationService';
* @param showFileImportButton {boolean} * @param showFileImportButton {boolean}
* *
* @param onDismiss {function} - if camera is closed via X button it gets triggered * @param onDismiss {function} - if camera is closed via X button it gets triggered
* @param options {object} - additional options to pass to navigate * @param useMerge {boolean} - if true, will merge the new screen with the current screen, otherwise will replace the current screen
* @return {Promise<string | null>} * @return {Promise<string>}
*/ */
function scanQrHelper( function scanQrHelper(
currentScreenName: string, currentScreenName: string,
showFileImportButton = true, showFileImportButton = true,
onDismiss?: () => void, onDismiss?: () => void,
options: { merge: boolean } = { merge: true }, useMerge = true,
): Promise<string | null> { ): Promise<string | null> {
return requestCameraAuthorization().then(() => { return requestCameraAuthorization().then(() => {
return new Promise(resolve => { return new Promise(resolve => {
const params: any = { let params = {};
showFileImportButton: Boolean(showFileImportButton),
};
if (options?.merge) { if (useMerge) {
if (onDismiss) { const onBarScanned = function (data: any) {
params.onDismiss = onDismiss;
}
params.onBarScanned = function (data: any) {
setTimeout(() => resolve(data.data || data), 1); setTimeout(() => resolve(data.data || data), 1);
navigationRef.navigate({ navigationRef.navigate({ name: currentScreenName, params: {}, merge: true });
name: currentScreenName,
params: {},
merge: options?.merge,
});
}; };
navigationRef.navigate({ params = {
name: 'ScanQRCodeRoot', showFileImportButton: Boolean(showFileImportButton),
params: { onDismiss,
screen: 'ScanQRCode', onBarScanned,
params, };
},
merge: true,
});
} else { } else {
navigationRef.navigate({ params = { launchedBy: currentScreenName, showFileImportButton: Boolean(showFileImportButton) };
name: 'ScanQRCodeRoot',
params: {
screen: 'ScanQRCode',
params: {
showFileImportButton: Boolean(showFileImportButton),
},
},
});
} }
navigationRef.navigate({
name: 'ScanQRCodeRoot',
params: {
screen: 'ScanQRCode',
params,
},
merge: true,
});
}); });
}); });
} }

View File

@ -1,42 +0,0 @@
{
"originHash" : "52530e6b1e3a85c8854952ef703a6d1bbe1acd82713be2b3166476b9b277db23",
"pins" : [
{
"identity" : "bugsnag-cocoa",
"kind" : "remoteSourceControl",
"location" : "https://github.com/bugsnag/bugsnag-cocoa",
"state" : {
"revision" : "16b9145fc66e5296f16e733f6feb5d0e450574e8",
"version" : "6.28.1"
}
},
{
"identity" : "efqrcode",
"kind" : "remoteSourceControl",
"location" : "https://github.com/EFPrefix/EFQRCode.git",
"state" : {
"revision" : "2991c2f318ad9529d93b2a73a382a3f9c72c64ce",
"version" : "6.2.2"
}
},
{
"identity" : "keychain-swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/evgenyneu/keychain-swift.git",
"state" : {
"revision" : "5e1b02b6a9dac2a759a1d5dbc175c86bd192a608",
"version" : "24.0.0"
}
},
{
"identity" : "swift_qrcodejs",
"kind" : "remoteSourceControl",
"location" : "https://github.com/ApolloZhu/swift_qrcodejs.git",
"state" : {
"revision" : "374dc7f7b9e76c6aeb393f6a84590c6d387e1ecb",
"version" : "2.2.2"
}
}
],
"version" : 3
}

View File

@ -865,4 +865,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: f19eea438501edfe85fb2fa51d40ba1b57540758 PODFILE CHECKSUM: f19eea438501edfe85fb2fa51d40ba1b57540758
COCOAPODS: 1.15.2 COCOAPODS: 1.14.3

View File

@ -3,7 +3,7 @@ import { SendDetailsParams } from './SendDetailsStackParamList';
export type DetailViewStackParamList = { export type DetailViewStackParamList = {
UnlockWithScreen: undefined; UnlockWithScreen: undefined;
WalletsList: undefined; WalletsList: { scannedData?: string };
WalletTransactions: { walletID: string; walletType: string }; WalletTransactions: { walletID: string; walletType: string };
LDKOpenChannelRoot: undefined; LDKOpenChannelRoot: undefined;
LdkInfo: undefined; LdkInfo: undefined;
@ -18,7 +18,7 @@ export type DetailViewStackParamList = {
LNDViewInvoice: { invoice: LightningTransaction; walletID: string }; LNDViewInvoice: { invoice: LightningTransaction; walletID: string };
LNDViewAdditionalInvoiceInformation: { invoiceId: string }; LNDViewAdditionalInvoiceInformation: { invoiceId: string };
LNDViewAdditionalInvoicePreImage: { invoiceId: string }; LNDViewAdditionalInvoicePreImage: { invoiceId: string };
Broadcast: undefined; Broadcast: { scannedData?: string };
IsItMyAddress: undefined; IsItMyAddress: undefined;
GenerateWord: undefined; GenerateWord: undefined;
LnurlPay: undefined; LnurlPay: undefined;

View File

@ -1,5 +1,5 @@
import React, { useState } from 'react'; import React, { useState, useEffect } from 'react';
import { useRoute } from '@react-navigation/native'; import { useRoute, RouteProp } from '@react-navigation/native';
import * as bitcoin from 'bitcoinjs-lib'; import * as bitcoin from 'bitcoinjs-lib';
import { ActivityIndicator, Keyboard, KeyboardAvoidingView, Linking, Platform, StyleSheet, TextInput, View } from 'react-native'; import { ActivityIndicator, Keyboard, KeyboardAvoidingView, Linking, Platform, StyleSheet, TextInput, View } from 'react-native';
@ -23,6 +23,7 @@ import SafeArea from '../../components/SafeArea';
import { useTheme } from '../../components/themes'; import { useTheme } from '../../components/themes';
import { scanQrHelper } from '../../helpers/scan-qr'; import { scanQrHelper } from '../../helpers/scan-qr';
import loc from '../../loc'; import loc from '../../loc';
import { DetailViewStackParamList } from '../../navigation/DetailViewStackParamList';
const BROADCAST_RESULT = Object.freeze({ const BROADCAST_RESULT = Object.freeze({
none: 'Input transaction hex', none: 'Input transaction hex',
@ -31,12 +32,10 @@ const BROADCAST_RESULT = Object.freeze({
error: 'error', error: 'error',
}); });
interface SuccessScreenProps { type RouteProps = RouteProp<DetailViewStackParamList, 'Broadcast'>;
tx: string;
}
const Broadcast: React.FC = () => { const Broadcast: React.FC = () => {
const { name } = useRoute(); const { name, params } = useRoute<RouteProps>();
const [tx, setTx] = useState<string | undefined>(); const [tx, setTx] = useState<string | undefined>();
const [txHex, setTxHex] = useState<string | undefined>(); const [txHex, setTxHex] = useState<string | undefined>();
const { colors } = useTheme(); const { colors } = useTheme();
@ -50,6 +49,14 @@ const Broadcast: React.FC = () => {
}, },
}); });
useEffect(() => {
const scannedData = params?.scannedData;
if (scannedData) {
handleScannedData(scannedData);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [params?.scannedData]);
const handleUpdateTxHex = (nextValue: string) => setTxHex(nextValue.trim()); const handleUpdateTxHex = (nextValue: string) => setTxHex(nextValue.trim());
const handleBroadcast = async () => { const handleBroadcast = async () => {
@ -81,10 +88,7 @@ const Broadcast: React.FC = () => {
} }
}; };
const handleQRScan = async () => { const handleScannedData = (scannedData: string) => {
const scannedData = await scanQrHelper(name);
if (!scannedData) return;
if (scannedData.indexOf('+') === -1 && scannedData.indexOf('=') === -1 && scannedData.indexOf('=') === -1) { if (scannedData.indexOf('+') === -1 && scannedData.indexOf('=') === -1 && scannedData.indexOf('=') === -1) {
// this looks like NOT base64, so maybe its transaction's hex // this looks like NOT base64, so maybe its transaction's hex
return handleUpdateTxHex(scannedData); return handleUpdateTxHex(scannedData);
@ -97,6 +101,10 @@ const Broadcast: React.FC = () => {
} catch (e) {} } catch (e) {}
}; };
const handleQRScan = () => {
scanQrHelper(name, true, undefined, false);
};
let status; let status;
switch (broadcastResult) { switch (broadcastResult) {
case BROADCAST_RESULT.none: case BROADCAST_RESULT.none:
@ -159,7 +167,7 @@ const Broadcast: React.FC = () => {
); );
}; };
const SuccessScreen: React.FC<SuccessScreenProps> = ({ tx }) => { const SuccessScreen: React.FC<{ tx: string }> = ({ tx }) => {
if (!tx) { if (!tx) {
return null; return null;
} }

View File

@ -127,9 +127,13 @@ const ScanQRCode = () => {
const data = decoder.toString(); const data = decoder.toString();
decoder = false; // nullify for future use (?) decoder = false; // nullify for future use (?)
if (launchedBy) { if (launchedBy) {
navigation.navigate({ name: launchedBy, params: {}, merge: true }); let merge = true;
if (typeof onBarScanned !== 'function') {
merge = false;
}
navigation.navigate({ name: launchedBy, params: { scannedData: data }, merge });
} }
onBarScanned({ data }); onBarScanned && onBarScanned({ data });
} else { } else {
setUrTotal(100); setUrTotal(100);
setUrHave(Math.floor(decoder.estimatedPercentComplete() * 100)); setUrHave(Math.floor(decoder.estimatedPercentComplete() * 100));
@ -176,9 +180,13 @@ const ScanQRCode = () => {
data = Buffer.from(payload, 'hex').toString(); data = Buffer.from(payload, 'hex').toString();
} }
if (launchedBy) { if (launchedBy) {
navigation.navigate({ name: launchedBy, params: {}, merge: true }); let merge = true;
if (typeof onBarScanned !== 'function') {
merge = false;
}
navigation.navigate({ name: launchedBy, params: { scannedData: data }, merge });
} }
onBarScanned({ data }); onBarScanned && onBarScanned({ data });
} else { } else {
setAnimatedQRCodeData(animatedQRCodeData); setAnimatedQRCodeData(animatedQRCodeData);
} }
@ -237,11 +245,15 @@ const ScanQRCode = () => {
try { try {
const hex = Base43.decode(ret.data); const hex = Base43.decode(ret.data);
bitcoin.Psbt.fromHex(hex); // if it doesnt throw - all good bitcoin.Psbt.fromHex(hex); // if it doesnt throw - all good
const data = Buffer.from(hex, 'hex').toString('base64');
if (launchedBy) { if (launchedBy) {
navigation.navigate({ name: launchedBy, params: {}, merge: true }); let merge = true;
if (typeof onBarScanned !== 'function') {
merge = false;
}
navigation.navigate({ name: launchedBy, params: { scannedData: data }, merge });
} }
onBarScanned({ data: Buffer.from(hex, 'hex').toString('base64') }); onBarScanned && onBarScanned({ data });
return; return;
} catch (_) {} } catch (_) {}
@ -249,9 +261,13 @@ const ScanQRCode = () => {
setIsLoading(true); setIsLoading(true);
try { try {
if (launchedBy) { if (launchedBy) {
navigation.navigate({ name: launchedBy, params: {}, merge: true }); let merge = true;
if (typeof onBarScanned !== 'function') {
merge = false;
}
navigation.navigate({ name: launchedBy, params: { scannedData: ret.data }, merge });
} }
onBarScanned(ret.data); onBarScanned && onBarScanned(ret.data);
} catch (e) { } catch (e) {
console.log(e); console.log(e);
} }
@ -304,7 +320,11 @@ const ScanQRCode = () => {
const dismiss = () => { const dismiss = () => {
if (launchedBy) { if (launchedBy) {
navigation.navigate({ name: launchedBy, params: {}, merge: true }); let merge = true;
if (typeof onBarScanned !== 'function') {
merge = false;
}
navigation.navigate({ name: launchedBy, params: {}, merge });
} else { } else {
navigation.goBack(); navigation.goBack();
} }

View File

@ -145,7 +145,6 @@ const DrawerList: React.FC<DrawerListProps> = memo(({ navigation }) => {
<Header leftText={loc.wallets.list_title} onNewWalletPress={onNewWalletPress} isDrawerList /> <Header leftText={loc.wallets.list_title} onNewWalletPress={onNewWalletPress} isDrawerList />
<WalletsCarousel <WalletsCarousel
data={state.wallets} data={state.wallets}
showNewWalletPanel
extraData={[state.wallets]} extraData={[state.wallets]}
onPress={handleClick} onPress={handleClick}
handleLongPress={handleLongPress} handleLongPress={handleLongPress}

View File

@ -1,5 +1,5 @@
import React, { useCallback, useEffect, useReducer, useRef } from 'react'; import React, { useCallback, useEffect, useReducer, useRef } from 'react';
import { useFocusEffect, useIsFocused, useRoute } from '@react-navigation/native'; import { useFocusEffect, useIsFocused, useRoute, RouteProp } from '@react-navigation/native';
import { findNodeHandle, Image, InteractionManager, SectionList, StyleSheet, Text, useWindowDimensions, View } from 'react-native'; import { findNodeHandle, Image, InteractionManager, SectionList, StyleSheet, Text, useWindowDimensions, View } from 'react-native';
import A from '../../blue_modules/analytics'; import A from '../../blue_modules/analytics';
import BlueClipboard from '../../blue_modules/clipboard'; import BlueClipboard from '../../blue_modules/clipboard';
@ -88,6 +88,7 @@ function reducer(state: WalletListState, action: WalletListAction) {
} }
type NavigationProps = NativeStackNavigationProp<DetailViewStackParamList, 'WalletsList'>; type NavigationProps = NativeStackNavigationProp<DetailViewStackParamList, 'WalletsList'>;
type RouteProps = RouteProp<DetailViewStackParamList, 'WalletsList'>;
const WalletsList: React.FC = () => { const WalletsList: React.FC = () => {
const [state, dispatch] = useReducer<React.Reducer<WalletListState, WalletListAction>>(reducer, initialState); const [state, dispatch] = useReducer<React.Reducer<WalletListState, WalletListAction>>(reducer, initialState);
@ -108,7 +109,8 @@ const WalletsList: React.FC = () => {
const { colors, scanImage } = useTheme(); const { colors, scanImage } = useTheme();
const { navigate } = useExtendedNavigation<NavigationProps>(); const { navigate } = useExtendedNavigation<NavigationProps>();
const isFocused = useIsFocused(); const isFocused = useIsFocused();
const routeName = useRoute().name; const route = useRoute<RouteProps>();
const routeName = route.name;
const dataSource = getTransactions(undefined, 10); const dataSource = getTransactions(undefined, 10);
const walletsCount = useRef<number>(wallets.length); const walletsCount = useRef<number>(wallets.length);
const walletActionButtonsRef = useRef<any>(); const walletActionButtonsRef = useRef<any>();
@ -149,6 +151,14 @@ const WalletsList: React.FC = () => {
walletsCount.current = wallets.length; walletsCount.current = wallets.length;
}, [wallets]); }, [wallets]);
useEffect(() => {
const scannedData = route.params?.scannedData;
if (scannedData) {
onBarScanned(scannedData);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [route.params?.scannedData]);
const verifyBalance = useCallback(() => { const verifyBalance = useCallback(() => {
if (getBalance() !== 0) { if (getBalance() !== 0) {
A(A.ENUM.GOT_NONZERO_BALANCE); A(A.ENUM.GOT_NONZERO_BALANCE);
@ -253,7 +263,6 @@ const WalletsList: React.FC = () => {
handleLongPress={handleLongPress} handleLongPress={handleLongPress}
onMomentumScrollEnd={onSnapToItem} onMomentumScrollEnd={onSnapToItem}
ref={walletsCarousel} ref={walletsCarousel}
showNewWalletPanel
onNewWalletPress={handleClick} onNewWalletPress={handleClick}
testID="WalletsList" testID="WalletsList"
horizontal horizontal
@ -332,9 +341,8 @@ const WalletsList: React.FC = () => {
}; };
const onScanButtonPressed = useCallback(() => { const onScanButtonPressed = useCallback(() => {
scanQrHelper(routeName).then(onBarScanned); scanQrHelper(routeName, true, undefined, false);
// eslint-disable-next-line react-hooks/exhaustive-deps }, [routeName]);
}, []);
const onBarScanned = useCallback( const onBarScanned = useCallback(
(value: any) => { (value: any) => {
@ -381,7 +389,7 @@ const WalletsList: React.FC = () => {
}); });
break; break;
case 2: case 2:
scanQrHelper(routeName, true).then(data => onBarScanned(data)); scanQrHelper(routeName, true, undefined, false);
break; break;
case 3: case 3:
if (!isClipboardEmpty) { if (!isClipboardEmpty) {

View File

@ -24,6 +24,7 @@ const WalletsImport = () => {
const route = useRoute(); const route = useRoute();
const label = route?.params?.label ?? ''; const label = route?.params?.label ?? '';
const triggerImport = route?.params?.triggerImport ?? false; const triggerImport = route?.params?.triggerImport ?? false;
const scannedData = route?.params?.scannedData ?? '';
const { isAdvancedModeEnabled } = useSettings(); const { isAdvancedModeEnabled } = useSettings();
const [importText, setImportText] = useState(label); const [importText, setImportText] = useState(label);
const [isToolbarVisibleForAndroid, setIsToolbarVisibleForAndroid] = useState(false); const [isToolbarVisibleForAndroid, setIsToolbarVisibleForAndroid] = useState(false);
@ -76,7 +77,14 @@ const WalletsImport = () => {
useEffect(() => { useEffect(() => {
if (triggerImport) importButtonPressed(); if (triggerImport) importButtonPressed();
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, [triggerImport]);
useEffect(() => {
if (scannedData) {
onBarScanned(scannedData);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [scannedData]);
const importButtonPressed = () => { const importButtonPressed = () => {
const textToImport = onBlur(); const textToImport = onBlur();
@ -102,7 +110,6 @@ const WalletsImport = () => {
screen: 'ScanQRCode', screen: 'ScanQRCode',
params: { params: {
launchedBy: route.name, launchedBy: route.name,
onBarScanned,
showFileImportButton: true, showFileImportButton: true,
}, },
}), }),