import React, { Component } from 'react'; import { View, Dimensions, Share, ScrollView, BackHandler } from 'react-native'; import { BlueLoading, BlueText, SafeBlueArea, BlueButton, BlueCopyTextToClipboard, BlueNavigationStyle, BlueSpacing20, } from '../../BlueComponents'; import PropTypes from 'prop-types'; import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; import { Icon } from 'react-native-elements'; /** @type {AppStorage} */ let BlueApp = require('../../BlueApp'); const loc = require('../../loc'); const EV = require('../../events'); const QRFast = require('react-native-qrcode'); const { width, height } = Dimensions.get('window'); export default class LNDViewInvoice extends Component { static navigationOptions = ({ navigation }) => navigation.getParam('isModal') === true ? { ...BlueNavigationStyle(navigation, true, () => navigation.dismiss()), title: 'Lightning Invoice', headerLeft: null, } : { ...BlueNavigationStyle(), title: 'Lightning Invoice' }; constructor(props) { super(props); const invoice = props.navigation.getParam('invoice'); const fromWallet = props.navigation.getParam('fromWallet'); this.state = { invoice, fromWallet, isLoading: typeof invoice === 'string', addressText: typeof invoice === 'object' && invoice.hasOwnProperty('payment_request') ? invoice.payment_request : invoice, isFetchingInvoices: true, qrCodeHeight: height > width ? width - 20 : width / 2, }; this.fetchInvoiceInterval = undefined; BackHandler.addEventListener('hardwareBackPress', this.handleBackButton); } async componentDidMount() { this.fetchInvoiceInterval = setInterval(async () => { if (this.state.isFetchingInvoices) { try { const userInvoices = await this.state.fromWallet.getUserInvoices(20); // fetching only last 20 invoices // for invoice that was created just now - that should be enough (it is basically the last one, so limit=1 would be sufficient) // but that might not work as intended IF user creates 21 invoices, and then tries to check the status of invoice #0, it just wont be updated const updatedUserInvoice = userInvoices.filter(invoice => typeof this.state.invoice === 'object' ? invoice.payment_request === this.state.invoice.payment_request : invoice.payment_request === this.state.invoice, )[0]; if (typeof updatedUserInvoice !== 'undefined') { this.setState({ invoice: updatedUserInvoice, isLoading: false, addressText: updatedUserInvoice.payment_request }); if (updatedUserInvoice.ispaid) { // we fetched the invoice, and it is paid :-) this.setState({ isFetchingInvoices: false }); ReactNativeHapticFeedback.trigger('notificationSuccess', false); clearInterval(this.fetchInvoiceInterval); this.fetchInvoiceInterval = undefined; EV(EV.enum.TRANSACTIONS_COUNT_CHANGED); } else { const currentDate = new Date(); const now = (currentDate.getTime() / 1000) | 0; const invoiceExpiration = updatedUserInvoice.timestamp + updatedUserInvoice.expire_time; if (invoiceExpiration < now && !updatedUserInvoice.ispaid) { // invoice expired :-( this.setState({ isFetchingInvoices: false }); ReactNativeHapticFeedback.trigger('notificationError', false); clearInterval(this.fetchInvoiceInterval); this.fetchInvoiceInterval = undefined; EV(EV.enum.TRANSACTIONS_COUNT_CHANGED); } } } } catch (error) { console.log(error); } } }, 3000); } componentWillUnmount() { clearInterval(this.fetchInvoiceInterval); this.fetchInvoiceInterval = undefined; BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton); } handleBackButton() { this.props.navigation.dismiss(); return true; } onLayout = () => { const { height } = Dimensions.get('window'); this.setState({ qrCodeHeight: height > width ? width - 20 : width / 2 }); }; render() { if (this.state.isLoading) { return ; } const { invoice } = this.state; if (typeof invoice === 'object') { const currentDate = new Date(); const now = (currentDate.getTime() / 1000) | 0; const invoiceExpiration = invoice.timestamp + invoice.expire_time; if (invoice.ispaid || invoice.type === 'paid_invoice') { return ( This invoice has been paid for ); } if (invoiceExpiration < now && !invoice.ispaid) { return ( This invoice was not paid for and has expired ); } else if (invoiceExpiration > now && invoice.ispaid) { if (invoice.ispaid) { return ( 'This invoice has been paid for.' ); } } } // Invoice has not expired, nor has it been paid for. return ( {invoice && invoice.amt && Please pay {invoice.amt} sats} {invoice && invoice.description && For: {invoice.description}} { Share.share({ message: 'lightning:' + invoice.payment_request, }); }} title={loc.receive.details.share} /> this.props.navigation.navigate('LNDViewAdditionalInvoiceInformation', { fromWallet: this.state.fromWallet })} title="Additional Information" /> ); } } LNDViewInvoice.propTypes = { navigation: PropTypes.shape({ goBack: PropTypes.function, navigate: PropTypes.function, getParam: PropTypes.function, dismiss: PropTypes.function, }), };