2018-12-28 01:26:46 +01:00
|
|
|
/* global alert */
|
2018-12-25 17:34:51 +01:00
|
|
|
import React, { Component } from 'react';
|
2019-01-01 04:21:14 +01:00
|
|
|
import { Animated, ScrollView, StyleSheet, View, TouchableOpacity, Clipboard, Dimensions, Share } from 'react-native';
|
2019-01-03 02:05:53 +01:00
|
|
|
import { BlueLoading, BlueText, SafeBlueArea, BlueButton, BlueNavigationStyle, BlueSpacing20 } from '../../BlueComponents';
|
2018-12-25 17:34:51 +01:00
|
|
|
import PropTypes from 'prop-types';
|
2018-12-27 07:12:19 +01:00
|
|
|
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
|
2018-12-30 16:34:13 +01:00
|
|
|
import { Icon } from 'react-native-elements';
|
2018-12-25 17:34:51 +01:00
|
|
|
/** @type {AppStorage} */
|
|
|
|
let BlueApp = require('../../BlueApp');
|
2018-12-27 07:12:19 +01:00
|
|
|
const loc = require('../../loc');
|
|
|
|
const EV = require('../../events');
|
2018-12-25 17:34:51 +01:00
|
|
|
const QRFast = require('react-native-qrcode');
|
2019-01-01 04:21:14 +01:00
|
|
|
const { width } = Dimensions.get('window');
|
2018-12-25 17:34:51 +01:00
|
|
|
|
|
|
|
export default class LNDViewInvoice extends Component {
|
|
|
|
static navigationOptions = ({ navigation }) => ({
|
|
|
|
...BlueNavigationStyle(navigation, true, () => navigation.dismiss()),
|
2019-01-03 02:41:27 +01:00
|
|
|
title: 'Lightning Invoice',
|
2018-12-25 17:34:51 +01:00
|
|
|
headerLeft: null,
|
|
|
|
});
|
2018-12-27 16:12:22 +01:00
|
|
|
|
2018-12-25 17:34:51 +01:00
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
2018-12-27 07:12:19 +01:00
|
|
|
const invoice = props.navigation.getParam('invoice');
|
|
|
|
const fromWallet = props.navigation.getParam('fromWallet');
|
2018-12-25 17:34:51 +01:00
|
|
|
this.state = {
|
|
|
|
invoice,
|
2018-12-27 07:12:19 +01:00
|
|
|
fromWallet,
|
2018-12-28 01:26:46 +01:00
|
|
|
isLoading: typeof invoice === 'string',
|
2019-01-01 23:31:42 +01:00
|
|
|
addressText: typeof invoice === 'object' && invoice.hasOwnProperty('payment_request') ? invoice.payment_request : invoice,
|
2018-12-30 16:34:13 +01:00
|
|
|
isFetchingInvoices: true,
|
2018-12-25 17:34:51 +01:00
|
|
|
};
|
2018-12-27 07:12:19 +01:00
|
|
|
this.fetchInvoiceInterval = undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
async componentDidMount() {
|
2018-12-28 00:33:39 +01:00
|
|
|
this.fetchInvoiceInterval = setInterval(async () => {
|
2018-12-30 16:34:13 +01:00
|
|
|
if (this.state.isFetchingInvoices) {
|
2018-12-28 01:26:46 +01:00
|
|
|
try {
|
|
|
|
const userInvoices = JSON.stringify(await this.state.fromWallet.getUserInvoices());
|
|
|
|
const updatedUserInvoice = JSON.parse(userInvoices).filter(invoice =>
|
|
|
|
typeof this.state.invoice === 'object'
|
|
|
|
? invoice.payment_request === this.state.invoice.payment_request
|
|
|
|
: invoice.payment_request === this.state.invoice,
|
|
|
|
)[0];
|
2019-01-03 02:10:16 +01:00
|
|
|
|
|
|
|
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 :-)
|
2018-12-28 01:26:46 +01:00
|
|
|
this.setState({ isFetchingInvoices: false });
|
2019-01-03 02:10:16 +01:00
|
|
|
ReactNativeHapticFeedback.trigger('notificationSuccess', false);
|
2018-12-28 01:26:46 +01:00
|
|
|
clearInterval(this.fetchInvoiceInterval);
|
|
|
|
this.fetchInvoiceInterval = undefined;
|
|
|
|
EV(EV.enum.TRANSACTIONS_COUNT_CHANGED);
|
2019-01-03 02:10:16 +01:00
|
|
|
} 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);
|
|
|
|
}
|
2018-12-28 01:26:46 +01:00
|
|
|
}
|
2018-12-28 00:40:55 +01:00
|
|
|
}
|
2018-12-28 01:26:46 +01:00
|
|
|
} catch (error) {
|
2019-01-03 02:10:16 +01:00
|
|
|
clearInterval(this.fetchInvoiceInterval);
|
|
|
|
this.fetchInvoiceInterval = undefined;
|
2018-12-28 01:26:46 +01:00
|
|
|
console.log(error);
|
|
|
|
alert(error);
|
|
|
|
this.props.navigation.dismiss();
|
2018-12-28 00:40:55 +01:00
|
|
|
}
|
2018-12-28 00:33:39 +01:00
|
|
|
}
|
2019-01-01 01:09:10 +01:00
|
|
|
}, 3000);
|
2018-12-27 07:12:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
componentWillUnmount() {
|
2018-12-27 16:12:22 +01:00
|
|
|
clearInterval(this.fetchInvoiceInterval);
|
2018-12-28 00:33:39 +01:00
|
|
|
this.fetchInvoiceInterval = undefined;
|
2018-12-25 17:34:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
copyToClipboard = () => {
|
|
|
|
this.setState({ addressText: loc.receive.details.copiedToClipboard }, () => {
|
2019-01-01 23:31:42 +01:00
|
|
|
Clipboard.setString(this.state.invoice.payment_request);
|
2018-12-28 22:01:55 +01:00
|
|
|
setTimeout(() => this.setState({ addressText: this.state.invoice.payment_request }), 1000);
|
2018-12-25 17:34:51 +01:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
render() {
|
|
|
|
if (this.state.isLoading) {
|
|
|
|
return <BlueLoading />;
|
|
|
|
}
|
|
|
|
|
2018-12-27 07:12:19 +01:00
|
|
|
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;
|
|
|
|
|
2019-01-01 23:31:42 +01:00
|
|
|
if (invoice.ispaid || invoice.type === 'paid_invoice') {
|
2018-12-27 07:12:19 +01:00
|
|
|
return (
|
|
|
|
<SafeBlueArea style={{ flex: 1 }}>
|
|
|
|
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
|
2018-12-30 16:34:13 +01:00
|
|
|
<View
|
|
|
|
style={{
|
|
|
|
backgroundColor: '#ccddf9',
|
|
|
|
width: 120,
|
|
|
|
height: 120,
|
|
|
|
borderRadius: 60,
|
|
|
|
alignSelf: 'center',
|
|
|
|
justifyContent: 'center',
|
|
|
|
marginTop: 43,
|
|
|
|
marginBottom: 53,
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<Icon name="check" size={50} type="font-awesome" color="#0f5cc0" />
|
|
|
|
</View>
|
|
|
|
<BlueText>This invoice has been paid for</BlueText>
|
2018-12-27 07:12:19 +01:00
|
|
|
</View>
|
|
|
|
</SafeBlueArea>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if (invoiceExpiration < now && !invoice.ispaid) {
|
|
|
|
return (
|
|
|
|
<SafeBlueArea style={{ flex: 1 }}>
|
|
|
|
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
|
2019-01-01 23:31:42 +01:00
|
|
|
<View
|
|
|
|
style={{
|
|
|
|
backgroundColor: '#ccddf9',
|
|
|
|
width: 120,
|
|
|
|
height: 120,
|
|
|
|
borderRadius: 60,
|
|
|
|
alignSelf: 'center',
|
|
|
|
justifyContent: 'center',
|
|
|
|
marginTop: 43,
|
|
|
|
marginBottom: 53,
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<Icon name="times" size={50} type="font-awesome" color="#0f5cc0" />
|
|
|
|
</View>
|
2018-12-30 16:34:13 +01:00
|
|
|
<BlueText>This invoice was not paid for and has expired</BlueText>
|
2018-12-27 07:12:19 +01:00
|
|
|
</View>
|
|
|
|
</SafeBlueArea>
|
|
|
|
);
|
|
|
|
} else if (invoiceExpiration > now && invoice.ispaid) {
|
|
|
|
if (invoice.ispaid) {
|
|
|
|
return (
|
|
|
|
<SafeBlueArea style={{ flex: 1 }}>
|
|
|
|
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
|
|
|
|
<BlueText>'This invoice has been paid for.'</BlueText>
|
|
|
|
</View>
|
|
|
|
</SafeBlueArea>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Invoice has not expired, nor has it been paid for.
|
2018-12-25 17:34:51 +01:00
|
|
|
return (
|
2019-01-03 02:05:53 +01:00
|
|
|
<SafeBlueArea>
|
|
|
|
<ScrollView style={{ flex: 1 }}>
|
|
|
|
<View
|
|
|
|
style={{
|
|
|
|
flex: 1,
|
|
|
|
alignItems: 'center',
|
|
|
|
marginTop: 8,
|
|
|
|
paddingHorizontal: 16,
|
|
|
|
justifyContent: 'space-between',
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<QRFast
|
|
|
|
value={typeof this.state.invoice === 'object' ? invoice.payment_request : invoice}
|
|
|
|
size={width - 40}
|
|
|
|
fgColor={BlueApp.settings.brandingColor}
|
|
|
|
bgColor={BlueApp.settings.foregroundColor}
|
|
|
|
/>
|
|
|
|
<BlueSpacing20 />
|
2019-01-01 23:31:42 +01:00
|
|
|
{invoice && invoice.amt && <BlueText>Please pay {invoice.amt} sats</BlueText>}
|
|
|
|
{invoice && invoice.description && <BlueText>For: {invoice.description}</BlueText>}
|
|
|
|
<TouchableOpacity onPress={this.copyToClipboard}>
|
|
|
|
<Animated.Text style={styles.address} numberOfLines={0}>
|
|
|
|
{this.state.addressText}
|
|
|
|
</Animated.Text>
|
|
|
|
</TouchableOpacity>
|
2018-12-30 16:34:13 +01:00
|
|
|
|
2019-01-01 23:31:42 +01:00
|
|
|
<BlueButton
|
|
|
|
icon={{
|
|
|
|
name: 'share-alternative',
|
|
|
|
type: 'entypo',
|
|
|
|
color: BlueApp.settings.buttonTextColor,
|
|
|
|
}}
|
|
|
|
onPress={async () => {
|
|
|
|
Share.share({
|
|
|
|
message: 'lightning:' + invoice.payment_request,
|
|
|
|
});
|
|
|
|
}}
|
|
|
|
title={loc.receive.details.share}
|
|
|
|
/>
|
|
|
|
<BlueButton
|
|
|
|
buttonStyle={{ backgroundColor: 'white' }}
|
|
|
|
icon={{
|
|
|
|
name: 'info',
|
|
|
|
type: 'entypo',
|
|
|
|
color: BlueApp.settings.buttonTextColor,
|
|
|
|
}}
|
|
|
|
onPress={() => this.props.navigation.navigate('LNDViewAdditionalInvoiceInformation', { fromWallet: this.state.fromWallet })}
|
|
|
|
title="Additional Information"
|
|
|
|
/>
|
2018-12-25 17:34:51 +01:00
|
|
|
</View>
|
2019-01-03 02:05:53 +01:00
|
|
|
<BlueSpacing20 />
|
2018-12-30 16:34:13 +01:00
|
|
|
</ScrollView>
|
2018-12-25 17:34:51 +01:00
|
|
|
</SafeBlueArea>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const styles = StyleSheet.create({
|
|
|
|
address: {
|
|
|
|
marginVertical: 32,
|
|
|
|
fontSize: 15,
|
|
|
|
color: '#9aa0aa',
|
|
|
|
textAlign: 'center',
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
LNDViewInvoice.propTypes = {
|
|
|
|
navigation: PropTypes.shape({
|
|
|
|
goBack: PropTypes.function,
|
2018-12-29 02:15:59 +01:00
|
|
|
navigate: PropTypes.function,
|
2018-12-25 17:34:51 +01:00
|
|
|
getParam: PropTypes.function,
|
2018-12-28 01:26:46 +01:00
|
|
|
dismiss: PropTypes.function,
|
2018-12-25 17:34:51 +01:00
|
|
|
}),
|
|
|
|
};
|