send tip modal
This commit is contained in:
parent
2d80c35ead
commit
b07c332c0f
9 changed files with 138 additions and 40 deletions
|
@ -26,11 +26,12 @@ type FormFieldProps = {
|
|||
prefix?: string,
|
||||
postfix?: string,
|
||||
error?: string | boolean,
|
||||
helper?: string | React.Node,
|
||||
};
|
||||
|
||||
export class FormField extends React.PureComponent<FormFieldProps> {
|
||||
render() {
|
||||
const { render, label, prefix, postfix, error } = this.props;
|
||||
const { render, label, prefix, postfix, error, helper } = this.props;
|
||||
/* eslint-disable jsx-a11y/label-has-for */
|
||||
// Will come back to this on the settings page
|
||||
// Need htmlFor on the label
|
||||
|
@ -47,6 +48,7 @@ export class FormField extends React.PureComponent<FormFieldProps> {
|
|||
{typeof error === 'string' ? error : __('There was an error')}
|
||||
</div>
|
||||
)}
|
||||
{helper && <div className="form-field__help">{helper}</div>}
|
||||
</div>
|
||||
);
|
||||
/* eslint-enable jsx-a11y/label-has-for */
|
||||
|
|
|
@ -1,66 +1,92 @@
|
|||
// I'll come back to this
|
||||
/* eslint-disable */
|
||||
// @flow
|
||||
import React from 'react';
|
||||
import Link from 'component/link';
|
||||
import { FormRow } from 'component/common/form';
|
||||
import Button from 'component/link';
|
||||
import { FormField } from 'component/common/form';
|
||||
import UriIndicator from 'component/uriIndicator';
|
||||
|
||||
class WalletSendTip extends React.PureComponent {
|
||||
constructor(props) {
|
||||
type Props = {
|
||||
claim_id: string,
|
||||
uri: string,
|
||||
title: string,
|
||||
errorMessage: string,
|
||||
isPending: boolean,
|
||||
sendSupport: (number, string, string) => void,
|
||||
onCancel: () => void,
|
||||
sendTipCallback?: () => void,
|
||||
};
|
||||
|
||||
type State = {
|
||||
amount: number,
|
||||
};
|
||||
|
||||
class WalletSendTip extends React.PureComponent<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
amount: 0.0,
|
||||
amount: 0,
|
||||
};
|
||||
|
||||
(this: any).handleSendButtonClicked = this.handleSendButtonClicked.bind(this);
|
||||
}
|
||||
|
||||
handleSendButtonClicked() {
|
||||
const { claim_id, uri } = this.props;
|
||||
const amount = this.state.amount;
|
||||
this.props.sendSupport(amount, claim_id, uri);
|
||||
const { claim_id: claimId, uri, sendSupport, sendTipCallback } = this.props;
|
||||
const { amount } = this.state;
|
||||
|
||||
sendSupport(amount, claimId, uri);
|
||||
|
||||
// ex: close modal
|
||||
if (sendTipCallback) {
|
||||
sendTipCallback();
|
||||
}
|
||||
}
|
||||
|
||||
handleSupportPriceChange(event) {
|
||||
handleSupportPriceChange(event: SyntheticInputEvent<*>) {
|
||||
this.setState({
|
||||
amount: Number(event.target.value),
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { errorMessage, isPending, title, uri } = this.props;
|
||||
const { errorMessage, isPending, title, uri, onCancel } = this.props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="card__title-primary">
|
||||
<h1>
|
||||
{__('Send a tip')} <UriIndicator uri={uri} />
|
||||
{__('Send a tip to')} <UriIndicator uri={uri} />
|
||||
</h1>
|
||||
</div>
|
||||
<div className="card__content">
|
||||
<FormRow
|
||||
<FormField
|
||||
label={__('Amount')}
|
||||
postfix={__('LBC')}
|
||||
min="0"
|
||||
step="any"
|
||||
type="number"
|
||||
errorMessage={errorMessage}
|
||||
error={errorMessage}
|
||||
helper={
|
||||
<span>
|
||||
{`${__('This will appear as a tip for "%s" located at %s.', title, uri)} `}
|
||||
<Link label={__('Learn more')} href="https://lbry.io/faq/tipping" />
|
||||
{__(`This will appear as a tip for ${title} located at ${uri}.`)}
|
||||
{" "}
|
||||
<Button label={__('Learn more')} fakeLink href="https://lbry.io/faq/tipping" />
|
||||
</span>
|
||||
}
|
||||
placeholder="1.00"
|
||||
onChange={event => this.handleSupportPriceChange(event)}
|
||||
render={() => (
|
||||
<input
|
||||
min="0"
|
||||
step="any"
|
||||
type="number"
|
||||
placeholder="1.00"
|
||||
onChange={event => this.handleSupportPriceChange(event)}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<div className="form-row-submit">
|
||||
<Link
|
||||
<div className="card__actions">
|
||||
<Button
|
||||
label={__('Send')}
|
||||
button="primary"
|
||||
disabled={isPending}
|
||||
onClick={this.handleSendButtonClicked.bind(this)}
|
||||
onClick={this.handleSendButtonClicked}
|
||||
/>
|
||||
<Link label={__('Cancel')} button="alt" navigate="/show" navigateParams={{ uri }} />
|
||||
<Button alt label={__('Cancel')} onClick={onCancel} navigateParams={{ uri }} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -69,4 +95,3 @@ class WalletSendTip extends React.PureComponent {
|
|||
}
|
||||
|
||||
export default WalletSendTip;
|
||||
/* eslint-enable */
|
||||
|
|
|
@ -14,3 +14,4 @@ export const TRANSACTION_FAILED = 'transaction_failed';
|
|||
export const REWARD_APPROVAL_REQUIRED = 'reward_approval_required';
|
||||
export const AFFIRM_PURCHASE = 'affirm_purchase';
|
||||
export const CONFIRM_CLAIM_REVOKE = 'confirmClaimRevoke';
|
||||
export const SEND_TIP = 'sendTip';
|
||||
|
|
|
@ -14,6 +14,7 @@ import ModalAffirmPurchase from 'modal/modalAffirmPurchase';
|
|||
import ModalRevokeClaim from 'modal/modalRevokeClaim';
|
||||
import ModalEmailCollection from '../modalEmailCollection';
|
||||
import ModalPhoneCollection from '../modalPhoneCollection';
|
||||
import ModalSendTip from '../modalSendTip';
|
||||
import * as modals from 'constants/modal_types';
|
||||
|
||||
class ModalRouter extends React.PureComponent {
|
||||
|
@ -129,6 +130,8 @@ class ModalRouter extends React.PureComponent {
|
|||
return <ModalPhoneCollection {...modalProps} />;
|
||||
case modals.EMAIL_COLLECTION:
|
||||
return <ModalEmailCollection {...modalProps} />;
|
||||
case modals.SEND_TIP:
|
||||
return <ModalSendTip {...modalProps} />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
|
9
src/renderer/modal/modalSendTip/index.js
Normal file
9
src/renderer/modal/modalSendTip/index.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { doCloseModal } from 'redux/actions/app';
|
||||
import ModalSendTip from './view';
|
||||
|
||||
const perform = dispatch => ({
|
||||
closeModal: () => dispatch(doCloseModal()),
|
||||
});
|
||||
|
||||
export default connect(null, perform)(ModalSendTip);
|
23
src/renderer/modal/modalSendTip/view.jsx
Normal file
23
src/renderer/modal/modalSendTip/view.jsx
Normal file
|
@ -0,0 +1,23 @@
|
|||
// @flow
|
||||
import React from 'react';
|
||||
import { Modal } from 'modal/modal';
|
||||
import SendTip from 'component/walletSendTip';
|
||||
|
||||
type Props = {
|
||||
closeModal: () => void,
|
||||
uri: string,
|
||||
};
|
||||
|
||||
class ModalSendTip extends React.PureComponent<Props> {
|
||||
render() {
|
||||
const { closeModal, uri } = this.props;
|
||||
|
||||
return (
|
||||
<Modal isOpen type="custom">
|
||||
<SendTip uri={uri} onCancel={closeModal} sendTipCallback={closeModal} />
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ModalSendTip;
|
|
@ -12,6 +12,7 @@ import {
|
|||
import { makeSelectCostInfoForUri } from 'redux/selectors/cost_info';
|
||||
import { selectShowNsfw } from 'redux/selectors/settings';
|
||||
import { selectMediaPaused } from 'redux/selectors/media';
|
||||
import { doOpenModal } from 'redux/actions/app';
|
||||
import FilePage from './view';
|
||||
|
||||
const select = (state, props) => ({
|
||||
|
@ -30,6 +31,7 @@ const perform = dispatch => ({
|
|||
navigate: (path, params) => dispatch(doNavigate(path, params)),
|
||||
fetchFileInfo: uri => dispatch(doFetchFileInfo(uri)),
|
||||
fetchCostInfo: uri => dispatch(doFetchCostInfoForUri(uri)),
|
||||
openModal: (modal, props) => dispatch(doOpenModal(modal, props)),
|
||||
});
|
||||
|
||||
export default connect(select, perform)(FilePage);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* eslint-disable */
|
||||
// @flow
|
||||
import React from 'react';
|
||||
import lbry from 'lbry';
|
||||
import { buildURI, normalizeURI } from 'lbryURI';
|
||||
|
@ -12,29 +12,58 @@ import Icon from 'component/common/icon';
|
|||
import WalletSendTip from 'component/walletSendTip';
|
||||
import DateTime from 'component/dateTime';
|
||||
import * as icons from 'constants/icons';
|
||||
import Link from 'component/link';
|
||||
import Button from 'component/link';
|
||||
import SubscribeButton from 'component/subscribeButton';
|
||||
import Page from 'component/page';
|
||||
import classnames from 'classnames';
|
||||
import player from 'render-media';
|
||||
import * as modals from 'constants/modal_types';
|
||||
|
||||
class FilePage extends React.PureComponent {
|
||||
type Props = {
|
||||
claim: {
|
||||
claim_id: string,
|
||||
height: number,
|
||||
channel_name: string,
|
||||
value: {
|
||||
publisherSignature: ?{
|
||||
certificateId: ?string
|
||||
}
|
||||
}
|
||||
},
|
||||
fileInfo: {},
|
||||
metadata: {
|
||||
title: string,
|
||||
thumbnail: string,
|
||||
nsfw: boolean
|
||||
},
|
||||
contentType: string,
|
||||
uri: string,
|
||||
rewardedContentClaimIds: Array<string>,
|
||||
obscureNsfw: boolean,
|
||||
playingUri: ?string,
|
||||
isPaused: boolean,
|
||||
openModal: (string, any) => void,
|
||||
fetchFileInfo: (string) => void,
|
||||
fetchCostInfo: (string) => void,
|
||||
}
|
||||
|
||||
class FilePage extends React.Component<Props> {
|
||||
componentDidMount() {
|
||||
this.fetchFileInfo(this.props);
|
||||
this.fetchCostInfo(this.props);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
componentWillReceiveProps(nextProps: Props) {
|
||||
this.fetchFileInfo(nextProps);
|
||||
}
|
||||
|
||||
fetchFileInfo(props) {
|
||||
fetchFileInfo(props: Props) {
|
||||
if (props.fileInfo === undefined) {
|
||||
props.fetchFileInfo(props.uri);
|
||||
}
|
||||
}
|
||||
|
||||
fetchCostInfo(props) {
|
||||
fetchCostInfo(props: Props) {
|
||||
if (props.costInfo === undefined) {
|
||||
props.fetchCostInfo(props.uri);
|
||||
}
|
||||
|
@ -51,6 +80,7 @@ class FilePage extends React.PureComponent {
|
|||
obscureNsfw,
|
||||
playingUri,
|
||||
isPaused,
|
||||
openModal,
|
||||
} = this.props;
|
||||
|
||||
// This should be included below in the page
|
||||
|
@ -65,9 +95,9 @@ class FilePage extends React.PureComponent {
|
|||
const shouldObscureThumbnail = obscureNsfw && metadata.nsfw;
|
||||
const thumbnail = metadata.thumbnail;
|
||||
const { height, channel_name: channelName, value } = claim;
|
||||
const mediaType = lbry.getMediaType(contentType);
|
||||
const isPlayable =
|
||||
Object.values(player.mime).indexOf(contentType) !== -1 || mediaType === 'audio';
|
||||
const mediaType = lbry.getMediaType(contentType);
|
||||
const channelClaimId =
|
||||
value && value.publisherSignature && value.publisherSignature.certificateId;
|
||||
let subscriptionUri;
|
||||
|
@ -76,7 +106,6 @@ class FilePage extends React.PureComponent {
|
|||
}
|
||||
|
||||
const isPlaying = playingUri === uri && !isPaused;
|
||||
console.log('isPlaying?', isPlaying);
|
||||
|
||||
return (
|
||||
<Page>
|
||||
|
@ -112,7 +141,12 @@ class FilePage extends React.PureComponent {
|
|||
<div className="card__channel-info">
|
||||
<UriIndicator uri={uri} link />
|
||||
<div className="card__actions card__actions--no-margin">
|
||||
<Link alt iconRight="Send" label={__('Enjoy this? Send a tip')} />
|
||||
<Button
|
||||
alt
|
||||
iconRight="Send"
|
||||
label={__('Enjoy this? Send a tip')}
|
||||
onClick={() => openModal(modals.SEND_TIP, { uri })}
|
||||
/>
|
||||
<SubscribeButton uri={subscriptionUri} channelName={channelName} />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -128,4 +162,3 @@ class FilePage extends React.PureComponent {
|
|||
}
|
||||
|
||||
export default FilePage;
|
||||
/* eslint-enable */
|
||||
|
|
|
@ -121,7 +121,7 @@
|
|||
color: var(--color-grey-dark);
|
||||
font-size: calc(var(--font-size-subtext-multiple) * 1em);
|
||||
padding-top: $spacing-vertical * 1/3;
|
||||
word-break: break-all;
|
||||
word-break: break-word;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue