import React, { Component } from 'react'; import { View, InteractionManager, Platform, TextInput, KeyboardAvoidingView, Keyboard, StyleSheet, ScrollView } from 'react-native'; import QRCode from 'react-native-qrcode-svg'; import bip21 from 'bip21'; import { BlueLoading, SafeBlueArea, BlueCopyTextToClipboard, BlueButton, BlueButtonLink, BlueNavigationStyle, is, BlueBitcoinAmount, BlueText, BlueSpacing20, BlueAlertWalletExportReminder, } from '../../BlueComponents'; import PropTypes from 'prop-types'; import Privacy from '../../Privacy'; import Share from 'react-native-share'; import { Chain, BitcoinUnit } from '../../models/bitcoinUnits'; import Modal from 'react-native-modal'; /** @type {AppStorage} */ const BlueApp = require('../../BlueApp'); const loc = require('../../loc'); export default class ReceiveDetails extends Component { static navigationOptions = ({ navigation }) => ({ ...BlueNavigationStyle(navigation, true), title: loc.receive.header, headerLeft: null, }); constructor(props) { super(props); let secret = props.navigation.state.params.secret || ''; this.state = { secret: secret, address: '', customLabel: '', customAmount: 0, bip21encoded: undefined, isCustom: false, isCustomModalVisible: false, }; } renderReceiveDetails = async () => { this.wallet.setUserHasSavedExport(true); await BlueApp.saveToDisk(); let address; if (this.wallet.getAddressAsync) { if (this.wallet.chain === Chain.ONCHAIN) { try { address = await Promise.race([this.wallet.getAddressAsync(), BlueApp.sleep(1000)]); } catch (_) {} if (!address) { // either sleep expired or getAddressAsync threw an exception console.warn('either sleep expired or getAddressAsync threw an exception'); address = this.wallet._getExternalAddressByIndex(this.wallet.next_free_address_index); } else { BlueApp.saveToDisk(); // caching whatever getAddressAsync() generated internally } this.setState({ address: address, }); } else if (this.wallet.chain === Chain.OFFCHAIN) { try { await Promise.race([this.wallet.getAddressAsync(), BlueApp.sleep(1000)]); address = this.wallet.getAddress(); } catch (_) {} if (!address) { // either sleep expired or getAddressAsync threw an exception console.warn('either sleep expired or getAddressAsync threw an exception'); address = this.wallet.getAddress(); } else { BlueApp.saveToDisk(); // caching whatever getAddressAsync() generated internally } } this.setState({ address: address, }); } else if (this.wallet.getAddress) { this.setState({ address: this.wallet.getAddress(), }); } InteractionManager.runAfterInteractions(async () => { const bip21encoded = bip21.encode(this.state.address); this.setState({ bip21encoded }); }); }; componentDidMount() { Privacy.enableBlur(); console.log('receive/details - componentDidMount'); for (let w of BlueApp.getWallets()) { if (w.getSecret() === this.state.secret) { // found our wallet this.wallet = w; } } if (this.wallet) { if (!this.wallet.getUserHasSavedExport()) { BlueAlertWalletExportReminder({ onSuccess: this.renderReceiveDetails, onFailure: () => { this.props.navigation.goBack(); this.props.navigation.navigate('WalletExport', { address: this.wallet.getAddress(), secret: this.wallet.getSecret(), }); }, }); } else { this.renderReceiveDetails(); } } } componentWillUnmount() { Privacy.disableBlur(); } renderCustomAmountModal = () => { return ( { Keyboard.dismiss(); this.setState({ isCustomModalVisible: false }); }} > this.setState({ customAmount: text })} /> this.setState({ customLabel: text })} placeholder={loc.receive.details.label} value={this.state.customLabel || ''} numberOfLines={1} style={{ flex: 1, marginHorizontal: 8, minHeight: 33 }} /> { this.setState({ isCustom: true, isCustomModalVisible: false, bip21encoded: bip21.encode(this.state.address, { amount: this.state.customAmount, label: this.state.customLabel }), }); }} /> { this.setState({ isCustom: false, isCustomModalVisible: false, customAmount: '', customLabel: '', bip21encoded: bip21.encode(this.state.addresss), }); }} /> ); }; showCustomAmountModal = () => { this.setState({ isCustomModalVisible: true }); }; render() { return ( {this.state.isCustom && ( <> {this.state.customAmount} {BitcoinUnit.BTC} {this.state.customLabel} )} {this.state.bip21encoded === undefined ? ( ) : ( (this.qrCodeSVG = c)} /> )} { if (this.qrCodeSVG === undefined) { Share.open({ message: this.state.bip21encoded }).catch(error => console.log(error)); } else { InteractionManager.runAfterInteractions(async () => { this.qrCodeSVG.toDataURL(data => { let shareImageBase64 = { message: this.state.bip21encoded, url: `data:image/png;base64,${data}`, }; Share.open(shareImageBase64).catch(error => console.log(error)); }); }); } }} title={loc.receive.details.share} /> {this.renderCustomAmountModal()} ); } } const styles = StyleSheet.create({ modalContent: { backgroundColor: '#FFFFFF', padding: 22, justifyContent: 'center', alignItems: 'center', borderTopLeftRadius: 16, borderTopRightRadius: 16, borderColor: 'rgba(0, 0, 0, 0.1)', minHeight: 350, height: 350, }, bottomModal: { justifyContent: 'flex-end', margin: 0, }, }); ReceiveDetails.propTypes = { navigation: PropTypes.shape({ goBack: PropTypes.func, navigate: PropTypes.func, state: PropTypes.shape({ params: PropTypes.shape({ secret: PropTypes.string, }), }), }), };