mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-02-23 15:20:55 +01:00
Merge pull request #6660 from BlueWallet/ref
REF: Refactor Handoff component
This commit is contained in:
commit
34fc84cbdc
10 changed files with 77 additions and 104 deletions
|
@ -2,24 +2,24 @@ import React from 'react';
|
||||||
import DefaultPreference from 'react-native-default-preference';
|
import DefaultPreference from 'react-native-default-preference';
|
||||||
// @ts-ignore: react-native-handoff is not in the type definition
|
// @ts-ignore: react-native-handoff is not in the type definition
|
||||||
import Handoff from 'react-native-handoff';
|
import Handoff from 'react-native-handoff';
|
||||||
|
import { useSettings } from '../hooks/context/useSettings';
|
||||||
import { GROUP_IO_BLUEWALLET } from '../blue_modules/currency';
|
import { GROUP_IO_BLUEWALLET } from '../blue_modules/currency';
|
||||||
import { BlueApp } from '../class';
|
import { BlueApp } from '../class';
|
||||||
import { useSettings } from '../hooks/context/useSettings';
|
import { HandOffComponentProps } from './types';
|
||||||
|
|
||||||
interface HandOffComponentProps {
|
const HandOffComponent: React.FC<HandOffComponentProps> = props => {
|
||||||
url?: string;
|
const { isHandOffUseEnabled } = useSettings();
|
||||||
title?: string;
|
|
||||||
type: (typeof HandOffComponent.activityTypes)[keyof typeof HandOffComponent.activityTypes];
|
|
||||||
userInfo?: object;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface HandOffComponentWithActivityTypes extends React.FC<HandOffComponentProps> {
|
if (process.env.NODE_ENV === 'development') {
|
||||||
activityTypes: {
|
console.debug('HandOffComponent: props', props);
|
||||||
ReceiveOnchain: string;
|
}
|
||||||
Xpub: string;
|
if (isHandOffUseEnabled) {
|
||||||
ViewInBlockExplorer: string;
|
return <Handoff {...props} />;
|
||||||
};
|
}
|
||||||
}
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const MemoizedHandOffComponent = React.memo(HandOffComponent);
|
||||||
|
|
||||||
export const setIsHandOffUseEnabled = async (value: boolean) => {
|
export const setIsHandOffUseEnabled = async (value: boolean) => {
|
||||||
await DefaultPreference.setName(GROUP_IO_BLUEWALLET);
|
await DefaultPreference.setName(GROUP_IO_BLUEWALLET);
|
||||||
|
@ -39,24 +39,4 @@ export const getIsHandOffUseEnabled = async (): Promise<boolean> => {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const HandOffComponent: HandOffComponentWithActivityTypes = props => {
|
export default MemoizedHandOffComponent;
|
||||||
const { isHandOffUseEnabled } = useSettings();
|
|
||||||
|
|
||||||
if (process.env.NODE_ENV === 'development') {
|
|
||||||
console.debug('HandOffComponent: props', props);
|
|
||||||
}
|
|
||||||
if (isHandOffUseEnabled) {
|
|
||||||
return <Handoff {...props} />;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const activityTypes = {
|
|
||||||
ReceiveOnchain: 'io.bluewallet.bluewallet.receiveonchain',
|
|
||||||
Xpub: 'io.bluewallet.bluewallet.xpub',
|
|
||||||
ViewInBlockExplorer: 'io.bluewallet.bluewallet.blockexplorer',
|
|
||||||
};
|
|
||||||
|
|
||||||
HandOffComponent.activityTypes = activityTypes;
|
|
||||||
|
|
||||||
export default HandOffComponent;
|
|
||||||
|
|
|
@ -1,21 +1,8 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { HandOffComponentProps } from './types';
|
||||||
|
|
||||||
interface HandOffComponentProps {
|
const HandOffComponent: React.FC<HandOffComponentProps> = props => {
|
||||||
url?: string;
|
console.debug('HandOffComponent: props', props);
|
||||||
title?: string;
|
|
||||||
type: (typeof HandOffComponent.activityTypes)[keyof typeof HandOffComponent.activityTypes];
|
|
||||||
userInfo?: object;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface HandOffComponentWithActivityTypes extends React.FC<HandOffComponentProps> {
|
|
||||||
activityTypes: {
|
|
||||||
ReceiveOnchain: string;
|
|
||||||
Xpub: string;
|
|
||||||
ViewInBlockExplorer: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const HandOffComponent: HandOffComponentWithActivityTypes = props => {
|
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,12 +12,4 @@ export const getIsHandOffUseEnabled = async (): Promise<boolean> => {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const activityTypes = {
|
|
||||||
ReceiveOnchain: 'io.bluewallet.bluewallet.receiveonchain',
|
|
||||||
Xpub: 'io.bluewallet.bluewallet.xpub',
|
|
||||||
ViewInBlockExplorer: 'io.bluewallet.bluewallet.blockexplorer',
|
|
||||||
};
|
|
||||||
|
|
||||||
HandOffComponent.activityTypes = activityTypes;
|
|
||||||
|
|
||||||
export default HandOffComponent;
|
export default HandOffComponent;
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect, useCallback } from 'react';
|
||||||
import { NativeEventEmitter, NativeModules } from 'react-native';
|
import { NativeEventEmitter, NativeModules } from 'react-native';
|
||||||
import * as NavigationService from '../NavigationService';
|
|
||||||
import HandOffComponent from './HandOffComponent.ios';
|
|
||||||
import { useStorage } from '../hooks/context/useStorage';
|
import { useStorage } from '../hooks/context/useStorage';
|
||||||
|
import { useExtendedNavigation } from '../hooks/useExtendedNavigation';
|
||||||
|
import { HandOffActivityType } from './types';
|
||||||
|
|
||||||
interface UserActivityData {
|
interface UserActivityData {
|
||||||
activityType: keyof typeof HandOffComponent.activityTypes;
|
activityType: HandOffActivityType;
|
||||||
userInfo: {
|
userInfo: {
|
||||||
address?: string;
|
address?: string;
|
||||||
xpub?: string;
|
xpub?: string;
|
||||||
|
@ -15,40 +15,40 @@ interface UserActivityData {
|
||||||
const { EventEmitter } = NativeModules;
|
const { EventEmitter } = NativeModules;
|
||||||
const eventEmitter = new NativeEventEmitter(EventEmitter);
|
const eventEmitter = new NativeEventEmitter(EventEmitter);
|
||||||
|
|
||||||
const HandOffComponentListener: React.FC = () => {
|
const HandOffComponentListener: React.FC = React.memo(() => {
|
||||||
const { walletsInitialized } = useStorage();
|
const { walletsInitialized } = useStorage();
|
||||||
|
const { navigate } = useExtendedNavigation();
|
||||||
|
|
||||||
|
const onUserActivityOpen = useCallback((data: UserActivityData) => {
|
||||||
|
switch (data.activityType) {
|
||||||
|
case HandOffActivityType.ReceiveOnchain:
|
||||||
|
navigate('ReceiveDetailsRoot', {
|
||||||
|
screen: 'ReceiveDetails',
|
||||||
|
params: {
|
||||||
|
address: data.userInfo.address,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case HandOffActivityType.Xpub:
|
||||||
|
navigate('WalletXpubRoot', {
|
||||||
|
screen: 'WalletXpub',
|
||||||
|
params: {
|
||||||
|
xpub: data.userInfo.xpub,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log(`Unhandled activity type: ${data.activityType}`);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!walletsInitialized) {
|
if (!walletsInitialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const onUserActivityOpen = (data: UserActivityData) => {
|
|
||||||
switch (data.activityType) {
|
|
||||||
case HandOffComponent.activityTypes.ReceiveOnchain:
|
|
||||||
NavigationService.navigate('ReceiveDetailsRoot', {
|
|
||||||
// @ts-ignore: fix later
|
|
||||||
screen: 'ReceiveDetails',
|
|
||||||
params: {
|
|
||||||
address: data.userInfo.address,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case HandOffComponent.activityTypes.Xpub:
|
|
||||||
NavigationService.navigate('WalletXpubRoot', {
|
|
||||||
// @ts-ignore: fix later
|
|
||||||
screen: 'WalletXpub',
|
|
||||||
params: {
|
|
||||||
xpub: data.userInfo.xpub,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
console.log(`Unhandled activity type: ${data.activityType}`);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const addListeners = () => {
|
const addListeners = () => {
|
||||||
const activitySubscription = eventEmitter.addListener('onUserActivityOpen', onUserActivityOpen);
|
const activitySubscription = eventEmitter.addListener('onUserActivityOpen', onUserActivityOpen);
|
||||||
|
|
||||||
|
@ -65,9 +65,9 @@ const HandOffComponentListener: React.FC = () => {
|
||||||
return () => {
|
return () => {
|
||||||
subscriptions.activitySubscription?.remove();
|
subscriptions.activitySubscription?.remove();
|
||||||
};
|
};
|
||||||
}, [walletsInitialized]);
|
}, [walletsInitialized, onUserActivityOpen]);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
};
|
});
|
||||||
|
|
||||||
export default HandOffComponentListener;
|
export default HandOffComponentListener;
|
||||||
|
|
|
@ -34,3 +34,16 @@ export interface ToolTipMenuProps {
|
||||||
onMenuWillShow?: () => void;
|
onMenuWillShow?: () => void;
|
||||||
onMenuWillHide?: () => void;
|
onMenuWillHide?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum HandOffActivityType {
|
||||||
|
ReceiveOnchain = 'io.bluewallet.bluewallet.receiveonchain',
|
||||||
|
Xpub = 'io.bluewallet.bluewallet.xpub',
|
||||||
|
ViewInBlockExplorer = 'io.bluewallet.bluewallet.blockexplorer',
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HandOffComponentProps {
|
||||||
|
url?: string;
|
||||||
|
title?: string;
|
||||||
|
type: HandOffActivityType;
|
||||||
|
userInfo?: object;
|
||||||
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ import loc, { formatBalance } from '../../loc';
|
||||||
import { BitcoinUnit, Chain } from '../../models/bitcoinUnits';
|
import { BitcoinUnit, Chain } from '../../models/bitcoinUnits';
|
||||||
import { SuccessView } from '../send/success';
|
import { SuccessView } from '../send/success';
|
||||||
import { useStorage } from '../../hooks/context/useStorage';
|
import { useStorage } from '../../hooks/context/useStorage';
|
||||||
|
import { HandOffActivityType } from '../../components/types';
|
||||||
|
|
||||||
const ReceiveDetails = () => {
|
const ReceiveDetails = () => {
|
||||||
const { walletID, address } = useRoute().params;
|
const { walletID, address } = useRoute().params;
|
||||||
|
@ -426,7 +427,7 @@ const ReceiveDetails = () => {
|
||||||
return (
|
return (
|
||||||
<View style={[styles.root, stylesHook.root]}>
|
<View style={[styles.root, stylesHook.root]}>
|
||||||
{address !== undefined && showAddress && (
|
{address !== undefined && showAddress && (
|
||||||
<HandOffComponent title={loc.send.details_address} type={HandOffComponent.activityTypes.ReceiveOnchain} userInfo={{ address }} />
|
<HandOffComponent title={loc.send.details_address} type={HandOffActivityType.ReceiveOnchain} userInfo={{ address }} />
|
||||||
)}
|
)}
|
||||||
{showConfirmedBalance ? renderConfirmedBalance() : null}
|
{showConfirmedBalance ? renderConfirmedBalance() : null}
|
||||||
{showPendingBalance ? renderPendingBalance() : null}
|
{showPendingBalance ? renderPendingBalance() : null}
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
|
import React, { useEffect, useRef } from 'react';
|
||||||
import { useNavigation, useRoute } from '@react-navigation/native';
|
import { useNavigation, useRoute } from '@react-navigation/native';
|
||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
import LottieView from 'lottie-react-native';
|
import LottieView from 'lottie-react-native';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React, { useEffect, useRef } from 'react';
|
|
||||||
import { StyleSheet, View } from 'react-native';
|
import { StyleSheet, View } from 'react-native';
|
||||||
import { Text } from 'react-native-elements';
|
import { Text } from 'react-native-elements';
|
||||||
|
|
||||||
import { BlueCard } from '../../BlueComponents';
|
import { BlueCard } from '../../BlueComponents';
|
||||||
import Button from '../../components/Button';
|
import Button from '../../components/Button';
|
||||||
import SafeArea from '../../components/SafeArea';
|
import SafeArea from '../../components/SafeArea';
|
||||||
|
@ -13,6 +12,7 @@ import { useTheme } from '../../components/themes';
|
||||||
import loc from '../../loc';
|
import loc from '../../loc';
|
||||||
import { BitcoinUnit } from '../../models/bitcoinUnits';
|
import { BitcoinUnit } from '../../models/bitcoinUnits';
|
||||||
import HandOffComponent from '../../components/HandOffComponent';
|
import HandOffComponent from '../../components/HandOffComponent';
|
||||||
|
import { HandOffActivityType } from '../../components/types';
|
||||||
|
|
||||||
const Success = () => {
|
const Success = () => {
|
||||||
const pop = () => {
|
const pop = () => {
|
||||||
|
@ -51,7 +51,7 @@ const Success = () => {
|
||||||
{txid && (
|
{txid && (
|
||||||
<HandOffComponent
|
<HandOffComponent
|
||||||
title={loc.transactions.details_title}
|
title={loc.transactions.details_title}
|
||||||
type={HandOffComponent.activityTypes.ViewInBlockExplorer}
|
type={HandOffActivityType.ViewInBlockExplorer}
|
||||||
url={`https://mempool.space/tx/${txid}`}
|
url={`https://mempool.space/tx/${txid}`}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import loc from '../../loc';
|
||||||
import { useExtendedNavigation } from '../../hooks/useExtendedNavigation';
|
import { useExtendedNavigation } from '../../hooks/useExtendedNavigation';
|
||||||
import { DetailViewStackParamList } from '../../navigation/DetailViewStackParamList';
|
import { DetailViewStackParamList } from '../../navigation/DetailViewStackParamList';
|
||||||
import { useStorage } from '../../hooks/context/useStorage';
|
import { useStorage } from '../../hooks/context/useStorage';
|
||||||
|
import { HandOffActivityType } from '../../components/types';
|
||||||
|
|
||||||
interface TransactionDetailsProps {
|
interface TransactionDetailsProps {
|
||||||
route: RouteProp<{ params: { hash: string; walletID: string } }, 'params'>;
|
route: RouteProp<{ params: { hash: string; walletID: string } }, 'params'>;
|
||||||
|
@ -259,7 +260,7 @@ const TransactionDetails = () => {
|
||||||
<ScrollView style={styles.scroll} automaticallyAdjustContentInsets contentInsetAdjustmentBehavior="automatic">
|
<ScrollView style={styles.scroll} automaticallyAdjustContentInsets contentInsetAdjustmentBehavior="automatic">
|
||||||
<HandOffComponent
|
<HandOffComponent
|
||||||
title={loc.transactions.details_title}
|
title={loc.transactions.details_title}
|
||||||
type={HandOffComponent.activityTypes.ViewInBlockExplorer}
|
type={HandOffActivityType.ViewInBlockExplorer}
|
||||||
url={`https://mempool.space/tx/${tx.hash}`}
|
url={`https://mempool.space/tx/${tx.hash}`}
|
||||||
/>
|
/>
|
||||||
<BlueCard>
|
<BlueCard>
|
||||||
|
|
|
@ -18,6 +18,7 @@ import { useTheme } from '../../components/themes';
|
||||||
import loc, { formatBalanceWithoutSuffix } from '../../loc';
|
import loc, { formatBalanceWithoutSuffix } from '../../loc';
|
||||||
import { BitcoinUnit } from '../../models/bitcoinUnits';
|
import { BitcoinUnit } from '../../models/bitcoinUnits';
|
||||||
import { useStorage } from '../../hooks/context/useStorage';
|
import { useStorage } from '../../hooks/context/useStorage';
|
||||||
|
import { HandOffActivityType } from '../../components/types';
|
||||||
import HeaderRightButton from '../../components/HeaderRightButton';
|
import HeaderRightButton from '../../components/HeaderRightButton';
|
||||||
|
|
||||||
enum ButtonStatus {
|
enum ButtonStatus {
|
||||||
|
@ -476,7 +477,7 @@ const TransactionStatus = () => {
|
||||||
<SafeArea>
|
<SafeArea>
|
||||||
<HandOffComponent
|
<HandOffComponent
|
||||||
title={loc.transactions.details_title}
|
title={loc.transactions.details_title}
|
||||||
type={HandOffComponent.activityTypes.ViewInBlockExplorer}
|
type={HandOffActivityType.ViewInBlockExplorer}
|
||||||
url={`https://mempool.space/tx/${tx.hash}`}
|
url={`https://mempool.space/tx/${tx.hash}`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ import { useTheme } from '../../components/themes';
|
||||||
import usePrivacy from '../../hooks/usePrivacy';
|
import usePrivacy from '../../hooks/usePrivacy';
|
||||||
import loc from '../../loc';
|
import loc from '../../loc';
|
||||||
import { useStorage } from '../../hooks/context/useStorage';
|
import { useStorage } from '../../hooks/context/useStorage';
|
||||||
|
import { HandOffActivityType } from '../../components/types';
|
||||||
|
|
||||||
const WalletExport = () => {
|
const WalletExport = () => {
|
||||||
const { wallets, saveToDisk } = useStorage();
|
const { wallets, saveToDisk } = useStorage();
|
||||||
|
@ -115,11 +116,7 @@ const WalletExport = () => {
|
||||||
</BlueText>
|
</BlueText>
|
||||||
)}
|
)}
|
||||||
{wallet.type === WatchOnlyWallet.type && (
|
{wallet.type === WatchOnlyWallet.type && (
|
||||||
<HandOffComponent
|
<HandOffComponent title={loc.wallets.xpub_title} type={HandOffActivityType.Xpub} userInfo={{ xpub: wallet.getSecret() }} />
|
||||||
title={loc.wallets.xpub_title}
|
|
||||||
type={HandOffComponent.activityTypes.Xpub}
|
|
||||||
userInfo={{ xpub: wallet.getSecret() }}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
))}
|
))}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import usePrivacy from '../../hooks/usePrivacy';
|
||||||
import loc from '../../loc';
|
import loc from '../../loc';
|
||||||
import { styles, useDynamicStyles } from './xpub.styles';
|
import { styles, useDynamicStyles } from './xpub.styles';
|
||||||
import { useStorage } from '../../hooks/context/useStorage';
|
import { useStorage } from '../../hooks/context/useStorage';
|
||||||
|
import { HandOffActivityType } from '../../components/types';
|
||||||
|
|
||||||
type WalletXpubRouteProp = RouteProp<{ params: { walletID: string; xpub: string } }, 'params'>;
|
type WalletXpubRouteProp = RouteProp<{ params: { walletID: string; xpub: string } }, 'params'>;
|
||||||
export type RootStackParamList = {
|
export type RootStackParamList = {
|
||||||
|
@ -94,7 +95,7 @@ const WalletXpub: React.FC = () => {
|
||||||
<BlueSpacing20 />
|
<BlueSpacing20 />
|
||||||
{xPubText && <CopyTextToClipboard text={xPubText} />}
|
{xPubText && <CopyTextToClipboard text={xPubText} />}
|
||||||
</View>
|
</View>
|
||||||
<HandOffComponent title={loc.wallets.xpub_title} type={HandOffComponent.activityTypes.Xpub} userInfo={{ xpub: xPubText }} />
|
<HandOffComponent title={loc.wallets.xpub_title} type={HandOffActivityType.Xpub} userInfo={{ xpub: xPubText }} />
|
||||||
<View style={styles.share}>
|
<View style={styles.share}>
|
||||||
<Button onPress={handleShareButtonPressed} title={loc.receive.details_share} />
|
<Button onPress={handleShareButtonPressed} title={loc.receive.details_share} />
|
||||||
</View>
|
</View>
|
||||||
|
|
Loading…
Add table
Reference in a new issue