From b07c332c0fa07b079d80690628330503c4bce312 Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Wed, 31 Jan 2018 13:26:06 -0800 Subject: [PATCH] send tip modal --- src/renderer/component/common/form.jsx | 4 +- src/renderer/component/walletSendTip/view.jsx | 81 ++++++++++++------- src/renderer/constants/modal_types.js | 1 + src/renderer/modal/modalRouter/view.jsx | 3 + src/renderer/modal/modalSendTip/index.js | 9 +++ src/renderer/modal/modalSendTip/view.jsx | 23 ++++++ src/renderer/page/file/index.js | 2 + src/renderer/page/file/view.jsx | 53 +++++++++--- src/renderer/scss/component/_card.scss | 2 +- 9 files changed, 138 insertions(+), 40 deletions(-) create mode 100644 src/renderer/modal/modalSendTip/index.js create mode 100644 src/renderer/modal/modalSendTip/view.jsx diff --git a/src/renderer/component/common/form.jsx b/src/renderer/component/common/form.jsx index 524e89ed2..c422e4b7f 100644 --- a/src/renderer/component/common/form.jsx +++ b/src/renderer/component/common/form.jsx @@ -26,11 +26,12 @@ type FormFieldProps = { prefix?: string, postfix?: string, error?: string | boolean, + helper?: string | React.Node, }; export class FormField extends React.PureComponent { 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 { {typeof error === 'string' ? error : __('There was an error')} )} + {helper &&
{helper}
} ); /* eslint-enable jsx-a11y/label-has-for */ diff --git a/src/renderer/component/walletSendTip/view.jsx b/src/renderer/component/walletSendTip/view.jsx index 99c3b7a0e..9bdb228ce 100644 --- a/src/renderer/component/walletSendTip/view.jsx +++ b/src/renderer/component/walletSendTip/view.jsx @@ -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 { + 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 (

- {__('Send a tip')} + {__('Send a tip to')}

- - {`${__('This will appear as a tip for "%s" located at %s.', title, uri)} `} - + {__(`This will appear as a tip for ${title} located at ${uri}.`)} + {" "} +
@@ -69,4 +95,3 @@ class WalletSendTip extends React.PureComponent { } export default WalletSendTip; -/* eslint-enable */ diff --git a/src/renderer/constants/modal_types.js b/src/renderer/constants/modal_types.js index 19b86238e..dd7f0167d 100644 --- a/src/renderer/constants/modal_types.js +++ b/src/renderer/constants/modal_types.js @@ -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'; diff --git a/src/renderer/modal/modalRouter/view.jsx b/src/renderer/modal/modalRouter/view.jsx index b84272a6c..16db6fee5 100644 --- a/src/renderer/modal/modalRouter/view.jsx +++ b/src/renderer/modal/modalRouter/view.jsx @@ -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 ; case modals.EMAIL_COLLECTION: return ; + case modals.SEND_TIP: + return ; default: return null; } diff --git a/src/renderer/modal/modalSendTip/index.js b/src/renderer/modal/modalSendTip/index.js new file mode 100644 index 000000000..d2b21e961 --- /dev/null +++ b/src/renderer/modal/modalSendTip/index.js @@ -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); diff --git a/src/renderer/modal/modalSendTip/view.jsx b/src/renderer/modal/modalSendTip/view.jsx new file mode 100644 index 000000000..6593d148d --- /dev/null +++ b/src/renderer/modal/modalSendTip/view.jsx @@ -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 { + render() { + const { closeModal, uri } = this.props; + + return ( + + + + ); + } +} + +export default ModalSendTip; diff --git a/src/renderer/page/file/index.js b/src/renderer/page/file/index.js index e1f7736ec..b157ed739 100644 --- a/src/renderer/page/file/index.js +++ b/src/renderer/page/file/index.js @@ -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); diff --git a/src/renderer/page/file/view.jsx b/src/renderer/page/file/view.jsx index 56113b31f..7d68eee3b 100644 --- a/src/renderer/page/file/view.jsx +++ b/src/renderer/page/file/view.jsx @@ -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, + obscureNsfw: boolean, + playingUri: ?string, + isPaused: boolean, + openModal: (string, any) => void, + fetchFileInfo: (string) => void, + fetchCostInfo: (string) => void, +} + +class FilePage extends React.Component { 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 ( @@ -112,7 +141,12 @@ class FilePage extends React.PureComponent {
- +
@@ -128,4 +162,3 @@ class FilePage extends React.PureComponent { } export default FilePage; -/* eslint-enable */ diff --git a/src/renderer/scss/component/_card.scss b/src/renderer/scss/component/_card.scss index bdaed9e18..fbdc43dac 100644 --- a/src/renderer/scss/component/_card.scss +++ b/src/renderer/scss/component/_card.scss @@ -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; }