Merge pull request #1154 from BlueWallet/limpbrains-migrate-to-react-navigation5

Limpbrains migrate to react navigation5
This commit is contained in:
Overtorment 2020-05-29 21:46:39 +01:00 committed by GitHub
commit 235b0aace5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
48 changed files with 3721 additions and 2405 deletions

73
App.js
View file

@ -1,8 +1,10 @@
import 'react-native-gesture-handler'; // should be on top
import React from 'react';
import { Linking, DeviceEventEmitter, AppState, Clipboard, StyleSheet, KeyboardAvoidingView, Platform, View } from 'react-native';
import Modal from 'react-native-modal';
import { NavigationActions } from 'react-navigation';
import MainBottomTabs from './MainBottomTabs';
import { NavigationContainer, CommonActions } from '@react-navigation/native';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import Navigation from './Navigation';
import NavigationService from './NavigationService';
import { BlueTextCentered, BlueButton } from './BlueComponents';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
@ -26,7 +28,7 @@ const loc = require('./loc');
const BlueApp = require('./BlueApp');
export default class App extends React.Component {
navigator = null;
navigation = null;
state = {
appState: AppState.currentState,
@ -45,13 +47,11 @@ export default class App extends React.Component {
popInitialAction = async data => {
if (data) {
// eslint-disable-next-line no-unused-expressions
this.navigator.dismiss;
const wallet = BlueApp.getWallets().find(wallet => wallet.getID() === data.userInfo.url.split('wallet/')[1]);
this.navigator.dispatch(
NavigationActions.navigate({
this.navigation.dispatch(
CommonActions.navigate({
name: 'WalletTransactions',
key: `WalletTransactions-${wallet.getID()}`,
routeName: 'WalletTransactions',
params: {
wallet,
},
@ -66,14 +66,12 @@ export default class App extends React.Component {
} else {
const isViewAllWalletsEnabled = await OnAppLaunch.isViewAllWalletsEnabled();
if (!isViewAllWalletsEnabled) {
// eslint-disable-next-line no-unused-expressions
this.navigator.dismiss;
const selectedDefaultWallet = await OnAppLaunch.getSelectedDefaultWallet();
const wallet = BlueApp.getWallets().find(wallet => wallet.getID() === selectedDefaultWallet.getID());
if (wallet) {
this.navigator.dispatch(
NavigationActions.navigate({
routeName: 'WalletTransactions',
this.navigation.dispatch(
CommonActions.navigate({
name: 'WalletTransactions',
key: `WalletTransactions-${wallet.getID()}`,
params: {
wallet,
@ -88,11 +86,9 @@ export default class App extends React.Component {
walletQuickActions = data => {
const wallet = BlueApp.getWallets().find(wallet => wallet.getID() === data.userInfo.url.split('wallet/')[1]);
// eslint-disable-next-line no-unused-expressions
this.navigator.dismiss;
this.navigator.dispatch(
NavigationActions.navigate({
routeName: 'WalletTransactions',
this.navigation.dispatch(
CommonActions.navigate({
name: 'WalletTransactions',
key: `WalletTransactions-${wallet.getID()}`,
params: {
wallet,
@ -148,10 +144,10 @@ export default class App extends React.Component {
isBothBitcoinAndLightningWalletSelect = wallet => {
const clipboardContent = this.state.clipboardContent;
if (wallet.chain === Chain.ONCHAIN) {
this.navigator &&
this.navigator.dispatch(
NavigationActions.navigate({
routeName: 'SendDetails',
this.navigation &&
this.navigation.dispatch(
CommonActions.navigate({
name: 'SendDetails',
params: {
uri: clipboardContent.bitcoin,
fromWallet: wallet,
@ -159,10 +155,10 @@ export default class App extends React.Component {
}),
);
} else if (wallet.chain === Chain.OFFCHAIN) {
this.navigator &&
this.navigator.dispatch(
NavigationActions.navigate({
routeName: 'ScanLndInvoice',
this.navigation &&
this.navigation.dispatch(
CommonActions.navigate({
name: 'ScanLndInvoice',
params: {
uri: clipboardContent.lndInvoice,
fromSecret: wallet.getSecret(),
@ -173,7 +169,7 @@ export default class App extends React.Component {
};
handleOpenURL = event => {
DeeplinkSchemaMatch.navigationRouteFor(event, value => this.navigator && this.navigator.dispatch(NavigationActions.navigate(value)));
DeeplinkSchemaMatch.navigationRouteFor(event, value => this.navigation && this.navigation.navigate(...value));
};
renderClipboardContentModal = () => {
@ -217,15 +213,20 @@ export default class App extends React.Component {
render() {
return (
<View style={{ flex: 1 }}>
<MainBottomTabs
ref={nav => {
this.navigator = nav;
NavigationService.setTopLevelNavigator(nav);
}}
/>
{this.renderClipboardContentModal()}
</View>
<SafeAreaProvider>
<View style={{ flex: 1 }}>
<NavigationContainer
ref={nav => {
this.navigation = nav;
NavigationService.setTopLevelNavigator(nav);
}}
>
<Navigation />
</NavigationContainer>
{this.renderClipboardContentModal()}
</View>
</SafeAreaProvider>
);
}
}

View file

@ -394,64 +394,84 @@ export const BlueAlertWalletExportReminder = ({ onSuccess = () => {}, onFailure
);
};
export const BlueNavigationStyle = (navigation, withNavigationCloseButton = false, customCloseButtonFunction = undefined) => ({
headerStyle: {
backgroundColor: BlueApp.settings.brandingColor,
borderBottomWidth: 0,
elevation: 0,
},
headerTitleStyle: {
fontWeight: '600',
color: BlueApp.settings.foregroundColor,
},
headerTintColor: BlueApp.settings.foregroundColor,
headerRight: withNavigationCloseButton ? (
<TouchableOpacity
style={{ width: 40, height: 40, padding: 14 }}
onPress={
customCloseButtonFunction === undefined
? () => {
Keyboard.dismiss();
navigation.goBack(null);
}
: customCloseButtonFunction
}
>
<Image style={{ alignSelf: 'center' }} source={require('./img/close.png')} />
</TouchableOpacity>
) : null,
headerBackTitle: null,
});
export const BlueNavigationStyle = (navigation, withNavigationCloseButton = false, customCloseButtonFunction = undefined) => {
let headerRight;
if (withNavigationCloseButton) {
headerRight = () => (
<TouchableOpacity
style={{ width: 40, height: 40, padding: 14 }}
onPress={
customCloseButtonFunction === undefined
? () => {
Keyboard.dismiss();
navigation.goBack(null);
}
: customCloseButtonFunction
}
>
<Image style={{ alignSelf: 'center' }} source={require('./img/close.png')} />
</TouchableOpacity>
);
} else {
headerRight = null;
}
export const BlueCreateTxNavigationStyle = (navigation, withAdvancedOptionsMenuButton = false, advancedOptionsMenuButtonAction) => ({
headerStyle: {
backgroundColor: BlueApp.settings.brandingColor,
borderBottomWidth: 0,
elevation: 0,
},
headerTitleStyle: {
fontWeight: '600',
color: BlueApp.settings.foregroundColor,
},
headerTintColor: BlueApp.settings.foregroundColor,
headerLeft: (
<TouchableOpacity
style={{ minWwidth: 40, height: 40, padding: 14 }}
onPress={() => {
Keyboard.dismiss();
navigation.goBack(null);
}}
>
<Image style={{ alignSelf: 'center' }} source={require('./img/close.png')} />
</TouchableOpacity>
),
headerRight: withAdvancedOptionsMenuButton ? (
<TouchableOpacity style={{ minWidth: 40, height: 40, padding: 14 }} onPress={advancedOptionsMenuButtonAction}>
<Icon size={22} name="kebab-horizontal" type="octicon" color={BlueApp.settings.foregroundColor} />
</TouchableOpacity>
) : null,
headerBackTitle: null,
});
return {
headerStyle: {
backgroundColor: BlueApp.settings.brandingColor,
borderBottomWidth: 0,
elevation: 0,
shadowOffset: { height: 0, width: 0 },
},
headerTitleStyle: {
fontWeight: '600',
color: BlueApp.settings.foregroundColor,
},
headerTintColor: BlueApp.settings.foregroundColor,
headerRight,
// headerBackTitle: null,
headerBackTitleVisible: false,
};
};
export const BlueCreateTxNavigationStyle = (navigation, withAdvancedOptionsMenuButton = false, advancedOptionsMenuButtonAction) => {
let headerRight;
if (withAdvancedOptionsMenuButton) {
headerRight = () => (
<TouchableOpacity style={{ minWidth: 40, height: 40, padding: 14 }} onPress={advancedOptionsMenuButtonAction}>
<Icon size={22} name="kebab-horizontal" type="octicon" color={BlueApp.settings.foregroundColor} />
</TouchableOpacity>
);
} else {
headerRight = null;
}
return {
headerStyle: {
backgroundColor: BlueApp.settings.brandingColor,
borderBottomWidth: 0,
elevation: 0,
shadowOffset: { height: 0, width: 0 },
},
headerTitleStyle: {
fontWeight: '600',
color: BlueApp.settings.foregroundColor,
},
headerTintColor: BlueApp.settings.foregroundColor,
headerLeft: () => (
<TouchableOpacity
style={{ minWwidth: 40, height: 40, padding: 14 }}
onPress={() => {
Keyboard.dismiss();
navigation.goBack(null);
}}
>
<Image style={{ alignSelf: 'center' }} source={require('./img/close.png')} />
</TouchableOpacity>
),
headerRight,
headerBackTitle: null,
};
};
export const BluePrivateBalance = () => {
return Platform.select({
@ -2245,7 +2265,7 @@ export class BlueBitcoinAmount extends Component {
};
render() {
const amount = this.props.amount || 0;
const amount = this.props.amount || '0';
let localCurrency = loc.formatBalanceWithoutSuffix(amount, BitcoinUnit.LOCAL_CURRENCY, false);
if (this.props.unit === BitcoinUnit.BTC) {
let sat = new BigNumber(amount);

View file

@ -1,418 +0,0 @@
import { createStackNavigator, createAppContainer } from 'react-navigation';
import Settings from './screen/settings/settings';
import About from './screen/settings/about';
import ReleaseNotes from './screen/settings/releasenotes';
import Licensing from './screen/settings/licensing';
import Selftest from './screen/selftest';
import Language from './screen/settings/language';
import Currency from './screen/settings/currency';
import EncryptStorage from './screen/settings/encryptStorage';
import PlausibleDeniability from './screen/plausibledeniability';
import LightningSettings from './screen/settings/lightningSettings';
import ElectrumSettings from './screen/settings/electrumSettings';
import GeneralSettings from './screen/settings/GeneralSettings';
import NetworkSettings from './screen/settings/NetworkSettings';
import DefaultView from './screen/settings/defaultView';
import WalletsList from './screen/wallets/list';
import WalletTransactions from './screen/wallets/transactions';
import AddWallet from './screen/wallets/add';
import PleaseBackup from './screen/wallets/pleaseBackup';
import PleaseBackupLNDHub from './screen/wallets/pleaseBackupLNDHub';
import ImportWallet from './screen/wallets/import';
import WalletDetails from './screen/wallets/details';
import WalletExport from './screen/wallets/export';
import WalletXpub from './screen/wallets/xpub';
import BuyBitcoin from './screen/wallets/buyBitcoin';
import HodlHodl from './screen/wallets/hodlHodl';
import Marketplace from './screen/wallets/marketplace';
import ReorderWallets from './screen/wallets/reorderWallets';
import SelectWallet from './screen/wallets/selectWallet';
import details from './screen/transactions/details';
import TransactionStatus from './screen/transactions/transactionStatus';
import cpfp from './screen/transactions/CPFP';
import rbfBumpFee from './screen/transactions/RBFBumpFee';
import rbfCancel from './screen/transactions/RBFCancel';
import receiveDetails from './screen/receive/details';
import sendDetails from './screen/send/details';
import ScanQRCode from './screen/send/ScanQRCode';
import sendCreate from './screen/send/create';
import Confirm from './screen/send/confirm';
import PsbtWithHardwareWallet from './screen/send/psbtWithHardwareWallet';
import Success from './screen/send/success';
import Broadcast from './screen/send/broadcast';
import ScanLndInvoice from './screen/lnd/scanLndInvoice';
import LappBrowser from './screen/lnd/browser';
import LNDCreateInvoice from './screen/lnd/lndCreateInvoice';
import LNDViewInvoice from './screen/lnd/lndViewInvoice';
import LNDViewAdditionalInvoiceInformation from './screen/lnd/lndViewAdditionalInvoiceInformation';
import AztecoRedeem from './screen/receive/aztecoRedeem';
const ReorderWalletsStackNavigator = createStackNavigator({
ReorderWallets: {
screen: ReorderWallets,
},
});
const ScanQRCodeStackNavigator = createStackNavigator({
ScanQRCode: {
screen: ScanQRCode,
},
});
const WalletsStackNavigator = createStackNavigator(
{
Wallets: {
screen: WalletsList,
path: 'wallets',
navigationOptions: {
header: null,
},
},
WalletTransactions: {
screen: WalletTransactions,
path: 'WalletTransactions',
routeName: 'WalletTransactions',
},
TransactionStatus: {
screen: TransactionStatus,
},
TransactionDetails: {
screen: details,
},
WalletDetails: {
screen: WalletDetails,
},
HodlHodl: {
screen: HodlHodl,
},
CPFP: {
screen: cpfp,
},
RBFBumpFee: {
screen: rbfBumpFee,
},
RBFCancel: {
screen: rbfCancel,
},
Settings: {
screen: Settings,
path: 'Settings',
navigationOptions: {
headerStyle: {
backgroundColor: '#FFFFFF',
borderBottomWidth: 0,
elevation: 0,
},
headerTintColor: '#0c2550',
},
},
SelectWallet: {
screen: SelectWallet,
},
Currency: {
screen: Currency,
},
About: {
screen: About,
path: 'About',
},
ReleaseNotes: {
screen: ReleaseNotes,
path: 'ReleaseNotes',
},
Selftest: {
screen: Selftest,
},
Licensing: {
screen: Licensing,
path: 'Licensing',
},
DefaultView: {
screen: DefaultView,
path: 'DefaultView',
},
Language: {
screen: Language,
path: 'Language',
},
EncryptStorage: {
screen: EncryptStorage,
path: 'EncryptStorage',
},
GeneralSettings: {
screen: GeneralSettings,
path: 'GeneralSettings',
},
NetworkSettings: {
screen: NetworkSettings,
path: 'NetworkSettings',
},
PlausibleDeniability: {
screen: PlausibleDeniability,
path: 'PlausibleDeniability',
},
LightningSettings: {
screen: LightningSettings,
path: 'LightningSettings',
},
ElectrumSettings: {
screen: ElectrumSettings,
path: 'ElectrumSettings',
},
LNDViewInvoice: {
screen: LNDViewInvoice,
swipeEnabled: false,
gesturesEnabled: false,
},
LNDViewAdditionalInvoiceInformation: {
screen: LNDViewAdditionalInvoiceInformation,
},
Broadcast: {
screen: Broadcast,
navigationOptions: () => ({
title: 'Broadcast',
headerStyle: {
backgroundColor: '#FFFFFF',
borderBottomWidth: 0,
},
headerTintColor: '#0c2550',
}),
},
},
{ headerBackTitleVisible: false },
);
const CreateTransactionStackNavigator = createStackNavigator({
SendDetails: {
routeName: 'SendDetails',
screen: sendDetails,
},
Confirm: {
screen: Confirm,
},
PsbtWithHardwareWallet: {
screen: PsbtWithHardwareWallet,
},
CreateTransaction: {
screen: sendCreate,
navigationOptions: {
headerStyle: {
backgroundColor: '#FFFFFF',
borderBottomWidth: 0,
},
headerTintColor: '#0c2550',
},
},
Success: {
screen: Success,
},
SelectWallet: {
screen: SelectWallet,
navigationOptions: {
headerRight: null,
},
},
});
const LNDCreateInvoiceStackNavigator = createStackNavigator({
LNDCreateInvoice: {
screen: LNDCreateInvoice,
},
SelectWallet: {
screen: SelectWallet,
navigationOptions: {
headerLeft: null,
},
},
LNDViewInvoice: {
screen: LNDViewInvoice,
swipeEnabled: false,
gesturesEnabled: false,
},
LNDViewAdditionalInvoiceInformation: {
screen: LNDViewAdditionalInvoiceInformation,
},
});
const CreateWalletStackNavigator = createStackNavigator({
AddWallet: {
screen: AddWallet,
},
ImportWallet: {
screen: ImportWallet,
routeName: 'ImportWallet',
},
PleaseBackup: {
screen: PleaseBackup,
},
PleaseBackupLNDHub: {
screen: PleaseBackupLNDHub,
swipeEnabled: false,
gesturesEnabled: false,
navigationOptions: {
header: null,
},
},
});
const LightningScanInvoiceStackNavigator = createStackNavigator({
ScanLndInvoice: {
screen: ScanLndInvoice,
},
SelectWallet: {
screen: SelectWallet,
navigationOptions: {
headerRight: null,
},
},
Success: {
screen: Success,
},
});
const HandleOffchainAndOnChainStackNavigator = createStackNavigator(
{
SelectWallet: {
screen: SelectWallet,
},
// LND:
ScanLndInvoice: {
screen: LightningScanInvoiceStackNavigator,
navigationOptions: {
header: null,
},
},
ScanQRCode: {
screen: ScanQRCodeStackNavigator,
navigationOptions: {
header: null,
},
},
SendDetails: {
screen: CreateTransactionStackNavigator,
navigationOptions: {
header: null,
},
},
},
{ headerBackTitleVisible: false },
);
const AztecoRedeemStackNavigator = createStackNavigator({
AztecoRedeem: {
screen: AztecoRedeem,
},
SelectWallet: {
screen: SelectWallet,
navigationOptions: {
headerLeft: null,
},
},
});
const MainBottomTabs = createStackNavigator(
{
Wallets: {
screen: WalletsStackNavigator,
path: 'wallets',
navigationOptions: {
header: null,
},
},
AddWallet: {
screen: CreateWalletStackNavigator,
navigationOptions: {
header: null,
},
},
WalletExport: {
screen: WalletExport,
},
WalletXpub: {
screen: WalletXpub,
},
BuyBitcoin: {
screen: BuyBitcoin,
},
Marketplace: {
screen: Marketplace,
},
//
SendDetails: {
routeName: 'SendDetails',
screen: CreateTransactionStackNavigator,
navigationOptions: {
header: null,
},
},
SelectWallet: {
screen: SelectWallet,
navigationOptions: {
headerLeft: null,
},
},
ReceiveDetails: {
screen: receiveDetails,
},
//
AztecoRedeem: {
screen: AztecoRedeemStackNavigator,
navigationOptions: {
header: null,
},
},
// LND:
ScanLndInvoice: {
screen: LightningScanInvoiceStackNavigator,
navigationOptions: {
header: null,
},
},
ScanQRCode: {
screen: ScanQRCodeStackNavigator,
navigationOptions: {
header: null,
},
},
LappBrowser: {
screen: LappBrowser,
},
ReorderWallets: {
screen: ReorderWalletsStackNavigator,
navigationOptions: {
header: null,
},
},
LNDCreateInvoice: {
screen: LNDCreateInvoiceStackNavigator,
navigationOptions: {
header: null,
},
},
HandleOffchainAndOnChain: {
screen: HandleOffchainAndOnChainStackNavigator,
navigationOptions: {
header: null,
},
},
},
{
mode: 'modal',
},
);
export default createAppContainer(MainBottomTabs);

240
Navigation.js Normal file
View file

@ -0,0 +1,240 @@
// import { createAppContainer } from '@react-navigation/native';
import React from 'react';
import { createStackNavigator } from '@react-navigation/stack';
import Settings from './screen/settings/settings';
import About from './screen/settings/about';
import ReleaseNotes from './screen/settings/releasenotes';
import Licensing from './screen/settings/licensing';
import Selftest from './screen/selftest';
import Language from './screen/settings/language';
import Currency from './screen/settings/currency';
import EncryptStorage from './screen/settings/encryptStorage';
import PlausibleDeniability from './screen/plausibledeniability';
import LightningSettings from './screen/settings/lightningSettings';
import ElectrumSettings from './screen/settings/electrumSettings';
import GeneralSettings from './screen/settings/GeneralSettings';
import NetworkSettings from './screen/settings/NetworkSettings';
import DefaultView from './screen/settings/defaultView';
import WalletsList from './screen/wallets/list';
import WalletTransactions from './screen/wallets/transactions';
import AddWallet from './screen/wallets/add';
import PleaseBackup from './screen/wallets/pleaseBackup';
import PleaseBackupLNDHub from './screen/wallets/pleaseBackupLNDHub';
import ImportWallet from './screen/wallets/import';
import WalletDetails from './screen/wallets/details';
import WalletExport from './screen/wallets/export';
import WalletXpub from './screen/wallets/xpub';
import BuyBitcoin from './screen/wallets/buyBitcoin';
import HodlHodl from './screen/wallets/hodlHodl';
import Marketplace from './screen/wallets/marketplace';
import ReorderWallets from './screen/wallets/reorderWallets';
import SelectWallet from './screen/wallets/selectWallet';
import TransactionDetails from './screen/transactions/details';
import TransactionStatus from './screen/transactions/transactionStatus';
import CPFP from './screen/transactions/CPFP';
import RBFBumpFee from './screen/transactions/RBFBumpFee';
import RBFCancel from './screen/transactions/RBFCancel';
import ReceiveDetails from './screen/receive/details';
import AztecoRedeem from './screen/receive/aztecoRedeem';
import SendDetails from './screen/send/details';
import ScanQRCode from './screen/send/ScanQRCode';
import SendCreate from './screen/send/create';
import Confirm from './screen/send/confirm';
import PsbtWithHardwareWallet from './screen/send/psbtWithHardwareWallet';
import Success from './screen/send/success';
import Broadcast from './screen/send/broadcast';
import ScanLndInvoice from './screen/lnd/scanLndInvoice';
import LappBrowser from './screen/lnd/browser';
import LNDCreateInvoice from './screen/lnd/lndCreateInvoice';
import LNDViewInvoice from './screen/lnd/lndViewInvoice';
import LNDViewAdditionalInvoiceInformation from './screen/lnd/lndViewAdditionalInvoiceInformation';
const WalletsStack = createStackNavigator();
const WalletsRoot = () => (
<WalletsStack.Navigator screenOptions={{ headerTitle: null, headerBackTitleVisible: false }}>
<WalletsStack.Screen name="WalletsList" component={WalletsList} options={{ headerShown: false }} />
<WalletsStack.Screen name="WalletTransactions" component={WalletTransactions} options={WalletTransactions.navigationOptions} />
<WalletsStack.Screen name="WalletDetails" component={WalletDetails} options={WalletDetails.navigationOptions} />
<WalletsStack.Screen name="TransactionDetails" component={TransactionDetails} options={TransactionDetails.navigationOptions} />
<WalletsStack.Screen name="TransactionStatus" component={TransactionStatus} options={TransactionStatus.navigationOptions} />
<WalletsStack.Screen name="HodlHodl" component={HodlHodl} options={HodlHodl.navigationOptions} />
<WalletsStack.Screen name="CPFP" component={CPFP} options={CPFP.navigationOptions} />
<WalletsStack.Screen name="RBFBumpFee" component={RBFBumpFee} options={RBFBumpFee.navigationOptions} />
<WalletsStack.Screen name="RBFCancel" component={RBFCancel} options={RBFCancel.navigationOptions} />
<WalletsStack.Screen
name="Settings"
component={Settings}
options={{
headerStyle: {
backgroundColor: '#FFFFFF',
borderBottomWidth: 0,
elevation: 0,
},
headerTintColor: '#0c2550',
}}
/>
<WalletsStack.Screen name="SelectWallet" component={SelectWallet} options={SelectWallet.navigationOptions} />
<WalletsStack.Screen name="Currency" component={Currency} options={Currency.navigationOptions} />
<WalletsStack.Screen name="About" component={About} options={About.navigationOptions} />
<WalletsStack.Screen name="ReleaseNotes" component={ReleaseNotes} options={ReleaseNotes.navigationOptions} />
<WalletsStack.Screen name="Selftest" component={Selftest} options={Selftest.navigationOptions} />
<WalletsStack.Screen name="Licensing" component={Licensing} options={Licensing.navigationOptions} />
<WalletsStack.Screen name="DefaultView" component={DefaultView} options={DefaultView.navigationOptions} />
<WalletsStack.Screen name="Language" component={Language} options={Language.navigationOptions} />
<WalletsStack.Screen name="EncryptStorage" component={EncryptStorage} options={EncryptStorage.navigationOptions} />
<WalletsStack.Screen name="GeneralSettings" component={GeneralSettings} options={GeneralSettings.navigationOptions} />
<WalletsStack.Screen name="NetworkSettings" component={NetworkSettings} options={NetworkSettings.navigationOptions} />
<WalletsStack.Screen name="PlausibleDeniability" component={PlausibleDeniability} options={PlausibleDeniability.navigationOptions} />
<WalletsStack.Screen name="LightningSettings" component={LightningSettings} options={LightningSettings.navigationOptions} />
<WalletsStack.Screen name="ElectrumSettings" component={ElectrumSettings} options={ElectrumSettings.navigationOptions} />
<WalletsStack.Screen
name="LNDViewInvoice"
component={LNDViewInvoice}
options={LNDViewInvoice.navigationOptions}
swipeEnabled={false}
gesturesEnabled={false}
/>
<WalletsStack.Screen
name="LNDViewAdditionalInvoiceInformation"
component={LNDViewAdditionalInvoiceInformation}
options={LNDViewAdditionalInvoiceInformation.navigationOptions}
/>
<WalletsStack.Screen
name="Broadcast"
component={Broadcast}
options={{
title: 'Broadcast',
headerStyle: {
backgroundColor: '#FFFFFF',
borderBottomWidth: 0,
},
headerTintColor: '#0c2550',
}}
/>
<WalletsStack.Screen name="ReorderWallets" component={ReorderWallets} options={ReorderWallets.navigationOptions} />
</WalletsStack.Navigator>
);
const AddWalletStack = createStackNavigator();
const AddWalletRoot = () => (
<AddWalletStack.Navigator screenOptions={{}}>
<AddWalletStack.Screen name="AddWallet" component={AddWallet} options={AddWallet.navigationOptions} />
<AddWalletStack.Screen name="ImportWallet" component={ImportWallet} options={ImportWallet.navigationOptions} />
<AddWalletStack.Screen name="PleaseBackup" component={PleaseBackup} options={PleaseBackup.navigationOptions} />
<AddWalletStack.Screen
name="PleaseBackupLNDHub"
component={PleaseBackupLNDHub}
swipeEnabled={false}
gesturesEnabled={false}
options={{ headerShown: false }}
/>
</AddWalletStack.Navigator>
);
// CreateTransactionStackNavigator === SendDetailsStack
const SendDetailsStack = createStackNavigator();
const SendDetailsRoot = () => (
<SendDetailsStack.Navigator>
<SendDetailsStack.Screen name="SendDetails" component={SendDetails} options={SendDetails.navigationOptions} />
<SendDetailsStack.Screen name="Confirm" component={Confirm} options={Confirm.navigationOptions} />
<SendDetailsStack.Screen
name="PsbtWithHardwareWallet"
component={PsbtWithHardwareWallet}
options={PsbtWithHardwareWallet.navigationOptions}
/>
<SendDetailsStack.Screen
name="CreateTransaction"
component={SendCreate}
options={{
headerStyle: {
backgroundColor: '#FFFFFF',
borderBottomWidth: 0,
},
headerTintColor: '#0c2550',
}}
/>
<SendDetailsStack.Screen name="Success" component={Success} options={Success.navigationOptions} />
<SendDetailsStack.Screen name="SelectWallet" component={SelectWallet} options={{ headerRight: null }} />
</SendDetailsStack.Navigator>
);
const LNDCreateInvoiceStack = createStackNavigator();
const LNDCreateInvoiceRoot = () => (
<LNDCreateInvoiceStack.Navigator>
<LNDCreateInvoiceStack.Screen name="LNDCreateInvoice" component={LNDCreateInvoice} options={LNDCreateInvoice.navigationOptions} />
<LNDCreateInvoiceStack.Screen name="SelectWallet" component={SelectWallet} options={{ headerLeft: null }} />
<LNDCreateInvoiceStack.Screen
name="LNDViewInvoice"
component={LNDViewInvoice}
options={LNDViewInvoice.navigationOptions}
swipeEnabled={false}
gesturesEnabled={false}
/>
<LNDCreateInvoiceStack.Screen
name="LNDViewAdditionalInvoiceInformation"
component={LNDViewAdditionalInvoiceInformation}
options={LNDViewAdditionalInvoiceInformation.navigationOptions}
/>
</LNDCreateInvoiceStack.Navigator>
);
// LightningScanInvoiceStackNavigator === ScanLndInvoiceStack
const ScanLndInvoiceStack = createStackNavigator();
const ScanLndInvoiceRoot = () => (
<ScanLndInvoiceStack.Navigator>
<ScanLndInvoiceStack.Screen name="ScanLndInvoice" component={ScanLndInvoice} options={ScanLndInvoice.navigationOptions} />
<ScanLndInvoiceStack.Screen name="SelectWallet" component={SelectWallet} options={{ headerLeft: null }} />
<ScanLndInvoiceStack.Screen name="Success" component={Success} options={Success.navigationOptions} />
</ScanLndInvoiceStack.Navigator>
);
const HandleOffchainAndOnChainStack = createStackNavigator();
const HandleOffchainAndOnChain = () => (
<HandleOffchainAndOnChainStack.Navigator screenOptions={{ headerBackTitleVisible: false }}>
{/* screens */}
<HandleOffchainAndOnChainStack.Screen name="SelectWallet" component={SelectWallet} options={SelectWallet.navigationOptions} />
<HandleOffchainAndOnChainStack.Screen name="ScanQRCode" component={ScanQRCode} options={ScanQRCode.navigationOptions} />
{/* stacks */}
<HandleOffchainAndOnChainStack.Screen name="ScanLndInvoice" component={ScanLndInvoiceRoot} options={{ headerShown: false }} />
<HandleOffchainAndOnChainStack.Screen name="SendDetails" component={SendDetailsRoot} options={{ headerShown: false }} />
</HandleOffchainAndOnChainStack.Navigator>
);
const AztecoRedeemStack = createStackNavigator();
const AztecoRedeemRoot = () => (
<AztecoRedeemStack.Navigator>
<AztecoRedeemStack.Screen name="AztecoRedeem" component={AztecoRedeem} options={AztecoRedeem.navigationOptions} />
<AztecoRedeemStack.Screen name="SelectWallet" component={SelectWallet} options={{ headerLeft: null }} />
</AztecoRedeemStack.Navigator>
);
const RootStack = createStackNavigator();
const Navigation = () => (
<RootStack.Navigator mode="modal">
{/* stacks */}
<RootStack.Screen name="WalletsRoot" component={WalletsRoot} options={{ headerShown: false }} />
<RootStack.Screen name="AddWalletRoot" component={AddWalletRoot} options={{ headerShown: false }} />
<RootStack.Screen name="SendDetailsRoot" component={SendDetailsRoot} options={{ headerShown: false }} />
<RootStack.Screen name="LNDCreateInvoiceRoot" component={LNDCreateInvoiceRoot} options={{ headerShown: false }} />
<RootStack.Screen name="ScanLndInvoiceRoot" component={ScanLndInvoiceRoot} options={{ headerShown: false }} />
<RootStack.Screen name="HandleOffchainAndOnChain" component={HandleOffchainAndOnChain} options={{ headerShown: false }} />
<RootStack.Screen name="AztecoRedeemRoot" component={AztecoRedeemRoot} options={{ headerShown: false }} />
{/* screens */}
<RootStack.Screen name="WalletExport" component={WalletExport} options={WalletExport.navigationOptions} />
<RootStack.Screen name="WalletXpub" component={WalletXpub} options={WalletXpub.navigationOptions} />
<RootStack.Screen name="BuyBitcoin" component={BuyBitcoin} options={BuyBitcoin.navigationOptions} />
<RootStack.Screen name="Marketplace" component={Marketplace} options={Marketplace.navigationOptions} />
<RootStack.Screen name="SelectWallet" component={SelectWallet} options={{ headerLeft: null }} />
<RootStack.Screen name="ReceiveDetails" component={ReceiveDetails} options={ReceiveDetails.navigationOptions} />
<RootStack.Screen name="ScanQRCode" component={ScanQRCode} options={{ headerShown: false }} />
<RootStack.Screen name="LappBrowser" component={LappBrowser} options={LappBrowser.navigationOptions} />
</RootStack.Navigator>
);
export default Navigation;

View file

@ -1,4 +1,4 @@
import { NavigationActions } from 'react-navigation';
// import { CommonActions } from '@react-navigation/native';
let _navigator;
@ -6,13 +6,8 @@ function setTopLevelNavigator(navigatorRef) {
_navigator = navigatorRef;
}
function navigate(routeName, params) {
_navigator.dispatch(
NavigationActions.navigate({
routeName,
params,
}),
);
function navigate(name, params) {
_navigator.navigate(name, params);
}
export default {

View file

@ -3,7 +3,7 @@ import { View, Image, TouchableOpacity } from 'react-native';
import { Icon } from 'react-native-elements';
import Biometric from './class/biometrics';
import PropTypes from 'prop-types';
import { SafeAreaView } from 'react-navigation';
import { SafeAreaView } from 'react-native-safe-area-context';
/** @type {AppStorage} */
const BlueApp = require('./BlueApp');

View file

@ -16,7 +16,7 @@ buildscript {
}
ext.kotlinVersion = '1.3.+'
dependencies {
classpath("com.android.tools.build:gradle:3.4.2")
classpath('com.android.tools.build:gradle:3.6.3')
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
// NOTE: Do not place your application dependencies here; they belong

View file

@ -28,7 +28,7 @@ class DeeplinkSchemaMatch {
* navigation dictionary required by react-navigation
*
* @param event {{url: string}} URL deeplink as passed to app, e.g. `bitcoin:bc1qh6tf004ty7z7un2v5ntu4mkf630545gvhs45u7?amount=666&label=Yo`
* @param completionHandler {function} Callback that returns {routeName: string, params: object}
* @param completionHandler {function} Callback that returns [string, params: object]
*/
static navigationRouteFor(event, completionHandler) {
if (event.url === null) {
@ -46,12 +46,15 @@ class DeeplinkSchemaMatch {
RNFS.readFile(event.url)
.then(file => {
if (file) {
completionHandler({
routeName: 'PsbtWithHardwareWallet',
params: {
deepLinkPSBT: file,
completionHandler([
'SendDetailsRoot',
{
screen: 'PsbtWithHardwareWallet',
params: {
deepLinkPSBT: file,
},
},
});
]);
}
})
.catch(e => console.warn(e));
@ -64,51 +67,66 @@ class DeeplinkSchemaMatch {
console.log(e);
}
if (isBothBitcoinAndLightning) {
completionHandler({
routeName: 'HandleOffchainAndOnChain',
params: {
onWalletSelect: wallet =>
completionHandler(DeeplinkSchemaMatch.isBothBitcoinAndLightningOnWalletSelect(wallet, isBothBitcoinAndLightning)),
completionHandler([
'HandleOffchainAndOnChain',
{
screen: 'SelectWallet',
params: {
onWalletSelect: wallet =>
completionHandler(DeeplinkSchemaMatch.isBothBitcoinAndLightningOnWalletSelect(wallet, isBothBitcoinAndLightning)),
},
},
});
]);
} else if (DeeplinkSchemaMatch.isBitcoinAddress(event.url) || BitcoinBIP70TransactionDecode.matchesPaymentURL(event.url)) {
completionHandler({
routeName: 'SendDetails',
params: {
uri: event.url,
completionHandler([
'SendDetailsRoot',
{
screen: 'SendDetails',
params: {
uri: event.url,
},
},
});
]);
} else if (DeeplinkSchemaMatch.isLightningInvoice(event.url)) {
completionHandler({
routeName: 'ScanLndInvoice',
params: {
uri: event.url,
completionHandler([
'ScanLndInvoiceRoot',
{
screen: 'ScanLndInvoice',
params: {
uri: event.url,
},
},
});
]);
} else if (DeeplinkSchemaMatch.isLnUrl(event.url)) {
completionHandler({
routeName: 'LNDCreateInvoice',
params: {
uri: event.url,
completionHandler([
'LNDCreateInvoiceRoot',
{
screen: 'LNDCreateInvoice',
params: {
uri: event.url,
},
},
});
]);
} else if (DeeplinkSchemaMatch.isSafelloRedirect(event)) {
let urlObject = url.parse(event.url, true) // eslint-disable-line
const safelloStateToken = urlObject.query['safello-state-token'];
completionHandler({
routeName: 'BuyBitcoin',
params: {
completionHandler([
'BuyBitcoin',
{
uri: event.url,
safelloStateToken,
},
});
]);
} else if (Azteco.isRedeemUrl(event.url)) {
completionHandler({
routeName: 'AztecoRedeem',
params: Azteco.getParamsFromUrl(event.url),
});
completionHandler([
'AztecoRedeemRoot',
{
screen: 'AztecoRedeem',
params: Azteco.getParamsFromUrl(event.url),
},
]);
} else {
let urlObject = url.parse(event.url, true); // eslint-disable-line
console.log('parsed', event.url, 'into', urlObject);
@ -161,14 +179,14 @@ class DeeplinkSchemaMatch {
return;
}
completionHandler({
routeName: 'LappBrowser',
params: {
completionHandler([
'LappBrowser',
{
fromSecret: lnWallet.getSecret(),
fromWallet: lnWallet,
url: urlObject.query.url,
},
});
]);
break;
}
}
@ -186,21 +204,21 @@ class DeeplinkSchemaMatch {
static isBothBitcoinAndLightningOnWalletSelect(wallet, uri) {
if (wallet.chain === Chain.ONCHAIN) {
return {
routeName: 'SendDetails',
params: {
return [
'SendDetails',
{
uri: uri.bitcoin,
fromWallet: wallet,
},
};
];
} else if (wallet.chain === Chain.OFFCHAIN) {
return {
routeName: 'ScanLndInvoice',
params: {
return [
'ScanLndInvoice',
{
uri: uri.lndInvoice,
fromSecret: wallet.getSecret(),
},
};
];
}
}

View file

@ -210,6 +210,8 @@ PODS:
- React
- react-native-randombytes (3.5.3):
- React
- react-native-safe-area-context (2.0.0):
- React
- react-native-slider (2.0.8):
- React
- react-native-tcp (3.3.2):
@ -255,7 +257,9 @@ PODS:
- React
- RemobileReactNativeQrcodeLocalImage (1.0.4):
- React
- RNCAsyncStorage (1.8.1):
- RNCAsyncStorage (1.10.0):
- React
- RNCMaskedView (0.1.10):
- React
- RNDefaultPreference (1.4.1):
- React
@ -273,6 +277,8 @@ PODS:
- React
- RNReactNativeHapticFeedback (1.9.0):
- React
- RNScreens (2.8.0):
- React
- RNSecureKeyStore (1.0.0):
- React
- RNSentry (1.3.7):
@ -321,6 +327,7 @@ DEPENDENCIES:
- react-native-document-picker (from `../node_modules/react-native-document-picker`)
- react-native-image-picker (from `../node_modules/react-native-image-picker`)
- react-native-randombytes (from `../node_modules/react-native-randombytes`)
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
- "react-native-slider (from `../node_modules/@react-native-community/slider`)"
- react-native-tcp (from `../node_modules/react-native-tcp`)
- react-native-webview (from `../node_modules/react-native-webview`)
@ -338,6 +345,7 @@ DEPENDENCIES:
- ReactNativePrivacySnapshot (from `../node_modules/react-native-privacy-snapshot`)
- "RemobileReactNativeQrcodeLocalImage (from `../node_modules/@remobile/react-native-qrcode-local-image`)"
- "RNCAsyncStorage (from `../node_modules/@react-native-community/async-storage`)"
- "RNCMaskedView (from `../node_modules/@react-native-community/masked-view`)"
- RNDefaultPreference (from `../node_modules/react-native-default-preference`)
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
- RNFS (from `../node_modules/react-native-fs`)
@ -346,6 +354,7 @@ DEPENDENCIES:
- RNQuickAction (from `../node_modules/react-native-quick-actions`)
- RNRate (from `../node_modules/react-native-rate`)
- RNReactNativeHapticFeedback (from `../node_modules/react-native-haptic-feedback`)
- RNScreens (from `../node_modules/react-native-screens`)
- RNSecureKeyStore (from `../node_modules/react-native-secure-key-store/ios`)
- "RNSentry (from `../node_modules/@sentry/react-native`)"
- RNShare (from `../node_modules/react-native-share`)
@ -410,6 +419,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-image-picker"
react-native-randombytes:
:path: "../node_modules/react-native-randombytes"
react-native-safe-area-context:
:path: "../node_modules/react-native-safe-area-context"
react-native-slider:
:path: "../node_modules/@react-native-community/slider"
react-native-tcp:
@ -442,6 +453,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/@remobile/react-native-qrcode-local-image"
RNCAsyncStorage:
:path: "../node_modules/@react-native-community/async-storage"
RNCMaskedView:
:path: "../node_modules/@react-native-community/masked-view"
RNDefaultPreference:
:path: "../node_modules/react-native-default-preference"
RNDeviceInfo:
@ -458,6 +471,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-rate"
RNReactNativeHapticFeedback:
:path: "../node_modules/react-native-haptic-feedback"
RNScreens:
:path: "../node_modules/react-native-screens"
RNSecureKeyStore:
:path: "../node_modules/react-native-secure-key-store/ios"
RNSentry:
@ -502,6 +517,7 @@ SPEC CHECKSUMS:
react-native-document-picker: e3516aff0dcf65ee0785d9bcf190eb10e2261154
react-native-image-picker: 3637d63fef7e32a230141ab4660d3ceb773c824f
react-native-randombytes: 991545e6eaaf700b4ee384c291ef3d572e0b2ca8
react-native-safe-area-context: 0b0460e3298465bdb4b859ea43c2d7b9128cf988
react-native-slider: b2f361499888302147205f17f6fffa921a7bda70
react-native-tcp: be8e119e631970aaeda7f6e3207f6b7be72d5eb8
react-native-webview: f11ac6c8bcaba5b71ddda1c12a10c8ea059b080f
@ -517,7 +533,8 @@ SPEC CHECKSUMS:
ReactCommon: 198c7c8d3591f975e5431bec1b0b3b581aa1c5dd
ReactNativePrivacySnapshot: cc295e45dc22810e9ff2c93380d643de20a77015
RemobileReactNativeQrcodeLocalImage: 57aadc12896b148fb5e04bc7c6805f3565f5c3fa
RNCAsyncStorage: 00bdf63f7f1e0f11d3323533dba4f222e58bf092
RNCAsyncStorage: b34d2399d3e25db01d5b881949b503bd3c224d57
RNCMaskedView: f5c7d14d6847b7b44853f7acb6284c1da30a3459
RNDefaultPreference: 12d246dd2222e66dadcd76cc1250560663befc3a
RNDeviceInfo: 12faae605ba42a1a5041c3c41a77834bc23f049d
RNFS: 2bd9eb49dc82fa9676382f0585b992c424cd59df
@ -526,6 +543,7 @@ SPEC CHECKSUMS:
RNQuickAction: 6d404a869dc872cde841ad3147416a670d13fa93
RNRate: d44a8bca6ee08f5d890ecccddaec2810955ffbb3
RNReactNativeHapticFeedback: 2566b468cc8d0e7bb2f84b23adc0f4614594d071
RNScreens: 62211832af51e0aebcf6e8c36bcf7dd65592f244
RNSecureKeyStore: f1ad870e53806453039f650720d2845c678d89c8
RNSentry: 370623102247ebea20191b5fb549ecc7a275b324
RNShare: 8b171d4b43c1d886917fdd303bf7a4b87167b05c
@ -539,4 +557,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: 932f5bffd3ddea34b78c9ed0921a6f8cccf442b5
COCOAPODS: 1.8.4
COCOAPODS: 1.9.1

4208
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -3,12 +3,12 @@
"version": "5.3.9",
"license": "MIT",
"devDependencies": {
"@babel/core": "^7.6.2",
"@babel/runtime": "^7.6.2",
"@babel/core": "^7.9.6",
"@babel/runtime": "^7.9.6",
"@react-native-community/eslint-config": "^0.0.5",
"babel-cli": "^6.26.0",
"babel-eslint": "^10.0.2",
"babel-jest": "^24.9.0",
"babel-eslint": "^10.1.0",
"babel-jest": "^26.0.1",
"babel-preset-flow": "^6.23.0",
"eslint": "^6.5.1",
"eslint-plugin-babel": "^5.3.0",
@ -16,10 +16,9 @@
"eslint-plugin-node": "^9.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-react": "^7.14.2",
"flow-bin": "^0.102.0",
"flow-bin": "^0.125.1",
"jest": "^24.9.0",
"jetifier": "^1.6.3",
"metro-react-native-babel-preset": "^0.56.0",
"prettier-eslint-cli": "^5.0.0",
"react-test-renderer": "16.9.0"
},
@ -60,10 +59,13 @@
]
},
"dependencies": {
"@babel/preset-env": "7.9.5",
"@babel/preset-env": "7.9.6",
"@react-native-community/async-storage": "1.10.0",
"@react-native-community/blur": "3.6.0",
"@react-native-community/masked-view": "0.1.10",
"@react-native-community/slider": "2.0.8",
"@react-navigation/native": "5.4.3",
"@react-navigation/stack": "5.4.0",
"@remobile/react-native-qrcode-local-image": "git+https://github.com/BlueWallet/react-native-qrcode-local-image.git",
"@sentry/react-native": "1.3.7",
"amplitude-js": "5.9.0",
@ -92,6 +94,7 @@
"frisbee": "3.1.2",
"intl": "1.2.5",
"lottie-react-native": "3.1.1",
"metro-react-native-babel-preset": "0.59.0",
"node-libs-react-native": "1.2.0",
"path-browserify": "1.0.0",
"pbkdf2": "3.0.17",
@ -124,6 +127,8 @@
"react-native-quick-actions": "0.3.13",
"react-native-randombytes": "3.5.3",
"react-native-rate": "1.1.10",
"react-native-safe-area-context": "2.0.0",
"react-native-screens": "2.8.0",
"react-native-secure-key-store": "git+https://github.com/BlueWallet/react-native-secure-key-store.git#4ba25dedb3d5ae15c22fd0ea0555116055630966",
"react-native-share": "2.0.0",
"react-native-snap-carousel": "3.9.0",
@ -134,8 +139,6 @@
"react-native-vector-icons": "6.6.0",
"react-native-watch-connectivity": "0.4.2",
"react-native-webview": "6.11.1",
"react-navigation": "3.11.0",
"react-navigation-hooks": "1.1.0",
"react-test-render": "1.1.2",
"readable-stream": "3.6.0",
"rn-nodeify": "10.2.0",

View file

@ -30,9 +30,9 @@ var webln = {
window.ReactNativeWebView.postMessage(JSON.stringify({ sendPayment: paymentRequest }));
return new Promise(function(resolve, reject) {
/* nop. intentionally, forever hang promise.
lapp page usually asynchroniously checks payment itself, via ajax,
so atm there's no need to pass payment preimage from RN to webview and fullfill promise.
might change in future */
lapp page usually asynchroniously checks payment itself, via ajax,
so atm there's no need to pass payment preimage from RN to webview and fullfill promise.
might change in future */
});
},
makeInvoice: function(RequestInvoiceArgs) {
@ -90,51 +90,51 @@ bluewalletResponses = {};
webln = {
enable : function () {
window.ReactNativeWebView.postMessage(JSON.stringify({'enable': true}));
return new Promise(function(resolve, reject){
resolve(true);
})
},
getInfo : function () {
window.ReactNativeWebView.postMessage('getInfo');
return new Promise(function(resolve, reject){
reject('not implemented');
})
},
sendPayment: function(paymentRequest) {
window.ReactNativeWebView.postMessage(JSON.stringify({ sendPayment: paymentRequest }));
return new Promise(function(resolve, reject) {
/* nop. intentionally, forever hang promise.
lapp page usually asynchroniously checks payment itself, via ajax,
so atm there's no need to pass payment preimage from RN to webview and fullfill promise.
might change in future */
});
},
makeInvoice: function (RequestInvoiceArgs) {
var id = Math.random();
window.ReactNativeWebView.postMessage(JSON.stringify({makeInvoice: RequestInvoiceArgs, id: id}));
return new Promise(function(resolve, reject) {
var interval = setInterval(function () {
if (bluewalletResponses[id]) {
clearInterval(interval);
resolve(bluewalletResponses[id]);
}
}, 1000);
});
},
signMessage: function () {
window.ReactNativeWebView.postMessage('signMessage');
return new Promise(function(resolve, reject){
reject('not implemented');
})
},
verifyMessage: function () {
window.ReactNativeWebView.postMessage('verifyMessage');
return new Promise(function(resolve, reject){
reject('not implemented');
})
},
enable : function () {
window.ReactNativeWebView.postMessage(JSON.stringify({'enable': true}));
return new Promise(function(resolve, reject){
resolve(true);
})
},
getInfo : function () {
window.ReactNativeWebView.postMessage('getInfo');
return new Promise(function(resolve, reject){
reject('not implemented');
})
},
sendPayment: function(paymentRequest) {
window.ReactNativeWebView.postMessage(JSON.stringify({ sendPayment: paymentRequest }));
return new Promise(function(resolve, reject) {
/* nop. intentionally, forever hang promise.
lapp page usually asynchroniously checks payment itself, via ajax,
so atm there's no need to pass payment preimage from RN to webview and fullfill promise.
might change in future */
});
},
makeInvoice: function (RequestInvoiceArgs) {
var id = Math.random();
window.ReactNativeWebView.postMessage(JSON.stringify({makeInvoice: RequestInvoiceArgs, id: id}));
return new Promise(function(resolve, reject) {
var interval = setInterval(function () {
if (bluewalletResponses[id]) {
clearInterval(interval);
resolve(bluewalletResponses[id]);
}
}, 1000);
});
},
signMessage: function () {
window.ReactNativeWebView.postMessage('signMessage');
return new Promise(function(resolve, reject){
reject('not implemented');
})
},
verifyMessage: function () {
window.ReactNativeWebView.postMessage('verifyMessage');
return new Promise(function(resolve, reject){
reject('not implemented');
})
},
};
@ -142,17 +142,17 @@ webln = {
/* listening to events that might come from RN: */
document.addEventListener("message", function(event) {
window.ReactNativeWebView.postMessage("inside webview, received post message: " + event.detail);
var json;
try {
json = JSON.parse(event.detail);
} catch (_) {}
window.ReactNativeWebView.postMessage("inside webview, received post message: " + event.detail);
var json;
try {
json = JSON.parse(event.detail);
} catch (_) {}
if (json && json.bluewalletResponse) {
/* this is an answer to one of our inside-webview calls.
we store it in answers hashmap for someone who cares about it */
bluewalletResponses[json.id] = json.bluewalletResponse
}
if (json && json.bluewalletResponse) {
/* this is an answer to one of our inside-webview calls.
we store it in answers hashmap for someone who cares about it */
bluewalletResponses[json.id] = json.bluewalletResponse
}
}, false);
@ -160,50 +160,50 @@ document.addEventListener("message", function(event) {
function tryToPay(invoice) {
window.ReactNativeWebView.postMessage(JSON.stringify({sendPayment:invoice}));
window.ReactNativeWebView.postMessage(JSON.stringify({sendPayment:invoice}));
}
/* for non-webln compatible pages we do it oldschool,
searching for all bolt11 manually */
searching for all bolt11 manually */
setInterval(function() {
window.ReactNativeWebView.postMessage('interval');
var searchText = "lnbc";
var searchText = "lnbc";
var aTags = document.getElementsByTagName("span");
var i;
for (i = 0; i < aTags.length; i++) {
if (aTags[i].textContent.indexOf(searchText) === 0) {
tryToPay(aTags[i].textContent);
}
}
var aTags = document.getElementsByTagName("span");
var i;
for (i = 0; i < aTags.length; i++) {
if (aTags[i].textContent.indexOf(searchText) === 0) {
tryToPay(aTags[i].textContent);
}
}
/* ------------------------- */
/* ------------------------- */
aTags = document.getElementsByTagName("input");
for (i = 0; i < aTags.length; i++) {
if (aTags[i].value.indexOf(searchText) === 0) {
tryToPay(aTags[i].value);
}
}
aTags = document.getElementsByTagName("input");
for (i = 0; i < aTags.length; i++) {
if (aTags[i].value.indexOf(searchText) === 0) {
tryToPay(aTags[i].value);
}
}
/* ------------------------- */
/* ------------------------- */
aTags = document.getElementsByTagName("a");
searchText = "lightning:lnbc";
aTags = document.getElementsByTagName("a");
searchText = "lightning:lnbc";
for (i = 0; i < aTags.length; i++) {
var href = aTags[i].getAttribute('href') + '';
if (href.indexOf(searchText) === 0) {
tryToPay(href.replace('lightning:', ''));
}
}
for (i = 0; i < aTags.length; i++) {
var href = aTags[i].getAttribute('href') + '';
if (href.indexOf(searchText) === 0) {
tryToPay(href.replace('lightning:', ''));
}
}
}, 1000);
`;
`;
export default class Browser extends Component {
static navigationOptions = ({ navigation }) => ({
@ -214,15 +214,15 @@ export default class Browser extends Component {
constructor(props) {
super(props);
if (!props.navigation.getParam('fromSecret')) throw new Error('Invalid param');
if (!props.navigation.getParam('fromWallet')) throw new Error('Invalid param');
if (!props.route.params.fromSecret) throw new Error('Invalid param');
if (!props.route.params.fromWallet) throw new Error('Invalid param');
let url;
if (props.navigation.getParam('url')) url = props.navigation.getParam('url');
if (props.route.params.url) url = props.route.params.url;
this.state = {
url: url || 'https://bluewallet.io/marketplace/',
fromSecret: props.navigation.getParam('fromSecret'),
fromWallet: props.navigation.getParam('fromWallet'),
fromSecret: props.route.params.fromSecret,
fromWallet: props.route.params.fromWallet,
canGoBack: false,
pageIsLoading: false,
stateURL: url || 'https://bluewallet.io/marketplace/',
@ -280,12 +280,9 @@ export default class Browser extends Component {
text: 'Pay',
onPress: () => {
console.log('OK Pressed');
this.props.navigation.navigate({
routeName: 'ScanLndInvoice',
params: {
uri: json.sendPayment,
fromSecret: this.state.fromSecret,
},
this.props.navigation.navigate('ScanLndInvoice', {
uri: json.sendPayment,
fromSecret: this.state.fromSecret,
});
},
},
@ -459,8 +456,10 @@ export default class Browser extends Component {
Browser.propTypes = {
navigation: PropTypes.shape({
getParam: PropTypes.func,
navigate: PropTypes.func,
goBack: PropTypes.func,
}),
route: PropTypes.shape({
params: PropTypes.object,
}),
};

View file

@ -39,7 +39,7 @@ export default class LNDCreateInvoice extends Component {
this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this._keyboardDidShow);
this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this._keyboardDidHide);
let fromWallet;
if (props.navigation.state.params.fromWallet) fromWallet = props.navigation.getParam('fromWallet');
if (props.route.params.fromWallet) fromWallet = props.route.params.fromWallet;
// fallback to first wallet if it exists
if (!fromWallet) {
@ -64,8 +64,8 @@ export default class LNDCreateInvoice extends Component {
renderReceiveDetails = async () => {
this.state.fromWallet.setUserHasSavedExport(true);
await BlueApp.saveToDisk();
if (this.props.navigation.state.params.uri) {
this.processLnurl(this.props.navigation.getParam('uri'));
if (this.props.route.params.uri) {
this.processLnurl(this.props.route.params.uri);
}
this.setState({ isLoading: false });
};
@ -77,7 +77,7 @@ export default class LNDCreateInvoice extends Component {
BlueAlertWalletExportReminder({
onSuccess: this.renderReceiveDetails,
onFailure: () => {
this.props.navigation.dismiss();
this.props.navigation.dangerouslyGetParent().pop();
this.props.navigation.navigate('WalletExport', {
wallet: this.state.fromWallet,
});
@ -211,7 +211,7 @@ export default class LNDCreateInvoice extends Component {
onPress={() => {
NavigationService.navigate('ScanQRCode', {
onBarScanned: this.processLnurl,
launchedBy: this.props.navigation.state.routeName,
launchedBy: this.props.route.name,
});
Keyboard.dismiss();
}}
@ -349,16 +349,15 @@ export default class LNDCreateInvoice extends Component {
LNDCreateInvoice.propTypes = {
navigation: PropTypes.shape({
goBack: PropTypes.func,
dismiss: PropTypes.func,
dangerouslyGetParent: PropTypes.func,
navigate: PropTypes.func,
getParam: PropTypes.func,
pop: PropTypes.func,
state: PropTypes.shape({
routeName: PropTypes.string,
params: PropTypes.shape({
uri: PropTypes.string,
fromWallet: PropTypes.shape({}),
}),
}),
route: PropTypes.shape({
name: PropTypes.string,
params: PropTypes.shape({
uri: PropTypes.string,
fromWallet: PropTypes.shape({}),
}),
}),
};

View file

@ -25,7 +25,7 @@ export default class LNDViewAdditionalInvoiceInformation extends Component {
state = { walletInfo: undefined };
async componentDidMount() {
const fromWallet = this.props.navigation.getParam('fromWallet');
const fromWallet = this.props.route.params.fromWallet;
try {
await fromWallet.fetchInfo();
} catch (_) {
@ -82,9 +82,7 @@ export default class LNDViewAdditionalInvoiceInformation extends Component {
}
LNDViewAdditionalInvoiceInformation.propTypes = {
navigation: PropTypes.shape({
goBack: PropTypes.func,
getParam: PropTypes.func,
dismiss: PropTypes.func,
route: PropTypes.shape({
params: PropTypes.object,
}),
};

View file

@ -22,10 +22,10 @@ const EV = require('../../events');
const { width, height } = Dimensions.get('window');
export default class LNDViewInvoice extends Component {
static navigationOptions = ({ navigation }) =>
navigation.getParam('isModal') === true
static navigationOptions = ({ navigation, route }) =>
route.params.isModal === true
? {
...BlueNavigationStyle(navigation, true, () => navigation.dismiss()),
...BlueNavigationStyle(navigation, true, () => navigation.dangerouslyGetParent().pop()),
title: 'Lightning Invoice',
headerLeft: null,
}
@ -33,8 +33,8 @@ export default class LNDViewInvoice extends Component {
constructor(props) {
super(props);
const invoice = props.navigation.getParam('invoice');
const fromWallet = props.navigation.getParam('fromWallet');
const invoice = props.route.params.invoice;
const fromWallet = props.route.params.fromWallet;
this.state = {
invoice,
fromWallet,
@ -323,7 +323,9 @@ LNDViewInvoice.propTypes = {
navigation: PropTypes.shape({
goBack: PropTypes.func,
navigate: PropTypes.func,
getParam: PropTypes.func,
popToTop: PropTypes.func,
}),
route: PropTypes.shape({
params: PropTypes.object,
}),
};

View file

@ -42,10 +42,10 @@ export default class ScanLndInvoice extends React.Component {
if (!BlueApp.getWallets().some(item => item.type === LightningCustodianWallet.type)) {
ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false });
alert('Before paying a Lightning invoice, you must first add a Lightning wallet.');
props.navigation.dismiss();
props.navigation.dangerouslyGetParent().pop();
} else {
let fromSecret;
if (props.navigation.state.params.fromSecret) fromSecret = props.navigation.state.params.fromSecret;
if (props.route.params.fromSecret) fromSecret = props.route.params.fromSecret;
let fromWallet = {};
if (!fromSecret) {
@ -72,8 +72,8 @@ export default class ScanLndInvoice extends React.Component {
}
static getDerivedStateFromProps(props, state) {
if (props.navigation.state.params.uri) {
let data = props.navigation.state.params.uri;
if (props.route.params.uri) {
let data = props.route.params.uri;
// handling BIP21 w/BOLT11 support
let ind = data.indexOf('lightning=');
if (ind !== -1) {
@ -290,7 +290,7 @@ export default class ScanLndInvoice extends React.Component {
isLoading={this.state.isLoading}
placeholder={loc.lnd.placeholder}
inputAccessoryViewID={BlueDismissKeyboardInputAccessory.InputAccessoryViewID}
launchedBy={this.props.navigation.state.routeName}
launchedBy={this.props.route.name}
/>
<View
style={{
@ -340,15 +340,14 @@ ScanLndInvoice.propTypes = {
goBack: PropTypes.func,
navigate: PropTypes.func,
pop: PropTypes.func,
getParam: PropTypes.func,
setParams: PropTypes.func,
dismiss: PropTypes.func,
state: PropTypes.shape({
routeName: PropTypes.string,
params: PropTypes.shape({
uri: PropTypes.string,
fromSecret: PropTypes.string,
}),
dangerouslyGetParent: PropTypes.func,
}),
route: PropTypes.shape({
name: PropTypes.string,
params: PropTypes.shape({
uri: PropTypes.string,
fromSecret: PropTypes.string,
}),
}),
};

View file

@ -70,7 +70,7 @@ export default class PlausibleDeniability extends Component {
EV(EV.enum.TRANSACTIONS_COUNT_CHANGED);
ReactNativeHapticFeedback.trigger('notificationSuccess', { ignoreAndroidSystemSettings: false });
alert(loc.plausibledeniability.success);
this.props.navigation.navigate('Wallets');
this.props.navigation.popToTop();
}}
/>
</ScrollView>

View file

@ -34,10 +34,10 @@ export default class AztecoRedeem extends Component {
toWallet = wallets[0];
}
this.state = {
c1: props.navigation.state.params.c1,
c2: props.navigation.state.params.c2,
c3: props.navigation.state.params.c3,
c4: props.navigation.state.params.c4,
c1: props.route.params.c1,
c2: props.route.params.c2,
c3: props.route.params.c3,
c4: props.route.params.c4,
isLoading: false,
toWallet,
renderWalletSelectionButtonHidden: false,
@ -136,13 +136,13 @@ AztecoRedeem.propTypes = {
pop: PropTypes.func,
goBack: PropTypes.func,
navigate: PropTypes.func,
state: PropTypes.shape({
params: PropTypes.shape({
c1: PropTypes.string,
c2: PropTypes.string,
c3: PropTypes.string,
c4: PropTypes.string,
}),
}),
route: PropTypes.shape({
params: PropTypes.shape({
c1: PropTypes.string,
c2: PropTypes.string,
c3: PropTypes.string,
c4: PropTypes.string,
}),
}),
};

View file

@ -1,7 +1,7 @@
import React, { useEffect, useState, useCallback } from 'react';
import { View, InteractionManager, Platform, TextInput, KeyboardAvoidingView, Keyboard, StyleSheet, ScrollView } from 'react-native';
import QRCode from 'react-native-qrcode-svg';
import { useNavigation, useNavigationParam, useIsFocused } from 'react-navigation-hooks';
import { useNavigation, useRoute, useIsFocused } from '@react-navigation/native';
import {
BlueLoading,
SafeBlueArea,
@ -27,7 +27,7 @@ const BlueApp = require('../../BlueApp');
const loc = require('../../loc');
const ReceiveDetails = () => {
const secret = useNavigationParam('secret');
const { secret } = useRoute().params;
const [wallet, setWallet] = useState();
const [isHandOffUseEnabled, setIsHandOffUseEnabled] = useState(false);
const [address, setAddress] = useState('');

View file

@ -4,18 +4,18 @@ import { Image, View, TouchableOpacity, Platform } from 'react-native';
import { RNCamera } from 'react-native-camera';
import { Icon } from 'react-native-elements';
import ImagePicker from 'react-native-image-picker';
import { useNavigationParam, useNavigation, useIsFocused } from 'react-navigation-hooks';
import { useNavigation, useRoute, useIsFocused } from '@react-navigation/native';
import DocumentPicker from 'react-native-document-picker';
import RNFS from 'react-native-fs';
const LocalQRCode = require('@remobile/react-native-qrcode-local-image');
const createHash = require('create-hash');
const ScanQRCode = () => {
const showFileImportButton = useNavigationParam('showFileImportButton') || false;
const [isLoading, setIsLoading] = useState(false);
const { navigate } = useNavigation();
const launchedBy = useNavigationParam('launchedBy');
const onBarScanned = useNavigationParam('onBarScanned');
const route = useRoute();
const showFileImportButton = route.params.showFileImportButton || false;
const { launchedBy, onBarScanned } = route.params;
const scannedCache = {};
const isFocused = useIsFocused();
@ -174,7 +174,7 @@ const ScanQRCode = () => {
};
ScanQRCode.navigationOptions = {
header: null,
headerShown: false,
};
export default ScanQRCode;

View file

@ -36,14 +36,14 @@ export default class Confirm extends Component {
this.state = {
isLoading: false,
fee: props.navigation.getParam('fee'),
feeSatoshi: new Bignumber(props.navigation.getParam('fee')).multipliedBy(100000000).toNumber(),
memo: props.navigation.getParam('memo'),
recipients: props.navigation.getParam('recipients'),
size: Math.round(props.navigation.getParam('tx').length / 2),
tx: props.navigation.getParam('tx'),
satoshiPerByte: props.navigation.getParam('satoshiPerByte'),
fromWallet: props.navigation.getParam('fromWallet'),
fee: props.route.params.fee,
feeSatoshi: new Bignumber(props.route.params.fee).multipliedBy(100000000).toNumber(),
memo: props.route.params.memo,
recipients: props.route.params.recipients,
size: Math.round(props.route.params.tx.length / 2),
tx: props.route.params.tx,
satoshiPerByte: props.route.params.satoshiPerByte,
fromWallet: props.route.params.fromWallet,
};
}
@ -100,7 +100,7 @@ export default class Confirm extends Component {
this.props.navigation.navigate('Success', {
fee: Number(this.state.fee),
amount,
dismissModal: () => this.props.navigation.dismiss(),
dismissModal: () => this.props.navigation.dangerouslyGetParent().pop(),
});
this.setState({ isLoading: false });
}
@ -244,20 +244,10 @@ const styles = StyleSheet.create({
Confirm.propTypes = {
navigation: PropTypes.shape({
goBack: PropTypes.func,
getParam: PropTypes.func,
navigate: PropTypes.func,
dismiss: PropTypes.func,
state: PropTypes.shape({
params: PropTypes.shape({
amount: PropTypes.string,
fee: PropTypes.number,
address: PropTypes.string,
memo: PropTypes.string,
fromWallet: PropTypes.shape({
fromAddress: PropTypes.string,
fromSecret: PropTypes.string,
}),
}),
}),
dangerouslyGetParent: PropTypes.func,
}),
route: PropTypes.shape({
params: PropTypes.object,
}),
};

View file

@ -28,15 +28,24 @@ const loc = require('../../loc');
const currency = require('../../currency');
export default class SendCreate extends Component {
static navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle,
title: loc.send.create.details,
headerRight: navigation.state.params.exportTXN ? (
<TouchableOpacity style={{ marginRight: 16 }} onPress={navigation.state.params.exportTXN}>
<Icon size={22} name="share-alternative" type="entypo" color={BlueApp.settings.foregroundColor} />
</TouchableOpacity>
) : null,
});
static navigationOptions = ({ navigation, route }) => {
let headerRight;
if (route.params.exportTXN) {
headerRight = () => (
<TouchableOpacity style={{ marginRight: 16 }} onPress={route.params.exportTXN}>
<Icon size={22} name="share-alternative" type="entypo" color={BlueApp.settings.foregroundColor} />
</TouchableOpacity>
);
} else {
headerRight = null;
}
return {
...BlueNavigationStyle,
title: loc.send.create.details,
headerRight,
};
};
constructor(props) {
super(props);
@ -44,14 +53,14 @@ export default class SendCreate extends Component {
props.navigation.setParams({ exportTXN: this.exportTXN });
this.state = {
isLoading: false,
fee: props.navigation.getParam('fee'),
recipients: props.navigation.getParam('recipients'),
memo: props.navigation.getParam('memo') || '',
size: Math.round(props.navigation.getParam('tx').length / 2),
tx: props.navigation.getParam('tx'),
satoshiPerByte: props.navigation.getParam('satoshiPerByte'),
wallet: props.navigation.getParam('wallet'),
feeSatoshi: props.navigation.getParam('feeSatoshi'),
fee: props.route.params.fee,
recipients: props.route.params.recipients,
memo: props.route.params.memo || '',
size: Math.round(props.route.params.tx.length / 2),
tx: props.route.params.tx,
satoshiPerByte: props.route.params.satoshiPerByte,
wallet: props.route.params.wallet,
feeSatoshi: props.route.params.feeSatoshi,
};
}
@ -209,16 +218,10 @@ SendCreate.propTypes = {
navigation: PropTypes.shape({
goBack: PropTypes.func,
setParams: PropTypes.func,
getParam: PropTypes.func,
navigate: PropTypes.func,
dismiss: PropTypes.func,
state: PropTypes.shape({
params: PropTypes.shape({
amount: PropTypes.string,
fee: PropTypes.number,
address: PropTypes.string,
memo: PropTypes.string,
}),
}),
}),
route: PropTypes.shape({
params: PropTypes.object,
}),
};

View file

@ -50,12 +50,8 @@ let loc = require('../../loc');
const btcAddressRx = /^[a-zA-Z0-9]{26,35}$/;
export default class SendDetails extends Component {
static navigationOptions = ({ navigation }) => ({
...BlueCreateTxNavigationStyle(
navigation,
navigation.state.params.withAdvancedOptionsMenuButton,
navigation.state.params.advancedOptionsMenuButtonAction,
),
static navigationOptions = ({ navigation, route }) => ({
...BlueCreateTxNavigationStyle(navigation, route.params.withAdvancedOptionsMenuButton, route.params.advancedOptionsMenuButtonAction),
title: loc.send.header,
});
@ -69,7 +65,7 @@ export default class SendDetails extends Component {
/** @type {LegacyWallet} */
let fromWallet = null;
if (props.navigation.state.params) fromWallet = props.navigation.state.params.fromWallet;
if (props.route.params) fromWallet = props.route.params.fromWallet;
const wallets = BlueApp.getWallets().filter(wallet => wallet.type !== LightningCustodianWallet.type);
@ -179,8 +175,8 @@ export default class SendDetails extends Component {
StatusBar.setBarStyle('dark-content');
let addresses = [];
let initialMemo = '';
if (this.props.navigation.state.params.uri) {
const uri = this.props.navigation.state.params.uri;
if (this.props.route.params.uri) {
const uri = this.props.route.params.uri;
if (BitcoinBIP70TransactionDecode.matchesPaymentURL(uri)) {
const { recipient, memo, fee, feeSliderValue } = await this.processBIP70Invoice(uri);
addresses.push(recipient);
@ -197,9 +193,9 @@ export default class SendDetails extends Component {
alert('Error: Unable to decode Bitcoin address');
}
}
} else if (this.props.navigation.state.params.address) {
addresses.push(new BitcoinTransaction(this.props.navigation.state.params.address));
if (this.props.navigation.state.params.memo) initialMemo = this.props.navigation.state.params.memo;
} else if (this.props.route.params.address) {
addresses.push(new BitcoinTransaction(this.props.route.params.address));
if (this.props.route.params.memo) initialMemo = this.props.route.params.memo;
this.setState({ addresses, memo: initialMemo, isLoading: false });
} else {
this.setState({ addresses: [new BitcoinTransaction()], isLoading: false });
@ -227,12 +223,12 @@ export default class SendDetails extends Component {
feeSliderValue: recommendedFees.fastestFee,
});
if (this.props.navigation.state.params.uri) {
if (BitcoinBIP70TransactionDecode.matchesPaymentURL(this.props.navigation.state.params.uri)) {
this.processBIP70Invoice(this.props.navigation.state.params.uri);
if (this.props.route.params.uri) {
if (BitcoinBIP70TransactionDecode.matchesPaymentURL(this.props.route.params.uri)) {
this.processBIP70Invoice(this.props.route.params.uri);
} else {
try {
const { address, amount, memo } = this.decodeBitcoinUri(this.props.navigation.getParam('uri'));
const { address, amount, memo } = this.decodeBitcoinUri(this.props.route.params.uri);
this.setState({ address, amount, memo, isLoading: false });
} catch (error) {
console.log(error);
@ -784,7 +780,7 @@ export default class SendDetails extends Component {
let rows = [];
for (let [index, item] of this.state.addresses.entries()) {
rows.push(
<View style={{ minWidth: width, maxWidth: width, width: width }}>
<View key={index} style={{ minWidth: width, maxWidth: width, width: width }}>
<BlueBitcoinAmount
isLoading={this.state.isLoading}
amount={item.amount ? item.amount.toString() : null}
@ -822,7 +818,7 @@ export default class SendDetails extends Component {
address={item.address}
isLoading={this.state.isLoading}
inputAccessoryViewID={BlueDismissKeyboardInputAccessory.InputAccessoryViewID}
launchedBy={this.props.navigation.state.routeName}
launchedBy={this.props.route.name}
/>
{this.state.addresses.length > 1 && (
<BlueText style={{ alignSelf: 'flex-end', marginRight: 18, marginVertical: 8 }}>
@ -869,7 +865,7 @@ export default class SendDetails extends Component {
}
return (
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
<View style={{ flex: 1, justifyContent: 'space-between' }}>
<View style={{ flex: 1, justifyContent: 'space-between', backgroundColor: '#FFFFFF' }}>
<View>
<KeyboardAvoidingView behavior="position">
<ScrollView
@ -995,18 +991,17 @@ SendDetails.propTypes = {
pop: PropTypes.func,
goBack: PropTypes.func,
navigate: PropTypes.func,
getParam: PropTypes.func,
setParams: PropTypes.func,
state: PropTypes.shape({
routeName: PropTypes.string,
params: PropTypes.shape({
amount: PropTypes.number,
address: PropTypes.string,
satoshiPerByte: PropTypes.string,
fromWallet: PropTypes.fromWallet,
memo: PropTypes.string,
uri: PropTypes.string,
}),
}),
route: PropTypes.shape({
name: PropTypes.string,
params: PropTypes.shape({
amount: PropTypes.number,
address: PropTypes.string,
satoshiPerByte: PropTypes.string,
fromWallet: PropTypes.fromWallet,
memo: PropTypes.string,
uri: PropTypes.string,
}),
}),
};

View file

@ -75,20 +75,20 @@ export default class PsbtWithHardwareWallet extends Component {
isLoading: false,
renderScanner: false,
qrCodeHeight: height > width ? width - 40 : width / 3,
memo: props.navigation.getParam('memo'),
psbt: props.navigation.getParam('psbt'),
fromWallet: props.navigation.getParam('fromWallet'),
isFirstPSBTAlreadyBase64: props.navigation.getParam('isFirstPSBTAlreadyBase64'),
memo: props.route.params.memo,
psbt: props.route.params.psbt,
fromWallet: props.route.params.fromWallet,
isFirstPSBTAlreadyBase64: props.route.params.isFirstPSBTAlreadyBase64,
isSecondPSBTAlreadyBase64: false,
deepLinkPSBT: undefined,
txhex: props.navigation.getParam('txhex') || undefined,
txhex: props.route.params.txhex || undefined,
};
this.fileName = `${Date.now()}.psbt`;
}
static getDerivedStateFromProps(nextProps, prevState) {
const deepLinkPSBT = nextProps.navigation.state.params.deepLinkPSBT;
const txhex = nextProps.navigation.state.params.txhex;
const deepLinkPSBT = nextProps.route.params.deepLinkPSBT;
const txhex = nextProps.route.params.txhex;
if (deepLinkPSBT) {
try {
let Tx = prevState.fromWallet.combinePsbt(
@ -182,7 +182,7 @@ export default class PsbtWithHardwareWallet extends Component {
<SafeBlueArea style={{ flex: 1 }}>
<BlueBigCheckmark style={{ marginTop: 143, marginBottom: 53 }} />
<BlueCard>
<BlueButton onPress={this.props.navigation.dismiss} title={loc.send.success.done} />
<BlueButton onPress={this.props.navigation.dangerouslyGetParent().pop} title={loc.send.success.done} />
</BlueCard>
</SafeBlueArea>
);
@ -352,17 +352,10 @@ export default class PsbtWithHardwareWallet extends Component {
PsbtWithHardwareWallet.propTypes = {
navigation: PropTypes.shape({
goBack: PropTypes.func,
getParam: PropTypes.func,
navigate: PropTypes.func,
dismiss: PropTypes.func,
state: PropTypes.shape({
params: PropTypes.shape({
memo: PropTypes.string,
fromWallet: PropTypes.shape({
fromAddress: PropTypes.string,
fromSecret: PropTypes.string,
}),
}),
}),
dangerouslyGetParent: PropTypes.func,
}),
route: PropTypes.shape({
params: PropTypes.object,
}),
};

View file

@ -9,7 +9,7 @@ let loc = require('../../loc');
export default class Success extends Component {
static navigationOptions = {
header: null,
headerShown: false,
gesturesEnabled: false,
};
@ -18,10 +18,10 @@ export default class Success extends Component {
console.log('send/success constructor');
this.state = {
amount: props.navigation.getParam('amount'),
fee: props.navigation.getParam('fee') || 0,
amountUnit: props.navigation.getParam('amountUnit') || BitcoinUnit.BTC,
invoiceDescription: props.navigation.getParam('invoiceDescription') || '',
amount: props.route.params.amount,
fee: props.route.params.fee || 0,
amountUnit: props.route.params.amountUnit || BitcoinUnit.BTC,
invoiceDescription: props.route.params.invoiceDescription || '',
};
}
@ -104,7 +104,7 @@ export default class Success extends Component {
<BlueCard>
<BlueButton
onPress={() => {
this.props.navigation.dismiss();
this.props.navigation.dangerouslyGetParent().pop();
}}
title={loc.send.success.done}
/>
@ -117,9 +117,8 @@ export default class Success extends Component {
Success.propTypes = {
navigation: PropTypes.shape({
goBack: PropTypes.func,
getParam: PropTypes.func,
navigate: PropTypes.func,
dismiss: PropTypes.func,
dangerouslyGetParent: PropTypes.func,
state: PropTypes.shape({
params: PropTypes.shape({
amount: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
@ -127,4 +126,7 @@ Success.propTypes = {
}),
}),
}),
route: PropTypes.shape({
params: PropTypes.object,
}),
};

View file

@ -3,7 +3,7 @@ import { ScrollView, Platform, TouchableWithoutFeedback, TouchableOpacity } from
import { BlueLoading, BlueText, BlueSpacing20, BlueListItem, SafeBlueArea, BlueNavigationStyle, BlueCard } from '../../BlueComponents';
import PropTypes from 'prop-types';
import { AppStorage } from '../../class';
import { useNavigation } from 'react-navigation-hooks';
import { useNavigation } from '@react-navigation/native';
import HandoffSettings from '../../class/handoff';
let BlueApp: AppStorage = require('../../BlueApp');
let loc = require('../../loc');

View file

@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react';
import { ScrollView, TouchableOpacity } from 'react-native';
import { BlueNavigationStyle, BlueLoading, SafeBlueArea, BlueListItem } from '../../BlueComponents';
import { useNavigation } from 'react-navigation-hooks';
import { useNavigation } from '@react-navigation/native';
const loc = require('../../loc');
const NetworkSettings = () => {

View file

@ -1,6 +1,6 @@
import React, { useEffect, useState } from 'react';
import { ScrollView, Linking, Dimensions, Image, View, Text } from 'react-native';
import { useNavigation } from 'react-navigation-hooks';
import { useNavigation } from '@react-navigation/native';
import {
BlueTextCentered,
BlueLoading,

View file

@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react';
import { TouchableOpacity, View, TouchableWithoutFeedback } from 'react-native';
import { SafeBlueArea, BlueCard, BlueText, BlueNavigationStyle, BlueListItem } from '../../BlueComponents';
import OnAppLaunch from '../../class/on-app-launch';
import { useNavigation } from 'react-navigation-hooks';
import { useNavigation } from '@react-navigation/native';
const BlueApp = require('../../BlueApp');
const DefaultView = () => {

View file

@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react';
import { ScrollView, TouchableOpacity } from 'react-native';
import { BlueNavigationStyle, BlueLoading, SafeBlueArea, BlueHeaderDefaultSub, BlueListItem } from '../../BlueComponents';
import { useNavigation } from 'react-navigation-hooks';
import { useNavigation } from '@react-navigation/native';
const loc = require('../../loc');
const Settings = () => {

View file

@ -33,8 +33,8 @@ export default class CPFP extends Component {
super(props);
let txid;
let wallet;
if (props.navigation.state.params) txid = props.navigation.state.params.txid;
if (props.navigation.state.params) wallet = props.navigation.state.params.wallet;
if (props.route.params) txid = props.route.params.txid;
if (props.route.params) wallet = props.route.params.wallet;
this.state = {
isLoading: true,
@ -230,11 +230,11 @@ CPFP.propTypes = {
navigation: PropTypes.shape({
popToTop: PropTypes.func,
navigate: PropTypes.func,
state: PropTypes.shape({
params: PropTypes.shape({
txid: PropTypes.string,
wallet: PropTypes.object,
}),
}),
route: PropTypes.shape({
params: PropTypes.shape({
txid: PropTypes.string,
wallet: PropTypes.object,
}),
}),
};

View file

@ -39,7 +39,7 @@ export default class TransactionsDetails extends Component {
constructor(props) {
super(props);
let hash = props.navigation.state.params.hash;
let hash = props.route.params.hash;
let foundTx = {};
let from = [];
let to = [];
@ -200,13 +200,10 @@ export default class TransactionsDetails extends Component {
}
TransactionsDetails.propTypes = {
navigation: PropTypes.shape({
goBack: PropTypes.func,
navigate: PropTypes.func,
state: PropTypes.shape({
params: PropTypes.shape({
hash: PropTypes.string,
}),
route: PropTypes.shape({
name: PropTypes.string,
params: PropTypes.shape({
hash: PropTypes.string,
}),
}),
};

View file

@ -35,7 +35,7 @@ export default class TransactionsStatus extends Component {
constructor(props) {
super(props);
let hash = props.navigation.state.params.hash;
let hash = props.route.params.hash;
let foundTx = {};
let from = [];
let to = [];
@ -358,4 +358,7 @@ TransactionsStatus.propTypes = {
}),
}),
}),
route: PropTypes.shape({
params: PropTypes.object,
}),
};

View file

@ -345,7 +345,7 @@ export default class WalletsAdd extends Component {
secret: w.getSecret(),
});
} else {
this.props.navigation.dismiss();
this.props.navigation.goBack();
}
}
});
@ -375,6 +375,5 @@ WalletsAdd.propTypes = {
navigation: PropTypes.shape({
navigate: PropTypes.func,
goBack: PropTypes.func,
dismiss: PropTypes.func,
}),
};

View file

@ -16,7 +16,7 @@ export default class BuyBitcoin extends Component {
constructor(props) {
super(props);
let wallet = props.navigation.state.params.wallet;
let wallet = props.route.params.wallet;
if (!wallet) console.warn('wallet was not passed to buyBitcoin');
this.state = {
@ -77,7 +77,7 @@ export default class BuyBitcoin extends Component {
return <BlueLoading />;
}
const { safelloStateToken } = this.props.navigation.state.params;
const { safelloStateToken } = this.props.route.params;
let uri = 'https://bluewallet.io/buy-bitcoin-redirect.html?address=' + this.state.address;
@ -102,13 +102,11 @@ export default class BuyBitcoin extends Component {
}
BuyBitcoin.propTypes = {
navigation: PropTypes.shape({
goBack: PropTypes.func,
state: PropTypes.shape({
params: PropTypes.shape({
wallet: PropTypes.object.isRequired,
safelloStateToken: PropTypes.string,
}),
route: PropTypes.shape({
name: PropTypes.string,
params: PropTypes.shape({
wallet: PropTypes.object.isRequired,
safelloStateToken: PropTypes.string,
}),
}),
};

View file

@ -31,16 +31,16 @@ const BlueApp = require('../../BlueApp');
const loc = require('../../loc');
export default class WalletDetails extends Component {
static navigationOptions = ({ navigation }) => ({
static navigationOptions = ({ navigation, route }) => ({
...BlueNavigationStyle(),
title: loc.wallets.details.title,
headerRight: (
headerRight: () => (
<TouchableOpacity
disabled={navigation.getParam('isLoading') === true}
disabled={route.params.isLoading === true}
style={{ marginHorizontal: 16, justifyContent: 'center', alignItems: 'center' }}
onPress={() => {
if (navigation.state.params.saveAction) {
navigation.getParam('saveAction')();
if (route.params.saveAction) {
route.params.saveAction();
}
}}
>
@ -52,7 +52,7 @@ export default class WalletDetails extends Component {
constructor(props) {
super(props);
const wallet = props.navigation.getParam('wallet');
const wallet = props.route.params.wallet;
const isLoading = true;
this.state = {
isLoading,
@ -334,7 +334,6 @@ export default class WalletDetails extends Component {
WalletDetails.propTypes = {
navigation: PropTypes.shape({
getParam: PropTypes.func,
state: PropTypes.shape({
params: PropTypes.shape({
secret: PropTypes.string,
@ -344,4 +343,7 @@ WalletDetails.propTypes = {
goBack: PropTypes.func,
setParams: PropTypes.func,
}),
route: PropTypes.shape({
params: PropTypes.object,
}),
};

View file

@ -20,7 +20,7 @@ export default class WalletExport extends Component {
constructor(props) {
super(props);
let wallet = props.navigation.state.params.wallet;
let wallet = props.route.params.wallet;
this.state = {
isLoading: true,
qrCodeHeight: height > width ? width - 40 : width / 2,
@ -111,12 +111,13 @@ export default class WalletExport extends Component {
WalletExport.propTypes = {
navigation: PropTypes.shape({
state: PropTypes.shape({
params: PropTypes.shape({
wallet: PropTypes.object.isRequired,
}),
}),
navigate: PropTypes.func,
goBack: PropTypes.func,
}),
route: PropTypes.shape({
name: PropTypes.string,
params: PropTypes.shape({
wallet: PropTypes.object.isRequired,
}),
}),
};

View file

@ -166,7 +166,7 @@ export default class HodlHodl extends Component {
constructor(props) {
super(props);
/** @type {AbstractWallet} */
let wallet = props.navigation.state.params.wallet;
let wallet = props.route.params.wallet;
this.state = {
isLoading: true,
@ -909,12 +909,9 @@ export default class HodlHodl extends Component {
}
HodlHodl.propTypes = {
navigation: PropTypes.shape({
goBack: PropTypes.func,
state: PropTypes.shape({
params: PropTypes.shape({
wallet: PropTypes.object,
}),
route: PropTypes.shape({
params: PropTypes.shape({
wallet: PropTypes.object,
}),
}),
};

View file

@ -13,15 +13,17 @@ import {
} from '../../BlueComponents';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import Privacy from '../../Privacy';
import { useNavigation, useNavigationParam } from 'react-navigation-hooks';
import { useNavigation, useRoute } from '@react-navigation/native';
import WalletImport from '../../class/wallet-import';
let loc = require('../../loc');
const { width } = Dimensions.get('window');
const WalletsImport = () => {
const [isToolbarVisibleForAndroid, setIsToolbarVisibleForAndroid] = useState(false);
const [importText, setImportText] = useState(useNavigationParam('label') || '');
const { navigate, dismiss } = useNavigation();
const route = useRoute();
const label = (route.params && route.params.label) || '';
const [importText, setImportText] = useState(label);
const navigation = useNavigation();
useEffect(() => {
Privacy.enableBlur();
@ -49,7 +51,7 @@ const WalletsImport = () => {
const importMnemonic = (importText, additionalProperties) => {
try {
WalletImport.processImportText(importText, additionalProperties);
dismiss();
navigation.dangerouslyGetParent().pop();
} catch (error) {
alert(loc.wallets.import.error);
ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false });
@ -93,7 +95,7 @@ const WalletsImport = () => {
<BlueButtonLink
title={loc.wallets.import.scan_qr}
onPress={() => {
navigate('ScanQRCode', { launchedBy: 'ImportWallet', onBarScanned, showFileImportButton: true });
navigation.navigate('ScanQRCode', { launchedBy: 'ImportWallet', onBarScanned, showFileImportButton: true });
}}
/>
</View>

View file

@ -15,11 +15,10 @@ import {
} from 'react-native';
import { BlueScanButton, WalletsCarousel, BlueHeaderDefaultMain, BlueTransactionListItem } from '../../BlueComponents';
import { Icon } from 'react-native-elements';
import { NavigationEvents } from 'react-navigation';
import DeeplinkSchemaMatch from '../../class/deeplink-schema-match';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import PropTypes from 'prop-types';
import { PlaceholderWallet, AppStorage } from '../../class';
import { AppStorage, PlaceholderWallet } from '../../class';
import WalletImport from '../../class/wallet-import';
import ActionSheet from '../ActionSheet';
import ImagePicker from 'react-native-image-picker';
@ -72,6 +71,18 @@ export default class WalletsList extends Component {
console.log(error);
}
});
this.interval = setInterval(() => {
this.setState(prev => ({ timeElapsed: prev.timeElapsed + 1 }));
}, 60000);
this.redrawScreen();
this._unsubscribe = this.props.navigation.addListener('focus', this.onNavigationEventFocus);
}
componentWillUnmount() {
clearInterval(this.interval);
this._unsubscribe();
}
/**
@ -188,7 +199,7 @@ export default class WalletsList extends Component {
} else {
// if its out of index - this must be last card with incentive to create wallet
if (!BlueApp.getWallets().some(wallet => wallet.type === PlaceholderWallet.type)) {
this.props.navigation.navigate('AddWallet');
this.props.navigation.navigate('AddWalletRoot');
}
}
};
@ -377,7 +388,7 @@ export default class WalletsList extends Component {
leftText={loc.wallets.list.title}
onNewWalletPress={
!BlueApp.getWallets().some(wallet => wallet.type === PlaceholderWallet.type)
? () => this.props.navigation.navigate('AddWallet')
? () => this.props.navigation.navigate('AddWalletRoot')
: null
}
/>
@ -453,7 +464,7 @@ export default class WalletsList extends Component {
onScanButtonPressed = () => {
this.props.navigation.navigate('ScanQRCode', {
launchedBy: this.props.navigation.state.routeName,
launchedBy: this.props.route.name,
onBarScanned: this.onBarScanned,
showFileImportButton: false,
});
@ -466,7 +477,7 @@ export default class WalletsList extends Component {
});
};
onNavigationEventDidFocus = () => {
onNavigationEventFocus = () => {
StatusBar.setBarStyle('dark-content');
this.redrawScreen();
};
@ -509,7 +520,7 @@ export default class WalletsList extends Component {
this.choosePhoto();
} else if (buttonIndex === 2) {
this.props.navigation.navigate('ScanQRCode', {
launchedBy: this.props.navigation.state.routeName,
launchedBy: this.props.route.name,
onBarScanned: this.onBarCodeRead,
showFileImportButton: false,
});
@ -532,7 +543,7 @@ export default class WalletsList extends Component {
text: 'Scan QR Code',
onPress: () =>
this.props.navigation.navigate('ScanQRCode', {
launchedBy: this.props.navigation.state.routeName,
launchedBy: this.props.route.name,
onBarScanned: this.onBarCodeRead,
showFileImportButton: false,
}),
@ -555,7 +566,6 @@ export default class WalletsList extends Component {
render() {
return (
<View style={{ flex: 1 }}>
<NavigationEvents onDidFocus={this.onNavigationEventDidFocus} />
<View style={styles.walletsListWrapper}>
{this.renderNavigationHeader()}
<SectionList
@ -606,9 +616,11 @@ const styles = StyleSheet.create({
WalletsList.propTypes = {
navigation: PropTypes.shape({
state: PropTypes.shape({
routeName: PropTypes.string,
}),
navigate: PropTypes.func,
addListener: PropTypes.func,
}),
route: PropTypes.shape({
name: PropTypes.string,
params: PropTypes.object,
}),
};

View file

@ -15,8 +15,8 @@ export default class Marketplace extends Component {
constructor(props) {
super(props);
if (!props.navigation.getParam('fromWallet')) throw new Error('Invalid param');
let fromWallet = props.navigation.getParam('fromWallet');
if (!props.route.params.fromWallet) throw new Error('Invalid param');
let fromWallet = props.route.params.fromWallet;
this.state = {
url: '',
@ -73,8 +73,10 @@ export default class Marketplace extends Component {
Marketplace.propTypes = {
navigation: PropTypes.shape({
getParam: PropTypes.func,
navigate: PropTypes.func,
goBack: PropTypes.func,
}),
route: PropTypes.shape({
params: PropTypes.object,
}),
};

View file

@ -1,19 +1,20 @@
import React, { useEffect, useState, useCallback } from 'react';
import { ActivityIndicator, View, BackHandler, Text, ScrollView } from 'react-native';
import { useNavigation, useRoute } from '@react-navigation/native';
import { BlueSpacing20, SafeBlueArea, BlueNavigationStyle, BlueText, BlueButton } from '../../BlueComponents';
import Privacy from '../../Privacy';
import { useNavigation, useNavigationParam } from 'react-navigation-hooks';
const loc = require('../../loc');
const PleaseBackup = () => {
const [isLoading, setIsLoading] = useState(true);
const words = useNavigationParam('secret').split(' ');
const { dismiss } = useNavigation();
const route = useRoute();
const words = route.params.secret.split(' ');
const navigation = useNavigation();
const handleBackButton = useCallback(() => {
dismiss();
navigation.dangerouslyGetParent().pop();
return true;
}, [dismiss]);
}, [navigation]);
useEffect(() => {
Privacy.enableBlur();
@ -77,7 +78,7 @@ const PleaseBackup = () => {
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', flexWrap: 'wrap' }}>
<View style={{ flex: 1 }}>
<BlueSpacing20 />
<BlueButton testID="PleasebackupOk" onPress={dismiss} title={loc.pleasebackup.ok} />
<BlueButton testID="PleasebackupOk" onPress={handleBackButton} title={loc.pleasebackup.ok} />
</View>
</View>
</View>

View file

@ -1,5 +1,5 @@
import React, { useState } from 'react';
import { useNavigation, useNavigationParam } from 'react-navigation-hooks';
import { useNavigation, useRoute } from '@react-navigation/native';
import { View, Dimensions } from 'react-native';
import { SafeBlueArea, BlueSpacing20, BlueCopyTextToClipboard, BlueButton, BlueCard, BlueTextCentered } from '../../BlueComponents';
import QRCode from 'react-native-qrcode-svg';
@ -8,7 +8,7 @@ const { height, width } = Dimensions.get('window');
const BlueApp = require('../../BlueApp');
const PleaseBackupLNDHub = () => {
const wallet = useNavigationParam('wallet');
const { wallet } = useRoute().params;
const navigation = useNavigation();
const [qrCodeHeight, setQrCodeHeight] = useState(height > width ? width - 40 : width / 2);
@ -41,7 +41,7 @@ const PleaseBackupLNDHub = () => {
<BlueSpacing20 />
<BlueCopyTextToClipboard text={wallet.secret} />
<BlueSpacing20 />
<BlueButton onPress={navigation.dismiss} title="OK, I have saved it." />
<BlueButton onPress={() => navigation.dangerouslyGetParent().pop()} title="OK, I have saved it." />
</BlueCard>
</ScrollView>
</SafeBlueArea>

View file

@ -13,13 +13,13 @@ let BlueApp = require('../../BlueApp');
let loc = require('../../loc/');
export default class ReorderWallets extends Component {
static navigationOptions = ({ navigation }) => ({
static navigationOptions = ({ navigation, route }) => ({
...BlueNavigationStyle(
navigation,
true,
navigation.getParam('customCloseButtonFunction') ? navigation.state.params.customCloseButtonFunction : undefined,
route.params && route.params.customCloseButtonFunction ? route.params.customCloseButtonFunction : undefined,
),
title: loc.wallets.reorder.title,
headerTitle: loc.wallets.reorder.title,
});
constructor(props) {
@ -44,9 +44,9 @@ export default class ReorderWallets extends Component {
setTimeout(function() {
EV(EV.enum.WALLETS_COUNT_CHANGED);
}, 500); // adds some animaton
this.props.navigation.dismiss();
this.props.navigation.goBack();
} else {
this.props.navigation.dismiss();
this.props.navigation.goBack();
}
},
});
@ -180,6 +180,6 @@ ReorderWallets.propTypes = {
navigation: PropTypes.shape({
navigate: PropTypes.func,
setParams: PropTypes.func,
dismiss: PropTypes.func,
goBack: PropTypes.func,
}),
};

View file

@ -6,15 +6,13 @@ import LinearGradient from 'react-native-linear-gradient';
import { LightningCustodianWallet } from '../../class/wallets/lightning-custodian-wallet';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import WalletGradient from '../../class/wallet-gradient';
import { useNavigationParam } from 'react-navigation-hooks';
import { useRoute } from '@react-navigation/native';
/** @type {AppStorage} */
const BlueApp = require('../../BlueApp');
const loc = require('../../loc');
const SelectWallet = () => {
const chainType = useNavigationParam('chainType');
const onWalletSelect = useNavigationParam('onWalletSelect');
const availableWallets = useNavigationParam('availableWallets');
const { chainType, onWalletSelect, availableWallets } = useRoute().params;
const [isLoading, setIsLoading] = useState(true);
let data = chainType
? BlueApp.getWallets().filter(item => item.chain === chainType && item.allowSend())

View file

@ -20,7 +20,6 @@ import {
Clipboard,
} from 'react-native';
import PropTypes from 'prop-types';
import { NavigationEvents } from 'react-navigation';
import ImagePicker from 'react-native-image-picker';
import {
BlueSendButtonIcon,
@ -46,28 +45,31 @@ let BlueElectrum = require('../../BlueElectrum');
const LocalQRCode = require('@remobile/react-native-qrcode-local-image');
export default class WalletTransactions extends Component {
static navigationOptions = ({ navigation }) => {
static navigationOptions = ({ navigation, route }) => {
return {
headerRight: (
headerRight: () => (
<TouchableOpacity
disabled={navigation.getParam('isLoading') === true}
disabled={route.params.isLoading === true}
style={{ marginHorizontal: 16, minWidth: 150, justifyContent: 'center', alignItems: 'flex-end' }}
onPress={() =>
navigation.navigate('WalletDetails', {
wallet: navigation.state.params.wallet,
wallet: route.params.wallet,
})
}
>
<Icon name="kebab-horizontal" type="octicon" size={22} color="#FFFFFF" />
</TouchableOpacity>
),
headerTitle: () => null,
headerStyle: {
backgroundColor: WalletGradient.headerColorFor(navigation.state.params.wallet.type),
backgroundColor: WalletGradient.headerColorFor(route.params.wallet.type),
borderBottomWidth: 0,
elevation: 0,
shadowRadius: 0,
// shadowRadius: 0,
shadowOffset: { height: 0, width: 0 },
},
headerTintColor: '#FFFFFF',
headerBackTitleVisible: false,
};
};
@ -78,7 +80,7 @@ export default class WalletTransactions extends Component {
// here, when we receive REMOTE_TRANSACTIONS_COUNT_CHANGED we fetch TXs and balance for current wallet
EV(EV.enum.REMOTE_TRANSACTIONS_COUNT_CHANGED, this.refreshTransactionsFunction.bind(this), true);
const wallet = props.navigation.getParam('wallet');
const wallet = props.route.params.wallet;
this.props.navigation.setParams({ wallet: wallet, isLoading: true });
this.state = {
isHandOffUseEnabled: false,
@ -100,6 +102,14 @@ export default class WalletTransactions extends Component {
}, 60000);
const isHandOffUseEnabled = await HandoffSettings.isHandoffUseEnabled();
this.setState({ isHandOffUseEnabled });
this._unsubscribeFocus = this.props.navigation.addListener('focus', () => {
StatusBar.setBarStyle('light-content');
if (Platform.OS === 'android') StatusBar.setBackgroundColor(WalletGradient.headerColorFor(this.props.route.params.wallet.type));
this.redrawScreen();
this.props.navigation.setParams({ isLoading: false });
});
this._unsubscribeBlur = this.props.navigation.addListener('blur', this.onWillBlur);
}
/**
@ -120,7 +130,7 @@ export default class WalletTransactions extends Component {
* @returns {Array}
*/
getTransactions(limit = Infinity) {
let wallet = this.props.navigation.getParam('wallet');
let wallet = this.props.route.params.wallet;
let txs = wallet.getTransactions();
for (let tx of txs) {
@ -230,7 +240,7 @@ export default class WalletTransactions extends Component {
- Shows Marketplace button to open in browser (iOS)
The idea is to avoid showing on iOS an appstore/market style app that goes against the TOS.
*/}
{this.state.wallet.getTransactions().length > 0 &&
this.state.wallet.type !== LightningCustodianWallet.type &&
@ -446,10 +456,13 @@ export default class WalletTransactions extends Component {
return alert(Err.message);
}
}
this.props.navigation.navigate('SendDetails', {
memo: loc.lnd.refill_lnd_balance,
address: toAddress,
fromWallet: wallet,
this.props.navigation.navigate('SendDetailsRoot', {
screen: 'SendDetails',
params: {
memo: loc.lnd.refill_lnd_balance,
address: toAddress,
fromWallet: wallet,
},
});
}
};
@ -462,11 +475,16 @@ export default class WalletTransactions extends Component {
componentWillUnmount() {
this.onWillBlur();
clearInterval(this.interval);
this._unsubscribeFocus();
this._unsubscribeBlur();
}
navigateToSendScreen = () => {
this.props.navigation.navigate('SendDetails', {
fromWallet: this.state.wallet,
this.props.navigation.navigate('SendDetailsRoot', {
screen: 'SendDetails',
params: {
fromWallet: this.state.wallet,
},
});
};
@ -486,12 +504,17 @@ export default class WalletTransactions extends Component {
if (!this.state.isLoading) {
this.setState({ isLoading: true }, () => {
this.setState({ isLoading: false });
this.props.navigation.navigate(this.state.wallet.chain === Chain.ONCHAIN ? 'SendDetails' : 'ScanLndInvoice', {
const params = {
fromSecret: this.state.wallet.getSecret(),
// ScanLndInvoice actrually uses `fromSecret` so keeping it for now
uri: ret.data ? ret.data : ret,
fromWallet: this.state.wallet,
});
};
if (this.state.wallet.chain === Chain.ONCHAIN) {
this.props.navigation.navigate('SendDetailsRoot', { screen: 'SendDetails', params });
} else {
this.props.navigation.navigate('ScanLndInvoiceRoot', { screen: 'ScanLndInvoice', params });
}
});
}
};
@ -534,7 +557,7 @@ export default class WalletTransactions extends Component {
this.choosePhoto();
} else if (buttonIndex === 2) {
this.props.navigation.navigate('ScanQRCode', {
launchedBy: this.props.navigation.state.routeName,
launchedBy: this.props.route.name,
onBarScanned: this.onBarCodeRead,
showFileImportButton: false,
});
@ -557,7 +580,7 @@ export default class WalletTransactions extends Component {
text: 'Scan QR Code',
onPress: () =>
this.props.navigation.navigate('ScanQRCode', {
launchedBy: this.props.navigation.state.routeName,
launchedBy: this.props.route.name,
onBarScanned: this.onBarCodeRead,
showFileImportButton: false,
}),
@ -588,15 +611,6 @@ export default class WalletTransactions extends Component {
url={`https://blockpath.com/search/addr?q=${this.state.wallet.getXpub()}`}
/>
)}
<NavigationEvents
onWillFocus={navigation => {
StatusBar.setBarStyle('light-content');
if (Platform.OS === 'android') StatusBar.setBackgroundColor(WalletGradient.headerColorFor(navigation.state.params.wallet.type));
this.redrawScreen();
}}
onWillBlur={() => this.onWillBlur()}
onDidFocus={() => this.props.navigation.setParams({ isLoading: false })}
/>
<BlueWalletNavigationHeader
wallet={this.state.wallet}
onWalletUnitChange={wallet =>
@ -730,7 +744,7 @@ export default class WalletTransactions extends Component {
<BlueReceiveButtonIcon
onPress={() => {
if (this.state.wallet.chain === Chain.OFFCHAIN) {
navigate('LNDCreateInvoice', { fromWallet: this.state.wallet });
navigate('LNDCreateInvoiceRoot', { screen: 'LNDCreateInvoice', params: { fromWallet: this.state.wallet } });
} else {
navigate('ReceiveDetails', { secret: this.state.wallet.getSecret() });
}
@ -752,7 +766,7 @@ export default class WalletTransactions extends Component {
onLongPress={this.sendButtonLongPress}
onPress={() => {
if (this.state.wallet.chain === Chain.OFFCHAIN) {
navigate('ScanLndInvoice', { fromSecret: this.state.wallet.getSecret() });
navigate('ScanLndInvoiceRoot', { screen: 'ScanLndInvoice', params: { fromSecret: this.state.wallet.getSecret() } });
} else {
if (
this.state.wallet.type === WatchOnlyWallet.type &&
@ -829,10 +843,11 @@ WalletTransactions.propTypes = {
navigation: PropTypes.shape({
navigate: PropTypes.func,
goBack: PropTypes.func,
getParam: PropTypes.func,
setParams: PropTypes.func,
state: PropTypes.shape({
routeName: PropTypes.string,
}),
addListener: PropTypes.func,
}),
route: PropTypes.shape({
name: PropTypes.string,
params: PropTypes.object,
}),
};

View file

@ -20,7 +20,7 @@ export default class WalletXpub extends Component {
constructor(props) {
super(props);
let secret = props.navigation.state.params.secret;
let secret = props.route.params.secret;
let wallet;
for (let w of BlueApp.getWallets()) {
@ -100,12 +100,13 @@ export default class WalletXpub extends Component {
WalletXpub.propTypes = {
navigation: PropTypes.shape({
state: PropTypes.shape({
params: PropTypes.shape({
secret: PropTypes.string,
}),
}),
navigate: PropTypes.func,
goBack: PropTypes.func,
}),
route: PropTypes.shape({
name: PropTypes.string,
params: PropTypes.shape({
secret: PropTypes.string,
}),
}),
};

View file

@ -75,80 +75,81 @@ describe('unit - DeepLinkSchemaMatch', function() {
const events = [
{
argument: { url: '12eQ9m4sgAwTSQoNXkRABKhCXCsjm2jdVG' },
expected: {
routeName: 'SendDetails',
params: {
uri: '12eQ9m4sgAwTSQoNXkRABKhCXCsjm2jdVG',
},
},
expected: ['SendDetailsRoot', { screen: 'SendDetails', params: { uri: '12eQ9m4sgAwTSQoNXkRABKhCXCsjm2jdVG' } }],
},
{
argument: { url: 'bitcoin:12eQ9m4sgAwTSQoNXkRABKhCXCsjm2jdVG' },
expected: {
routeName: 'SendDetails',
params: {
uri: 'bitcoin:12eQ9m4sgAwTSQoNXkRABKhCXCsjm2jdVG',
},
},
expected: ['SendDetailsRoot', { screen: 'SendDetails', params: { uri: 'bitcoin:12eQ9m4sgAwTSQoNXkRABKhCXCsjm2jdVG' } }],
},
{
argument: { url: 'BITCOIN:BC1Q3RL0MKYK0ZRTXFMQN9WPCD3GNAZ00YV9YP0HXE?amount=666&label=Yo' },
expected: {
routeName: 'SendDetails',
params: {
uri: 'BITCOIN:BC1Q3RL0MKYK0ZRTXFMQN9WPCD3GNAZ00YV9YP0HXE?amount=666&label=Yo',
},
},
expected: [
'SendDetailsRoot',
{ screen: 'SendDetails', params: { uri: 'BITCOIN:BC1Q3RL0MKYK0ZRTXFMQN9WPCD3GNAZ00YV9YP0HXE?amount=666&label=Yo' } },
],
},
{
argument: { url: 'bluewallet:BITCOIN:BC1Q3RL0MKYK0ZRTXFMQN9WPCD3GNAZ00YV9YP0HXE?amount=666&label=Yo' },
expected: {
routeName: 'SendDetails',
params: {
uri: 'BITCOIN:BC1Q3RL0MKYK0ZRTXFMQN9WPCD3GNAZ00YV9YP0HXE?amount=666&label=Yo',
},
},
expected: [
'SendDetailsRoot',
{ screen: 'SendDetails', params: { uri: 'BITCOIN:BC1Q3RL0MKYK0ZRTXFMQN9WPCD3GNAZ00YV9YP0HXE?amount=666&label=Yo' } },
],
},
{
argument: {
url:
'lightning:lnbc10u1pwjqwkkpp5vlc3tttdzhpk9fwzkkue0sf2pumtza7qyw9vucxyyeh0yaqq66yqdq5f38z6mmwd3ujqar9wd6qcqzpgxq97zvuqrzjqvgptfurj3528snx6e3dtwepafxw5fpzdymw9pj20jj09sunnqmwqz9hx5qqtmgqqqqqqqlgqqqqqqgqjq5duu3fs9xq9vn89qk3ezwpygecu4p3n69wm3tnl28rpgn2gmk5hjaznemw0gy32wrslpn3g24khcgnpua9q04fttm2y8pnhmhhc2gncplz0zde',
},
expected: {
routeName: 'ScanLndInvoice',
params: {
uri:
'lightning:lnbc10u1pwjqwkkpp5vlc3tttdzhpk9fwzkkue0sf2pumtza7qyw9vucxyyeh0yaqq66yqdq5f38z6mmwd3ujqar9wd6qcqzpgxq97zvuqrzjqvgptfurj3528snx6e3dtwepafxw5fpzdymw9pj20jj09sunnqmwqz9hx5qqtmgqqqqqqqlgqqqqqqgqjq5duu3fs9xq9vn89qk3ezwpygecu4p3n69wm3tnl28rpgn2gmk5hjaznemw0gy32wrslpn3g24khcgnpua9q04fttm2y8pnhmhhc2gncplz0zde',
expected: [
'ScanLndInvoiceRoot',
{
screen: 'ScanLndInvoice',
params: {
uri:
'lightning:lnbc10u1pwjqwkkpp5vlc3tttdzhpk9fwzkkue0sf2pumtza7qyw9vucxyyeh0yaqq66yqdq5f38z6mmwd3ujqar9wd6qcqzpgxq97zvuqrzjqvgptfurj3528snx6e3dtwepafxw5fpzdymw9pj20jj09sunnqmwqz9hx5qqtmgqqqqqqqlgqqqqqqgqjq5duu3fs9xq9vn89qk3ezwpygecu4p3n69wm3tnl28rpgn2gmk5hjaznemw0gy32wrslpn3g24khcgnpua9q04fttm2y8pnhmhhc2gncplz0zde',
},
},
},
],
},
{
argument: {
url:
'bluewallet:lightning:lnbc10u1pwjqwkkpp5vlc3tttdzhpk9fwzkkue0sf2pumtza7qyw9vucxyyeh0yaqq66yqdq5f38z6mmwd3ujqar9wd6qcqzpgxq97zvuqrzjqvgptfurj3528snx6e3dtwepafxw5fpzdymw9pj20jj09sunnqmwqz9hx5qqtmgqqqqqqqlgqqqqqqgqjq5duu3fs9xq9vn89qk3ezwpygecu4p3n69wm3tnl28rpgn2gmk5hjaznemw0gy32wrslpn3g24khcgnpua9q04fttm2y8pnhmhhc2gncplz0zde',
},
expected: {
routeName: 'ScanLndInvoice',
params: {
uri:
'lightning:lnbc10u1pwjqwkkpp5vlc3tttdzhpk9fwzkkue0sf2pumtza7qyw9vucxyyeh0yaqq66yqdq5f38z6mmwd3ujqar9wd6qcqzpgxq97zvuqrzjqvgptfurj3528snx6e3dtwepafxw5fpzdymw9pj20jj09sunnqmwqz9hx5qqtmgqqqqqqqlgqqqqqqgqjq5duu3fs9xq9vn89qk3ezwpygecu4p3n69wm3tnl28rpgn2gmk5hjaznemw0gy32wrslpn3g24khcgnpua9q04fttm2y8pnhmhhc2gncplz0zde',
expected: [
'ScanLndInvoiceRoot',
{
screen: 'ScanLndInvoice',
params: {
uri:
'lightning:lnbc10u1pwjqwkkpp5vlc3tttdzhpk9fwzkkue0sf2pumtza7qyw9vucxyyeh0yaqq66yqdq5f38z6mmwd3ujqar9wd6qcqzpgxq97zvuqrzjqvgptfurj3528snx6e3dtwepafxw5fpzdymw9pj20jj09sunnqmwqz9hx5qqtmgqqqqqqqlgqqqqqqgqjq5duu3fs9xq9vn89qk3ezwpygecu4p3n69wm3tnl28rpgn2gmk5hjaznemw0gy32wrslpn3g24khcgnpua9q04fttm2y8pnhmhhc2gncplz0zde',
},
},
},
],
},
{
argument: {
url: 'https://azte.co/?c1=3062&c2=2586&c3=5053&c4=5261',
},
expected: {
routeName: 'AztecoRedeem',
params: {
uri: 'https://azte.co/?c1=3062&c2=2586&c3=5053&c4=5261',
c1: '3062',
c2: '2586',
c3: '5053',
c4: '5261',
expected: [
'AztecoRedeemRoot',
{
screen: 'AztecoRedeem',
params: { c1: '3062', c2: '2586', c3: '5053', c4: '5261', uri: 'https://azte.co/?c1=3062&c2=2586&c3=5053&c4=5261' },
},
],
},
{
argument: {
url: 'https://azte.co/?c1=3062&c2=2586&c3=5053&c4=5261',
},
expected: [
'AztecoRedeemRoot',
{
screen: 'AztecoRedeem',
params: { c1: '3062', c2: '2586', c3: '5053', c4: '5261', uri: 'https://azte.co/?c1=3062&c2=2586&c3=5053&c4=5261' },
},
],
},
];