[redesign] File page #963

Merged
neb-b merged 2 commits from redesign-wip into redesign 2018-02-01 23:19:39 +01:00
9 changed files with 138 additions and 40 deletions
Showing only changes of commit b07c332c0f - Show all commits

View file

@ -26,11 +26,12 @@ type FormFieldProps = {
prefix?: string, prefix?: string,
postfix?: string, postfix?: string,
error?: string | boolean, error?: string | boolean,
helper?: string | React.Node,
}; };
export class FormField extends React.PureComponent<FormFieldProps> { export class FormField extends React.PureComponent<FormFieldProps> {
render() { 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 */ /* eslint-disable jsx-a11y/label-has-for */
// Will come back to this on the settings page // Will come back to this on the settings page
// Need htmlFor on the label // Need htmlFor on the label
@ -47,6 +48,7 @@ export class FormField extends React.PureComponent<FormFieldProps> {
{typeof error === 'string' ? error : __('There was an error')} {typeof error === 'string' ? error : __('There was an error')}
</div> </div>
)} )}
{helper && <div className="form-field__help">{helper}</div>}
</div> </div>
); );
/* eslint-enable jsx-a11y/label-has-for */ /* eslint-enable jsx-a11y/label-has-for */

View file

@ -1,66 +1,92 @@
// I'll come back to this // @flow
/* eslint-disable */
import React from 'react'; import React from 'react';
import Link from 'component/link'; import Button from 'component/link';
import { FormRow } from 'component/common/form'; import { FormField } from 'component/common/form';
import UriIndicator from 'component/uriIndicator'; import UriIndicator from 'component/uriIndicator';
class WalletSendTip extends React.PureComponent { type Props = {
constructor(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); super(props);
this.state = { this.state = {
amount: 0.0, amount: 0,
}; };
(this: any).handleSendButtonClicked = this.handleSendButtonClicked.bind(this);
} }
handleSendButtonClicked() { handleSendButtonClicked() {
const { claim_id, uri } = this.props; const { claim_id: claimId, uri, sendSupport, sendTipCallback } = this.props;
const amount = this.state.amount; const { amount } = this.state;
this.props.sendSupport(amount, claim_id, uri);
sendSupport(amount, claimId, uri);
liamcardenas commented 2018-02-01 22:34:25 +01:00 (Migrated from github.com)
Review

I dont think it really matters, but isn't the better way to do this to make a type for WalletSendTip?

I dont think it really matters, but isn't the better way to do this to make a type for WalletSendTip?
neb-b commented 2018-02-01 23:11:20 +01:00 (Migrated from github.com)
Review

Not sure I follow

Not sure I follow
// ex: close modal
if (sendTipCallback) {
sendTipCallback();
}
} }
handleSupportPriceChange(event) { handleSupportPriceChange(event: SyntheticInputEvent<*>) {
this.setState({ this.setState({
amount: Number(event.target.value), amount: Number(event.target.value),
}); });
} }
render() { render() {
const { errorMessage, isPending, title, uri } = this.props; const { errorMessage, isPending, title, uri, onCancel } = this.props;
return ( return (
<div> <div>
<div className="card__title-primary"> <div className="card__title-primary">
<h1> <h1>
{__('Send a tip')} <UriIndicator uri={uri} /> {__('Send a tip to')} <UriIndicator uri={uri} />
</h1> </h1>
</div> </div>
<div className="card__content"> <div className="card__content">
<FormRow <FormField
label={__('Amount')} label={__('Amount')}
postfix={__('LBC')} postfix={__('LBC')}
min="0" error={errorMessage}
step="any"
type="number"
errorMessage={errorMessage}
helper={ helper={
<span> <span>
{`${__('This will appear as a tip for "%s" located at %s.', title, uri)} `} {__(`This will appear as a tip for ${title} located at ${uri}.`)}
<Link label={__('Learn more')} href="https://lbry.io/faq/tipping" /> {" "}
<Button label={__('Learn more')} fakeLink href="https://lbry.io/faq/tipping" />
</span> </span>
} }
placeholder="1.00" render={() => (
onChange={event => this.handleSupportPriceChange(event)} <input
min="0"
step="any"
type="number"
placeholder="1.00"
onChange={event => this.handleSupportPriceChange(event)}
/>
)}
/> />
<div className="form-row-submit"> <div className="card__actions">
<Link <Button
label={__('Send')} label={__('Send')}
button="primary"
disabled={isPending} 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> </div>
</div> </div>
@ -69,4 +95,3 @@ class WalletSendTip extends React.PureComponent {
} }
export default WalletSendTip; export default WalletSendTip;
/* eslint-enable */

View file

@ -14,3 +14,4 @@ export const TRANSACTION_FAILED = 'transaction_failed';
export const REWARD_APPROVAL_REQUIRED = 'reward_approval_required'; export const REWARD_APPROVAL_REQUIRED = 'reward_approval_required';
export const AFFIRM_PURCHASE = 'affirm_purchase'; export const AFFIRM_PURCHASE = 'affirm_purchase';
export const CONFIRM_CLAIM_REVOKE = 'confirmClaimRevoke'; export const CONFIRM_CLAIM_REVOKE = 'confirmClaimRevoke';
export const SEND_TIP = 'sendTip';

View file

@ -14,6 +14,7 @@ import ModalAffirmPurchase from 'modal/modalAffirmPurchase';
import ModalRevokeClaim from 'modal/modalRevokeClaim'; import ModalRevokeClaim from 'modal/modalRevokeClaim';
import ModalEmailCollection from '../modalEmailCollection'; import ModalEmailCollection from '../modalEmailCollection';
import ModalPhoneCollection from '../modalPhoneCollection'; import ModalPhoneCollection from '../modalPhoneCollection';
import ModalSendTip from '../modalSendTip';
import * as modals from 'constants/modal_types'; import * as modals from 'constants/modal_types';
class ModalRouter extends React.PureComponent { class ModalRouter extends React.PureComponent {
@ -129,6 +130,8 @@ class ModalRouter extends React.PureComponent {
return <ModalPhoneCollection {...modalProps} />; return <ModalPhoneCollection {...modalProps} />;
case modals.EMAIL_COLLECTION: case modals.EMAIL_COLLECTION:
return <ModalEmailCollection {...modalProps} />; return <ModalEmailCollection {...modalProps} />;
case modals.SEND_TIP:
return <ModalSendTip {...modalProps} />;
default: default:
return null; return null;
} }

View 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);

View 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;

View file

@ -12,6 +12,7 @@ import {
import { makeSelectCostInfoForUri } from 'redux/selectors/cost_info'; import { makeSelectCostInfoForUri } from 'redux/selectors/cost_info';
import { selectShowNsfw } from 'redux/selectors/settings'; import { selectShowNsfw } from 'redux/selectors/settings';
import { selectMediaPaused } from 'redux/selectors/media'; import { selectMediaPaused } from 'redux/selectors/media';
import { doOpenModal } from 'redux/actions/app';
import FilePage from './view'; import FilePage from './view';
const select = (state, props) => ({ const select = (state, props) => ({
@ -30,6 +31,7 @@ const perform = dispatch => ({
navigate: (path, params) => dispatch(doNavigate(path, params)), navigate: (path, params) => dispatch(doNavigate(path, params)),
fetchFileInfo: uri => dispatch(doFetchFileInfo(uri)), fetchFileInfo: uri => dispatch(doFetchFileInfo(uri)),
fetchCostInfo: uri => dispatch(doFetchCostInfoForUri(uri)), fetchCostInfo: uri => dispatch(doFetchCostInfoForUri(uri)),
openModal: (modal, props) => dispatch(doOpenModal(modal, props)),
}); });
export default connect(select, perform)(FilePage); export default connect(select, perform)(FilePage);

View file

@ -1,4 +1,4 @@
/* eslint-disable */ // @flow
import React from 'react'; import React from 'react';
import lbry from 'lbry'; import lbry from 'lbry';
import { buildURI, normalizeURI } from 'lbryURI'; import { buildURI, normalizeURI } from 'lbryURI';
@ -12,29 +12,58 @@ import Icon from 'component/common/icon';
import WalletSendTip from 'component/walletSendTip'; import WalletSendTip from 'component/walletSendTip';
import DateTime from 'component/dateTime'; import DateTime from 'component/dateTime';
import * as icons from 'constants/icons'; import * as icons from 'constants/icons';
import Link from 'component/link'; import Button from 'component/link';
import SubscribeButton from 'component/subscribeButton'; import SubscribeButton from 'component/subscribeButton';
import Page from 'component/page'; import Page from 'component/page';
import classnames from 'classnames'; import classnames from 'classnames';
import player from 'render-media'; 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() { componentDidMount() {
this.fetchFileInfo(this.props); this.fetchFileInfo(this.props);
this.fetchCostInfo(this.props); this.fetchCostInfo(this.props);
} }
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps: Props) {
this.fetchFileInfo(nextProps); this.fetchFileInfo(nextProps);
} }
fetchFileInfo(props) { fetchFileInfo(props: Props) {
if (props.fileInfo === undefined) { if (props.fileInfo === undefined) {
props.fetchFileInfo(props.uri); props.fetchFileInfo(props.uri);
} }
} }
fetchCostInfo(props) { fetchCostInfo(props: Props) {
if (props.costInfo === undefined) { if (props.costInfo === undefined) {
props.fetchCostInfo(props.uri); props.fetchCostInfo(props.uri);
} }
@ -51,6 +80,7 @@ class FilePage extends React.PureComponent {
obscureNsfw, obscureNsfw,
playingUri, playingUri,
isPaused, isPaused,
openModal,
} = this.props; } = this.props;
// This should be included below in the page // This should be included below in the page
@ -65,9 +95,9 @@ class FilePage extends React.PureComponent {
const shouldObscureThumbnail = obscureNsfw && metadata.nsfw; const shouldObscureThumbnail = obscureNsfw && metadata.nsfw;
const thumbnail = metadata.thumbnail; const thumbnail = metadata.thumbnail;
const { height, channel_name: channelName, value } = claim; const { height, channel_name: channelName, value } = claim;
const mediaType = lbry.getMediaType(contentType);
const isPlayable = const isPlayable =
Object.values(player.mime).indexOf(contentType) !== -1 || mediaType === 'audio'; Object.values(player.mime).indexOf(contentType) !== -1 || mediaType === 'audio';
const mediaType = lbry.getMediaType(contentType);
const channelClaimId = const channelClaimId =
value && value.publisherSignature && value.publisherSignature.certificateId; value && value.publisherSignature && value.publisherSignature.certificateId;
let subscriptionUri; let subscriptionUri;
@ -76,7 +106,6 @@ class FilePage extends React.PureComponent {
} }
const isPlaying = playingUri === uri && !isPaused; const isPlaying = playingUri === uri && !isPaused;
console.log('isPlaying?', isPlaying);
return ( return (
<Page> <Page>
@ -112,7 +141,12 @@ class FilePage extends React.PureComponent {
<div className="card__channel-info"> <div className="card__channel-info">
<UriIndicator uri={uri} link /> <UriIndicator uri={uri} link />
<div className="card__actions card__actions--no-margin"> <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} /> <SubscribeButton uri={subscriptionUri} channelName={channelName} />
</div> </div>
</div> </div>
@ -128,4 +162,3 @@ class FilePage extends React.PureComponent {
} }
export default FilePage; export default FilePage;
/* eslint-enable */

View file

@ -121,7 +121,7 @@
color: var(--color-grey-dark); color: var(--color-grey-dark);
font-size: calc(var(--font-size-subtext-multiple) * 1em); font-size: calc(var(--font-size-subtext-multiple) * 1em);
padding-top: $spacing-vertical * 1/3; padding-top: $spacing-vertical * 1/3;
word-break: break-all; word-break: break-word;
font-weight: 300; font-weight: 300;
} }