Merge pull request #1935 from lbryio/reward-codes

Add reward code redemption
This commit is contained in:
Sean Yesmunt 2018-10-01 21:11:04 -04:00 committed by GitHub
commit 3357d14d9c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
48 changed files with 717 additions and 454 deletions

View file

@ -39,6 +39,7 @@
"no-return-assign": 0, "no-return-assign": 0,
"react/require-default-props": 0, "react/require-default-props": 0,
"react/jsx-closing-tag-location": 0, "react/jsx-closing-tag-location": 0,
"jsx-a11y/no-noninteractive-element-to-interactive-role": 0 "jsx-a11y/no-noninteractive-element-to-interactive-role": 0,
"class-methods-use-this": 0
} }
} }

View file

@ -30,7 +30,7 @@
"flow-defs": "flow-typed install", "flow-defs": "flow-typed install",
"release": "yarn compile && electron-builder build", "release": "yarn compile && electron-builder build",
"precommit": "lint-staged", "precommit": "lint-staged",
"preinstall": "yarn cache clean lbry-redux", "preinstall": "yarn cache clean lbry-redux && yarn cache clean lbryinc",
"postinstall": "electron-builder install-app-deps && node build/downloadDaemon.js" "postinstall": "electron-builder install-app-deps && node build/downloadDaemon.js"
}, },
"dependencies": { "dependencies": {
@ -50,8 +50,8 @@
"formik": "^0.10.4", "formik": "^0.10.4",
"hast-util-sanitize": "^1.1.2", "hast-util-sanitize": "^1.1.2",
"keytar": "^4.2.1", "keytar": "^4.2.1",
"lbry-redux": "lbryio/lbry-redux#fa141b9175500b874bb77da0258e18d902e069b9", "lbry-redux": "lbryio/lbry-redux#c079b108c3bc4ba2b4fb85fb112b52cfc040c301",
"lbryinc": "lbryio/lbryinc#c09aa2645ecccb33c83e9a9545ff119232910f6f", "lbryinc": "lbryio/lbryinc#de7ff055605b02a24821f0f9bab1d206eb7f235d",
"localforage": "^1.7.1", "localforage": "^1.7.1",
"mammoth": "^1.4.6", "mammoth": "^1.4.6",
"mime": "^2.3.1", "mime": "^2.3.1",

View file

@ -24,7 +24,7 @@ const makeSelect = () => {
}; };
const perform = dispatch => ({ const perform = dispatch => ({
claimReward: reward => dispatch(doClaimRewardType(reward.reward_type, true)), claimReward: reward => dispatch(doClaimRewardType(reward.reward_type)),
clearError: reward => dispatch(doClaimRewardClearError(reward)), clearError: reward => dispatch(doClaimRewardClearError(reward)),
navigate: path => dispatch(doNavigate(path)), navigate: path => dispatch(doNavigate(path)),
}); });

View file

@ -1,5 +1,12 @@
import React from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { MODALS, doNotify } from 'lbry-redux';
import RewardTile from './view'; import RewardTile from './view';
export default connect(null, null)(RewardTile); const perform = dispatch => ({
openRewardCodeModal: () => dispatch(doNotify({ id: MODALS.REWARD_GENERATED_CODE })),
});
export default connect(
null,
perform
)(RewardTile);

View file

@ -7,6 +7,7 @@ import { rewards } from 'lbryinc';
import * as icons from 'constants/icons'; import * as icons from 'constants/icons';
type Props = { type Props = {
openRewardCodeModal: () => void,
reward: { reward: {
id: string, id: string,
reward_title: string, reward_title: string,
@ -19,7 +20,7 @@ type Props = {
}; };
const RewardTile = (props: Props) => { const RewardTile = (props: Props) => {
const { reward } = props; const { reward, openRewardCodeModal } = props;
const claimed = !!reward.transaction_id; const claimed = !!reward.transaction_id;
return ( return (
@ -27,6 +28,9 @@ const RewardTile = (props: Props) => {
<div className="card__title">{reward.reward_title}</div> <div className="card__title">{reward.reward_title}</div>
<div className="card__subtitle">{reward.reward_description}</div> <div className="card__subtitle">{reward.reward_description}</div>
<div className="card__actions"> <div className="card__actions">
{reward.reward_type === rewards.TYPE_GENERATED_CODE && (
<Button button="primary" onClick={openRewardCodeModal} label={__('Enter Code')} />
)}
{reward.reward_type === rewards.TYPE_REFERRAL && ( {reward.reward_type === rewards.TYPE_REFERRAL && (
<Button button="primary" navigate="/invite" label={__('Go To Invites')} /> <Button button="primary" navigate="/invite" label={__('Go To Invites')} />
)} )}

View file

@ -37,47 +37,41 @@ class SocialShare extends React.PureComponent<Props> {
: `${speechPrefix}${claimName}#${claimId}`; : `${speechPrefix}${claimName}#${claimId}`;
return ( return (
<div> <section className="card__content">
<div className="card__title"> <Address address={speechURL} noSnackbar />
<h2>{__('Share This Content')}</h2> <div className="card__actions card__actions--center">
<Tooltip onComponent body={__('Facebook')}>
<div className="card__content"> <Button
<Address address={speechURL} noSnackbar /> iconColor="blue"
</div> icon={icons.FACEBOOK}
<div className="card__actions card__actions--center"> button="alt"
<Tooltip onComponent body={__('Facebook')}> label={__('')}
<Button href={`https://facebook.com/sharer/sharer.php?u=${speechURL}`}
iconColor="blue" />
icon={icons.FACEBOOK} </Tooltip>
button="alt" <Tooltip onComponent body={__('Twitter')}>
label={__('')} <Button
href={`https://facebook.com/sharer/sharer.php?u=${speechURL}`} iconColor="blue"
/> icon={icons.TWITTER}
</Tooltip> button="alt"
<Tooltip onComponent body={__('Twitter')}> label={__('')}
<Button href={`https://twitter.com/home?status=${speechURL}`}
iconColor="blue" />
icon={icons.TWITTER} </Tooltip>
button="alt" <Tooltip onComponent body={__('View on Spee.ch')}>
label={__('')} <Button
href={`https://twitter.com/home?status=${speechURL}`} icon={icons.GLOBE}
/> iconColor="blue"
</Tooltip> button="alt"
<Tooltip onComponent body={__('View on Spee.ch')}> label={__('')}
<Button href={`${speechURL}`}
icon={icons.GLOBE} />
iconColor="blue" </Tooltip>
button="alt"
label={__('')}
href={`${speechURL}`}
/>
</Tooltip>
</div>
<div className="card__actions">
<Button button="link" label={__('Done')} onClick={onDone} />
</div>
</div> </div>
</div> <div className="card__actions">
<Button button="link" label={__('Done')} onClick={onDone} />
</div>
</section>
); );
} }
} }

View file

@ -47,7 +47,7 @@ class UserEmailNew extends React.PureComponent<Props, State> {
</p> </p>
<p>{__("We'll never sell your email, and you can unsubscribe at any time.")}</p> <p>{__("We'll never sell your email, and you can unsubscribe at any time.")}</p>
<Form onSubmit={this.handleSubmit}> <Form onSubmit={this.handleSubmit}>
<FormRow> <FormRow padded>
<FormField <FormField
stretch stretch
type="email" type="email"
@ -63,6 +63,9 @@ class UserEmailNew extends React.PureComponent<Props, State> {
<Submit label="Submit" disabled={isPending} /> <Submit label="Submit" disabled={isPending} />
{cancelButton} {cancelButton}
</div> </div>
<div className="card__content help">
{`${__('Your email may be used to sync usage data across devices.')} `}
</div>
</Form> </Form>
</div> </div>
); );

View file

@ -56,7 +56,7 @@ class UserEmailVerify extends React.PureComponent<Props, State> {
return ( return (
<Form onSubmit={this.handleSubmit}> <Form onSubmit={this.handleSubmit}>
<p>Please enter the verification code emailed to {email}.</p> <p>Please enter the verification code emailed to {email}.</p>
<FormRow> <FormRow padded>
<FormField <FormField
stretch stretch
name="code" name="code"

View file

@ -2,7 +2,6 @@
import React from 'react'; import React from 'react';
import Button from 'component/button'; import Button from 'component/button';
import { FormField } from 'component/common/form'; import { FormField } from 'component/common/form';
import UriIndicator from 'component/uriIndicator';
import type { Claim } from 'types/claim'; import type { Claim } from 'types/claim';
type Props = { type Props = {
@ -71,56 +70,44 @@ class WalletSendTip extends React.PureComponent<Props, State> {
} }
render() { render() {
const { title, isPending, uri, onCancel, balance } = this.props; const { title, isPending, uri, onCancel } = this.props;
const { tipAmount, tipError } = this.state; const { tipAmount, tipError } = this.state;
return ( return (
<div> <section className="card__content">
<div className="card__title"> <FormField
<h1> autoFocus
{__('Send a tip to')} <UriIndicator uri={uri} /> label={
</h1> (tipAmount &&
</div> tipAmount !== 0 &&
<div className="card__content"> `Tip ${tipAmount.toFixed(8).replace(/\.?0+$/, '')} LBC`) ||
<FormField __('Amount')
autoFocus }
label={ postfix={__('LBC')}
(tipAmount && className="input--price-amount"
tipAmount !== 0 && error={tipError}
`Tip ${tipAmount.toFixed(8).replace(/\.?0+$/, '')} LBC`) || min="0"
__('Amount') step="any"
} type="number"
postfix={__('LBC')} placeholder="1.23"
className="input--price-amount" onChange={event => this.handleSupportPriceChange(event)}
error={tipError} helper={
min="0" <span>
step="any" {__(`This will appear as a tip for "${title}".`)}{' '}
type="number" <Button label={__('Learn more')} button="link" href="https://lbry.io/faq/tipping" />
placeholder="1.23" </span>
onChange={event => this.handleSupportPriceChange(event)} }
helper={ />
<span> <div className="card__actions">
{__(`This will appear as a tip for ${title} located at ${uri}.`)}{' '} <Button
<Button label={__('Learn more')} button="link" href="https://lbry.io/faq/tipping" /> button="primary"
</span> label={__('Send')}
} disabled={isPending || tipError}
onClick={this.handleSendButtonClicked}
/> />
<div className="card__actions"> <Button button="link" label={__('Cancel')} onClick={onCancel} navigateParams={{ uri }} />
<Button
button="primary"
label={__('Send')}
disabled={isPending || tipError}
onClick={this.handleSendButtonClicked}
/>
<Button
button="link"
label={__('Cancel')}
onClick={onCancel}
navigateParams={{ uri }}
/>
</div>
</div> </div>
</div> </section>
); );
} }
} }

View file

@ -23,6 +23,7 @@ type ModalProps = {
expandButtonLabel?: string, expandButtonLabel?: string,
hideButtonLabel?: string, hideButtonLabel?: string,
fullScreen: boolean, fullScreen: boolean,
title: string,
}; };
export class Modal extends React.PureComponent<ModalProps> { export class Modal extends React.PureComponent<ModalProps> {
@ -51,6 +52,7 @@ export class Modal extends React.PureComponent<ModalProps> {
fullScreen, fullScreen,
className, className,
overlayClassName, overlayClassName,
title,
...modalProps ...modalProps
} = this.props; } = this.props;
return ( return (
@ -65,6 +67,7 @@ export class Modal extends React.PureComponent<ModalProps> {
![null, undefined, ''].includes(overlayClassName) ? overlayClassName : 'modal-overlay' ![null, undefined, ''].includes(overlayClassName) ? overlayClassName : 'modal-overlay'
} }
> >
<h1 className="modal__header">{title}</h1>
<div>{children}</div> <div>{children}</div>
{type === 'custom' ? null : ( // custom modals define their own buttons {type === 'custom' ? null : ( // custom modals define their own buttons
<div className="card__actions card__actions--center"> <div className="card__actions card__actions--center">

View file

@ -1,8 +1,18 @@
// @flow
import React from 'react'; import React from 'react';
import FilePrice from 'component/filePrice'; import FilePrice from 'component/filePrice';
import { Modal } from 'modal/modal'; import { Modal } from 'modal/modal';
import type { Metadata } from 'types/claim';
class ModalAffirmPurchase extends React.PureComponent { type Props = {
closeModal: () => void,
loadVideo: string => void,
uri: string,
cancelPurchase: () => void,
metadata: Metadata,
};
class ModalAffirmPurchase extends React.PureComponent<Props> {
constructor() { constructor() {
super(); super();
@ -25,15 +35,18 @@ class ModalAffirmPurchase extends React.PureComponent {
<Modal <Modal
type="confirm" type="confirm"
isOpen isOpen
title={__('Confirm Purchase')}
contentLabel={__('Confirm Purchase')} contentLabel={__('Confirm Purchase')}
onConfirmed={this.onAffirmPurchase} onConfirmed={this.onAffirmPurchase}
onAborted={cancelPurchase} onAborted={cancelPurchase}
> >
{__('This will purchase')} <strong>{title}</strong> {__('for')}{' '} <section className="card__content">
<strong> {__('This will purchase')} <strong>{`"${title}"`}</strong> {__('for')}{' '}
<FilePrice uri={uri} showFullPrice inheritStyle showLBC={false} /> <strong>
</strong>{' '} <FilePrice uri={uri} showFullPrice inheritStyle showLBC={false} />
{__('credits')}. </strong>{' '}
{__('credits')}.
</section>
</Modal> </Modal>
); );
} }

View file

@ -1,7 +1,12 @@
// @flow
import React from 'react'; import React from 'react';
import { Modal } from 'modal/modal'; import { Modal } from 'modal/modal';
class ModalAuthFailure extends React.PureComponent { type Props = {
close: () => void,
};
class ModalAuthFailure extends React.PureComponent<Props> {
render() { render() {
const { close } = this.props; const { close } = this.props;
@ -9,6 +14,7 @@ class ModalAuthFailure extends React.PureComponent {
<Modal <Modal
isOpen isOpen
contentLabel={__('Unable to Authenticate')} contentLabel={__('Unable to Authenticate')}
title={__('Authentication Failure')}
type="confirm" type="confirm"
confirmButtonLabel={__('Reload')} confirmButtonLabel={__('Reload')}
abortButtonLabel={__('Continue')} abortButtonLabel={__('Continue')}
@ -17,12 +23,13 @@ class ModalAuthFailure extends React.PureComponent {
}} }}
onAborted={close} onAborted={close}
> >
<h3>{__('Authentication Failure')}</h3> <section className="card__content">
<p> <p>
{__( {__(
'If reloading does not fix this, or you see this at every start up, please email help@lbry.io.' 'If reloading does not fix this, or you see this at every start up, please email help@lbry.io.'
)} )}
</p> </p>
</section>
</Modal> </Modal>
); );
} }

View file

@ -1,11 +1,15 @@
// @flow
import React from 'react'; import React from 'react';
import { Modal } from 'modal/modal'; import { Modal } from 'modal/modal';
import { Line } from 'rc-progress';
import Button from 'component/button'; import Button from 'component/button';
import { ipcRenderer } from 'electron';
const { ipcRenderer } = require('electron'); type Props = {
closeModal: () => void,
declineAutoUpdate: () => void,
};
class ModalAutoUpdateConfirm extends React.PureComponent { class ModalAutoUpdateConfirm extends React.PureComponent<Props> {
render() { render() {
const { closeModal, declineAutoUpdate } = this.props; const { closeModal, declineAutoUpdate } = this.props;
@ -14,6 +18,7 @@ class ModalAutoUpdateConfirm extends React.PureComponent {
isOpen isOpen
type="confirm" type="confirm"
contentLabel={__('Update Downloaded')} contentLabel={__('Update Downloaded')}
title={__('LBRY Update Ready')}
confirmButtonLabel={__('Upgrade')} confirmButtonLabel={__('Upgrade')}
abortButtonLabel={__('Not now')} abortButtonLabel={__('Not now')}
onConfirmed={() => { onConfirmed={() => {
@ -24,10 +29,9 @@ class ModalAutoUpdateConfirm extends React.PureComponent {
closeModal(); closeModal();
}} }}
> >
<section> <section className="card__content">
<h3 className="text-center">{__('LBRY Update Ready')}</h3>
<p>{__('Your LBRY update is ready. Restart LBRY now to use it!')}</p> <p>{__('Your LBRY update is ready. Restart LBRY now to use it!')}</p>
<p className="meta text-center"> <p className="meta">
{__('Want to know what has changed?')} See the{' '} {__('Want to know what has changed?')} See the{' '}
<Button <Button
button="link" button="link"

View file

@ -26,6 +26,7 @@ class ModalAutoUpdateDownloaded extends React.PureComponent<Props> {
isOpen isOpen
type="confirm" type="confirm"
contentLabel={__('Update Downloaded')} contentLabel={__('Update Downloaded')}
title={__('LBRY Leveled Up')}
confirmButtonLabel={__('Use it Now')} confirmButtonLabel={__('Use it Now')}
abortButtonLabel={__('Upgrade on Close')} abortButtonLabel={__('Upgrade on Close')}
confirmButtonDisabled={this.state.disabled} confirmButtonDisabled={this.state.disabled}
@ -39,8 +40,7 @@ class ModalAutoUpdateDownloaded extends React.PureComponent<Props> {
closeModal(); closeModal();
}} }}
> >
<section> <section className="card__content">
<h3 className="text-center">{__('LBRY Leveled Up')}</h3>
<p> <p>
{__( {__(
'A new version of LBRY has been released, downloaded, and is ready for you to use pending a restart.' 'A new version of LBRY has been released, downloaded, and is ready for you to use pending a restart.'

View file

@ -25,21 +25,24 @@ class ModalConfirmThumbnailUpload extends React.PureComponent<Props> {
return ( return (
<Modal <Modal
isOpen isOpen
title={__('Upload Thumbnail')}
contentLabel={__('Confirm Thumbnail Upload')} contentLabel={__('Confirm Thumbnail Upload')}
type="confirm" type="confirm"
confirmButtonLabel={__('Upload')} confirmButtonLabel={__('Upload')}
onConfirmed={() => this.upload()} onConfirmed={() => this.upload()}
onAborted={closeModal} onAborted={closeModal}
> >
<p>{__('Are you sure you want to upload this thumbnail to spee.ch')}?</p> <section className="card__content">
<blockquote>{path}</blockquote> <p>{__('Are you sure you want to upload this thumbnail to spee.ch')}?</p>
<FormField <blockquote>{path}</blockquote>
type="checkbox" <FormField
name="content_is_mature" type="checkbox"
postfix={__('Mature audiences only')} name="content_is_mature"
checked={nsfw} postfix={__('Mature audiences only')}
onChange={event => updatePublishForm({ nsfw: event.target.checked })} checked={nsfw}
/> onChange={event => updatePublishForm({ nsfw: event.target.checked })}
/>
</section>
</Modal> </Modal>
); );
} }

View file

@ -21,21 +21,20 @@ class ModalConfirmTransaction extends React.PureComponent<Props> {
return ( return (
<Modal <Modal
isOpen isOpen
title={__('Send LBC')}
contentLabel={__('Confirm Transaction')} contentLabel={__('Confirm Transaction')}
type="confirm" type="confirm"
confirmButtonLabel={__('Continue')} confirmButtonLabel={__('Send')}
onConfirmed={() => this.onConfirmed()} onConfirmed={() => this.onConfirmed()}
onAborted={closeModal} onAborted={closeModal}
> >
<p>{__('Are you sure you want to ')}</p> <section className="card__content">
<h1> <p>{__('Sending: ')}</p>
{__('send ')} {amount} LBC <blockquote>{amount} LBC</blockquote>
</h1> <p>{__('To address: ')}</p>
<p>{__('Sending: ')}</p> <blockquote>{address}</blockquote>
<blockquote>{amount} LBC</blockquote> <p>{__('Once the transaction is sent, it cannot be reversed.')}</p>
<p>{__('To address: ')}</p> </section>
<blockquote>{address}</blockquote>
<p>{__('Once the transaction is sent, it cannot be reversed.')}</p>
</Modal> </Modal>
); );
} }

View file

@ -17,9 +17,8 @@ const ModalCreditIntro = (props: Props) => {
const totalRewardRounded = Math.floor(totalRewardValue / 10) * 10; const totalRewardRounded = Math.floor(totalRewardValue / 10) * 10;
return ( return (
<Modal type="custom" isOpen contentLabel="Welcome to LBRY"> <Modal type="custom" isOpen contentLabel="Welcome to LBRY" title={__('LBRY Credits Needed')}>
<section> <section className="card__content">
<h3 className="modal__header">{__('Computer Wizard Needs Tokens Badly')}</h3>
<p> <p>
Some actions require LBRY credits (<em> Some actions require LBRY credits (<em>
<CurrencySymbol /> <CurrencySymbol />

View file

@ -1,9 +1,18 @@
// @flow
import React from 'react'; import React from 'react';
import { Modal } from 'modal/modal'; import { Modal } from 'modal/modal';
import { Line } from 'rc-progress'; import { Line } from 'rc-progress';
import Button from 'component/button'; import Button from 'component/button';
class ModalDownloading extends React.PureComponent { type Props = {
downloadProgress: ?number,
downloadComplete: boolean,
downloadItem: string,
startUpgrade: () => void,
cancelUpgrade: () => void,
};
class ModalDownloading extends React.PureComponent<Props> {
render() { render() {
const { const {
downloadProgress, downloadProgress,
@ -14,44 +23,49 @@ class ModalDownloading extends React.PureComponent {
} = this.props; } = this.props;
return ( return (
<Modal isOpen contentLabel={__('Downloading Update')} type="custom"> <Modal
{__('Downloading Update')} title={__('Downloading Update')}
{downloadProgress ? `: ${downloadProgress}%` : null} isOpen
<Line percent={downloadProgress || 0} strokeWidth="4" /> contentLabel={__('Downloading Update')}
{downloadComplete ? ( type="custom"
<div> >
<br /> <section className="card__content">
<p>{__('Click "Begin Upgrade" to start the upgrade process.')}</p> {downloadProgress ? `${downloadProgress}% ${__('complete')}` : null}
<p> <Line percent={downloadProgress || 0} strokeWidth="4" />
{__(
'The app will close, and you will be prompted to install the latest version of LBRY.'
)}
</p>
<p>
{__(
'To launch installation manually, close LBRY and run the command below in the terminal.'
)}
</p>
<blockquote>sudo dpkg -i {downloadItem}</blockquote>
<p>{__('After the install is complete, please reopen the app.')}</p>
</div>
) : null}
<div className="modal__buttons">
{downloadComplete ? ( {downloadComplete ? (
<Button <React.Fragment>
button="primary" <p>{__('Click "Begin Upgrade" to start the upgrade process.')}</p>
label={__('Begin Upgrade')} <p>
className="modal__button" {__(
onClick={startUpgrade} 'The app will close, and you will be prompted to install the latest version of LBRY.'
/> )}
</p>
<p>
{__(
'To launch installation manually, close LBRY and run the command below in the terminal.'
)}
</p>
<blockquote>sudo dpkg -i {downloadItem}</blockquote>
<p>{__('After the install is complete, please reopen the app.')}</p>
</React.Fragment>
) : null} ) : null}
<Button <div className="modal__buttons">
button="link" {downloadComplete ? (
label={__('Cancel')} <Button
className="modal__button" button="primary"
onClick={cancelUpgrade} label={__('Begin Upgrade')}
/> className="modal__button"
</div> onClick={startUpgrade}
/>
) : null}
<Button
button="link"
label={__('Cancel')}
className="modal__button"
onClick={cancelUpgrade}
/>
</div>
</section>
</Modal> </Modal>
); );
} }

View file

@ -16,7 +16,6 @@ class ModalEmailCollection extends React.PureComponent<Props> {
const { closeModal, email, user } = this.props; const { closeModal, email, user } = this.props;
const cancelButton = <Button button="link" onClick={closeModal} label={__('Not Now')} />; const cancelButton = <Button button="link" onClick={closeModal} label={__('Not Now')} />;
if (user && !user.has_verified_email && !email) { if (user && !user.has_verified_email && !email) {
return <UserEmailNew cancelButton={cancelButton} />; return <UserEmailNew cancelButton={cancelButton} />;
} else if (user && !user.has_verified_email) { } else if (user && !user.has_verified_email) {
@ -35,16 +34,8 @@ class ModalEmailCollection extends React.PureComponent<Props> {
} }
return ( return (
<Modal type="custom" isOpen contentLabel="Email"> <Modal type="custom" isOpen contentLabel="Email" title={__('Can We Stay In Touch?')}>
<section> <section className="card__content">{this.renderInner()}</section>
<h3 className="modal__header">Can We Stay In Touch?</h3>
<div className="card__content">{this.renderInner()}</div>
<div className="card__content">
<div className="help">
{`${__('Your email may be used to sync usage data across devices.')} `}
</div>
</div>
</section>
</Modal> </Modal>
); );
} }

View file

@ -1,8 +1,14 @@
// @flow
import React from 'react'; import React from 'react';
import Native from 'native'; import Native from 'native';
import { ExpandableModal } from 'modal/modal'; import { ExpandableModal } from 'modal/modal';
class ModalError extends React.PureComponent { type Props = {
error: string | { message: string },
closeModal: () => void,
};
class ModalError extends React.PureComponent<Props> {
render() { render() {
const { closeModal, error } = this.props; const { closeModal, error } = this.props;
@ -23,37 +29,39 @@ class ModalError extends React.PureComponent {
const label = errorKeyLabels[key]; const label = errorKeyLabels[key];
errorInfoList.push( errorInfoList.push(
<li key={key}> <li key={key}>
<strong>{label}</strong>: <code>{val}</code> <strong>{label}</strong>: {val}
</li> </li>
); );
} }
const errorInfo = <ul className="error-modal__error-list">{errorInfoList}</ul>; const errorInfo = <ul className="error-modal__error-list">{errorInfoList}</ul>;
return ( return (
<ExpandableModal <ExpandableModal
isOpen isOpen
contentLabel={__('Error')} contentLabel={__('Error')}
className="error-modal" title={
overlayClassName="error-modal-overlay" <React.Fragment>
onConfirmed={closeModal} {__('Error')}{' '}
extraContent={errorInfo}
>
<h3 className="modal__header">{__('Error')}</h3>
<div className="error-modal__content">
<div>
<img <img
alt="" alt=""
className="error-modal__warning-symbol" className="error-modal__warning-symbol"
src={Native.imagePath('warning.png')} src={Native.imagePath('warning.png')}
/> />
</div> </React.Fragment>
}
className="error-modal"
overlayClassName="error-modal-overlay"
onConfirmed={closeModal}
extraContent={errorInfo}
>
<section className="card__content">
<p> <p>
{__( {__(
"We're sorry that LBRY has encountered an error. This has been reported and we will investigate the problem." "We're sorry that LBRY has encountered an error. This has been reported and we will investigate the problem."
)} )}
</p> </p>
</div> </section>
</ExpandableModal> </ExpandableModal>
); );
} }

View file

@ -1,15 +1,33 @@
// @flow
import React from 'react'; import React from 'react';
import { Modal } from 'modal/modal'; import { Modal } from 'modal/modal';
import type { Metadata } from 'types/claim';
class ModalFileTimeout extends React.PureComponent { type Props = {
metadata: Metadata,
closeModal: () => void,
};
class ModalFileTimeout extends React.PureComponent<Props> {
render() { render() {
const { const {
metadata: { title }, metadata: { title },
closeModal,
} = this.props; } = this.props;
return ( return (
<Modal isOpen contentLabel={__('Download failed')} onConfirmed={closeModal}> <Modal
{__('LBRY was unable to download the stream')} <strong>{title}</strong>. isOpen
title={__('Unable to Download')}
contentLabel={__('Download failed')}
onConfirmed={closeModal}
>
<section className="card__content">
<p className="card__error-msg">
{__('LBRY was unable to download the stream')}:
<div>{`"${title}"`}</div>
</p>
</section>
</Modal> </Modal>
); );
} }

View file

@ -1,10 +1,12 @@
// I"ll come back to This // @flow
/* esline-disable */
import React from 'react'; import React from 'react';
import { Modal } from 'modal/modal'; import { Modal } from 'modal/modal';
import CreditAmount from 'component/common/credit-amount';
class ModalFirstReward extends React.PureComponent { type Props = {
closeModal: () => void,
};
class ModalFirstReward extends React.PureComponent<Props> {
render() { render() {
const { closeModal } = this.props; const { closeModal } = this.props;
@ -14,10 +16,10 @@ class ModalFirstReward extends React.PureComponent {
overlayClassName="modal-overlay modal-overlay--clear" overlayClassName="modal-overlay modal-overlay--clear"
isOpen isOpen
contentLabel={__('Welcome to LBRY')} contentLabel={__('Welcome to LBRY')}
title={__('Your First Reward')}
onConfirmed={closeModal} onConfirmed={closeModal}
> >
<section> <section className="card__content">
<h3 className="modal__header">{__('Your First Reward')}</h3>
<p>{__('You just earned your first reward!')}</p> <p>{__('You just earned your first reward!')}</p>
<p> <p>
{__( {__(
@ -41,4 +43,3 @@ class ModalFirstReward extends React.PureComponent {
} }
export default ModalFirstReward; export default ModalFirstReward;
/* eslint-enable */

View file

@ -1,14 +1,19 @@
// @flow
import React from 'react'; import React from 'react';
import { Modal } from 'modal/modal'; import { Modal } from 'modal/modal';
import Button from 'component/button'; import Button from 'component/button';
const ModalFirstSubscription = props => { type Props = {
closeModal: () => void,
navigate: string => void,
};
const ModalFirstSubscription = (props: Props) => {
const { closeModal, navigate } = props; const { closeModal, navigate } = props;
return ( return (
<Modal type="custom" isOpen contentLabel="Subscriptions 101"> <Modal type="custom" isOpen contentLabel="Subscriptions 101" title={__('Subscriptions 101')}>
<section> <section className="card__content">
<h3 className="modal__header">{__('Subscriptions 101')}</h3>
<p>{__('You just subscribed to your first channel. Awesome!')}</p> <p>{__('You just subscribed to your first channel. Awesome!')}</p>
<p>{__('A few quick things to know:')}</p> <p>{__('A few quick things to know:')}</p>
<p className="card__content"> <p className="card__content">

View file

@ -15,6 +15,7 @@ class ModalIncompatibleDaemon extends React.PureComponent<Props> {
return ( return (
<Modal <Modal
isOpen isOpen
title={__('Incompatible Daemon')}
contentLabel={__('Incompatible daemon running')} contentLabel={__('Incompatible daemon running')}
type="confirm" type="confirm"
confirmButtonLabel={__('Close LBRY and daemon')} confirmButtonLabel={__('Close LBRY and daemon')}
@ -22,9 +23,11 @@ class ModalIncompatibleDaemon extends React.PureComponent<Props> {
onConfirmed={quitAnyDaemon} onConfirmed={quitAnyDaemon}
onAborted={quit} onAborted={quit}
> >
{__( <p>
'This browser is running with an incompatible version of the LBRY protocol, please close the LBRY app and rerun the installation package to repair it. ' {__(
)} 'This browser is running with an incompatible version of the LBRY protocol, please close the LBRY app and rerun the installation package to repair it. '
)}
</p>
<Button <Button
button="link" button="link"
label={__('Learn more')} label={__('Learn more')}

View file

@ -23,20 +23,22 @@ class ModalOpenExternalLink extends React.PureComponent<Props> {
return ( return (
<Modal <Modal
isOpen isOpen
title={__('Warning!')}
contentLabel={__('Confirm External Link')} contentLabel={__('Confirm External Link')}
type="confirm" type="confirm"
confirmButtonLabel={__('Continue')} confirmButtonLabel={__('Continue')}
onConfirmed={() => this.openExternalLink()} onConfirmed={() => this.openExternalLink()}
onAborted={closeModal} onAborted={closeModal}
> >
<h1>Warning!</h1> <section className="card__content">
<p>{__('This link leads to an external website.')}</p> <p>{__('This link leads to an external website.')}</p>
<blockquote>{uri}</blockquote> <blockquote>{uri}</blockquote>
<p> <p>
{__( {__(
'LBRY Inc is not responsible for its content, click continue to proceed at your own risk.' 'LBRY Inc is not responsible for its content, click continue to proceed at your own risk.'
)} )}
</p> </p>
</section>
</Modal> </Modal>
); );
} }

View file

@ -1,10 +1,19 @@
// @flow
import React from 'react'; import React from 'react';
import { Modal } from 'modal/modal'; import { Modal } from 'modal/modal';
import Button from 'component/button'; import Button from 'component/button';
import UserPhoneNew from 'component/userPhoneNew'; import UserPhoneNew from 'component/userPhoneNew';
import UserPhoneVerify from 'component/userPhoneVerify'; import UserPhoneVerify from 'component/userPhoneVerify';
class ModalPhoneCollection extends React.PureComponent { type Props = {
phone: ?number,
user: {
phone_number: ?number,
},
closeModal: () => void,
};
class ModalPhoneCollection extends React.PureComponent<Props> {
renderInner() { renderInner() {
const { closeModal, phone, user } = this.props; const { closeModal, phone, user } = this.props;
@ -15,7 +24,7 @@ class ModalPhoneCollection extends React.PureComponent {
} else if (!user.phone_number) { } else if (!user.phone_number) {
return <UserPhoneVerify cancelButton={cancelButton} />; return <UserPhoneVerify cancelButton={cancelButton} />;
} }
closeModal(); return closeModal();
} }
render() { render() {
@ -27,11 +36,8 @@ class ModalPhoneCollection extends React.PureComponent {
} }
return ( return (
<Modal type="custom" isOpen contentLabel="Phone"> <Modal type="custom" isOpen contentLabel="Phone" title={__('Verify Your Phone')}>
<section> <section className="card__content">{this.renderInner()}</section>
<h3 className="modal__header">Verify Your Phone</h3>
{this.renderInner()}
</section>
</Modal> </Modal>
); );
} }

View file

@ -16,6 +16,7 @@ class ModalSendTip extends React.PureComponent<Props> {
return ( return (
<Modal <Modal
isOpen isOpen
title={__('Success')}
contentLabel={__('File published')} contentLabel={__('File published')}
onConfirmed={() => { onConfirmed={() => {
clearPublish(); clearPublish();
@ -23,13 +24,15 @@ class ModalSendTip extends React.PureComponent<Props> {
closeModal(); closeModal();
}} }}
> >
<p>{__('Your file has been published to LBRY at the address')}</p> <section className="card__content">
<p className="card__success-msg">{uri}</p> <p>{__('Your file has been published to LBRY at the address')}</p>
<p> <p className="card__success-msg">{uri}</p>
{__( <p>
'The file will take a few minutes to appear for other LBRY users. Until then it will be listed as "pending" under your published files.' {__(
)} 'The file will take a few minutes to appear for other LBRY users. Until then it will be listed as "pending" under your published files.'
</p> )}
</p>
</section>
</Modal> </Modal>
); );
} }

View file

@ -60,34 +60,38 @@ class ModalRemoveFile extends React.PureComponent<Props, State> {
return ( return (
<Modal <Modal
isOpen isOpen
title={__('Remove File')}
contentLabel={__('Confirm File Remove')} contentLabel={__('Confirm File Remove')}
type="confirm" type="confirm"
confirmButtonLabel={__('Remove')} confirmButtonLabel={__('Remove')}
onConfirmed={() => deleteFile(outpoint, deleteChecked, abandonClaimChecked)} onConfirmed={() => deleteFile(outpoint, deleteChecked, abandonClaimChecked)}
onAborted={closeModal} onAborted={closeModal}
> >
<p> <section className="card__content">
{__("Are you sure you'd like to remove")} <cite>{title}</cite> {__('from the LBRY app?')} <p>
</p> {__("Are you sure you'd like to remove")} <cite>{`"${title}"`}</cite>{' '}
{__('from the LBRY app?')}
</p>
<FormRow padded> <FormRow padded>
<FormField
prefix={__('Also delete this file from my computer')}
type="checkbox"
checked={deleteChecked}
onChange={this.handleDeleteCheckboxClicked}
/>
</FormRow>
{claimIsMine && (
<FormRow>
<FormField <FormField
prefix={__('Abandon the claim for this URI')} prefix={__('Also delete this file from my computer')}
type="checkbox" type="checkbox"
checked={abandonClaimChecked} checked={deleteChecked}
onChange={this.handleAbandonClaimCheckboxClicked} onChange={this.handleDeleteCheckboxClicked}
/> />
</FormRow> </FormRow>
)} {claimIsMine && (
<FormRow>
<FormField
prefix={__('Abandon the claim for this URI')}
type="checkbox"
checked={abandonClaimChecked}
onChange={this.handleAbandonClaimCheckboxClicked}
/>
</FormRow>
)}
</section>
</Modal> </Modal>
); );
} }

View file

@ -1,10 +1,52 @@
// @flow
import React from 'react'; import React from 'react';
import { Modal } from 'modal/modal'; import { Modal } from 'modal/modal';
import * as txnTypes from 'constants/transaction_types'; import * as txnTypes from 'constants/transaction_types';
class ModalRevokeClaim extends React.PureComponent { type Props = {
constructor(props) { closeModal: () => void,
super(props); abandonClaim: (string, number) => void,
txid: string,
nout: number,
};
class ModalRevokeClaim extends React.PureComponent<Props> {
constructor() {
super();
(this: any).revokeClaim = this.revokeClaim.bind(this);
}
getButtonLabel(type) {
if (type === txnTypes.TIP) {
return 'Confirm Tip Unlock';
}
return 'Confirm Claim Revoke';
}
getMsgBody(type) {
if (type === txnTypes.TIP) {
return (
<React.Fragment>
<p>{__('Are you sure you want to unlock these credits?')}</p>
<p>
{__(
'These credits are permanently yours and can be unlocked at any time. Unlocking them allows you to spend them, but can hurt the performance of your content in lookups and search results. It is recommended you leave tips locked until you need or want to spend them.'
)}
</p>
</React.Fragment>
);
}
return (
<React.Fragment>
<p>{__('Are you sure want to revoke this claim?')}</p>
<p>
{__(
'This will prevent others from resolving and accessing the content you published. It will return the LBC to your spendable balance, less a small transaction fee.'
)}
</p>
</React.Fragment>
);
} }
revokeClaim() { revokeClaim() {
@ -14,52 +56,6 @@ class ModalRevokeClaim extends React.PureComponent {
this.props.abandonClaim(txid, nout); this.props.abandonClaim(txid, nout);
} }
getButtonLabel(type) {
if (type == txnTypes.TIP) {
return 'Confirm Tip Unlock';
}
return 'Confirm Claim Revoke';
}
getMsgBody(type) {
if (type == txnTypes.TIP) {
return (
<div>
<h3>{__('Confirm Tip Unlock')}</h3>
<p>
{__('Are you sure you want to unlock these credits?')}
<br />
<br />
{__(
'These credits are permanently yours and can be\
unlocked at any time. Unlocking them allows you to\
spend them, but can hurt the performance of your\
content in lookups and search results. It is\
recommended you leave tips locked until you\
need or want to spend them.'
)}
</p>
</div>
);
}
return (
<div>
<h3>{__('Confirm Claim Revoke')}</h3>
<p>
{__('Are you sure want to revoke this claim?')}
<br />
<br />
{__(
'This will prevent others from resolving and\
accessing the content you published. It will return\
the LBC to your spendable balance, less a small\
transaction fee.'
)}
</p>
</div>
);
}
render() { render() {
const { transactionItems, txid, nout, closeModal } = this.props; const { transactionItems, txid, nout, closeModal } = this.props;
const { type } = transactionItems.find(claim => claim.txid == txid && claim.nout == nout); const { type } = transactionItems.find(claim => claim.txid == txid && claim.nout == nout);
@ -67,13 +63,14 @@ class ModalRevokeClaim extends React.PureComponent {
return ( return (
<Modal <Modal
isOpen isOpen
title={type === txnTypes.TIP ? __('Confirm Tip Unlock') : __('Confirm Claim Revoke')}
contentLabel={__('Confirm Claim Revoke')} contentLabel={__('Confirm Claim Revoke')}
type="confirm" type="confirm"
confirmButtonLabel={this.getButtonLabel(type)} confirmButtonLabel={this.getButtonLabel(type)}
onConfirmed={this.revokeClaim.bind(this)} onConfirmed={this.revokeClaim}
onAborted={closeModal} onAborted={closeModal}
> >
{this.getMsgBody(type)} <section className="card__content">{this.getMsgBody(type)}</section>
</Modal> </Modal>
); );
} }

View file

@ -1,13 +1,20 @@
// @flow
import React from 'react'; import React from 'react';
import { Modal } from 'modal/modal'; import { Modal } from 'modal/modal';
class ModalRewardApprovalRequired extends React.PureComponent { type Props = {
closeModal: () => void,
doAuth: () => void,
};
class ModalRewardApprovalRequired extends React.PureComponent<Props> {
render() { render() {
const { closeModal, doAuth } = this.props; const { closeModal, doAuth } = this.props;
return ( return (
<Modal <Modal
isOpen isOpen
title={__('Hmm. Are you real?')}
contentLabel={__('Human Verification Required')} contentLabel={__('Human Verification Required')}
onConfirmed={doAuth} onConfirmed={doAuth}
onAborted={closeModal} onAborted={closeModal}
@ -15,8 +22,7 @@ class ModalRewardApprovalRequired extends React.PureComponent {
confirmButtonLabel={__("I'm Totally Real")} confirmButtonLabel={__("I'm Totally Real")}
abortButtonLabel={__('Never Mind')} abortButtonLabel={__('Never Mind')}
> >
<section> <section className="card__content">
<h3 className="modal__header">{__('This is awkward. Are you real?')}</h3>
<p> <p>
{__( {__(
"Before we can give you any credits, we need to perform a brief check to make sure you're a new and unique person." "Before we can give you any credits, we need to perform a brief check to make sure you're a new and unique person."

View file

@ -0,0 +1,28 @@
// @flow
import { connect } from 'react-redux';
import { doHideNotification } from 'lbry-redux';
import {
makeSelectClaimRewardError,
doClaimRewardType,
makeSelectIsRewardClaimPending,
rewards as REWARD_TYPES,
} from 'lbryinc';
import ModalRewardCode from './view';
const select = (state): {} => ({
rewardIsPending: makeSelectIsRewardClaimPending()(state, {
reward_type: REWARD_TYPES.TYPE_REWARD_CODE,
}),
error: makeSelectClaimRewardError()(state, { reward_type: REWARD_TYPES.TYPE_REWARD_CODE }),
});
const perform = dispatch => ({
closeModal: () => dispatch(doHideNotification()),
submitRewardCode: (code: string) =>
dispatch(doClaimRewardType(REWARD_TYPES.TYPE_REWARD_CODE, { params: { code } })),
});
export default connect(
select,
perform
)(ModalRewardCode);

View file

@ -0,0 +1,81 @@
// @flow
import * as React from 'react';
import { FormRow, FormField } from 'component/common/form';
import { Modal } from 'modal/modal';
import Button from 'component/button';
type Props = {
closeModal: () => void,
error: ?string,
rewardIsPending: boolean,
submitRewardCode: string => void,
};
type State = {
rewardCode: string,
};
class ModalRewardCode extends React.PureComponent<Props, State> {
constructor() {
super();
this.state = {
rewardCode: '',
};
(this: any).handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit() {
const { rewardCode } = this.state;
const { submitRewardCode } = this.props;
submitRewardCode(rewardCode);
}
render() {
const { closeModal, rewardIsPending, error } = this.props;
const { rewardCode } = this.state;
return (
<Modal
isOpen
title={__('Enter Reward Code')}
contentLabel={__('Enter Reward Code')}
type="confirm"
confirmButtonLabel={__('Redeem')}
abortButtonLabel={__('Cancel')}
onConfirmed={this.handleSubmit}
onAborted={closeModal}
confirmButtonDisabled={rewardIsPending}
>
<section className="card__content">
<FormRow>
<FormField
stretch
autoFocus
type="text"
label={__('Code')}
placeholder="0123abc"
error={error}
value={rewardCode}
onChange={e => this.setState({ rewardCode: e.target.value })}
helper={
<React.Fragment>
{__('Redeem a custom reward code for LBC')}
{'. '}
<Button
button="link"
href="https://lbry.io/faq/rewards#reward-code"
label={__('Learn more')}
/>.
</React.Fragment>
}
/>
</FormRow>
</section>
</Modal>
);
}
}
export default ModalRewardCode;

View file

@ -1,3 +1,4 @@
// @flow
import React from 'react'; import React from 'react';
import { MODALS } from 'lbry-redux'; import { MODALS } from 'lbry-redux';
import ModalError from 'modal/modalError'; import ModalError from 'modal/modalError';
@ -27,13 +28,15 @@ import ModalConfirmThumbnailUpload from 'modal/modalConfirmThumbnailUpload';
import ModalWalletEncrypt from 'modal/modalWalletEncrypt'; import ModalWalletEncrypt from 'modal/modalWalletEncrypt';
import ModalWalletDecrypt from 'modal/modalWalletDecrypt'; import ModalWalletDecrypt from 'modal/modalWalletDecrypt';
import ModalWalletUnlock from 'modal/modalWalletUnlock'; import ModalWalletUnlock from 'modal/modalWalletUnlock';
import ModalRewardCode from 'modal/modalRewardCode';
type Props = { type Props = {
modal: string, notification: { id: string },
notificationProps: {},
}; };
class ModalRouter extends React.PureComponent<Props> { class ModalRouter extends React.PureComponent<Props> {
constructor(props) { constructor(props: Props) {
super(props); super(props);
this.state = { this.state = {
@ -51,7 +54,7 @@ class ModalRouter extends React.PureComponent<Props> {
} }
showTransitionModals(props) { showTransitionModals(props) {
const { modal, modalProps, openModal, page } = props; const { modal, openModal, page } = props;
if (modal) { if (modal) {
return; return;
@ -80,6 +83,8 @@ class ModalRouter extends React.PureComponent<Props> {
if (!isWelcomeAcknowledged && user && !user.is_reward_approved && !user.is_identity_verified) { if (!isWelcomeAcknowledged && user && !user.is_reward_approved && !user.is_identity_verified) {
return MODALS.WELCOME; return MODALS.WELCOME;
} }
return undefined;
} }
checkShowEmail(props) { checkShowEmail(props) {
@ -92,6 +97,8 @@ class ModalRouter extends React.PureComponent<Props> {
) { ) {
return MODALS.EMAIL_COLLECTION; return MODALS.EMAIL_COLLECTION;
} }
return undefined;
} }
checkShowCreditIntro(props) { checkShowCreditIntro(props) {
@ -104,6 +111,8 @@ class ModalRouter extends React.PureComponent<Props> {
) { ) {
return MODALS.INSUFFICIENT_CREDITS; return MODALS.INSUFFICIENT_CREDITS;
} }
return undefined;
} }
isPaidShowPage(props) { isPaidShowPage(props) {
@ -177,6 +186,8 @@ class ModalRouter extends React.PureComponent<Props> {
return <ModalWalletDecrypt {...notificationProps} />; return <ModalWalletDecrypt {...notificationProps} />;
case MODALS.WALLET_UNLOCK: case MODALS.WALLET_UNLOCK:
return <ModalWalletUnlock {...notificationProps} />; return <ModalWalletUnlock {...notificationProps} />;
case MODALS.REWARD_GENERATED_CODE:
return <ModalRewardCode {...notificationProps} />;
default: default:
return null; return null;
} }

View file

@ -2,6 +2,7 @@
import React from 'react'; import React from 'react';
import { Modal } from 'modal/modal'; import { Modal } from 'modal/modal';
import SendTip from 'component/walletSendTip'; import SendTip from 'component/walletSendTip';
import UriIndicator from 'component/uriIndicator';
type Props = { type Props = {
closeModal: () => void, closeModal: () => void,
@ -13,7 +14,16 @@ class ModalSendTip extends React.PureComponent<Props> {
const { closeModal, uri } = this.props; const { closeModal, uri } = this.props;
return ( return (
<Modal onAborted={closeModal} isOpen type="custom"> <Modal
onAborted={closeModal}
isOpen
type="custom"
title={
<React.Fragment>
{__('Send a tip to')} <UriIndicator uri={uri} />
</React.Fragment>
}
>
<SendTip uri={uri} onCancel={closeModal} sendTipCallback={closeModal} /> <SendTip uri={uri} onCancel={closeModal} sendTipCallback={closeModal} />
</Modal> </Modal>
); );

View file

@ -12,7 +12,7 @@ class ModalSocialShare extends React.PureComponent<Props> {
render() { render() {
const { closeModal, uri } = this.props; const { closeModal, uri } = this.props;
return ( return (
<Modal isOpen onAborted={closeModal} type="custom"> <Modal isOpen onAborted={closeModal} type="custom" title={__('Share')}>
<SocialShare uri={uri} onDone={closeModal} /> <SocialShare uri={uri} onDone={closeModal} />
</Modal> </Modal>
); );

View file

@ -1,14 +1,22 @@
// @flow
import React from 'react'; import React from 'react';
import { Modal } from 'modal/modal'; import { Modal } from 'modal/modal';
class ModalTransactionFailed extends React.PureComponent { type Props = {
closeModal: () => void,
};
class ModalTransactionFailed extends React.PureComponent<Props> {
render() { render() {
const { closeModal } = this.props; const { closeModal } = this.props;
return ( return (
<Modal isOpen contentLabel={__('Transaction failed')} onConfirmed={closeModal}> <Modal
{__('Transaction failed.')}: isOpen
</Modal> contentLabel={__('Transaction failed')}
title={__('Transaction Failed')}
onConfirmed={closeModal}
/>
); );
} }
} }

View file

@ -1,8 +1,14 @@
// @flow
import React from 'react'; import React from 'react';
import { Modal } from 'modal/modal'; import { Modal } from 'modal/modal';
import Button from 'component/button'; import Button from 'component/button';
class ModalUpgrade extends React.PureComponent { type Props = {
downloadUpgrade: () => void,
skipUpgrade: () => void,
};
class ModalUpgrade extends React.PureComponent<Props> {
render() { render() {
const { downloadUpgrade, skipUpgrade } = this.props; const { downloadUpgrade, skipUpgrade } = this.props;
@ -10,26 +16,27 @@ class ModalUpgrade extends React.PureComponent {
<Modal <Modal
isOpen isOpen
contentLabel={__('Upgrade available')} contentLabel={__('Upgrade available')}
title={__('LBRY Leveled Up')}
type="confirm" type="confirm"
confirmButtonLabel={__('Upgrade')} confirmButtonLabel={__('Upgrade')}
abortButtonLabel={__('Skip')} abortButtonLabel={__('Skip')}
onConfirmed={downloadUpgrade} onConfirmed={downloadUpgrade}
onAborted={skipUpgrade} onAborted={skipUpgrade}
> >
<h3 className="text-center">{__('LBRY Leveled Up')}</h3> <div className="card__content">
<br /> <p>
<p> {__('An updated version of LBRY is now available.')}{' '}
{__('An updated version of LBRY is now available.')}{' '} {__('Your version is out of date and may be unreliable or insecure.')}
{__('Your version is out of date and may be unreliable or insecure.')} </p>
</p> <p className="meta">
<p className="meta text-center"> {__('Want to know what has changed?')} See the{' '}
{__('Want to know what has changed?')} See the{' '} <Button
<Button button="link"
button="link" label={__('release notes')}
label={__('release notes')} href="https://github.com/lbryio/lbry-desktop/releases"
href="https://github.com/lbryio/lbry-desktop/releases" />.
/>. </p>
</p> </div>
</Modal> </Modal>
); );
} }

View file

@ -1,12 +1,12 @@
// @flow // @flow
import React from 'react'; import React from 'react';
import { Form, FormRow, FormField } from 'component/common/form'; import { Form } from 'component/common/form';
import { Modal } from 'modal/modal'; import { Modal } from 'modal/modal';
import Button from 'component/button'; import Button from 'component/button';
type Props = { type Props = {
closeModal: () => void, closeModal: () => void,
unlockWallet: string => void, decryptWallet: () => void,
walletDecryptSucceded: boolean, walletDecryptSucceded: boolean,
updateWalletStatus: boolean, updateWalletStatus: boolean,
}; };
@ -16,11 +16,6 @@ class ModalWalletDecrypt extends React.PureComponent<Props> {
submitted: false, // Prior actions could be marked complete submitted: false, // Prior actions could be marked complete
}; };
submitDecryptForm() {
this.setState({ submitted: true });
this.props.decryptWallet();
}
componentDidUpdate() { componentDidUpdate() {
const { props, state } = this; const { props, state } = this;
@ -30,12 +25,18 @@ class ModalWalletDecrypt extends React.PureComponent<Props> {
} }
} }
submitDecryptForm() {
this.setState({ submitted: true });
this.props.decryptWallet();
}
render() { render() {
const { closeModal, walletDecryptSucceded } = this.props; const { closeModalgaa } = this.props;
return ( return (
<Modal <Modal
isOpen isOpen
title={__('Decrypt Wallet')}
contentLabel={__('Decrypt Wallet')} contentLabel={__('Decrypt Wallet')}
type="confirm" type="confirm"
confirmButtonLabel={__('Decrypt Wallet')} confirmButtonLabel={__('Decrypt Wallet')}
@ -43,18 +44,22 @@ class ModalWalletDecrypt extends React.PureComponent<Props> {
onConfirmed={() => this.submitDecryptForm()} onConfirmed={() => this.submitDecryptForm()}
onAborted={closeModal} onAborted={closeModal}
> >
<Form onSubmit={() => this.submitDecryptForm()}> <section className="card__content">
{__( <Form onSubmit={() => this.submitDecryptForm()}>
'Your wallet has been encrypted with a local password, performing this action will remove this password.' <p>
)} {__(
<div className="card__actions"> 'Your wallet has been encrypted with a local password, performing this action will remove this password.'
<Button )}
button="link" </p>
label={__('Learn more')} <div className="card__actions">
href="https://lbry.io/faq/wallet-encryption" <Button
/> button="link"
</div> label={__('Learn more')}
</Form> href="https://lbry.io/faq/wallet-encryption"
/>
</div>
</Form>
</section>
</Modal> </Modal>
); );
} }

View file

@ -82,6 +82,7 @@ class ModalWalletEncrypt extends React.PureComponent<Props> {
return ( return (
<Modal <Modal
isOpen isOpen
title={__('Encrypt Wallet')}
contentLabel={__('Encrypt Wallet')} contentLabel={__('Encrypt Wallet')}
type="confirm" type="confirm"
confirmButtonLabel={__('Encrypt Wallet')} confirmButtonLabel={__('Encrypt Wallet')}
@ -89,54 +90,59 @@ class ModalWalletEncrypt extends React.PureComponent<Props> {
onConfirmed={() => this.submitEncryptForm()} onConfirmed={() => this.submitEncryptForm()}
onAborted={closeModal} onAborted={closeModal}
> >
<Form onSubmit={() => this.submitEncryptForm()}> <section className="card__content">
{__( <Form onSubmit={() => this.submitEncryptForm()}>
'Encrypting your wallet will require a password to access your local wallet data when LBRY starts. Please enter a new password for your wallet.' <p>
)} {__(
<FormRow padded> 'Encrypting your wallet will require a password to access your local wallet data when LBRY starts. Please enter a new password for your wallet.'
<FormField )}
stretch </p>
autoFocus <FormRow padded>
error={passwordMismatch === true ? 'Passwords do not match' : false} <FormField
label={__('New Password')} stretch
type="password" autoFocus
name="wallet-new-password" error={passwordMismatch === true ? 'Passwords do not match' : false}
onChange={event => this.onChangeNewPassword(event)} label={__('New Password')}
/> type="password"
</FormRow> name="wallet-new-password"
<FormRow padded> onChange={event => this.onChangeNewPassword(event)}
<FormField />
stretch </FormRow>
error={passwordMismatch === true ? 'Passwords do not match' : false} <FormRow padded>
label={__('Confirm Password')} <FormField
type="password" stretch
name="wallet-new-password-confirm" error={passwordMismatch === true ? 'Passwords do not match' : false}
onChange={event => this.onChangeNewPasswordConfirm(event)} label={__('Confirm Password')}
/> type="password"
</FormRow> name="wallet-new-password-confirm"
<br /> onChange={event => this.onChangeNewPasswordConfirm(event)}
{__( />
'If your password is lost, it cannot be recovered. You will not be able to access your wallet without a password.' </FormRow>
)} <p>
<FormRow padded> {__(
<FormField 'If your password is lost, it cannot be recovered. You will not be able to access your wallet without a password.'
stretch )}
error={understandError === true ? 'You must enter "I understand"' : false} </p>
label={__('Enter "I understand"')} <FormRow padded>
type="text" <FormField
name="wallet-understand" stretch
onChange={event => this.onChangeUnderstandConfirm(event)} error={understandError === true ? 'You must enter "I understand"' : false}
/> label={__('Enter "I understand"')}
</FormRow> type="text"
<div className="card__actions"> name="wallet-understand"
<Button onChange={event => this.onChangeUnderstandConfirm(event)}
button="link" />
label={__('Learn more')} </FormRow>
href="https://lbry.io/faq/wallet-encryption" <div className="card__actions">
/> <Button
</div> button="link"
{failMessage && <div className="error-text">{__(failMessage)}</div>} label={__('Learn more')}
</Form> href="https://lbry.io/faq/wallet-encryption"
/>
</div>
{failMessage && <div className="error-text">{__(failMessage)}</div>}
</Form>
</section>
</Modal> </Modal>
); );
} }

View file

@ -36,6 +36,7 @@ class ModalWalletUnlock extends React.PureComponent<Props> {
return ( return (
<Modal <Modal
isOpen isOpen
title={__('Unlock Wallet')}
contentLabel={__('Unlock Wallet')} contentLabel={__('Unlock Wallet')}
type="confirm" type="confirm"
shouldCloseOnOverlayClick={false} shouldCloseOnOverlayClick={false}
@ -44,29 +45,33 @@ class ModalWalletUnlock extends React.PureComponent<Props> {
onConfirmed={() => unlockWallet(password)} onConfirmed={() => unlockWallet(password)}
onAborted={quit} onAborted={quit}
> >
<Form onSubmit={() => unlockWallet(password)}> <section className="card__content">
{__( <Form onSubmit={() => unlockWallet(password)}>
'Your wallet has been encrypted with a local password. Please enter your wallet password to proceed.' <p>
)} {__(
<FormRow padded> 'Your wallet has been encrypted with a local password. Please enter your wallet password to proceed.'
<FormField )}
stretch </p>
autoFocus <FormRow padded>
error={walletUnlockSucceded === false ? 'Incorrect Password' : false} <FormField
label={__('Wallet Password')} stretch
type="password" autoFocus
name="wallet-password" error={walletUnlockSucceded === false ? 'Incorrect Password' : false}
onChange={event => this.onChangePassword(event)} label={__('Wallet Password')}
/> type="password"
</FormRow> name="wallet-password"
<div className="card__actions"> onChange={event => this.onChangePassword(event)}
<Button />
button="link" </FormRow>
label={__('Learn more')} <div className="card__actions">
href="https://lbry.io/faq/wallet-encryption" <Button
/> button="link"
</div> label={__('Learn more')}
</Form> href="https://lbry.io/faq/wallet-encryption"
/>
</div>
</Form>
</section>
</Modal> </Modal>
); );
} }

View file

@ -6,9 +6,8 @@ const ModalWelcome = props => {
const { closeModal } = props; const { closeModal } = props;
return ( return (
<Modal type="custom" isOpen contentLabel="Welcome to LBRY"> <Modal type="custom" isOpen contentLabel="Welcome to LBRY" title={__('Welcome to LBRY')}>
<section> <section className="card__content">
<h3 className="modal__header">{__('Welcome to LBRY')}</h3>
<p> <p>
{__('Using LBRY is like dating a centaur. Totally normal up top, and')}{' '} {__('Using LBRY is like dating a centaur. Totally normal up top, and')}{' '}
<em>{__('way different')}</em> {__('underneath.')} <em>{__('way different')}</em> {__('underneath.')}
@ -18,7 +17,7 @@ const ModalWelcome = props => {
{__('Below, LBRY is controlled by users -- you -- via blockchain and decentralization.')} {__('Below, LBRY is controlled by users -- you -- via blockchain and decentralization.')}
</p> </p>
<div className="modal__buttons"> <div className="modal__buttons">
<Button button="primary" onClick={closeModal} label={__("Blockchain Centaurs? I'm In")} /> <Button button="primary" onClick={closeModal} label={__("I'm In")} />
</div> </div>
</section> </section>
</Modal> </Modal>

View file

@ -7,6 +7,7 @@ import Button from 'component/button';
import Page from 'component/page'; import Page from 'component/page';
import classnames from 'classnames'; import classnames from 'classnames';
import type { Reward } from 'types/reward'; import type { Reward } from 'types/reward';
import { rewards as REWARD_TYPES } from 'lbryinc';
type Props = { type Props = {
doAuth: () => void, doAuth: () => void,
@ -125,6 +126,16 @@ class RewardsPage extends React.PureComponent<Props> {
'card--disabled': isNotEligible, 'card--disabled': isNotEligible,
})} })}
> >
<RewardTile
key={REWARD_TYPES.TYPE_GENERATED_CODE}
reward={{
reward_type: REWARD_TYPES.TYPE_GENERATED_CODE,
reward_title: __('Custom Code'),
reward_description: __(
'Are you a supermodel or rockstar that received a custom reward code? Claim it here.'
),
}}
/>
{rewards.map(reward => <RewardTile key={reward.reward_type} reward={reward} />)} {rewards.map(reward => <RewardTile key={reward.reward_type} reward={reward} />)}
</div> </div>
); );

View file

@ -153,6 +153,10 @@ dd {
p { p {
font-family: 'metropolis-medium'; font-family: 'metropolis-medium';
&:not(:first-of-type) {
margin-top: $spacing-vertical * 1/3;
}
} }
.page { .page {
@ -361,7 +365,7 @@ p {
.meta { .meta {
font-family: 'metropolis-medium'; font-family: 'metropolis-medium';
font-size: 14px; font-size: 0.8em;
color: var(--color-meta-light); color: var(--color-meta-light);
} }

View file

@ -37,6 +37,7 @@ $large-breakpoint: 1921px;
--color-green-blue: #2ec1a8; --color-green-blue: #2ec1a8;
--color-purple: #8165b0; --color-purple: #8165b0;
--color-blue-grey: #203049; --color-blue-grey: #203049;
--color-red-light: #fff6f6;
/* Colors */ /* Colors */
--color-divider: #e3e3e3; --color-divider: #e3e3e3;
@ -157,6 +158,9 @@ $large-breakpoint: 1921px;
--success-msg-color: var(--color-green); --success-msg-color: var(--color-green);
--success-msg-border: var(--color-green-blue); --success-msg-border: var(--color-green-blue);
--success-msg-bg: var(--color-green-light); --success-msg-bg: var(--color-green-light);
--error-msg-color: var(--color-error);
--error-msg-border: var(--color-error);
--error-msg-bg: var(--color-red-light);
/* File */ /* File */
--file-tile-media-height: 125px; --file-tile-media-height: 125px;

View file

@ -429,15 +429,13 @@
} }
.card__list--rewards { .card__list--rewards {
column-count: 2;
column-gap: $spacing-vertical * 1/3;
.card { .card {
display: inline-block; display: inline-block;
width: calc(50% - 10px); margin: 0 0 $spacing-vertical * 1/3;
margin-bottom: 20px; width: 100%;
vertical-align: top;
&:not(:nth-child(2n + 1)) {
margin-left: 20px;
}
} }
} }
@ -458,6 +456,14 @@
margin: $spacing-vertical * 1/3 0; margin: $spacing-vertical * 1/3 0;
} }
.card__error-msg {
border-left: 2px solid var(--error-msg-border);
color: var(--error-msg-color);
background-color: var(--error-msg-bg);
padding: $spacing-vertical * 1/3;
margin: $spacing-vertical * 1/3 0;
}
.card__media--autothumb { .card__media--autothumb {
color: red !important; color: red !important;
} }

View file

@ -21,7 +21,6 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
align-items: center;
border: var(--modal-border); border: var(--modal-border);
background: var(--modal-bg); background: var(--modal-bg);
overflow: auto; overflow: auto;
@ -74,8 +73,7 @@
} }
.modal__header { .modal__header {
margin-bottom: $spacing-vertical * 2/3; font-size: 2em;
text-align: center;
} }
.modal__buttons { .modal__buttons {
@ -104,8 +102,8 @@
} }
.error-modal__warning-symbol { .error-modal__warning-symbol {
margin-top: 6px; margin-top: -5px;
margin-right: 7px; height: 28px;
} }
.download-started-modal__file-path { .download-started-modal__file-path {
@ -118,15 +116,13 @@
} }
.error-modal__error-list { .error-modal__error-list {
/*shitty hack/temp fix for long errors making modal unusable*/ margin-top: $spacing-vertical * 1/3;
border: 1px solid var(--input-border-color); padding: $spacing-vertical * 1/3;
padding: 8px;
list-style: none; list-style: none;
max-height: 400px; max-height: 400px;
max-width: var(--modal-width); max-width: var(--modal-width);
overflow-y: scroll; overflow-y: scroll;
} color: #a94442;
background-color: #ffe0df;
.error-modal__content p { border-left: 2px solid #a94442;
padding: 0 0 $spacing-vertical $spacing-vertical;
} }

View file

@ -31,7 +31,7 @@ module.exports = {
}, },
plugins: isDev ? [ plugins: isDev ? [
new FilewatcherPlugin({ new FilewatcherPlugin({
watchFileRegex: [require.resolve('lbry-redux')], watchFileRegex: [require.resolve('lbry-redux'), require.resolve('lbryinc')],
}), }),
] : [], ] : [],
}; };

View file

@ -5662,16 +5662,16 @@ lbry-redux@lbryio/lbry-redux:
proxy-polyfill "0.1.6" proxy-polyfill "0.1.6"
reselect "^3.0.0" reselect "^3.0.0"
lbry-redux@lbryio/lbry-redux#fa141b9175500b874bb77da0258e18d902e069b9: lbry-redux@lbryio/lbry-redux#c079b108c3bc4ba2b4fb85fb112b52cfc040c301:
version "0.0.1" version "0.0.1"
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/fa141b9175500b874bb77da0258e18d902e069b9" resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/c079b108c3bc4ba2b4fb85fb112b52cfc040c301"
dependencies: dependencies:
proxy-polyfill "0.1.6" proxy-polyfill "0.1.6"
reselect "^3.0.0" reselect "^3.0.0"
lbryinc@lbryio/lbryinc#c09aa2645ecccb33c83e9a9545ff119232910f6f: lbryinc@lbryio/lbryinc#de7ff055605b02a24821f0f9bab1d206eb7f235d:
version "0.0.1" version "0.0.1"
resolved "https://codeload.github.com/lbryio/lbryinc/tar.gz/c09aa2645ecccb33c83e9a9545ff119232910f6f" resolved "https://codeload.github.com/lbryio/lbryinc/tar.gz/de7ff055605b02a24821f0f9bab1d206eb7f235d"
dependencies: dependencies:
lbry-redux lbryio/lbry-redux lbry-redux lbryio/lbry-redux
reselect "^3.0.0" reselect "^3.0.0"