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.

178 lines
4.9 KiB

import React from 'react'
import PropTypes from 'prop-types'
import { Box, Flex } from 'rebass'
import { FormattedMessage, FormattedRelative, injectIntl } from 'react-intl'
import { decodePayReq } from 'lib/utils/crypto'
import { showNotification } from 'lib/utils/notifications'
import copy from 'copy-to-clipboard'
import { Bar, DataRow, Button, Dropdown, QRCode, Text, Truncate, Value } from 'components/UI'
import messages from './messages'
class RequestSummary extends React.Component {
state = {
isExpired: null,
timer: null
}
static propTypes = {
/** Currently selected cryptocurrency (key). */
cryptoCurrency: PropTypes.string.isRequired,
/** List of supported cryptocurrencies. */
cryptoCurrencies: PropTypes.arrayOf(
PropTypes.shape({
key: PropTypes.string.isRequired,
name: PropTypes.string.isRequired
})
).isRequired,
/** Boolean indicating wether the invoice has already been paid. */
isPaid: PropTypes.bool,
/** Lightning Payment request. */
payReq: PropTypes.string.isRequired,
/** Set the current cryptocurrency. */
setCryptoCurrency: PropTypes.func.isRequired
}
static defaultProps = {
isPaid: false
}
componentDidMount() {
const { payReq } = this.props
let invoice
try {
invoice = decodePayReq(payReq)
const expiresIn = invoice.timeExpireDate * 1000 - Date.now()
if (expiresIn >= 0) {
this.setState({ isExpired: false })
const timer = setInterval(() => this.setState({ isExpired: true }), expiresIn)
this.setState({ timer })
} else {
this.setState({ isExpired: true })
}
} catch (e) {
return null
}
}
componentWillUnmount() {
const { timer } = this.state
clearInterval(timer)
}
copyPaymentRequest = () => {
const { intl, payReq } = this.props
copy(payReq)
showNotification(
intl.formatMessage({ ...messages.address_notification_title }),
intl.formatMessage({ ...messages.copied_notification_description })
)
}
render() {
const {
cryptoCurrency,
cryptoCurrencies,
isPaid,
payReq,
setCryptoCurrency,
...rest
} = this.props
const { isExpired } = this.state
let invoice
try {
invoice = decodePayReq(payReq)
} catch (e) {
return null
}
const { satoshis } = invoice
const descriptionTag = invoice.tags.find(tag => tag.tagName === 'description') || {}
const memo = descriptionTag.data
return (
<Box {...rest}>
{memo && (
<React.Fragment>
<DataRow left={<FormattedMessage {...messages.memo} />} right={memo} /> <Bar />{' '}
</React.Fragment>
)}
<DataRow
left={<FormattedMessage {...messages.amount} />}
right={
<Flex alignItems="center" justifyContent="flex-end">
<Value value={satoshis} currency={cryptoCurrency} />
<Dropdown
activeKey={cryptoCurrency}
items={cryptoCurrencies}
onChange={setCryptoCurrency}
justify="right"
ml={2}
/>
</Flex>
}
/>
<Bar />
<DataRow
left={<FormattedMessage {...messages.qrcode} />}
right={
<Text>
<QRCode value={payReq} size="125px" />
</Text>
}
/>
<Bar />
<DataRow
left={<FormattedMessage {...messages.ln_invoice} />}
right=<React.Fragment>
<Text
fontSize="xs"
fontWeight="normal"
mb={2}
css={{ 'word-wrap': 'break-word' }}
className="hint--bottom-left"
data-hint={payReq}
>
<Truncate text={payReq} maxlen={40} />
</Text>
<Button type="button" size="small" onClick={this.copyPaymentRequest}>
<FormattedMessage {...messages.copy_button_text} />
</Button>
</React.Fragment>
/>
<Bar />
<DataRow
left={<FormattedMessage {...messages.status} />}
right={
<React.Fragment>
<Text color={isPaid || !isExpired ? 'superGreen' : 'superRed'} fontWeight="normal">
{isExpired ? 'Expired ' : 'Expires '}
<FormattedRelative value={invoice.timeExpireDateString} updateInterval={1000} />
</Text>
<Text
color={isPaid ? 'superGreen' : isExpired ? 'superRed' : 'grey'}
fontWeight="normal"
>
{isPaid ? (
<FormattedMessage {...messages.paid} />
) : (
<FormattedMessage {...messages.not_paid} />
)}
</Text>
</React.Fragment>
}
/>
</Box>
)
}
}
export default injectIntl(RequestSummary)