diff --git a/flow-typed/web.js b/flow-typed/web.js new file mode 100644 index 000000000..69b1914e0 --- /dev/null +++ b/flow-typed/web.js @@ -0,0 +1,3 @@ +// @flow + +declare var IS_WEB: boolean; diff --git a/src/ui/component/common/lbc-symbol.jsx b/src/ui/component/common/lbc-symbol.jsx index 612247836..0fb91fe46 100644 --- a/src/ui/component/common/lbc-symbol.jsx +++ b/src/ui/component/common/lbc-symbol.jsx @@ -1,6 +1,6 @@ // @flow import React from 'react'; -const LbcSymbol = () => <span> LBC</span>; // ℄ +const LbcSymbol = () => <span>LBC</span>; // ℄ export default LbcSymbol; diff --git a/src/ui/component/fileViewer/internal/player.jsx b/src/ui/component/fileViewer/internal/player.jsx index 0cb98774a..cc602c63e 100644 --- a/src/ui/component/fileViewer/internal/player.jsx +++ b/src/ui/component/fileViewer/internal/player.jsx @@ -202,8 +202,8 @@ class MediaPlayer extends React.PureComponent<Props, State> { } // @if TARGET='app' - sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); + sleep(ms: number) { + return new Promise<void>(resolve => setTimeout(resolve, ms)); } refreshMetadata() { diff --git a/src/ui/component/fileViewer/view.jsx b/src/ui/component/fileViewer/view.jsx index 914d8ceef..34336951c 100644 --- a/src/ui/component/fileViewer/view.jsx +++ b/src/ui/component/fileViewer/view.jsx @@ -47,6 +47,7 @@ type Props = { nextFileToPlay: ?string, navigate: (string, {}) => void, costInfo: ?{ cost: number }, + insufficientCredits: boolean, }; class FileViewer extends React.PureComponent<Props> { @@ -150,7 +151,11 @@ class FileViewer extends React.PureComponent<Props> { } playContent() { - const { play, uri, fileInfo, isDownloading, isLoading } = this.props; + const { play, uri, fileInfo, isDownloading, isLoading, insufficientCredits } = this.props; + + if (insufficientCredits) { + return; + } // @if TARGET='app' if (fileInfo || isDownloading || isLoading) { @@ -220,6 +225,7 @@ class FileViewer extends React.PureComponent<Props> { className, obscureNsfw, mediaType, + insufficientCredits, } = this.props; const isPlaying = playingUri === uri; @@ -246,7 +252,10 @@ class FileViewer extends React.PureComponent<Props> { } const poster = metadata && metadata.thumbnail; - const layoverClass = classnames('content__cover', { 'card__media--nsfw': shouldObscureNsfw }); + const layoverClass = classnames('content__cover', { + 'card__media--nsfw': shouldObscureNsfw, + 'card__media--disabled': insufficientCredits, + }); const layoverStyle = !shouldObscureNsfw && poster ? { backgroundImage: `url("${poster}")` } : {}; diff --git a/src/ui/component/header/view.jsx b/src/ui/component/header/view.jsx index 75d923e62..769571697 100644 --- a/src/ui/component/header/view.jsx +++ b/src/ui/component/header/view.jsx @@ -85,8 +85,7 @@ const Header = (props: Props) => { title={`Your balance is ${balance} LBRY Credits`} label={ <React.Fragment> - <span>{roundedBalance}</span> - <LbcSymbol /> + {roundedBalance} <LbcSymbol /> </React.Fragment> } navigate="/$/wallet" @@ -94,6 +93,7 @@ const Header = (props: Props) => { <Button className="header__navigation-item header__navigation-item--right-action" + activeClass="header__navigation-item--active" description={__('Publish content')} icon={ICONS.UPLOAD} iconSize={24} diff --git a/src/ui/component/publishForm/view.jsx b/src/ui/component/publishForm/view.jsx index 1dcf62c56..1c8a4a954 100644 --- a/src/ui/component/publishForm/view.jsx +++ b/src/ui/component/publishForm/view.jsx @@ -332,6 +332,7 @@ class PublishForm extends React.PureComponent<Props> { resetThumbnailStatus, isStillEditing, amountNeededForTakeover, + balance, } = this.props; const formDisabled = (!filePath && !editingURI) || publishing; @@ -352,7 +353,7 @@ class PublishForm extends React.PureComponent<Props> { <Form onSubmit={this.handlePublish}> <section className={classnames('card card--section', { - 'card--disabled': IS_WEB || publishing, + 'card--disabled': IS_WEB || publishing || balance === 0, })} > <header className="card__header"> diff --git a/src/ui/component/router/view.jsx b/src/ui/component/router/view.jsx index 03cd902fc..15289bc74 100644 --- a/src/ui/component/router/view.jsx +++ b/src/ui/component/router/view.jsx @@ -41,6 +41,7 @@ export default function AppRouter() { <DiscoverPage path="/" /> <ShowPage path="/:claimName/:claimId" /> <ShowPage path="/:claimName" /> + {/* <ShowPage path="/" uri="five" /> */} <AuthPage path={`$/${PAGES.AUTH}`} /> <BackupPage path={`$/${PAGES.BACKUP}`} /> diff --git a/src/ui/component/yrbl/index.jsx b/src/ui/component/yrbl/index.jsx index 7b486783f..a2ba9bd2b 100644 --- a/src/ui/component/yrbl/index.jsx +++ b/src/ui/component/yrbl/index.jsx @@ -27,12 +27,12 @@ export default class extends React.PureComponent<Props> { const image = yrblTypes[type]; return ( - <div className="yrbl-wrap"> - <img alt="Friendly gerbil" className={classnames('yrbl', className)} src={image} /> + <div className="yrbl__wrap"> + <img alt="Friendly gerbil" className={classnames('yrbl', className)} src={`/${image}`} /> {title && subtitle && ( - <div className="card__content"> + <div className="yrbl__content"> <h2 className="card__title">{title}</h2> - <div className="card__subtitle">{subtitle}</div> + <div className="card__content">{subtitle}</div> </div> )} </div> diff --git a/src/ui/constants/modal_types.js b/src/ui/constants/modal_types.js index bf4b1ad4c..14eb7429d 100644 --- a/src/ui/constants/modal_types.js +++ b/src/ui/constants/modal_types.js @@ -6,7 +6,6 @@ export const DOWNLOADING = 'downloading'; export const AUTO_UPDATE_DOWNLOADED = 'auto_update_downloaded'; export const AUTO_UPDATE_CONFIRM = 'auto_update_confirm'; export const ERROR = 'error'; -export const INSUFFICIENT_CREDITS = 'insufficient_credits'; export const UPGRADE = 'upgrade'; export const WELCOME = 'welcome'; export const EMAIL_COLLECTION = 'email_collection'; diff --git a/src/ui/modal/modalCreditIntro/index.js b/src/ui/modal/modalCreditIntro/index.js deleted file mode 100644 index 69f8b718a..000000000 --- a/src/ui/modal/modalCreditIntro/index.js +++ /dev/null @@ -1,31 +0,0 @@ -import { connect } from 'react-redux'; -import { doSetClientSetting } from 'redux/actions/settings'; -import { selectUserIsRewardApproved, selectUnclaimedRewardValue } from 'lbryinc'; -import { selectBalance } from 'lbry-redux'; -import { doHideModal } from 'redux/actions/app'; -import * as settings from 'constants/settings'; -import ModalCreditIntro from './view'; -import { navigate } from '@reach/router'; - -const select = state => ({ - currentBalance: selectBalance(state), - isRewardApproved: selectUserIsRewardApproved(state), - totalRewardValue: selectUnclaimedRewardValue(state), -}); - -const perform = dispatch => () => ({ - addBalance: () => { - navigate('/$/getcredits'); - dispatch(doSetClientSetting(settings.CREDIT_REQUIRED_ACKNOWLEDGED, true)); - dispatch(doHideModal()); - }, - closeModal: () => { - dispatch(doSetClientSetting(settings.CREDIT_REQUIRED_ACKNOWLEDGED, true)); - dispatch(doHideModal()); - }, -}); - -export default connect( - select, - perform -)(ModalCreditIntro); diff --git a/src/ui/modal/modalCreditIntro/view.jsx b/src/ui/modal/modalCreditIntro/view.jsx deleted file mode 100644 index 5d3f411ee..000000000 --- a/src/ui/modal/modalCreditIntro/view.jsx +++ /dev/null @@ -1,56 +0,0 @@ -// @flow -import React from 'react'; -import { Modal } from 'modal/modal'; -import CurrencySymbol from 'component/common/lbc-symbol'; -import CreditAmount from 'component/common/credit-amount'; -import Button from 'component/button'; - -type Props = { - totalRewardValue: number, - currentBalance: number, - closeModal: () => void, - addBalance: () => void, -}; - -const ModalCreditIntro = (props: Props) => { - const { closeModal, totalRewardValue, currentBalance, addBalance } = props; - const totalRewardRounded = Math.floor(totalRewardValue / 10) * 10; - - return ( - <Modal type="custom" isOpen contentLabel="Welcome to LBRY" title={__('LBRY Credits Needed')}> - <section className="card__content"> - <p> - Some actions require LBRY credits ( - <em> - <CurrencySymbol /> - </em> - ), the blockchain token that powers the LBRY network. - </p> - {currentBalance <= 0 && ( - <p> - You currently have <CreditAmount inheritStyle amount={currentBalance} />, so the actions - you can take are limited. - </p> - )} - {Boolean(totalRewardValue) && ( - <p> - {__(' There are a variety of ways to get credits, including more than')}{' '} - <CreditAmount inheritStyle amount={totalRewardRounded} />{' '} - {__('in free rewards for participating in the LBRY beta.')} - </p> - )} - </section> - - <div className="card__actions"> - <Button button="primary" onClick={addBalance} label={__('Get Credits')} /> - <Button - button="link" - onClick={closeModal} - label={currentBalance <= 0 ? __('Use Without LBC') : __('Meh, Not Now')} - /> - </div> - </Modal> - ); -}; - -export default ModalCreditIntro; diff --git a/src/ui/modal/modalRouter/index.js b/src/ui/modal/modalRouter/index.js index 2ff9387a5..422f215ca 100644 --- a/src/ui/modal/modalRouter/index.js +++ b/src/ui/modal/modalRouter/index.js @@ -1,28 +1,15 @@ import { connect } from 'react-redux'; -import * as settings from 'constants/settings'; -import { selectBalance, makeSelectCostInfoForUri, selectError, doToast } from 'lbry-redux'; -import { makeSelectClientSetting } from 'redux/selectors/settings'; -import { selectUser, selectUserIsVerificationCandidate } from 'lbryinc'; import { selectModal } from 'redux/selectors/app'; import { doOpenModal } from 'redux/actions/app'; +import { selectError } from 'lbry-redux'; import ModalRouter from './view'; const select = (state, props) => ({ - balance: selectBalance(state), - showPageCost: makeSelectCostInfoForUri(props.uri)(state), - isVerificationCandidate: selectUserIsVerificationCandidate(state), - isCreditIntroAcknowledged: makeSelectClientSetting(settings.CREDIT_REQUIRED_ACKNOWLEDGED)(state), - isEmailCollectionAcknowledged: makeSelectClientSetting(settings.EMAIL_COLLECTION_ACKNOWLEDGED)( - state - ), - isWelcomeAcknowledged: makeSelectClientSetting(settings.NEW_USER_ACKNOWLEDGED)(state), - user: selectUser(state), modal: selectModal(state), error: selectError(state), }); const perform = dispatch => ({ - showToast: props => dispatch(doToast(props)), openModal: props => dispatch(doOpenModal(props)), }); diff --git a/src/ui/modal/modalRouter/view.jsx b/src/ui/modal/modalRouter/view.jsx index 69d68d0fb..90e524f36 100644 --- a/src/ui/modal/modalRouter/view.jsx +++ b/src/ui/modal/modalRouter/view.jsx @@ -10,7 +10,6 @@ import ModalUpgrade from 'modal/modalUpgrade'; import ModalWelcome from 'modal/modalWelcome'; import ModalFirstReward from 'modal/modalFirstReward'; import ModalRewardApprovalRequired from 'modal/modalRewardApprovalRequired'; -import ModalCreditIntro from 'modal/modalCreditIntro'; import ModalRemoveFile from 'modal/modalRemoveFile'; import ModalTransactionFailed from 'modal/modalTransactionFailed'; import ModalFileTimeout from 'modal/modalFileTimeout'; @@ -32,162 +31,76 @@ import ModalRewardCode from 'modal/modalRewardCode'; type Props = { modal: { id: string, modalProps: {} }, error: { message: string }, - openModal: string => void, - page: string, - isWelcomeAcknowledged: boolean, - isEmailCollectionAcknowledged: boolean, - isVerificationCandidate: boolean, - isCreditIntroAcknowledged: boolean, - balance: number, - showPageCost: number, - user: { - is_reward_approved: boolean, - is_identity_verified: boolean, - has_verified_email: boolean, - }, }; -type State = { - lastTransitionModal: ?string, - lastTransitionPage: ?string, -}; +function ModalRouter(props: Props) { + const { modal, error } = props; -class ModalRouter extends React.PureComponent<Props, State> { - constructor(props: Props) { - super(props); - - this.state = { - lastTransitionModal: null, - lastTransitionPage: null, - }; + if (error) { + return <ModalError {...error} />; } - componentWillMount() { - this.showTransitionModals(this.props); + if (!modal) { + return null; } - componentWillReceiveProps(nextProps: Props) { - this.showTransitionModals(nextProps); - } + const { id, modalProps } = modal; - showTransitionModals(props: Props) { - const { modal, openModal, page } = props; - - if (modal) { - return; - } - - const transitionModal = [this.checkShowCreditIntro].reduce( - (acc, func) => (!acc ? func.bind(this)(props) : acc), - false - ); - - if ( - transitionModal && - (transitionModal !== this.state.lastTransitionModal || page !== this.state.lastTransitionPage) - ) { - openModal(transitionModal); - this.setState({ - lastTransitionModal: transitionModal, - lastTransitionPage: page, - }); - } - } - - checkShowCreditIntro(props: Props) { - // @if TARGET='app' - // This doesn't make sense to show until the web has wallet support - const { balance, page, isCreditIntroAcknowledged } = props; - - if ( - balance === 0 && - !isCreditIntroAcknowledged && - (['send', 'publish'].includes(page) || this.isPaidShowPage(props)) - ) { - return MODALS.INSUFFICIENT_CREDITS; - } - // @endif - - return undefined; - } - - isPaidShowPage(props: Props) { - const { page, showPageCost } = props; - // Fix me - return page === 'show' && showPageCost > 0; - } - - render() { - const { modal, error } = this.props; - - if (error) { - return <ModalError {...error} />; - } - - if (!modal) { + switch (id) { + case MODALS.UPGRADE: + return <ModalUpgrade {...modalProps} />; + case MODALS.DOWNLOADING: + return <ModalDownloading {...modalProps} />; + case MODALS.AUTO_UPDATE_DOWNLOADED: + return <ModalAutoUpdateDownloaded {...modalProps} />; + case MODALS.AUTO_UPDATE_CONFIRM: + return <ModalAutoUpdateConfirm {...modalProps} />; + case MODALS.ERROR: + return <ModalError {...modalProps} />; + case MODALS.FILE_TIMEOUT: + return <ModalFileTimeout {...modalProps} />; + case MODALS.WELCOME: + return <ModalWelcome {...modalProps} />; + case MODALS.FIRST_REWARD: + return <ModalFirstReward {...modalProps} />; + case MODALS.AUTHENTICATION_FAILURE: + return <ModalAuthFailure {...modalProps} />; + case MODALS.TRANSACTION_FAILED: + return <ModalTransactionFailed {...modalProps} />; + case MODALS.REWARD_APPROVAL_REQUIRED: + return <ModalRewardApprovalRequired {...modalProps} />; + case MODALS.CONFIRM_FILE_REMOVE: + return <ModalRemoveFile {...modalProps} />; + case MODALS.AFFIRM_PURCHASE: + return <ModalAffirmPurchase {...modalProps} />; + case MODALS.CONFIRM_CLAIM_REVOKE: + return <ModalRevokeClaim {...modalProps} />; + case MODALS.PHONE_COLLECTION: + return <ModalPhoneCollection {...modalProps} />; + case MODALS.FIRST_SUBSCRIPTION: + return <ModalFirstSubscription {...modalProps} />; + case MODALS.SEND_TIP: + return <ModalSendTip {...modalProps} />; + case MODALS.SOCIAL_SHARE: + return <ModalSocialShare {...modalProps} />; + case MODALS.PUBLISH: + return <ModalPublish {...modalProps} />; + case MODALS.CONFIRM_EXTERNAL_LINK: + return <ModalOpenExternalLink {...modalProps} />; + case MODALS.CONFIRM_TRANSACTION: + return <ModalConfirmTransaction {...modalProps} />; + case MODALS.CONFIRM_THUMBNAIL_UPLOAD: + return <ModalConfirmThumbnailUpload {...modalProps} />; + case MODALS.WALLET_ENCRYPT: + return <ModalWalletEncrypt {...modalProps} />; + case MODALS.WALLET_DECRYPT: + return <ModalWalletDecrypt {...modalProps} />; + case MODALS.WALLET_UNLOCK: + return <ModalWalletUnlock {...modalProps} />; + case MODALS.REWARD_GENERATED_CODE: + return <ModalRewardCode {...modalProps} />; + default: return null; - } - - const { id, modalProps } = modal; - - switch (id) { - case MODALS.UPGRADE: - return <ModalUpgrade {...modalProps} />; - case MODALS.DOWNLOADING: - return <ModalDownloading {...modalProps} />; - case MODALS.AUTO_UPDATE_DOWNLOADED: - return <ModalAutoUpdateDownloaded {...modalProps} />; - case MODALS.AUTO_UPDATE_CONFIRM: - return <ModalAutoUpdateConfirm {...modalProps} />; - case MODALS.ERROR: - return <ModalError {...modalProps} />; - case MODALS.FILE_TIMEOUT: - return <ModalFileTimeout {...modalProps} />; - case MODALS.INSUFFICIENT_CREDITS: - return <ModalCreditIntro {...modalProps} />; - case MODALS.WELCOME: - return <ModalWelcome {...modalProps} />; - case MODALS.FIRST_REWARD: - return <ModalFirstReward {...modalProps} />; - case MODALS.AUTHENTICATION_FAILURE: - return <ModalAuthFailure {...modalProps} />; - case MODALS.TRANSACTION_FAILED: - return <ModalTransactionFailed {...modalProps} />; - case MODALS.REWARD_APPROVAL_REQUIRED: - return <ModalRewardApprovalRequired {...modalProps} />; - case MODALS.CONFIRM_FILE_REMOVE: - return <ModalRemoveFile {...modalProps} />; - case MODALS.AFFIRM_PURCHASE: - return <ModalAffirmPurchase {...modalProps} />; - case MODALS.CONFIRM_CLAIM_REVOKE: - return <ModalRevokeClaim {...modalProps} />; - case MODALS.PHONE_COLLECTION: - return <ModalPhoneCollection {...modalProps} />; - case MODALS.FIRST_SUBSCRIPTION: - return <ModalFirstSubscription {...modalProps} />; - case MODALS.SEND_TIP: - return <ModalSendTip {...modalProps} />; - case MODALS.SOCIAL_SHARE: - return <ModalSocialShare {...modalProps} />; - case MODALS.PUBLISH: - return <ModalPublish {...modalProps} />; - case MODALS.CONFIRM_EXTERNAL_LINK: - return <ModalOpenExternalLink {...modalProps} />; - case MODALS.CONFIRM_TRANSACTION: - return <ModalConfirmTransaction {...modalProps} />; - case MODALS.CONFIRM_THUMBNAIL_UPLOAD: - return <ModalConfirmThumbnailUpload {...modalProps} />; - case MODALS.WALLET_ENCRYPT: - return <ModalWalletEncrypt {...modalProps} />; - case MODALS.WALLET_DECRYPT: - return <ModalWalletDecrypt {...modalProps} />; - case MODALS.WALLET_UNLOCK: - return <ModalWalletUnlock {...modalProps} />; - case MODALS.REWARD_GENERATED_CODE: - return <ModalRewardCode {...modalProps} />; - default: - return null; - } } } diff --git a/src/ui/page/file/index.js b/src/ui/page/file/index.js index 921eba8b0..b543d4150 100644 --- a/src/ui/page/file/index.js +++ b/src/ui/page/file/index.js @@ -12,6 +12,7 @@ import { makeSelectContentTypeForUri, makeSelectMetadataForUri, makeSelectChannelForClaimUri, + selectBalance, } from 'lbry-redux'; import { doFetchViewCount, @@ -39,6 +40,7 @@ const select = (state, props) => ({ isSubscribed: makeSelectIsSubscribed(props.uri)(state), channelUri: makeSelectChannelForClaimUri(props.uri, true)(state), viewCount: makeSelectViewCountForUri(props.uri)(state), + balance: selectBalance(state), }); const perform = dispatch => ({ diff --git a/src/ui/page/file/view.jsx b/src/ui/page/file/view.jsx index 7c9eae257..5124a2e02 100644 --- a/src/ui/page/file/view.jsx +++ b/src/ui/page/file/view.jsx @@ -42,6 +42,7 @@ type Props = { openModal: (id: string, { uri: string }) => void, markSubscriptionRead: (string, string) => void, fetchViewCount: string => void, + balance: number, }; class FilePage extends React.Component<Props> { @@ -135,6 +136,7 @@ class FilePage extends React.Component<Props> { fileInfo, channelUri, viewCount, + balance, } = this.props; // File info @@ -147,6 +149,7 @@ class FilePage extends React.Component<Props> { const mediaType = getMediaType(contentType, fileName); const showFile = PLAYABLE_MEDIA_TYPES.includes(mediaType) || PREVIEW_MEDIA_TYPES.includes(mediaType); + const speechShareable = costInfo && costInfo.cost === 0 && @@ -168,11 +171,32 @@ class FilePage extends React.Component<Props> { editUri = buildURI(uriObject); } + const insufficientCredits = costInfo && costInfo.cost > balance; + return ( <Page notContained className="main--file-page"> <div className="grid-area--content"> - <h1 className="media__uri">{uri}</h1> - {showFile && <FileViewer className="content__embedded" uri={uri} mediaType={mediaType} />} + <h1 className="media__uri"> + <Button navigate={uri} label={uri} /> + </h1> + {insufficientCredits && ( + <div className="media__insufficient-credits help--warning"> + {__( + 'The publisher has chosen to charge LBC to view this content. Your balance is currently to low to view it.' + )}{' '} + {__('Checkout')}{' '} + <Button button="link" navigate="/$/rewards" label={__('the rewards page')} />{' '} + {__('or send more LBC to your wallet.')} + </div> + )} + {showFile && ( + <FileViewer + insufficientCredits={insufficientCredits} + className="content__embedded" + uri={uri} + mediaType={mediaType} + /> + )} {!showFile && (thumbnail ? ( <Thumbnail shouldObscure={shouldObscureThumbnail} src={thumbnail} /> diff --git a/src/ui/page/publish/index.js b/src/ui/page/publish/index.js index 19ccb3c60..8389f1622 100644 --- a/src/ui/page/publish/index.js +++ b/src/ui/page/publish/index.js @@ -14,6 +14,7 @@ import { doPublish, doPrepareEdit, } from 'redux/actions/publish'; +import { selectUnclaimedRewardValue } from 'lbryinc'; import PublishPage from './view'; const select = state => ({ @@ -27,6 +28,7 @@ const select = state => ({ isStillEditing: selectIsStillEditing(state), balance: selectBalance(state), isResolvingUri: selectIsResolvingPublishUris(state), + totalRewardValue: selectUnclaimedRewardValue(state), }); const perform = dispatch => ({ diff --git a/src/ui/page/publish/view.jsx b/src/ui/page/publish/view.jsx index 0745e9430..6903a79b4 100644 --- a/src/ui/page/publish/view.jsx +++ b/src/ui/page/publish/view.jsx @@ -1,19 +1,65 @@ -import React from 'react'; +import React, { Fragment } from 'react'; import PublishForm from 'component/publishForm'; import Page from 'component/page'; +import Yrbl from 'component/yrbl'; +import LbcSymbol from 'component/common/lbc-symbol'; +import CreditAmount from 'component/common/credit-amount'; +import Button from 'component/button'; class PublishPage extends React.PureComponent { scrollToTop = () => { - // #content wraps every <Page> - const mainContent = document.getElementById('content'); + const mainContent = document.querySelector('main'); if (mainContent) { mainContent.scrollTop = 0; // It would be nice to animate this } }; render() { + const { balance, totalRewardValue } = this.props; + const totalRewardRounded = Math.floor(totalRewardValue / 10) * 10; + return ( <Page> + {balance === 0 && ( + <Fragment> + <Yrbl + title={__("You can't publish things quite yet")} + subtitle={ + <Fragment> + <p> + {__( + 'LBRY uses a blockchain, which is a fancy way of saying that users (you) are in control of your data.' + )} + </p> + <p> + {__('Because of the blockchain, some actions require LBRY credits')} ( + <LbcSymbol /> + ). + </p> + <p> + <LbcSymbol />{' '} + {__( + 'allows you to do some neat things, like paying your favorite creators for their content. And no company can stop you.' + )} + </p> + </Fragment> + } + /> + <section className="card card--section"> + <header className="card__header"> + <h1 className="card__title">{__('LBRY Credits Required')}</h1> + </header> + <p className="card__subtitle"> + {__(' There are a variety of ways to get credits, including more than')}{' '} + <CreditAmount inheritStyle amount={totalRewardRounded} />{' '} + {__('in free rewards for participating in the LBRY beta.')} + </p> + <div className="card__actions"> + <Button button="link" navigate="/$/rewards" label={__('Checkout the rewards')} /> + </div> + </section> + </Fragment> + )} <PublishForm {...this.props} scrollToTop={this.scrollToTop} /> </Page> ); diff --git a/src/ui/redux/actions/content.js b/src/ui/redux/actions/content.js index dd8b8a05d..a2afb26b1 100644 --- a/src/ui/redux/actions/content.js +++ b/src/ui/redux/actions/content.js @@ -272,7 +272,6 @@ export function doPurchaseUri( if (cost > balance) { dispatch(doSetPlayingUri(null)); - dispatch(doOpenModal(MODALS.INSUFFICIENT_CREDITS)); Promise.resolve(); return; } diff --git a/src/ui/scss/component/_card.scss b/src/ui/scss/component/_card.scss index 8ea599ca6..164ad18c0 100644 --- a/src/ui/scss/component/_card.scss +++ b/src/ui/scss/component/_card.scss @@ -1,7 +1,7 @@ .card { background-color: $lbry-white; border: 1px solid $lbry-gray-1; - margin-bottom: var(--spacing-vertical-large); + margin-bottom: var(--spacing-vertical-xlarge); position: relative; html[data-mode='dark'] & { @@ -84,6 +84,11 @@ p:not(:last-child) { margin-bottom: var(--spacing-vertical-medium); } + + .badge { + bottom: -0.15rem; + position: relative; + } } // C A R D @@ -92,10 +97,6 @@ .card__header { position: relative; - + .card__content { - margin-top: var(--spacing-vertical-medium); - } - &:not(.card__header--flat) { margin-bottom: var(--spacing-vertical-small); } @@ -195,6 +196,10 @@ .button { font-size: 1.2rem; } + + + .card__content { + margin-top: var(--spacing-vertical-medium); + } } .card__title--flex { diff --git a/src/ui/scss/component/_content.scss b/src/ui/scss/component/_content.scss index a1c9a85a9..2fbc41b85 100644 --- a/src/ui/scss/component/_content.scss +++ b/src/ui/scss/component/_content.scss @@ -67,6 +67,11 @@ background-color: $lbry-grape-3; } +.card__media--disabled { + opacity: 0.5; + pointer-events: none; +} + .content__loading { width: 100%; height: 100%; diff --git a/src/ui/scss/component/_header.scss b/src/ui/scss/component/_header.scss index 62f444b7a..12ad4be1f 100644 --- a/src/ui/scss/component/_header.scss +++ b/src/ui/scss/component/_header.scss @@ -81,6 +81,14 @@ } } +.header__navigation-item--active { + background-image: linear-gradient( + to bottom, + transparent 0%, + mix(transparent, $lbry-teal-3, 70%) 90% + ); +} + .header__navigation-item--back, .header__navigation-item--forward, .header__navigation-item--home, diff --git a/src/ui/scss/component/_media.scss b/src/ui/scss/component/_media.scss index 81624e156..5363166dc 100644 --- a/src/ui/scss/component/_media.scss +++ b/src/ui/scss/component/_media.scss @@ -155,6 +155,10 @@ opacity: 0.6; } +.media__insufficient-credits { + padding: 10px; +} + // M E D I A // A C T I O N S diff --git a/src/ui/scss/component/_yrbl.scss b/src/ui/scss/component/_yrbl.scss index 8d6f92a6d..6e9b1df4e 100644 --- a/src/ui/scss/component/_yrbl.scss +++ b/src/ui/scss/component/_yrbl.scss @@ -1,10 +1,10 @@ -.yrbl-wrap { +.yrbl__wrap { align-items: center; display: flex; justify-content: center; vertical-align: middle; text-align: left; - margin-bottom: var(--spacing-vertical-large); + margin-bottom: var(--spacing-vertical-xlarge); } .yrbl { @@ -12,6 +12,10 @@ margin-right: var(--spacing-vertical-large); } +.yrbl__content { + max-width: 500px; +} + .yrbl--first-run { align-self: center; height: 250px; diff --git a/src/ui/scss/init/_gui.scss b/src/ui/scss/init/_gui.scss index c10d86524..6899fdd90 100644 --- a/src/ui/scss/init/_gui.scss +++ b/src/ui/scss/init/_gui.scss @@ -170,7 +170,7 @@ code { } html[data-mode='dark'] & { - background-color: $lbry-yellow-4; + background-color: $lbry-yellow-3; color: $lbry-black; } } diff --git a/src/ui/scss/init/_vars.scss b/src/ui/scss/init/_vars.scss index 90972d9e5..c583d702f 100644 --- a/src/ui/scss/init/_vars.scss +++ b/src/ui/scss/init/_vars.scss @@ -17,6 +17,7 @@ $large-breakpoint: 1921px; --spacing-vertical-small: calc(2rem / 3); --spacing-vertical-medium: calc(2rem / 2); --spacing-vertical-large: 2rem; + --spacing-vertical-xlarge: 3rem; --file-page-max-width: 1787px; --file-max-height: 788px;