|
|
@ -1,6 +1,6 @@ |
|
|
|
/* eslint react/prop-types: 0 */ |
|
|
|
/** @type {AppStorage} */ |
|
|
|
import React, { Component } from 'react'; |
|
|
|
import React, { Component, useEffect, useState } from 'react'; |
|
|
|
import Ionicons from 'react-native-vector-icons/Ionicons'; |
|
|
|
import PropTypes from 'prop-types'; |
|
|
|
import { Icon, FormLabel, FormInput, Text, Header, List, ListItem } from 'react-native-elements'; |
|
|
@ -17,7 +17,6 @@ import { |
|
|
|
Image, |
|
|
|
Keyboard, |
|
|
|
SafeAreaView, |
|
|
|
InteractionManager, |
|
|
|
InputAccessoryView, |
|
|
|
Clipboard, |
|
|
|
Platform, |
|
|
@ -1383,27 +1382,32 @@ export class NewWalletPanel extends Component { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
export class BlueTransactionListItem extends Component { |
|
|
|
static propTypes = { |
|
|
|
item: PropTypes.shape().isRequired, |
|
|
|
itemPriceUnit: PropTypes.string, |
|
|
|
}; |
|
|
|
|
|
|
|
static defaultProps = { |
|
|
|
itemPriceUnit: BitcoinUnit.BTC, |
|
|
|
}; |
|
|
|
|
|
|
|
state = { transactionTimeToReadable: '...', subtitleNumberOfLines: 1 }; |
|
|
|
export const BlueTransactionListItem = (item, itemPriceUnit = BitcoinUnit.BTC) => { |
|
|
|
item = item.item; |
|
|
|
|
|
|
|
txMemo = () => { |
|
|
|
if (BlueApp.tx_metadata[this.props.item.hash] && BlueApp.tx_metadata[this.props.item.hash]['memo']) { |
|
|
|
return BlueApp.tx_metadata[this.props.item.hash]['memo']; |
|
|
|
useEffect(() => { |
|
|
|
const calculateTimeLabel = () => { |
|
|
|
const transactionTimeToReadable = loc.transactionTimeToReadable(item.received); |
|
|
|
return setTransactionTimeToReadable(transactionTimeToReadable); |
|
|
|
}; |
|
|
|
calculateTimeLabel(); |
|
|
|
const interval = setInterval(() => { |
|
|
|
calculateTimeLabel(); |
|
|
|
}, 60000); |
|
|
|
return () => clearInterval(interval); |
|
|
|
}, [item]); |
|
|
|
|
|
|
|
const [transactionTimeToReadable, setTransactionTimeToReadable] = useState('...'); |
|
|
|
const [subtitleNumberOfLines, setSubtitleNumberOfLines] = useState(1); |
|
|
|
|
|
|
|
const txMemo = () => { |
|
|
|
if (BlueApp.tx_metadata[item.hash] && BlueApp.tx_metadata[item.hash]['memo']) { |
|
|
|
return BlueApp.tx_metadata[item.hash]['memo']; |
|
|
|
} |
|
|
|
return ''; |
|
|
|
}; |
|
|
|
|
|
|
|
rowTitle = () => { |
|
|
|
const item = this.props.item; |
|
|
|
const rowTitle = () => { |
|
|
|
if (item.type === 'user_invoice' || item.type === 'payment_request') { |
|
|
|
if (isNaN(item.value)) { |
|
|
|
item.value = '0'; |
|
|
@ -1413,21 +1417,20 @@ export class BlueTransactionListItem extends Component { |
|
|
|
const invoiceExpiration = item.timestamp + item.expire_time; |
|
|
|
|
|
|
|
if (invoiceExpiration > now) { |
|
|
|
return loc.formatBalanceWithoutSuffix(item.value && item.value, this.props.itemPriceUnit, true).toString(); |
|
|
|
return loc.formatBalanceWithoutSuffix(item.value && item.value, itemPriceUnit, true).toString(); |
|
|
|
} else if (invoiceExpiration < now) { |
|
|
|
if (item.ispaid) { |
|
|
|
return loc.formatBalanceWithoutSuffix(item.value && item.value, this.props.itemPriceUnit, true).toString(); |
|
|
|
return loc.formatBalanceWithoutSuffix(item.value && item.value, itemPriceUnit, true).toString(); |
|
|
|
} else { |
|
|
|
return loc.lnd.expired; |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
return loc.formatBalanceWithoutSuffix(item.value && item.value, this.props.itemPriceUnit, true).toString(); |
|
|
|
return loc.formatBalanceWithoutSuffix(item.value && item.value, itemPriceUnit, true).toString(); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
rowTitleStyle = () => { |
|
|
|
const item = this.props.item; |
|
|
|
const rowTitleStyle = () => { |
|
|
|
let color = BlueApp.settings.successColor; |
|
|
|
|
|
|
|
if (item.type === 'user_invoice' || item.type === 'payment_request') { |
|
|
@ -1455,9 +1458,9 @@ export class BlueTransactionListItem extends Component { |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
avatar = () => { |
|
|
|
const avatar = () => { |
|
|
|
// is it lightning refill tx?
|
|
|
|
if (this.props.item.category === 'receive' && this.props.item.confirmations < 3) { |
|
|
|
if (item.category === 'receive' && item.confirmations < 3) { |
|
|
|
return ( |
|
|
|
<View style={{ width: 25 }}> |
|
|
|
<BlueTransactionPendingIcon /> |
|
|
@ -1465,14 +1468,14 @@ export class BlueTransactionListItem extends Component { |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
if (this.props.item.type && this.props.item.type === 'bitcoind_tx') { |
|
|
|
if (item.type && item.type === 'bitcoind_tx') { |
|
|
|
return ( |
|
|
|
<View style={{ width: 25 }}> |
|
|
|
<BlueTransactionOnchainIcon /> |
|
|
|
</View> |
|
|
|
); |
|
|
|
} |
|
|
|
if (this.props.item.type === 'paid_invoice') { |
|
|
|
if (item.type === 'paid_invoice') { |
|
|
|
// is it lightning offchain payment?
|
|
|
|
return ( |
|
|
|
<View style={{ width: 25 }}> |
|
|
@ -1481,11 +1484,11 @@ export class BlueTransactionListItem extends Component { |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
if (this.props.item.type === 'user_invoice' || this.props.item.type === 'payment_request') { |
|
|
|
if (!this.props.item.ispaid) { |
|
|
|
if (item.type === 'user_invoice' || item.type === 'payment_request') { |
|
|
|
if (!item.ispaid) { |
|
|
|
const currentDate = new Date(); |
|
|
|
const now = (currentDate.getTime() / 1000) | 0; |
|
|
|
const invoiceExpiration = this.props.item.timestamp + this.props.item.expire_time; |
|
|
|
const invoiceExpiration = item.timestamp + item.expire_time; |
|
|
|
if (invoiceExpiration < now) { |
|
|
|
return ( |
|
|
|
<View style={{ width: 25 }}> |
|
|
@ -1502,13 +1505,13 @@ export class BlueTransactionListItem extends Component { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (!this.props.item.confirmations) { |
|
|
|
if (!item.confirmations) { |
|
|
|
return ( |
|
|
|
<View style={{ width: 25 }}> |
|
|
|
<BlueTransactionPendingIcon /> |
|
|
|
</View> |
|
|
|
); |
|
|
|
} else if (this.props.item.value < 0) { |
|
|
|
} else if (item.value < 0) { |
|
|
|
return ( |
|
|
|
<View style={{ width: 25 }}> |
|
|
|
<BlueTransactionOutgoingIcon /> |
|
|
@ -1523,32 +1526,24 @@ export class BlueTransactionListItem extends Component { |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
subtitle = () => { |
|
|
|
return ( |
|
|
|
(this.props.item.confirmations < 7 ? loc.transactions.list.conf + ': ' + this.props.item.confirmations + ' ' : '') + |
|
|
|
this.txMemo() + |
|
|
|
(this.props.item.memo || '') |
|
|
|
); |
|
|
|
const subtitle = () => { |
|
|
|
return (item.confirmations < 7 ? loc.transactions.list.conf + ': ' + item.confirmations + ' ' : '') + txMemo() + (item.memo || ''); |
|
|
|
}; |
|
|
|
|
|
|
|
onPress = () => { |
|
|
|
if (this.props.item.hash) { |
|
|
|
NavigationService.navigate('TransactionStatus', { hash: this.props.item.hash }); |
|
|
|
} else if ( |
|
|
|
this.props.item.type === 'user_invoice' || |
|
|
|
this.props.item.type === 'payment_request' || |
|
|
|
this.props.item.type === 'paid_invoice' |
|
|
|
) { |
|
|
|
const onPress = () => { |
|
|
|
if (item.hash) { |
|
|
|
NavigationService.navigate('TransactionStatus', { hash: item.hash }); |
|
|
|
} else if (item.type === 'user_invoice' || item.type === 'payment_request' || item.type === 'paid_invoice') { |
|
|
|
const lightningWallet = BlueApp.getWallets().filter(wallet => { |
|
|
|
if (typeof wallet === 'object') { |
|
|
|
if (wallet.hasOwnProperty('secret')) { |
|
|
|
return wallet.getSecret() === this.props.item.fromWallet; |
|
|
|
return wallet.getSecret() === item.fromWallet; |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
if (lightningWallet.length === 1) { |
|
|
|
NavigationService.navigate('LNDViewInvoice', { |
|
|
|
invoice: this.props.item, |
|
|
|
invoice: item, |
|
|
|
fromWallet: lightningWallet[0], |
|
|
|
isModal: false, |
|
|
|
}); |
|
|
@ -1556,40 +1551,32 @@ export class BlueTransactionListItem extends Component { |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
componentDidMount() { |
|
|
|
InteractionManager.runAfterInteractions(() => { |
|
|
|
const transactionTimeToReadable = loc.transactionTimeToReadable(this.props.item.received); |
|
|
|
this.setState({ transactionTimeToReadable }); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
onLongPress = () => { |
|
|
|
if (this.state.subtitleNumberOfLines === 1) { |
|
|
|
this.setState({ subtitleNumberOfLines: 0 }); |
|
|
|
const onLongPress = () => { |
|
|
|
if (subtitleNumberOfLines === 1) { |
|
|
|
setSubtitleNumberOfLines(0); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
render() { |
|
|
|
return ( |
|
|
|
<BlueListItem |
|
|
|
avatar={this.avatar()} |
|
|
|
title={this.state.transactionTimeToReadable} |
|
|
|
subtitle={this.subtitle()} |
|
|
|
subtitleNumberOfLines={this.state.subtitleNumberOfLines} |
|
|
|
onPress={this.onPress} |
|
|
|
onLongPress={this.onLongPress} |
|
|
|
badge={{ |
|
|
|
value: 3, |
|
|
|
textStyle: { color: 'orange' }, |
|
|
|
containerStyle: { marginTop: 0 }, |
|
|
|
}} |
|
|
|
hideChevron |
|
|
|
rightTitle={this.rowTitle()} |
|
|
|
rightTitleStyle={this.rowTitleStyle()} |
|
|
|
/> |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
return ( |
|
|
|
<BlueListItem |
|
|
|
avatar={avatar()} |
|
|
|
title={transactionTimeToReadable} |
|
|
|
titleNumberOfLines={subtitleNumberOfLines} |
|
|
|
subtitle={subtitle()} |
|
|
|
subtitleNumberOfLines={subtitleNumberOfLines} |
|
|
|
onPress={onPress} |
|
|
|
onLongPress={onLongPress} |
|
|
|
badge={{ |
|
|
|
value: 3, |
|
|
|
textStyle: { color: 'orange' }, |
|
|
|
containerStyle: { marginTop: 0 }, |
|
|
|
}} |
|
|
|
hideChevron |
|
|
|
rightTitle={rowTitle()} |
|
|
|
rightTitleStyle={rowTitleStyle()} |
|
|
|
/> |
|
|
|
); |
|
|
|
}; |
|
|
|
|
|
|
|
export class BlueListTransactionItem extends Component { |
|
|
|
static propTypes = { |
|
|
|