Browse Source

ADD: Created BlueAddressInput

pulltorefresh
Marcos Rodriguez Vélez 6 years ago
parent
commit
f4d448b4b3
  1. 2
      App.js
  2. 66
      BlueComponents.js
  3. 25
      NavigationService.js
  4. 2
      android/app/src/main/res/values/strings.xml
  5. 4
      events.js
  6. 2
      ios/BlueWallet/Info.plist
  7. 6
      package-lock.json
  8. 2
      package.json
  9. 71
      screen/lnd/scanLndInvoice.js
  10. 65
      screen/send/details.js
  11. 17
      screen/send/scanQrAddress.js

2
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 {
<MainBottomTabs
ref={nav => {
this.navigator = nav;
NavigationService.setTopLevelNavigator(nav);
}}
/>
);

66
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 (
<View
style={{
flexDirection: 'row',
borderColor: '#d2d2d2',
borderBottomColor: '#d2d2d2',
borderWidth: 1.0,
borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5',
minHeight: 44,
height: 44,
marginHorizontal: 20,
alignItems: 'center',
marginVertical: 8,
borderRadius: 4,
}}
>
<TextInput
onChangeText={text => {
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}
/>
<TouchableOpacity
disabled={this.props.isLoading}
onPress={() => 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,
}}
>
<Icon name="qrcode" size={22} type="font-awesome" color="#FFFFFF" />
<Text style={{ color: '#FFFFFF' }}>{loc.send.details.scan}</Text>
</TouchableOpacity>
</View>
);
}
}
export class BlueBitcoinAmount extends Component {
static propTypes = {
isLoading: PropTypes.bool,

25
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,
};

2
android/app/src/main/res/values/strings.xml

@ -1,3 +1,3 @@
<resources>
<string name="app_name">BlueWallet</string>
<string name="app_name">Blue Wallet</string>
</resources>

4
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',
};

2
ios/BlueWallet/Info.plist

@ -5,7 +5,7 @@
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>BlueWallet</string>
<string>Blue Wallet</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>

6
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"
}

2
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",

71
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 {
/>
<BlueSpacing20 />
<BlueCard>
<View
style={{
flexDirection: 'row',
borderColor: '#d2d2d2',
borderBottomColor: '#d2d2d2',
borderWidth: 1.0,
borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5',
minHeight: 44,
height: 44,
marginHorizontal: 20,
alignItems: 'center',
marginVertical: 8,
borderRadius: 4,
}}
>
<TextInput
<BlueAddressInput
onChangeText={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}
onBarScanned={this.processInvoice}
address={this.state.destination}
/>
<TouchableOpacity
disabled={this.state.isLoading}
onPress={() => 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,
}}
>
<Icon name="qrcode" size={22} type="font-awesome" color="#FFFFFF" />
<Text style={{ color: '#FFFFFF' }}>{loc.send.details.scan}</Text>
</TouchableOpacity>
</View>
<View
style={{
flexDirection: 'row',

65
screen/send/details.js

@ -14,7 +14,7 @@ import {
Text,
} from 'react-native';
import { Icon } from 'react-native-elements';
import { BlueNavigationStyle, BlueButton, BlueBitcoinAmount } from '../../BlueComponents';
import { BlueNavigationStyle, BlueButton, BlueBitcoinAmount, BlueAddressInput } from '../../BlueComponents';
import PropTypes from 'prop-types';
import Modal from 'react-native-modal';
import NetworkTransactionFees, { NetworkTransactionFee } from '../../models/networkTransactionFees';
@ -23,7 +23,6 @@ import { BitcoinUnit } from '../../models/bitcoinUnits';
import { HDLegacyP2PKHWallet, HDSegwitP2SHWallet } from '../../class';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
const bip21 = require('bip21');
let EV = require('../../events');
let BigNumber = require('bignumber.js');
/** @type {AppStorage} */
let BlueApp = require('../../BlueApp');
@ -82,11 +81,15 @@ export default class SendDetails extends Component {
};
}
async componentDidMount() {
EV(EV.enum.CREATE_TRANSACTION_NEW_DESTINATION_ADDRESS, data => {
processAddressData = data => {
this.props.navigation.goBack(null);
this.setState(
{ isLoading: false },
{ 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,
);
});
};
async componentDidMount() {
let recommendedFees = await NetworkTransactionFees.recommendedFees().catch(response => {
this.setState({
fee: response.halfHourFee,
@ -497,23 +501,7 @@ export default class SendDetails extends Component {
amount={this.state.amount}
onChangeText={text => this.setState({ amount: text })}
/>
<View
style={{
flexDirection: 'row',
borderColor: '#d2d2d2',
borderBottomColor: '#d2d2d2',
borderWidth: 1.0,
borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5',
minHeight: 44,
height: 44,
marginHorizontal: 20,
alignItems: 'center',
marginVertical: 8,
borderRadius: 4,
}}
>
<TextInput
<BlueAddressInput
onChangeText={text => {
if (!this.processBIP70Invoice(text)) {
this.setState({ address: text.replace(' ', ''), isLoading: false, bip70TransactionExpiration: null });
@ -521,32 +509,9 @@ export default class SendDetails extends Component {
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}
onBarScanned={this.processAddressData}
address={this.state.address}
/>
<TouchableOpacity
disabled={this.state.isLoading}
onPress={() => 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,
}}
>
<Icon name="qrcode" size={22} type="font-awesome" color="#FFFFFF" />
<Text style={{ color: '#FFFFFF' }}>{loc.send.details.scan}</Text>
</TouchableOpacity>
</View>
<View
hide={!this.state.showMemoRow}
style={{

17
screen/send/scanQrAddress.js

@ -5,7 +5,6 @@ import PropTypes from 'prop-types';
import Camera from 'react-native-camera';
import Permissions from 'react-native-permissions';
import { SafeBlueArea } from '../../BlueComponents';
let EV = require('../../events');
export default class CameraExample extends React.Component {
static navigationOptions = {
@ -24,15 +23,20 @@ export default class CameraExample extends React.Component {
this.ignoreRead = false;
}, 2000);
this.props.navigation.goBack();
EV(EV.enum.CREATE_TRANSACTION_NEW_DESTINATION_ADDRESS, ret.data);
const onBarScanned = this.props.navigation.getParam('onBarScanned');
onBarScanned(ret.data);
} // end
async componentDidMount() {
componentDidMount() {
Permissions.request('camera').then(response => {
// 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,
}),
};

Loading…
Cancel
Save