diff --git a/App.js b/App.js index 757362e0..aeb3f2d1 100644 --- a/App.js +++ b/App.js @@ -2,6 +2,7 @@ import React from 'react'; import { Linking } from 'react-native'; import { NavigationActions } from 'react-navigation'; import MainBottomTabs from './MainBottomTabs'; +import NavigationService from './NavigationService'; export default class App extends React.Component { navigator = null; @@ -53,6 +54,7 @@ export default class App extends React.Component { { this.navigator = nav; + NavigationService.setTopLevelNavigator(nav); }} /> ); diff --git a/BlueComponents.js b/BlueComponents.js index d0dfa1b4..26818ce0 100644 --- a/BlueComponents.js +++ b/BlueComponents.js @@ -29,6 +29,7 @@ import { HDLegacyBreadwalletWallet } from './class/hd-legacy-breadwallet-wallet' import { HDSegwitP2SHWallet } from './class/hd-segwit-p2sh-wallet'; import { LightningCustodianWallet } from './class/lightning-custodian-wallet'; import { BitcoinUnit } from './models/bitcoinUnits'; +import NavigationService from './NavigationService'; let loc = require('./loc/'); /** @type {AppStorage} */ let BlueApp = require('./BlueApp'); @@ -1167,6 +1168,71 @@ export class WalletsCarousel extends Component { } } +export class BlueAddressInput extends Component { + static propTypes = { + isLoading: PropTypes.bool, + onChangeText: PropTypes.func, + onBarScanned: PropTypes.func, + address: PropTypes.string, + }; + + static defaultProps = { + isLoading: false, + address: '', + }; + + render() { + return ( + + { + this.props.onChangeText(text); + }} + placeholder={loc.send.details.address} + numberOfLines={1} + value={this.props.address} + style={{ flex: 1, marginHorizontal: 8, minHeight: 33 }} + editable={!this.props.isLoading} + /> + NavigationService.navigate('ScanQrAddress', { onBarScanned: this.props.onBarScanned })} + style={{ + width: 75, + height: 36, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + backgroundColor: '#bebebe', + borderRadius: 4, + paddingVertical: 4, + paddingHorizontal: 8, + marginHorizontal: 4, + }} + > + + {loc.send.details.scan} + + + ); + } +} + export class BlueBitcoinAmount extends Component { static propTypes = { isLoading: PropTypes.bool, diff --git a/NavigationService.js b/NavigationService.js new file mode 100644 index 00000000..03c95e75 --- /dev/null +++ b/NavigationService.js @@ -0,0 +1,25 @@ +// NavigationService.js + +import { NavigationActions } from 'react-navigation'; + +let _navigator; + +function setTopLevelNavigator(navigatorRef) { + _navigator = navigatorRef; +} + +function navigate(routeName, params) { + _navigator.dispatch( + NavigationActions.navigate({ + routeName, + params, + }), + ); +} + +// add other navigation functions that you need and export them + +export default { + navigate, + setTopLevelNavigator, +}; diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index f0a8fbef..6cf99bf9 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -1,3 +1,3 @@ - BlueWallet + Blue Wallet diff --git a/events.js b/events.js index aae3fe3e..92f46a9e 100644 --- a/events.js +++ b/events.js @@ -36,10 +36,6 @@ EV.enum = { // changed (usually for current wallet) REMOTE_TRANSACTIONS_COUNT_CHANGED: 'REMOTE_TRANSACTIONS_COUNT_CHANGED', - // emitted when QR scanner scanned address that should be used in CREATE TRANSACTION screen - // thus, previous screen (CREATE TRANSACTION screen) will update it's input content - CREATE_TRANSACTION_NEW_DESTINATION_ADDRESS: 'CREATE_TRANSACTION_NEW_DESTINATION_ADDRESS', - // RECEIVE_ADDRESS_CHANGED: 'RECEIVE_ADDRESS_CHANGED', }; diff --git a/ios/BlueWallet/Info.plist b/ios/BlueWallet/Info.plist index 3e2d98c3..fc20a80b 100644 --- a/ios/BlueWallet/Info.plist +++ b/ios/BlueWallet/Info.plist @@ -5,7 +5,7 @@ CFBundleDevelopmentRegion en CFBundleDisplayName - BlueWallet + Blue Wallet CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier diff --git a/package-lock.json b/package-lock.json index bc7ea09c..31d1e1ea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9584,9 +9584,9 @@ } }, "react-native-svg": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-9.0.2.tgz", - "integrity": "sha512-WXX/EuRzeWjBK3xmuxFvZQiJQLM0uUFQnpjNhFhD05nyF7YU/EGTZY4yZ8qTamhbvn7TW0opqaMtxaG7m0wpUg==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-9.0.3.tgz", + "integrity": "sha512-lGhwMQaS3QuRTmLV7Et7ntOhrYfgNpJJn0YyMwSu6umfvVGW5ghFiZkOH4b7DaSfH8+uzy5DZL2RdEH+6C5mOw==", "requires": { "color": "^2.0.1" } diff --git a/package.json b/package.json index a57d41f5..5bc0b68c 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "react-native-sentry": "^0.40.2", "react-native-snap-carousel": "^3.7.4", "react-native-sortable-list": "0.0.22", - "react-native-svg": "^9.0.2", + "react-native-svg": "^9.0.3", "react-native-vector-icons": "^6.2.0", "react-native-webview": "2.8.0", "react-native-wkwebview-reborn": "^2.0.0", diff --git a/screen/lnd/scanLndInvoice.js b/screen/lnd/scanLndInvoice.js index e8a216c3..30341847 100644 --- a/screen/lnd/scanLndInvoice.js +++ b/screen/lnd/scanLndInvoice.js @@ -1,9 +1,16 @@ /* global alert */ import React from 'react'; -import { Text, Dimensions, ActivityIndicator, View, TouchableOpacity, TouchableWithoutFeedback, TextInput, Keyboard } from 'react-native'; -import { Icon } from 'react-native-elements'; +import { Text, Dimensions, ActivityIndicator, View, TouchableWithoutFeedback, Keyboard } from 'react-native'; import PropTypes from 'prop-types'; -import { BlueSpacing20, BlueButton, SafeBlueArea, BlueCard, BlueNavigationStyle, BlueBitcoinAmount } from '../../BlueComponents'; +import { + BlueSpacing20, + BlueButton, + SafeBlueArea, + BlueCard, + BlueNavigationStyle, + BlueAddressInput, + BlueBitcoinAmount, +} from '../../BlueComponents'; import { LightningCustodianWallet } from '../../class/lightning-custodian-wallet'; import { BitcoinUnit } from '../../models/bitcoinUnits'; /** @type {AppStorage} */ @@ -59,20 +66,13 @@ export default class ScanLndInvoice extends React.Component { } async componentDidMount() { - EV( - EV.enum.CREATE_TRANSACTION_NEW_DESTINATION_ADDRESS, - data => { - this.processInvoice(data); - }, - true, - ); - if (this.props.navigation.state.params.uri) { this.processTextForInvoice(this.props.navigation.getParam('uri')); } } - processInvoice(data) { + processInvoice = data => { + this.props.navigation.goBack(null); this.setState({ isLoading: true }, async () => { if (this.ignoreRead) return; this.ignoreRead = true; @@ -122,7 +122,7 @@ export default class ScanLndInvoice extends React.Component { alert(Err.message); } }); - } + }; async pay() { if (!this.state.hasOwnProperty('decoded')) { @@ -212,53 +212,14 @@ export default class ScanLndInvoice extends React.Component { /> - { + this.setState({ destination: text }); + this.processTextForInvoice(text); }} - > - { - this.setState({ destination: text }); - this.processTextForInvoice(text); - }} - placeholder={loc.wallets.details.destination} - numberOfLines={1} - value={this.state.destination} - style={{ flex: 1, marginHorizontal: 8, minHeight: 33, height: 33 }} - editable={!this.state.isLoading} - /> - this.props.navigation.navigate('ScanQrAddress')} - style={{ - width: 75, - height: 36, - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - backgroundColor: '#bebebe', - borderRadius: 4, - paddingVertical: 4, - paddingHorizontal: 8, - marginHorizontal: 4, - }} - > - - {loc.send.details.scan} - - + onBarScanned={this.processInvoice} + address={this.state.destination} + /> { - this.setState( - { isLoading: false }, - () => { + processAddressData = data => { + this.props.navigation.goBack(null); + this.setState( + { isLoading: true }, + () => { + console.warn(data); + if (BitcoinBIP70TransactionDecode.matchesPaymentURL(data)) { + this.processBIP70Invoice(data); + } else { data = data.replace('bitcoin:', ''); if (btcAddressRx.test(data) || data.indexOf('bc1') === 0) { this.setState({ @@ -112,14 +115,15 @@ export default class SendDetails extends Component { bip70TransactionExpiration: null, isLoading: false, }); - } else if (BitcoinBIP70TransactionDecode.matchesPaymentURL(data)) { - this.processBIP70Invoice(data); } } - }, - true, - ); - }); + } + }, + true, + ); + }; + + async componentDidMount() { let recommendedFees = await NetworkTransactionFees.recommendedFees().catch(response => { this.setState({ fee: response.halfHourFee, @@ -497,56 +501,17 @@ export default class SendDetails extends Component { amount={this.state.amount} onChangeText={text => this.setState({ amount: text })} /> - { + if (!this.processBIP70Invoice(text)) { + this.setState({ address: text.replace(' ', ''), isLoading: false, bip70TransactionExpiration: null }); + } else { + this.setState({ address: text.replace(' ', ''), isLoading: false, bip70TransactionExpiration: null }); + } }} - > - { - if (!this.processBIP70Invoice(text)) { - this.setState({ address: text.replace(' ', ''), isLoading: false, bip70TransactionExpiration: null }); - } else { - this.setState({ address: text.replace(' ', ''), isLoading: false, bip70TransactionExpiration: null }); - } - }} - placeholder={loc.send.details.address} - numberOfLines={1} - value={this.state.address} - style={{ flex: 1, marginHorizontal: 8, minHeight: 33 }} - editable={!this.state.isLoading} - /> - this.props.navigation.navigate('ScanQrAddress')} - style={{ - width: 75, - height: 36, - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - backgroundColor: '#bebebe', - borderRadius: 4, - paddingVertical: 4, - paddingHorizontal: 8, - marginHorizontal: 4, - }} - > - - {loc.send.details.scan} - - + onBarScanned={this.processAddressData} + address={this.state.address} + /> { // Response is one of: 'authorized', 'denied', 'restricted', or 'undetermined' this.setState({ hasCameraPermission: response === 'authorized' }); }); + + // For testing in Simulator + // const onBarScanned = this.props.navigation.getParam('onBarScanned'); + // onBarScanned('lnbc4223u1pwyj632pp5f2m0rpyflj9dx4a3kljkts6xadjfeuplcfkqz8lecnmjfpl75wyqdphgf5hgun9ve5kcmpqx43ngwfkvyexzwf3xcurvvpsxqcrgefcx3nxgdqcqzysxqr8pqfppjec6wr6uvxqz2dc75f8c9x2u0h6a88f9jzn04eyg7v73at8r8q4h0649h97xr8ukq858xnhumfdw8gecqgr7jac6znpjhdpe6lgymjrwvjwr0ns38ptd5lssvqja2knmlpuz2kssp8v3cst'); + // } render() { @@ -70,7 +74,8 @@ export default class CameraExample extends React.Component { CameraExample.propTypes = { navigation: PropTypes.shape({ - goBack: PropTypes.function, - dismiss: PropTypes.function, + goBack: PropTypes.func, + dismiss: PropTypes.func, + getParam: PropTypes.func, }), };