2020-04-10 19:31:36 +02:00
|
|
|
// @flow
|
|
|
|
import * as ICONS from 'constants/icons';
|
|
|
|
import React from 'react';
|
|
|
|
import ButtonTransaction from 'component/common/transaction-link';
|
|
|
|
import CreditAmount from 'component/common/credit-amount';
|
|
|
|
import DateTime from 'component/dateTime';
|
|
|
|
import Button from 'component/button';
|
2020-04-14 22:37:20 +02:00
|
|
|
import Spinner from 'component/spinner';
|
2020-04-15 16:12:54 +02:00
|
|
|
import { toCapitalCase } from 'util/string';
|
2020-04-24 15:51:00 +02:00
|
|
|
import { buildURI, parseURI, TXO_LIST as TXO, ABANDON_STATES } from 'lbry-redux';
|
2020-04-10 19:31:36 +02:00
|
|
|
|
|
|
|
type Props = {
|
|
|
|
txo: Txo,
|
2020-04-14 22:37:20 +02:00
|
|
|
revokeClaim: (Txo, (string) => void) => void,
|
2020-04-10 19:31:36 +02:00
|
|
|
isRevokeable: boolean,
|
|
|
|
reward: ?{
|
|
|
|
reward_title: string,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
type State = {
|
2020-04-14 22:37:20 +02:00
|
|
|
abandonState: string,
|
2020-04-10 19:31:36 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
class TxoListItem extends React.PureComponent<Props, State> {
|
|
|
|
constructor() {
|
|
|
|
super();
|
2020-04-24 15:51:00 +02:00
|
|
|
this.state = { abandonState: ABANDON_STATES.READY };
|
2020-04-10 19:31:36 +02:00
|
|
|
(this: any).abandonClaim = this.abandonClaim.bind(this);
|
|
|
|
(this: any).getLink = this.getLink.bind(this);
|
|
|
|
}
|
|
|
|
|
2020-10-02 06:53:32 +02:00
|
|
|
getLink(type: string, tip: boolean, valueType: string) {
|
2020-04-14 22:37:20 +02:00
|
|
|
const { abandonState } = this.state;
|
2020-09-30 23:40:09 +02:00
|
|
|
|
2020-10-02 06:53:32 +02:00
|
|
|
if (type === 'claim' && valueType !== 'repost') {
|
2020-09-30 23:40:09 +02:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2020-04-24 15:51:00 +02:00
|
|
|
if (this.state.abandonState === ABANDON_STATES.PENDING) {
|
2020-04-14 22:37:20 +02:00
|
|
|
return <Spinner type={'small'} />;
|
|
|
|
}
|
2020-09-30 23:40:09 +02:00
|
|
|
|
2020-05-22 03:19:01 +02:00
|
|
|
if (tip && type === TXO.SUPPORT) {
|
2020-04-10 19:31:36 +02:00
|
|
|
return (
|
|
|
|
<Button
|
2020-06-13 14:11:12 +02:00
|
|
|
disabled={abandonState === ABANDON_STATES.DONE}
|
2020-04-10 19:31:36 +02:00
|
|
|
button="secondary"
|
|
|
|
icon={ICONS.UNLOCK}
|
|
|
|
onClick={this.abandonClaim}
|
2020-08-26 22:28:33 +02:00
|
|
|
title={__('Unlock tip')}
|
2020-04-10 19:31:36 +02:00
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
const abandonTitle = type === TXO.SUPPORT ? 'Abandon Support' : 'Abandon Claim';
|
|
|
|
return (
|
|
|
|
<Button
|
2020-06-13 14:11:12 +02:00
|
|
|
disabled={abandonState === ABANDON_STATES.DONE}
|
2020-04-10 19:31:36 +02:00
|
|
|
button="secondary"
|
|
|
|
icon={ICONS.DELETE}
|
|
|
|
onClick={this.abandonClaim}
|
|
|
|
title={__(abandonTitle)}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
abandonClaim() {
|
2020-04-15 16:12:54 +02:00
|
|
|
this.props.revokeClaim(this.props.txo, abandonState => this.setState({ abandonState }));
|
2020-04-10 19:31:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
|
|
|
const { reward, txo, isRevokeable } = this.props;
|
|
|
|
|
|
|
|
const {
|
|
|
|
amount,
|
|
|
|
claim_id: claimId,
|
|
|
|
normalized_name: txoListName,
|
|
|
|
timestamp,
|
|
|
|
txid,
|
|
|
|
type,
|
|
|
|
value_type: valueType,
|
2020-04-15 16:12:54 +02:00
|
|
|
is_my_input: isMyInput,
|
2020-04-10 19:31:36 +02:00
|
|
|
is_my_output: isMyOutput,
|
|
|
|
} = txo;
|
|
|
|
|
|
|
|
const name = txoListName;
|
|
|
|
const isMinus = (type === 'support' || type === 'payment' || type === 'other') && isMyInput && !isMyOutput;
|
|
|
|
const isTip = type === 'support' && ((isMyInput && !isMyOutput) || (!isMyInput && isMyOutput));
|
|
|
|
const date = new Date(timestamp * 1000);
|
|
|
|
|
|
|
|
// Ensure the claim name exists and is valid
|
|
|
|
let uri;
|
|
|
|
let claimName;
|
|
|
|
try {
|
|
|
|
if (name.startsWith('@')) {
|
|
|
|
({ claimName } = parseURI(name));
|
|
|
|
uri = buildURI({ channelName: claimName, channelClaimId: claimId });
|
|
|
|
} else {
|
|
|
|
({ claimName } = parseURI(name));
|
|
|
|
uri = buildURI({ streamName: claimName, streamClaimId: claimId });
|
|
|
|
}
|
|
|
|
} catch (e) {}
|
|
|
|
|
|
|
|
const dateFormat = {
|
|
|
|
month: 'short',
|
|
|
|
day: 'numeric',
|
|
|
|
year: 'numeric',
|
|
|
|
};
|
|
|
|
|
|
|
|
const forClaim = name && claimId;
|
|
|
|
|
|
|
|
return (
|
|
|
|
<tr>
|
|
|
|
<td>
|
|
|
|
{timestamp ? (
|
|
|
|
<div>
|
|
|
|
<DateTime date={date} show={DateTime.SHOW_DATE} formatOptions={dateFormat} />
|
|
|
|
<div className="table__item-label">
|
|
|
|
<DateTime date={date} show={DateTime.SHOW_TIME} />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
) : (
|
|
|
|
<span className="empty">{__('Pending')}</span>
|
|
|
|
)}
|
|
|
|
</td>
|
|
|
|
<td className="table__item--actionable">
|
|
|
|
<span>
|
2020-06-16 01:02:03 +02:00
|
|
|
{(isTip && __('Tip')) ||
|
2020-10-09 08:09:13 +02:00
|
|
|
(type === 'support' && !isTip && __('Support --[noun; transaction type]--')) ||
|
2020-07-23 19:02:07 +02:00
|
|
|
(valueType && ((valueType === 'stream' && __('Upload')) || __(toCapitalCase(valueType)))) ||
|
2020-04-15 16:12:54 +02:00
|
|
|
(type && __(toCapitalCase(type)))}
|
2020-04-10 19:31:36 +02:00
|
|
|
</span>{' '}
|
2020-10-02 06:53:32 +02:00
|
|
|
{isRevokeable && this.getLink(type, isTip, valueType)}
|
2020-04-10 19:31:36 +02:00
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
{forClaim && <Button button="link" navigate={uri} label={claimName} disabled={!date} />}
|
|
|
|
{!forClaim && reward && <span>{reward.reward_title}</span>}
|
|
|
|
</td>
|
|
|
|
|
|
|
|
<td>
|
|
|
|
<ButtonTransaction id={txid} />
|
|
|
|
</td>
|
|
|
|
<td className="table__item--align-right">
|
|
|
|
<CreditAmount
|
|
|
|
showPlus={isMinus}
|
|
|
|
amount={isMinus ? Number(0 - amount) : Number(amount)}
|
|
|
|
precision={8}
|
|
|
|
showLBC={false}
|
|
|
|
/>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export default TxoListItem;
|