diff --git a/BlueComponents.js b/BlueComponents.js index e6e01726..efbfd36e 100644 --- a/BlueComponents.js +++ b/BlueComponents.js @@ -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 ( @@ -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 ( ); } - if (this.props.item.type === 'paid_invoice') { + if (item.type === 'paid_invoice') { // is it lightning offchain payment? return ( @@ -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 ( @@ -1502,13 +1505,13 @@ export class BlueTransactionListItem extends Component { } } - if (!this.props.item.confirmations) { + if (!item.confirmations) { return ( ); - } else if (this.props.item.value < 0) { + } else if (item.value < 0) { return ( @@ -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 ( - - ); - } -} + return ( + + ); +}; export class BlueListTransactionItem extends Component { static propTypes = { diff --git a/loc/index.js b/loc/index.js index 2e4e0d19..6466a324 100644 --- a/loc/index.js +++ b/loc/index.js @@ -188,7 +188,7 @@ strings.formatBalance = (balance, toUnit, withFormatting = false) => { * @param toUnit {String} Value from models/bitcoinUnits.js * @returns {string} */ -strings.formatBalanceWithoutSuffix = (balance, toUnit, withFormatting = false) => { +strings.formatBalanceWithoutSuffix = (balance = 0, toUnit, withFormatting = false) => { if (toUnit === undefined) { return balance; } diff --git a/screen/wallets/transactions.js b/screen/wallets/transactions.js index 04321624..c515cb0c 100644 --- a/screen/wallets/transactions.js +++ b/screen/wallets/transactions.js @@ -433,6 +433,7 @@ export default class WalletTransactions extends Component { refreshControl={ this.refreshTransactions()} refreshing={this.state.showShowFlatListRefreshControl} /> } + extraData={this.state.dataSource} data={this.state.dataSource} keyExtractor={this._keyExtractor} renderItem={this.renderItem}