You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
263 lines
7.7 KiB
263 lines
7.7 KiB
import React, { Component } from 'react'
|
|
import PropTypes from 'prop-types'
|
|
import Isvg from 'react-inlinesvg'
|
|
import searchIcon from 'icons/search.svg'
|
|
import xIcon from 'icons/x.svg'
|
|
import FaRepeat from 'react-icons/lib/fa/repeat'
|
|
|
|
import { FormattedMessage, injectIntl } from 'react-intl'
|
|
|
|
import Wallet from 'components/Wallet'
|
|
import Invoice from './Invoice'
|
|
import Payment from './Payment'
|
|
import Transaction from './Transaction'
|
|
|
|
import styles from './Activity.scss'
|
|
|
|
import messages from './messages'
|
|
|
|
class Activity extends Component {
|
|
constructor(props, context) {
|
|
super(props, context)
|
|
this.renderActivity = this.renderActivity.bind(this)
|
|
|
|
this.state = {
|
|
refreshing: false
|
|
}
|
|
}
|
|
|
|
componentWillMount() {
|
|
const {
|
|
fetchPayments,
|
|
fetchInvoices,
|
|
fetchTransactions,
|
|
fetchBalance,
|
|
fetchChannels
|
|
} = this.props
|
|
|
|
fetchBalance()
|
|
fetchPayments()
|
|
fetchInvoices()
|
|
fetchTransactions()
|
|
fetchChannels()
|
|
|
|
// HACK: wait 10 seconds and fetch channels again, allowing the node to establish connections with the remote party
|
|
setTimeout(() => fetchChannels(), 10000)
|
|
}
|
|
|
|
renderActivity(activity) {
|
|
const { ticker, currentTicker, showActivityModal, network, currencyName } = this.props
|
|
|
|
if (Object.prototype.hasOwnProperty.call(activity, 'block_hash')) {
|
|
// activity is an on-chain tx
|
|
return (
|
|
<Transaction
|
|
transaction={activity}
|
|
ticker={ticker}
|
|
currentTicker={currentTicker}
|
|
showActivityModal={showActivityModal}
|
|
currencyName={currencyName}
|
|
/>
|
|
)
|
|
} else if (Object.prototype.hasOwnProperty.call(activity, 'payment_request')) {
|
|
// activity is an LN invoice
|
|
return (
|
|
<Invoice
|
|
invoice={activity}
|
|
ticker={ticker}
|
|
currentTicker={currentTicker}
|
|
showActivityModal={showActivityModal}
|
|
currencyName={currencyName}
|
|
/>
|
|
)
|
|
}
|
|
// activity is an LN payment
|
|
return (
|
|
<Payment
|
|
payment={activity}
|
|
ticker={ticker}
|
|
currentTicker={currentTicker}
|
|
showActivityModal={showActivityModal}
|
|
nodes={network.nodes}
|
|
currencyName={currencyName}
|
|
/>
|
|
)
|
|
}
|
|
|
|
render() {
|
|
const {
|
|
balance,
|
|
activity: { filters, filter, filterPulldown, searchActive, searchText, showExpiredRequests },
|
|
changeFilter,
|
|
currentActivity,
|
|
showExpiredToggle,
|
|
toggleExpiredRequests,
|
|
|
|
fetchPayments,
|
|
fetchInvoices,
|
|
fetchTransactions,
|
|
fetchBalance,
|
|
|
|
updateSearchActive,
|
|
updateSearchText,
|
|
walletProps,
|
|
intl
|
|
} = this.props
|
|
|
|
if (balance.channelBalance === null || balance.walletBalance === null) {
|
|
return null
|
|
}
|
|
|
|
const refreshClicked = () => {
|
|
// turn the spinner on
|
|
this.setState({ refreshing: true })
|
|
|
|
// store event in icon so we dont get an error when react clears it
|
|
const icon = this.repeat.childNodes
|
|
|
|
// fetch data
|
|
fetchBalance()
|
|
fetchPayments()
|
|
fetchInvoices()
|
|
fetchTransactions()
|
|
|
|
// wait for the svg to appear as child
|
|
const svgTimeout = setTimeout(() => {
|
|
if (icon[0].tagName === 'svg') {
|
|
// spin icon for 1 sec
|
|
icon[0].style.animation = 'spin 1000ms linear 1'
|
|
clearTimeout(svgTimeout)
|
|
}
|
|
}, 1)
|
|
|
|
// clear animation after the second so we can reuse it
|
|
const refreshTimeout = setTimeout(() => {
|
|
icon[0].style.animation = ''
|
|
this.setState({ refreshing: false })
|
|
clearTimeout(refreshTimeout)
|
|
}, 1000)
|
|
}
|
|
|
|
const { refreshing } = this.state
|
|
return (
|
|
<div>
|
|
<Wallet {...walletProps} />
|
|
|
|
<div className={styles.activities}>
|
|
{searchActive ? (
|
|
<header className={`${styles.header} ${styles.search}`}>
|
|
<section>
|
|
<input
|
|
placeholder={intl.formatMessage({ ...messages.search })}
|
|
value={searchText}
|
|
onChange={event => updateSearchText(event.target.value)}
|
|
/>
|
|
</section>
|
|
<section
|
|
onClick={() => {
|
|
updateSearchActive(false)
|
|
updateSearchText('')
|
|
}}
|
|
>
|
|
<span className={styles.xIcon}>
|
|
<Isvg src={xIcon} />
|
|
</span>
|
|
</section>
|
|
</header>
|
|
) : (
|
|
<header className={styles.header}>
|
|
<section>
|
|
<ul className={styles.filters}>
|
|
{filters.map(f => (
|
|
<li
|
|
key={f.key}
|
|
className={f.key === filter.key ? styles.activeFilter : undefined}
|
|
onClick={() => changeFilter(f)}
|
|
>
|
|
<FormattedMessage {...messages[f.name]} />
|
|
|
|
<div className={f.key === filter.key ? styles.activeBorder : undefined} />
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<ul className={styles.actions}>
|
|
<li onClick={refreshClicked}>
|
|
<span
|
|
className={styles.refresh}
|
|
ref={ref => {
|
|
this.repeat = ref
|
|
}}
|
|
>
|
|
{refreshing ? <FaRepeat /> : <FormattedMessage {...messages.refresh} />}
|
|
</span>
|
|
</li>
|
|
<li className={styles.activeFilter} onClick={() => updateSearchActive(true)}>
|
|
<Isvg src={searchIcon} />
|
|
</li>
|
|
</ul>
|
|
</section>
|
|
</header>
|
|
)}
|
|
<ul
|
|
className={`${styles.activityContainer} ${
|
|
filterPulldown ? styles.pulldown : undefined
|
|
}`}
|
|
>
|
|
{currentActivity.map((activityBlock, index) => (
|
|
<li className={styles.activity} key={index}>
|
|
<h2>{activityBlock.title}</h2>
|
|
<ul>
|
|
{activityBlock.activity.map((activity, i) => (
|
|
<li key={i}>{this.renderActivity(activity.el)}</li>
|
|
))}
|
|
</ul>
|
|
</li>
|
|
))}
|
|
{showExpiredToggle &&
|
|
currentActivity.length > 0 && (
|
|
<li>
|
|
<div className={styles.toggleExpired} onClick={toggleExpiredRequests}>
|
|
{showExpiredRequests ? (
|
|
<FormattedMessage {...messages.hide_expired} />
|
|
) : (
|
|
<FormattedMessage {...messages.show_expired} />
|
|
)}
|
|
</div>
|
|
</li>
|
|
)}
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
}
|
|
|
|
Activity.propTypes = {
|
|
fetchPayments: PropTypes.func.isRequired,
|
|
fetchInvoices: PropTypes.func.isRequired,
|
|
fetchTransactions: PropTypes.func.isRequired,
|
|
fetchBalance: PropTypes.func.isRequired,
|
|
fetchChannels: PropTypes.func.isRequired,
|
|
|
|
ticker: PropTypes.object.isRequired,
|
|
currentTicker: PropTypes.object.isRequired,
|
|
network: PropTypes.object.isRequired,
|
|
|
|
showActivityModal: PropTypes.func.isRequired,
|
|
changeFilter: PropTypes.func.isRequired,
|
|
updateSearchActive: PropTypes.func.isRequired,
|
|
updateSearchText: PropTypes.func.isRequired,
|
|
toggleExpiredRequests: PropTypes.func.isRequired,
|
|
|
|
activity: PropTypes.object.isRequired,
|
|
currentActivity: PropTypes.array.isRequired,
|
|
showExpiredToggle: PropTypes.bool.isRequired,
|
|
balance: PropTypes.object.isRequired,
|
|
walletProps: PropTypes.object.isRequired,
|
|
|
|
currencyName: PropTypes.string.isRequired
|
|
}
|
|
|
|
export default injectIntl(Activity)
|
|
|