mirror of
https://github.com/LBRYFoundation/lbry-desktop.git
synced 2025-08-23 17:47:24 +00:00
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",
|
"imagesloaded": "^4.1.4",
|
||||||
"json-loader": "^0.5.4",
|
"json-loader": "^0.5.4",
|
||||||
"lbry-format": "https://github.com/lbryio/lbry-format.git",
|
"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",
|
"lbryinc": "lbryio/lbryinc#eee2cb730ecec95a1344a755035755b0d4dad5cf",
|
||||||
"lint-staged": "^7.0.2",
|
"lint-staged": "^7.0.2",
|
||||||
"localforage": "^1.7.1",
|
"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%",
|
"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.",
|
"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.",
|
"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--"
|
"--end--": "--end--"
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,10 @@ import {
|
||||||
selectUtxoCounts,
|
selectUtxoCounts,
|
||||||
doFetchUtxoCounts,
|
doFetchUtxoCounts,
|
||||||
doUtxoConsolidate,
|
doUtxoConsolidate,
|
||||||
selectPendingOtherTransactions,
|
|
||||||
selectIsConsolidatingUtxos,
|
selectIsConsolidatingUtxos,
|
||||||
|
selectIsMassClaimingTips,
|
||||||
|
selectPendingConsolidateTxid,
|
||||||
|
selectPendingMassClaimTxid,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { doOpenModal } from 'redux/actions/app';
|
import { doOpenModal } from 'redux/actions/app';
|
||||||
import { selectSyncHash } from 'redux/selectors/sync';
|
import { selectSyncHash } from 'redux/selectors/sync';
|
||||||
|
@ -25,8 +27,10 @@ const select = state => ({
|
||||||
hasSynced: Boolean(selectSyncHash(state)),
|
hasSynced: Boolean(selectSyncHash(state)),
|
||||||
fetchingUtxoCounts: selectIsFetchingUtxoCounts(state),
|
fetchingUtxoCounts: selectIsFetchingUtxoCounts(state),
|
||||||
consolidatingUtxos: selectIsConsolidatingUtxos(state),
|
consolidatingUtxos: selectIsConsolidatingUtxos(state),
|
||||||
|
massClaimingTips: selectIsMassClaimingTips(state),
|
||||||
utxoCounts: selectUtxoCounts(state),
|
utxoCounts: selectUtxoCounts(state),
|
||||||
pendingUtxoConsolidating: selectPendingOtherTransactions(state),
|
consolidateIsPending: selectPendingConsolidateTxid(state),
|
||||||
|
massClaimIsPending: selectPendingMassClaimTxid(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, {
|
export default connect(select, {
|
||||||
|
|
|
@ -23,11 +23,13 @@ type Props = {
|
||||||
doUtxoConsolidate: () => void,
|
doUtxoConsolidate: () => void,
|
||||||
fetchingUtxoCounts: boolean,
|
fetchingUtxoCounts: boolean,
|
||||||
consolidatingUtxos: boolean,
|
consolidatingUtxos: boolean,
|
||||||
|
consolidateIsPending: boolean,
|
||||||
|
massClaimingTips: boolean,
|
||||||
|
massClaimIsPending: boolean,
|
||||||
utxoCounts: { [string]: number },
|
utxoCounts: { [string]: number },
|
||||||
pendingUtxoConsolidating: Array<string>,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const WALLET_CONSOLIDATE_UTXOS = 400;
|
export const WALLET_CONSOLIDATE_UTXOS = 400;
|
||||||
const LARGE_WALLET_BALANCE = 100;
|
const LARGE_WALLET_BALANCE = 100;
|
||||||
|
|
||||||
const WalletBalance = (props: Props) => {
|
const WalletBalance = (props: Props) => {
|
||||||
|
@ -38,23 +40,27 @@ const WalletBalance = (props: Props) => {
|
||||||
tipsBalance,
|
tipsBalance,
|
||||||
doOpenModal,
|
doOpenModal,
|
||||||
hasSynced,
|
hasSynced,
|
||||||
pendingUtxoConsolidating,
|
|
||||||
doUtxoConsolidate,
|
doUtxoConsolidate,
|
||||||
doFetchUtxoCounts,
|
doFetchUtxoCounts,
|
||||||
consolidatingUtxos,
|
consolidatingUtxos,
|
||||||
|
consolidateIsPending,
|
||||||
|
massClaimingTips,
|
||||||
|
massClaimIsPending,
|
||||||
utxoCounts,
|
utxoCounts,
|
||||||
} = props;
|
} = props;
|
||||||
const [detailsExpanded, setDetailsExpanded] = React.useState(false);
|
const [detailsExpanded, setDetailsExpanded] = React.useState(false);
|
||||||
|
|
||||||
const { other: otherCount = 0 } = utxoCounts || {};
|
const { other: otherCount = 0 } = utxoCounts || {};
|
||||||
|
|
||||||
const totalBalance = balance + tipsBalance + supportsBalance + claimsBalance;
|
const totalBalance = balance + tipsBalance + supportsBalance + claimsBalance;
|
||||||
const totalLocked = tipsBalance + claimsBalance + supportsBalance;
|
const totalLocked = tipsBalance + claimsBalance + supportsBalance;
|
||||||
|
const operationPending = massClaimIsPending || massClaimingTips || consolidateIsPending || consolidatingUtxos;
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (balance > LARGE_WALLET_BALANCE) {
|
if (balance > LARGE_WALLET_BALANCE && detailsExpanded) {
|
||||||
doFetchUtxoCounts();
|
doFetchUtxoCounts();
|
||||||
}
|
}
|
||||||
}, [doFetchUtxoCounts, balance]);
|
}, [doFetchUtxoCounts, balance, detailsExpanded]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
|
@ -71,7 +77,7 @@ const WalletBalance = (props: Props) => {
|
||||||
actions={
|
actions={
|
||||||
<>
|
<>
|
||||||
<h2 className="section__title--small">
|
<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
|
%lbc_amount% immediately spendable
|
||||||
</I18nMessage>
|
</I18nMessage>
|
||||||
</h2>
|
</h2>
|
||||||
|
@ -79,7 +85,7 @@ const WalletBalance = (props: Props) => {
|
||||||
<h2 className="section__title--small">
|
<h2 className="section__title--small">
|
||||||
<I18nMessage
|
<I18nMessage
|
||||||
tokens={{
|
tokens={{
|
||||||
lbc_amount: <CreditAmount amount={totalLocked} precision={8} />,
|
lbc_amount: <CreditAmount amount={totalLocked} precision={4} />,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
%lbc_amount% boosting content
|
%lbc_amount% boosting content
|
||||||
|
@ -95,27 +101,38 @@ const WalletBalance = (props: Props) => {
|
||||||
<div className="section__subtitle">
|
<div className="section__subtitle">
|
||||||
<dl>
|
<dl>
|
||||||
<dt>
|
<dt>
|
||||||
{__('...earned from others')}
|
<span className="dt__text">{__('...earned from others')}</span>
|
||||||
<span className="help--dt">({__('Unlock to spend')})</span>
|
<span className="help--dt">({__('Unlock to spend')})</span>
|
||||||
</dt>
|
</dt>
|
||||||
<dd>
|
<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>
|
</dd>
|
||||||
|
|
||||||
<dt>
|
<dt>
|
||||||
{__('...on initial publishes')}
|
<span className="dt__text">{__('...on initial publishes')}</span>
|
||||||
<span className="help--dt">({__('Delete or edit past content to spend')})</span>
|
<span className="help--dt">({__('Delete or edit past content to spend')})</span>
|
||||||
</dt>
|
</dt>
|
||||||
<dd>
|
<dd>
|
||||||
<CreditAmount amount={claimsBalance} precision={8} />
|
<CreditAmount amount={claimsBalance} precision={4} />
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt>
|
<dt>
|
||||||
{__('...supporting content')}
|
<span className="dt__text">{__('...supporting content')}</span>
|
||||||
<span className="help--dt">({__('Delete supports to spend')})</span>
|
<span className="help--dt">({__('Delete supports to spend')})</span>
|
||||||
</dt>
|
</dt>
|
||||||
<dd>
|
<dd>
|
||||||
<CreditAmount amount={supportsBalance} precision={8} />
|
<CreditAmount amount={supportsBalance} precision={4} />
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
|
@ -149,7 +166,7 @@ const WalletBalance = (props: Props) => {
|
||||||
onClick={() => doOpenModal(MODALS.WALLET_SEND)}
|
onClick={() => doOpenModal(MODALS.WALLET_SEND)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{(otherCount > WALLET_CONSOLIDATE_UTXOS || pendingUtxoConsolidating.length || consolidatingUtxos) && (
|
{(otherCount > WALLET_CONSOLIDATE_UTXOS || consolidateIsPending || consolidatingUtxos) && (
|
||||||
<p className="help">
|
<p className="help">
|
||||||
<I18nMessage
|
<I18nMessage
|
||||||
tokens={{
|
tokens={{
|
||||||
|
@ -157,11 +174,9 @@ const WalletBalance = (props: Props) => {
|
||||||
<Button
|
<Button
|
||||||
button="link"
|
button="link"
|
||||||
onClick={() => doUtxoConsolidate()}
|
onClick={() => doUtxoConsolidate()}
|
||||||
disabled={pendingUtxoConsolidating.length || consolidatingUtxos}
|
disabled={operationPending}
|
||||||
label={
|
label={
|
||||||
pendingUtxoConsolidating.length || consolidatingUtxos
|
consolidateIsPending || consolidatingUtxos ? __('Consolidating...') : __('Consolidate Now')
|
||||||
? __('Consolidating')
|
|
||||||
: __('Consolidate Now')
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
|
|
|
@ -39,6 +39,7 @@ export const SET_REFERRER = 'set_referrer';
|
||||||
export const REPOST = 'repost';
|
export const REPOST = 'repost';
|
||||||
export const SIGN_OUT = 'sign_out';
|
export const SIGN_OUT = 'sign_out';
|
||||||
export const LIQUIDATE_SUPPORTS = 'liquidate_supports';
|
export const LIQUIDATE_SUPPORTS = 'liquidate_supports';
|
||||||
|
export const MASS_TIP_UNLOCK = 'mass_tip_unlock';
|
||||||
export const CONFIRM_AGE = 'confirm_age';
|
export const CONFIRM_AGE = 'confirm_age';
|
||||||
export const SYNC_ENABLE = 'SYNC_ENABLE';
|
export const SYNC_ENABLE = 'SYNC_ENABLE';
|
||||||
export const REMOVE_BLOCKED = 'remove_blocked';
|
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 ModalImageUpload from 'modal/modalImageUpload';
|
||||||
import ModalMobileSearch from 'modal/modalMobileSearch';
|
import ModalMobileSearch from 'modal/modalMobileSearch';
|
||||||
import ModalViewImage from 'modal/modalViewImage';
|
import ModalViewImage from 'modal/modalViewImage';
|
||||||
|
import ModalMassTipsUnlock from 'modal/modalMassTipUnlock';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
modal: { id: string, modalProps: {} },
|
modal: { id: string, modalProps: {} },
|
||||||
|
@ -154,6 +155,8 @@ function ModalRouter(props: Props) {
|
||||||
return <ModalMobileSearch {...modalProps} />;
|
return <ModalMobileSearch {...modalProps} />;
|
||||||
case MODALS.VIEW_IMAGE:
|
case MODALS.VIEW_IMAGE:
|
||||||
return <ModalViewImage {...modalProps} />;
|
return <ModalViewImage {...modalProps} />;
|
||||||
|
case MODALS.MASS_TIP_UNLOCK:
|
||||||
|
return <ModalMassTipsUnlock {...modalProps} />;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,17 +88,38 @@ dt {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dt__text {
|
||||||
|
margin-right: var(--spacing-s);
|
||||||
|
}
|
||||||
|
|
||||||
dd {
|
dd {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
flex-basis: 45%;
|
flex-basis: 45%;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
text-align: right;
|
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,
|
dt,
|
||||||
dd {
|
dd {
|
||||||
padding: var(--spacing-m) var(--spacing-s);
|
padding: var(--spacing-m) var(--spacing-s);
|
||||||
|
|
||||||
border-top: 1px solid var(--color-border);
|
border-top: 1px solid var(--color-border);
|
||||||
|
|
||||||
&:last-of-type {
|
&:last-of-type {
|
||||||
|
@ -267,7 +288,6 @@ textarea {
|
||||||
@extend .help;
|
@extend .help;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-left: var(--spacing-s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.help--spendable {
|
.help--spendable {
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
--color-text-subtitle: #767676;
|
--color-text-subtitle: #767676;
|
||||||
--color-text-warning: #212529;
|
--color-text-warning: #212529;
|
||||||
--color-help-warning-bg: #fef3c7;
|
--color-help-warning-bg: #fef3c7;
|
||||||
--color-help-warning-text: black;
|
--color-help-warning-text: #555555;
|
||||||
--color-text-warning--background: var(--lbry-yellow-1);
|
--color-text-warning--background: var(--lbry-yellow-1);
|
||||||
--color-blockquote: var(--color-gray-3);
|
--color-blockquote: var(--color-gray-3);
|
||||||
--color-blockquote-bg: var(--color-gray-1);
|
--color-blockquote-bg: var(--color-gray-1);
|
||||||
|
|
|
@ -6911,9 +6911,9 @@ lazy-val@^1.0.4:
|
||||||
yargs "^13.2.2"
|
yargs "^13.2.2"
|
||||||
zstd-codec "^0.1.1"
|
zstd-codec "^0.1.1"
|
||||||
|
|
||||||
lbry-redux@lbryio/lbry-redux#7bd6ae1824f9241fdaea6441558fb52f0e465553:
|
lbry-redux@lbryio/lbry-redux#ba141f762b1802bd937c2dec8ac0140c708d4df6:
|
||||||
version "0.0.1"
|
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:
|
dependencies:
|
||||||
proxy-polyfill "0.1.6"
|
proxy-polyfill "0.1.6"
|
||||||
reselect "^3.0.0"
|
reselect "^3.0.0"
|
||||||
|
|
Loading…
Add table
Reference in a new issue