mass claim tips
bump ui pass move mass tip unlock to modal better track wallet operations in progress
This commit is contained in:
parent
03f419a49c
commit
d01f3da174
11 changed files with 160 additions and 26 deletions
|
@ -142,7 +142,7 @@
|
|||
"imagesloaded": "^4.1.4",
|
||||
"json-loader": "^0.5.4",
|
||||
"lbry-format": "https://github.com/lbryio/lbry-format.git",
|
||||
"lbry-redux": "lbryio/lbry-redux#7bd6ae1824f9241fdaea6441558fb52f0e465553",
|
||||
"lbry-redux": "lbryio/lbry-redux#ba141f762b1802bd937c2dec8ac0140c708d4df6",
|
||||
"lbryinc": "lbryio/lbryinc#eee2cb730ecec95a1344a755035755b0d4dad5cf",
|
||||
"lint-staged": "^7.0.2",
|
||||
"localforage": "^1.7.1",
|
||||
|
|
|
@ -1564,5 +1564,7 @@
|
|||
"Deposit cannot be higher than your available balance: %balance%": "Deposit cannot be higher than your available balance: %balance%",
|
||||
"This channel has disabled comments on their page.": "This channel has disabled comments on their page.",
|
||||
"The creator of this content has disabled comments.": "The creator of this content has disabled comments.",
|
||||
"These %lbc% help your content in search rankings. You can unlock them but that's less fun. %unlock%": "These %lbc% help your content in search rankings. You can unlock them but that's less fun. %unlock%",
|
||||
"You have a lot of tips. This could take some time.": "You have a lot of tips. This could take some time.",
|
||||
"--end--": "--end--"
|
||||
}
|
||||
|
|
|
@ -8,8 +8,10 @@ import {
|
|||
selectUtxoCounts,
|
||||
doFetchUtxoCounts,
|
||||
doUtxoConsolidate,
|
||||
selectPendingOtherTransactions,
|
||||
selectIsConsolidatingUtxos,
|
||||
selectIsMassClaimingTips,
|
||||
selectPendingConsolidateTxid,
|
||||
selectPendingMassClaimTxid,
|
||||
} from 'lbry-redux';
|
||||
import { doOpenModal } from 'redux/actions/app';
|
||||
import { selectSyncHash } from 'redux/selectors/sync';
|
||||
|
@ -25,8 +27,10 @@ const select = state => ({
|
|||
hasSynced: Boolean(selectSyncHash(state)),
|
||||
fetchingUtxoCounts: selectIsFetchingUtxoCounts(state),
|
||||
consolidatingUtxos: selectIsConsolidatingUtxos(state),
|
||||
massClaimingTips: selectIsMassClaimingTips(state),
|
||||
utxoCounts: selectUtxoCounts(state),
|
||||
pendingUtxoConsolidating: selectPendingOtherTransactions(state),
|
||||
consolidateIsPending: selectPendingConsolidateTxid(state),
|
||||
massClaimIsPending: selectPendingMassClaimTxid(state),
|
||||
});
|
||||
|
||||
export default connect(select, {
|
||||
|
|
|
@ -23,11 +23,13 @@ type Props = {
|
|||
doUtxoConsolidate: () => void,
|
||||
fetchingUtxoCounts: boolean,
|
||||
consolidatingUtxos: boolean,
|
||||
consolidateIsPending: boolean,
|
||||
massClaimingTips: boolean,
|
||||
massClaimIsPending: boolean,
|
||||
utxoCounts: { [string]: number },
|
||||
pendingUtxoConsolidating: Array<string>,
|
||||
};
|
||||
|
||||
const WALLET_CONSOLIDATE_UTXOS = 400;
|
||||
export const WALLET_CONSOLIDATE_UTXOS = 400;
|
||||
const LARGE_WALLET_BALANCE = 100;
|
||||
|
||||
const WalletBalance = (props: Props) => {
|
||||
|
@ -38,23 +40,27 @@ const WalletBalance = (props: Props) => {
|
|||
tipsBalance,
|
||||
doOpenModal,
|
||||
hasSynced,
|
||||
pendingUtxoConsolidating,
|
||||
doUtxoConsolidate,
|
||||
doFetchUtxoCounts,
|
||||
consolidatingUtxos,
|
||||
consolidateIsPending,
|
||||
massClaimingTips,
|
||||
massClaimIsPending,
|
||||
utxoCounts,
|
||||
} = props;
|
||||
const [detailsExpanded, setDetailsExpanded] = React.useState(false);
|
||||
|
||||
const { other: otherCount = 0 } = utxoCounts || {};
|
||||
|
||||
const totalBalance = balance + tipsBalance + supportsBalance + claimsBalance;
|
||||
const totalLocked = tipsBalance + claimsBalance + supportsBalance;
|
||||
const operationPending = massClaimIsPending || massClaimingTips || consolidateIsPending || consolidatingUtxos;
|
||||
|
||||
React.useEffect(() => {
|
||||
if (balance > LARGE_WALLET_BALANCE) {
|
||||
if (balance > LARGE_WALLET_BALANCE && detailsExpanded) {
|
||||
doFetchUtxoCounts();
|
||||
}
|
||||
}, [doFetchUtxoCounts, balance]);
|
||||
}, [doFetchUtxoCounts, balance, detailsExpanded]);
|
||||
|
||||
return (
|
||||
<Card
|
||||
|
@ -71,7 +77,7 @@ const WalletBalance = (props: Props) => {
|
|||
actions={
|
||||
<>
|
||||
<h2 className="section__title--small">
|
||||
<I18nMessage tokens={{ lbc_amount: <CreditAmount amount={balance} precision={8} /> }}>
|
||||
<I18nMessage tokens={{ lbc_amount: <CreditAmount amount={balance} precision={4} /> }}>
|
||||
%lbc_amount% immediately spendable
|
||||
</I18nMessage>
|
||||
</h2>
|
||||
|
@ -79,7 +85,7 @@ const WalletBalance = (props: Props) => {
|
|||
<h2 className="section__title--small">
|
||||
<I18nMessage
|
||||
tokens={{
|
||||
lbc_amount: <CreditAmount amount={totalLocked} precision={8} />,
|
||||
lbc_amount: <CreditAmount amount={totalLocked} precision={4} />,
|
||||
}}
|
||||
>
|
||||
%lbc_amount% boosting content
|
||||
|
@ -95,27 +101,38 @@ const WalletBalance = (props: Props) => {
|
|||
<div className="section__subtitle">
|
||||
<dl>
|
||||
<dt>
|
||||
{__('...earned from others')}
|
||||
<span className="dt__text">{__('...earned from others')}</span>
|
||||
<span className="help--dt">({__('Unlock to spend')})</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<CreditAmount amount={tipsBalance} precision={8} />
|
||||
<span className="dd__text">
|
||||
{Boolean(tipsBalance) && (
|
||||
<Button
|
||||
button="link"
|
||||
className="dd__button"
|
||||
disabled={operationPending}
|
||||
icon={ICONS.UNLOCK}
|
||||
onClick={() => doOpenModal(MODALS.MASS_TIP_UNLOCK)}
|
||||
/>
|
||||
)}
|
||||
<CreditAmount amount={tipsBalance} precision={4} />
|
||||
</span>
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
{__('...on initial publishes')}
|
||||
<span className="dt__text">{__('...on initial publishes')}</span>
|
||||
<span className="help--dt">({__('Delete or edit past content to spend')})</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<CreditAmount amount={claimsBalance} precision={8} />
|
||||
<CreditAmount amount={claimsBalance} precision={4} />
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
{__('...supporting content')}
|
||||
<span className="dt__text">{__('...supporting content')}</span>
|
||||
<span className="help--dt">({__('Delete supports to spend')})</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<CreditAmount amount={supportsBalance} precision={8} />
|
||||
<CreditAmount amount={supportsBalance} precision={4} />
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
@ -149,7 +166,7 @@ const WalletBalance = (props: Props) => {
|
|||
onClick={() => doOpenModal(MODALS.WALLET_SEND)}
|
||||
/>
|
||||
</div>
|
||||
{(otherCount > WALLET_CONSOLIDATE_UTXOS || pendingUtxoConsolidating.length || consolidatingUtxos) && (
|
||||
{(otherCount > WALLET_CONSOLIDATE_UTXOS || consolidateIsPending || consolidatingUtxos) && (
|
||||
<p className="help">
|
||||
<I18nMessage
|
||||
tokens={{
|
||||
|
@ -157,11 +174,9 @@ const WalletBalance = (props: Props) => {
|
|||
<Button
|
||||
button="link"
|
||||
onClick={() => doUtxoConsolidate()}
|
||||
disabled={pendingUtxoConsolidating.length || consolidatingUtxos}
|
||||
disabled={operationPending}
|
||||
label={
|
||||
pendingUtxoConsolidating.length || consolidatingUtxos
|
||||
? __('Consolidating')
|
||||
: __('Consolidate Now')
|
||||
consolidateIsPending || consolidatingUtxos ? __('Consolidating...') : __('Consolidate Now')
|
||||
}
|
||||
/>
|
||||
),
|
||||
|
|
|
@ -39,6 +39,7 @@ export const SET_REFERRER = 'set_referrer';
|
|||
export const REPOST = 'repost';
|
||||
export const SIGN_OUT = 'sign_out';
|
||||
export const LIQUIDATE_SUPPORTS = 'liquidate_supports';
|
||||
export const MASS_TIP_UNLOCK = 'mass_tip_unlock';
|
||||
export const CONFIRM_AGE = 'confirm_age';
|
||||
export const SYNC_ENABLE = 'SYNC_ENABLE';
|
||||
export const REMOVE_BLOCKED = 'remove_blocked';
|
||||
|
|
15
ui/modal/modalMassTipUnlock/index.js
Normal file
15
ui/modal/modalMassTipUnlock/index.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { doHideModal } from 'redux/actions/app';
|
||||
import { selectIsMassClaimingTips, doTipClaimMass, selectUtxoCounts, selectTipsBalance } from 'lbry-redux';
|
||||
import ModalSupportsLiquidate from './view';
|
||||
|
||||
const select = state => ({
|
||||
massClaimingTips: selectIsMassClaimingTips(state),
|
||||
utxoCounts: selectUtxoCounts(state),
|
||||
tipsBalance: selectTipsBalance(state) || 0,
|
||||
});
|
||||
|
||||
export default connect(select, {
|
||||
doTipClaimMass,
|
||||
doHideModal,
|
||||
})(ModalSupportsLiquidate);
|
74
ui/modal/modalMassTipUnlock/view.jsx
Normal file
74
ui/modal/modalMassTipUnlock/view.jsx
Normal file
|
@ -0,0 +1,74 @@
|
|||
// @flow
|
||||
import * as ICONS from 'constants/icons';
|
||||
import React from 'react';
|
||||
import { Modal } from 'modal/modal';
|
||||
import I18nMessage from 'component/i18nMessage';
|
||||
import Button from 'component/button';
|
||||
import LbcSymbol from 'component/common/lbc-symbol';
|
||||
import Card from 'component/common/card';
|
||||
import { WALLET_CONSOLIDATE_UTXOS } from 'component/walletBalance/view';
|
||||
|
||||
type Props = {
|
||||
doHideModal: () => void,
|
||||
tipsBalance: number,
|
||||
doTipClaimMass: () => void,
|
||||
massClaimingTips: boolean,
|
||||
utxoCounts: { [string]: number },
|
||||
};
|
||||
|
||||
export default function ModalSupportsLiquidate(props: Props) {
|
||||
const { doHideModal, doTipClaimMass, massClaimingTips, utxoCounts, tipsBalance } = props;
|
||||
const { support: supportCount = 0 } = utxoCounts || {};
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!tipsBalance) {
|
||||
doHideModal();
|
||||
}
|
||||
}, [tipsBalance, doHideModal]);
|
||||
|
||||
return (
|
||||
<Modal isOpen contentLabel={__('Unlock all tips')} type="card" confirmButtonLabel="done" onAborted={doHideModal}>
|
||||
<Card
|
||||
icon={ICONS.UNLOCK}
|
||||
title={__('Unlock all tips')}
|
||||
subtitle={
|
||||
<>
|
||||
<p>
|
||||
<I18nMessage
|
||||
tokens={{
|
||||
lbc: <LbcSymbol />,
|
||||
}}
|
||||
>
|
||||
These %lbc% help your content in search rankings. You can unlock them but that's less fun.
|
||||
</I18nMessage>
|
||||
</p>
|
||||
<p>
|
||||
<I18nMessage
|
||||
tokens={{
|
||||
learn_more: <Button button="link" label={__('Learn More')} href="https://lbry.com/faq/tipping" />,
|
||||
}}
|
||||
>
|
||||
It's usually only worth unlocking what you intend to use immediately. %learn_more%
|
||||
</I18nMessage>
|
||||
</p>
|
||||
</>
|
||||
}
|
||||
actions={
|
||||
<>
|
||||
<div className="section__actions">
|
||||
<Button
|
||||
button="primary"
|
||||
onClick={() => doTipClaimMass()}
|
||||
disabled={massClaimingTips}
|
||||
label={massClaimingTips ? __('Working...') : __('Unlock All')}
|
||||
/>
|
||||
</div>
|
||||
{supportCount > WALLET_CONSOLIDATE_UTXOS && (
|
||||
<span className="help">{__('You have a lot of tips. This could take some time.')}</span>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
}
|
|
@ -43,6 +43,7 @@ import ModalSyncEnable from 'modal/modalSyncEnable';
|
|||
import ModalImageUpload from 'modal/modalImageUpload';
|
||||
import ModalMobileSearch from 'modal/modalMobileSearch';
|
||||
import ModalViewImage from 'modal/modalViewImage';
|
||||
import ModalMassTipsUnlock from 'modal/modalMassTipUnlock';
|
||||
|
||||
type Props = {
|
||||
modal: { id: string, modalProps: {} },
|
||||
|
@ -154,6 +155,8 @@ function ModalRouter(props: Props) {
|
|||
return <ModalMobileSearch {...modalProps} />;
|
||||
case MODALS.VIEW_IMAGE:
|
||||
return <ModalViewImage {...modalProps} />;
|
||||
case MODALS.MASS_TIP_UNLOCK:
|
||||
return <ModalMassTipsUnlock {...modalProps} />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -88,17 +88,38 @@ dt {
|
|||
font-weight: bold;
|
||||
}
|
||||
|
||||
.dt__text {
|
||||
margin-right: var(--spacing-s);
|
||||
}
|
||||
|
||||
dd {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
flex-basis: 45%;
|
||||
flex-grow: 1;
|
||||
margin: 0;
|
||||
text-align: right;
|
||||
|
||||
.help--warning {
|
||||
margin-bottom: 0;
|
||||
margin-top: var(--spacing-s);
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
.dd__text {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.dd__button {
|
||||
margin-right: var(--spacing-s);
|
||||
}
|
||||
|
||||
dt,
|
||||
dd {
|
||||
padding: var(--spacing-m) var(--spacing-s);
|
||||
|
||||
border-top: 1px solid var(--color-border);
|
||||
|
||||
&:last-of-type {
|
||||
|
@ -267,7 +288,6 @@ textarea {
|
|||
@extend .help;
|
||||
display: inline-block;
|
||||
margin-top: 0;
|
||||
margin-left: var(--spacing-s);
|
||||
}
|
||||
|
||||
.help--spendable {
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
--color-text-subtitle: #767676;
|
||||
--color-text-warning: #212529;
|
||||
--color-help-warning-bg: #fef3c7;
|
||||
--color-help-warning-text: black;
|
||||
--color-help-warning-text: #555555;
|
||||
--color-text-warning--background: var(--lbry-yellow-1);
|
||||
--color-blockquote: var(--color-gray-3);
|
||||
--color-blockquote-bg: var(--color-gray-1);
|
||||
|
|
|
@ -6911,9 +6911,9 @@ lazy-val@^1.0.4:
|
|||
yargs "^13.2.2"
|
||||
zstd-codec "^0.1.1"
|
||||
|
||||
lbry-redux@lbryio/lbry-redux#7bd6ae1824f9241fdaea6441558fb52f0e465553:
|
||||
lbry-redux@lbryio/lbry-redux#ba141f762b1802bd937c2dec8ac0140c708d4df6:
|
||||
version "0.0.1"
|
||||
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/7bd6ae1824f9241fdaea6441558fb52f0e465553"
|
||||
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/ba141f762b1802bd937c2dec8ac0140c708d4df6"
|
||||
dependencies:
|
||||
proxy-polyfill "0.1.6"
|
||||
reselect "^3.0.0"
|
||||
|
|
Loading…
Reference in a new issue