mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-02-20 14:05:27 +01:00
ADD: Created BlueAddressInput
This commit is contained in:
parent
536f43b473
commit
f4d448b4b3
11 changed files with 157 additions and 137 deletions
2
App.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);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -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
Normal file
25
NavigationService.js
Normal file
|
@ -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,
|
||||
};
|
|
@ -1,3 +1,3 @@
|
|||
<resources>
|
||||
<string name="app_name">BlueWallet</string>
|
||||
<string name="app_name">Blue Wallet</string>
|
||||
</resources>
|
||||
|
|
|
@ -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',
|
||||
};
|
||||
|
||||
|
|
|
@ -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
generated
6
package-lock.json
generated
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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,
|
||||
<BlueAddressInput
|
||||
onChangeText={text => {
|
||||
this.setState({ destination: text });
|
||||
this.processTextForInvoice(text);
|
||||
}}
|
||||
>
|
||||
<TextInput
|
||||
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}
|
||||
/>
|
||||
<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>
|
||||
onBarScanned={this.processInvoice}
|
||||
address={this.state.destination}
|
||||
/>
|
||||
<View
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
|
|
|
@ -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 => {
|
||||
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 })}
|
||||
/>
|
||||
<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,
|
||||
<BlueAddressInput
|
||||
onChangeText={text => {
|
||||
if (!this.processBIP70Invoice(text)) {
|
||||
this.setState({ address: text.replace(' ', ''), isLoading: false, bip70TransactionExpiration: null });
|
||||
} else {
|
||||
this.setState({ address: text.replace(' ', ''), isLoading: false, bip70TransactionExpiration: null });
|
||||
}
|
||||
}}
|
||||
>
|
||||
<TextInput
|
||||
onChangeText={text => {
|
||||
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}
|
||||
/>
|
||||
<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>
|
||||
onBarScanned={this.processAddressData}
|
||||
address={this.state.address}
|
||||
/>
|
||||
<View
|
||||
hide={!this.state.showMemoRow}
|
||||
style={{
|
||||
|
|
|
@ -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…
Add table
Reference in a new issue