confirmation cleanup
This commit is contained in:
parent
01e0a2a5db
commit
deb4107dd0
8 changed files with 146 additions and 167 deletions
|
@ -135,7 +135,7 @@
|
|||
"imagesloaded": "^4.1.4",
|
||||
"json-loader": "^0.5.4",
|
||||
"lbry-format": "https://github.com/lbryio/lbry-format.git",
|
||||
"lbry-redux": "lbryio/lbry-redux#70c2ffc0bd8b69e44fc867b98c4763f387494c4d",
|
||||
"lbry-redux": "lbryio/lbry-redux#f8ac5359d9d05fba2c3a536003a9d4c64b86c9f0",
|
||||
"lbryinc": "lbryio/lbryinc#3ceb09549cb5ec22927ce3bea44ae8dbe2e4a006",
|
||||
"lint-staged": "^7.0.2",
|
||||
"localforage": "^1.7.1",
|
||||
|
|
|
@ -8,6 +8,7 @@ import {
|
|||
SETTINGS,
|
||||
selectMyChannelClaims,
|
||||
makeSelectClaimIsMine,
|
||||
selectFetchingMyChannels,
|
||||
} from 'lbry-redux';
|
||||
import WalletSendTip from './view';
|
||||
import { doOpenModal, doHideModal } from 'redux/actions/app';
|
||||
|
@ -23,12 +24,13 @@ const select = (state, props) => ({
|
|||
instantTipMax: makeSelectClientSetting(SETTINGS.INSTANT_PURCHASE_MAX)(state),
|
||||
channels: selectMyChannelClaims(state),
|
||||
claimIsMine: makeSelectClaimIsMine(props.uri)(state),
|
||||
fetchingChannels: selectFetchingMyChannels(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
openModal: (modal, props) => dispatch(doOpenModal(modal, props)),
|
||||
closeModal: () => dispatch(doHideModal()),
|
||||
sendSupport: (amount, claimId, isSupport) => dispatch(doSendTip(amount, claimId, isSupport)),
|
||||
sendSupport: (params, isSupport) => dispatch(doSendTip(params, isSupport)),
|
||||
});
|
||||
|
||||
export default withRouter(connect(select, perform)(WalletSendTip));
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
// @flow
|
||||
import * as MODALS from 'constants/modal_types';
|
||||
import * as ICONS from 'constants/icons';
|
||||
import * as PAGES from 'constants/pages';
|
||||
import React from 'react';
|
||||
import Button from 'component/button';
|
||||
import { FormField, Form } from 'component/common/form';
|
||||
import { MINIMUM_PUBLISH_BID } from 'constants/claim';
|
||||
import { MINIMUM_PUBLISH_BID, CHANNEL_ANONYMOUS } from 'constants/claim';
|
||||
import useIsMobile from 'effects/use-is-mobile';
|
||||
import CreditAmount from 'component/common/credit-amount';
|
||||
import I18nMessage from 'component/i18nMessage';
|
||||
|
@ -18,17 +17,19 @@ import usePersistedState from 'effects/use-persisted-state';
|
|||
|
||||
const DEFAULT_TIP_AMOUNTS = [5, 25, 100, 1000];
|
||||
|
||||
type SupportParams = { amount: number, claim_id: string, channel_id?: string };
|
||||
|
||||
type Props = {
|
||||
uri: string,
|
||||
claimIsMine: boolean,
|
||||
title: string,
|
||||
claim: StreamClaim,
|
||||
isPending: boolean,
|
||||
sendSupport: (number, string, boolean) => void,
|
||||
sendSupport: (SupportParams, boolean) => void,
|
||||
closeModal: () => void,
|
||||
balance: number,
|
||||
isSupport: boolean,
|
||||
openModal: (id: string, { tipAmount: number, claimId: string, isSupport: boolean }) => void,
|
||||
fetchingChannels: boolean,
|
||||
instantTipEnabled: boolean,
|
||||
instantTipMax: { amount: number, currency: string },
|
||||
channels: ?Array<ChannelClaim>,
|
||||
|
@ -44,19 +45,21 @@ function WalletSendTip(props: Props) {
|
|||
claim = {},
|
||||
instantTipEnabled,
|
||||
instantTipMax,
|
||||
openModal,
|
||||
sendSupport,
|
||||
closeModal,
|
||||
channels,
|
||||
fetchingChannels,
|
||||
} = props;
|
||||
const [tipAmount, setTipAmount] = React.useState(DEFAULT_TIP_AMOUNTS[0]);
|
||||
const [tipError, setTipError] = React.useState();
|
||||
const [isSupport, setIsSupport] = React.useState(claimIsMine);
|
||||
const [showMore, setShowMore] = React.useState(false);
|
||||
const [isConfirming, setIsConfirming] = React.useState(false);
|
||||
const isMobile = useIsMobile();
|
||||
const [selectedChannel, setSelectedChannel] = usePersistedState('comment-support:channel');
|
||||
|
||||
const { claim_id: claimId } = claim;
|
||||
const { channelName } = parseURI(uri);
|
||||
|
||||
const channelStrings = channels && channels.map(channel => channel.permanent_url).join(',');
|
||||
React.useEffect(() => {
|
||||
if (!selectedChannel && channelStrings) {
|
||||
|
@ -89,11 +92,27 @@ function WalletSendTip(props: Props) {
|
|||
}, [tipAmount, balance, setTipError]);
|
||||
|
||||
function sendSupportOrConfirm(instantTipMaxAmount = null) {
|
||||
if (!isSupport && (!instantTipMaxAmount || !instantTipEnabled || tipAmount > instantTipMaxAmount)) {
|
||||
const modalProps = { uri, tipAmount, claimId, title, isSupport };
|
||||
openModal(MODALS.CONFIRM_SEND_TIP, modalProps);
|
||||
let selectedChannelId;
|
||||
if (selectedChannel !== CHANNEL_ANONYMOUS) {
|
||||
const selectedChannelClaim = channels && channels.find(channelClaim => channelClaim.name === selectedChannel);
|
||||
|
||||
if (selectedChannelClaim) {
|
||||
selectedChannelId = selectedChannelClaim.claim_id;
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
!isSupport &&
|
||||
!isConfirming &&
|
||||
(!instantTipMaxAmount || !instantTipEnabled || tipAmount > instantTipMaxAmount)
|
||||
) {
|
||||
setIsConfirming(true);
|
||||
} else {
|
||||
sendSupport(tipAmount, claimId, isSupport);
|
||||
const supportParams: SupportParams = { amount: tipAmount, claim_id: claimId };
|
||||
if (selectedChannelId) {
|
||||
supportParams.channel_id = selectedChannelId;
|
||||
}
|
||||
sendSupport(supportParams, isSupport);
|
||||
closeModal();
|
||||
}
|
||||
}
|
||||
|
@ -147,94 +166,114 @@ function WalletSendTip(props: Props) {
|
|||
</React.Fragment>
|
||||
}
|
||||
actions={
|
||||
<>
|
||||
<div className="section">
|
||||
<SelectChannel
|
||||
label="Channel to show support as"
|
||||
channel={selectedChannel}
|
||||
onChannelChange={newChannel => setSelectedChannel(newChannel)}
|
||||
/>
|
||||
</div>
|
||||
isConfirming ? (
|
||||
<>
|
||||
<div className="section section--padded card--inline confirm__wrapper">
|
||||
<div className="section">
|
||||
<div className="confirm__label">{__('To')}</div>
|
||||
<div className="confirm__value">{channelName || title}</div>
|
||||
<div className="confirm__label">{__('From')}</div>
|
||||
<div className="confirm__value">{selectedChannel}</div>
|
||||
<div className="confirm__label">{__(isSupport ? 'Supporting' : 'Tipping')}</div>
|
||||
<div className="confirm__value">{tipAmount} LBC</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="section__actions">
|
||||
<Button autoFocus button="primary" disabled={isPending} label={__('Confirm')} />
|
||||
<Button button="link" label={__('Cancel')} onClick={() => setIsConfirming(false)} />
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<div className="section">
|
||||
<SelectChannel
|
||||
label="Channel to show support as"
|
||||
channel={selectedChannel}
|
||||
onChannelChange={newChannel => setSelectedChannel(newChannel)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="section">
|
||||
{DEFAULT_TIP_AMOUNTS.map(amount => (
|
||||
<div className="section">
|
||||
{DEFAULT_TIP_AMOUNTS.map(amount => (
|
||||
<Button
|
||||
key={amount}
|
||||
disabled={amount > balance}
|
||||
button="alt"
|
||||
className={classnames('button-toggle', {
|
||||
'button-toggle--active': tipAmount === amount,
|
||||
'button-toggle--disabled': amount > balance,
|
||||
})}
|
||||
label={`${amount} LBC`}
|
||||
onClick={() => setTipAmount(amount)}
|
||||
/>
|
||||
))}
|
||||
<Button
|
||||
key={amount}
|
||||
disabled={amount > balance}
|
||||
button="alt"
|
||||
className={classnames('button-toggle', {
|
||||
'button-toggle--active': tipAmount === amount,
|
||||
'button-toggle--disabled': amount > balance,
|
||||
'button-toggle--active': !DEFAULT_TIP_AMOUNTS.includes(tipAmount),
|
||||
})}
|
||||
label={`${amount} LBC`}
|
||||
onClick={() => setTipAmount(amount)}
|
||||
/>
|
||||
))}
|
||||
<Button
|
||||
button="alt"
|
||||
className={classnames('button-toggle', {
|
||||
'button-toggle--active': !DEFAULT_TIP_AMOUNTS.includes(tipAmount),
|
||||
})}
|
||||
label={__('Custom')}
|
||||
onClick={() => setShowMore(true)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{showMore && (
|
||||
<div className="section">
|
||||
<FormField
|
||||
autoFocus
|
||||
name="tip-input"
|
||||
label={
|
||||
<React.Fragment>
|
||||
{'Custom support amount'}{' '}
|
||||
{isMobile && (
|
||||
<I18nMessage tokens={{ lbc_balance: <CreditAmount badge={false} amount={balance} /> }}>
|
||||
(%lbc_balance% available)
|
||||
</I18nMessage>
|
||||
)}
|
||||
</React.Fragment>
|
||||
}
|
||||
className="form-field--price-amount"
|
||||
error={tipError}
|
||||
min="0"
|
||||
step="any"
|
||||
type="number"
|
||||
placeholder="1.23"
|
||||
onChange={event => handleSupportPriceChange(event)}
|
||||
label={__('Custom')}
|
||||
onClick={() => setShowMore(true)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="section__actions">
|
||||
<Button
|
||||
autoFocus
|
||||
icon={isSupport ? undefined : ICONS.SUPPORT}
|
||||
button="primary"
|
||||
type="submit"
|
||||
disabled={isPending || tipError || !tipAmount}
|
||||
label={
|
||||
isSupport
|
||||
? __('Send Revokable Support')
|
||||
: __('Send a %amount% Tip', { amount: tipAmount ? `${tipAmount} LBC` : '' })
|
||||
}
|
||||
/>
|
||||
{!claimIsMine && (
|
||||
<FormField
|
||||
name="toggle-is-support"
|
||||
type="checkbox"
|
||||
label={__('Make this support permanent')}
|
||||
checked={!isSupport}
|
||||
onChange={() => setIsSupport(!isSupport)}
|
||||
/>
|
||||
{showMore && (
|
||||
<div className="section">
|
||||
<FormField
|
||||
autoFocus
|
||||
name="tip-input"
|
||||
label={
|
||||
<React.Fragment>
|
||||
{'Custom support amount'}{' '}
|
||||
{isMobile && (
|
||||
<I18nMessage tokens={{ lbc_balance: <CreditAmount badge={false} amount={balance} /> }}>
|
||||
(%lbc_balance% available)
|
||||
</I18nMessage>
|
||||
)}
|
||||
</React.Fragment>
|
||||
}
|
||||
className="form-field--price-amount"
|
||||
error={tipError}
|
||||
min="0"
|
||||
step="any"
|
||||
type="number"
|
||||
placeholder="1.23"
|
||||
onChange={event => handleSupportPriceChange(event)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{DEFAULT_TIP_AMOUNTS.some(val => val > balance) && (
|
||||
<div className="section">
|
||||
<Button button="link" label={__('Buy More LBC')} />
|
||||
|
||||
<div className="section__actions">
|
||||
<Button
|
||||
autoFocus
|
||||
icon={isSupport ? undefined : ICONS.SUPPORT}
|
||||
button="primary"
|
||||
type="submit"
|
||||
disabled={fetchingChannels || isPending || tipError || !tipAmount}
|
||||
label={
|
||||
isSupport
|
||||
? __('Send Revokable Support')
|
||||
: __('Send a %amount% Tip', { amount: tipAmount ? `${tipAmount} LBC` : '' })
|
||||
}
|
||||
/>
|
||||
{fetchingChannels && <span className="help">{__('Loading your channels...')}</span>}
|
||||
{!claimIsMine && !fetchingChannels && (
|
||||
<FormField
|
||||
name="toggle-is-support"
|
||||
type="checkbox"
|
||||
label={__('Make this support permanent')}
|
||||
checked={!isSupport}
|
||||
onChange={() => setIsSupport(!isSupport)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
{DEFAULT_TIP_AMOUNTS.some(val => val > balance) && (
|
||||
<div className="section">
|
||||
<Button button="link" label={__('Buy More LBC')} />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { doSendTip } from 'lbry-redux';
|
||||
import { doHideModal } from 'redux/actions/app';
|
||||
import ModalConfirmSendTip from './view';
|
||||
|
||||
const perform = dispatch => ({
|
||||
closeModal: () => dispatch(doHideModal()),
|
||||
sendSupport: (tipAmount, claimId, isSupport) => dispatch(doSendTip(tipAmount, claimId, isSupport)),
|
||||
});
|
||||
|
||||
export default connect(null, perform)(ModalConfirmSendTip);
|
|
@ -1,61 +0,0 @@
|
|||
// @flow
|
||||
import React from 'react';
|
||||
import { parseURI } from 'lbry-redux';
|
||||
import Button from 'component/button';
|
||||
import { Form } from 'component/common/form';
|
||||
import { Modal } from 'modal/modal';
|
||||
import Card from 'component/common/card';
|
||||
|
||||
type Props = {
|
||||
uri: string,
|
||||
claimId: string,
|
||||
title: string,
|
||||
tipAmount: number,
|
||||
isSupport: boolean,
|
||||
closeModal: () => void,
|
||||
sendSupport: (number, string, boolean) => void,
|
||||
};
|
||||
|
||||
class ModalConfirmSendTip extends React.PureComponent<Props> {
|
||||
onConfirmed() {
|
||||
const { closeModal, sendSupport, tipAmount, claimId, isSupport } = this.props;
|
||||
sendSupport(tipAmount, claimId, isSupport);
|
||||
closeModal();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { tipAmount, title, isSupport, closeModal, uri } = this.props;
|
||||
const cardTitle = __(isSupport ? 'Confirm Support' : 'Confirm Tip');
|
||||
const { channelName } = parseURI(uri);
|
||||
|
||||
return (
|
||||
<Modal isOpen type="card" onAborted={closeModal} contentLabel={cardTitle}>
|
||||
<Form onSubmit={() => this.onConfirmed()}>
|
||||
<Card
|
||||
title={cardTitle}
|
||||
body={
|
||||
<>
|
||||
<div className="section">
|
||||
<label>{__(isSupport ? 'Supporting: ' : 'Tipping: ')}</label>
|
||||
<blockquote>{tipAmount} LBC</blockquote>
|
||||
</div>
|
||||
<div className="section">
|
||||
<label>{__('To: ')}</label>
|
||||
<blockquote>{title || channelName}</blockquote>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
actions={
|
||||
<div className="section__actions">
|
||||
<Button autoFocus button="primary" type="submit" label={__('Send')} />
|
||||
<Button button="link" label={__('Cancel')} onClick={closeModal} />
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
</Form>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ModalConfirmSendTip;
|
|
@ -19,7 +19,6 @@ import ModalFirstSubscription from 'modal/modalFirstSubscription';
|
|||
import ModalConfirmTransaction from 'modal/modalConfirmTransaction';
|
||||
import ModalSocialShare from 'modal/modalSocialShare';
|
||||
import ModalSendTip from 'modal/modalSendTip';
|
||||
import ModalConfirmSendTip from 'modal/modalConfirmSendTip';
|
||||
import ModalPublish from 'modal/modalPublish';
|
||||
import ModalOpenExternalResource from 'modal/modalOpenExternalResource';
|
||||
import ModalConfirmThumbnailUpload from 'modal/modalConfirmThumbnailUpload';
|
||||
|
@ -97,8 +96,6 @@ function ModalRouter(props: Props) {
|
|||
return <ModalFirstSubscription {...modalProps} />;
|
||||
case MODALS.SEND_TIP:
|
||||
return <ModalSendTip {...modalProps} />;
|
||||
case MODALS.CONFIRM_SEND_TIP:
|
||||
return <ModalConfirmSendTip {...modalProps} />;
|
||||
case MODALS.SOCIAL_SHARE:
|
||||
return <ModalSocialShare {...modalProps} />;
|
||||
case MODALS.PUBLISH:
|
||||
|
|
|
@ -288,3 +288,16 @@ textarea {
|
|||
.privacy-img {
|
||||
height: 10rem;
|
||||
}
|
||||
|
||||
.confirm__label {
|
||||
@extend label;
|
||||
}
|
||||
|
||||
.confirm__value {
|
||||
margin-bottom: var(--spacing-m);
|
||||
font-size: var(--font-large);
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6207,9 +6207,9 @@ lazy-val@^1.0.4:
|
|||
yargs "^13.2.2"
|
||||
zstd-codec "^0.1.1"
|
||||
|
||||
lbry-redux@lbryio/lbry-redux#70c2ffc0bd8b69e44fc867b98c4763f387494c4d:
|
||||
lbry-redux@lbryio/lbry-redux#f8ac5359d9d05fba2c3a536003a9d4c64b86c9f0:
|
||||
version "0.0.1"
|
||||
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/70c2ffc0bd8b69e44fc867b98c4763f387494c4d"
|
||||
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/f8ac5359d9d05fba2c3a536003a9d4c64b86c9f0"
|
||||
dependencies:
|
||||
proxy-polyfill "0.1.6"
|
||||
reselect "^3.0.0"
|
||||
|
|
Loading…
Add table
Reference in a new issue