diff --git a/flow-typed/publish.js b/flow-typed/publish.js index 0d1cc0acf..8ad2339b3 100644 --- a/flow-typed/publish.js +++ b/flow-typed/publish.js @@ -48,4 +48,5 @@ declare type PublishParams = { }, claim: StreamClaim, nsfw: boolean, + tags: Array, }; diff --git a/src/ui/component/button/view.jsx b/src/ui/component/button/view.jsx index ddf31ecb2..effdef03b 100644 --- a/src/ui/component/button/view.jsx +++ b/src/ui/component/button/view.jsx @@ -1,4 +1,5 @@ // @flow +import type { Node } from 'react'; import React, { forwardRef } from 'react'; import Icon from 'component/common/icon'; import classnames from 'classnames'; @@ -14,13 +15,12 @@ type Props = { icon: ?string, iconRight: ?string, disabled: ?boolean, - children: ?React.Node, + children: ?Node, navigate: ?string, className: ?string, description: ?string, type: string, button: ?string, // primary, secondary, alt, link - iconColor?: string, iconSize?: number, constrict: ?boolean, // to shorten the button and ellipsis, only use for links activeClass?: string, @@ -31,7 +31,9 @@ type Props = { onMouseLeave: ?(any) => any, }; -const Button = forwardRef((props: Props, ref) => { +// use forwardRef to allow consumers to pass refs to the button content if they want to +// flow requires forwardRef have default type arguments passed to it +const Button = forwardRef((props: Props, ref: any) => { const { type = 'button', onClick, @@ -48,7 +50,6 @@ const Button = forwardRef((props: Props, ref) => { className, description, button, - iconColor, iconSize, constrict, activeClass, @@ -74,10 +75,10 @@ const Button = forwardRef((props: Props, ref) => { const content = ( - {icon && } + {icon && } {label && {label}} {children && children} - {iconRight && } + {iconRight && } ); diff --git a/src/ui/component/claimList/view.jsx b/src/ui/component/claimList/view.jsx index c8f26e0f3..8458175ca 100644 --- a/src/ui/component/claimList/view.jsx +++ b/src/ui/component/claimList/view.jsx @@ -2,7 +2,7 @@ import type { Node } from 'react'; import React from 'react'; import classnames from 'classnames'; -import ClaimListItem from 'component/claimListItem'; +import ClaimPreview from 'component/claimPreview'; import Spinner from 'component/spinner'; import { FormField } from 'component/common/form'; import usePersistedState from 'util/use-persisted-state'; @@ -36,10 +36,10 @@ export default function ClaimList(props: Props) { return (
{header !== false && ( -
+
{header || ( )} {loading && } -
{headerAltControls}
+
{headerAltControls}
)} - {meta &&
{meta}
} + {meta &&
{meta}
} {hasUris && (
    {sortedUris.map((uri, index) => ( - - {index === 4 && injectedItem &&
  • {injectedItem}
  • } + + {index === 4 && injectedItem &&
  • {injectedItem}
  • }
    ))}
diff --git a/src/ui/component/claimListDiscover/view.jsx b/src/ui/component/claimListDiscover/view.jsx index 40f0b7a20..331b4389a 100644 --- a/src/ui/component/claimListDiscover/view.jsx +++ b/src/ui/component/claimListDiscover/view.jsx @@ -70,7 +70,7 @@ function ClaimListDiscover(props: Props) { const header = (

setPersonalSort(e.target.value)} > @@ -107,7 +107,7 @@ function ClaimListDiscover(props: Props) { {typeSort === 'top' && ( ({ pending: makeSelectClaimIsPending(props.uri)(state), @@ -32,4 +32,4 @@ const perform = dispatch => ({ export default connect( select, perform -)(ClaimListItem); +)(ClaimPreview); diff --git a/src/ui/component/claimPreview/index.js b/src/ui/component/claimPreview/index.js new file mode 100644 index 000000000..6d08b46e0 --- /dev/null +++ b/src/ui/component/claimPreview/index.js @@ -0,0 +1,35 @@ +import { connect } from 'react-redux'; +import { + doResolveUri, + makeSelectClaimForUri, + makeSelectIsUriResolving, + makeSelectClaimIsMine, + makeSelectClaimIsPending, + makeSelectThumbnailForUri, + makeSelectTitleForUri, + makeSelectClaimIsNsfw, +} from 'lbry-redux'; +import { selectBlackListedOutpoints } from 'lbryinc'; +import { selectShowNsfw } from 'redux/selectors/settings'; +import ClaimPreview from './view'; + +const select = (state, props) => ({ + pending: makeSelectClaimIsPending(props.uri)(state), + claim: makeSelectClaimForUri(props.uri)(state), + obscureNsfw: !selectShowNsfw(state), + claimIsMine: makeSelectClaimIsMine(props.uri)(state), + isResolvingUri: makeSelectIsUriResolving(props.uri)(state), + thumbnail: makeSelectThumbnailForUri(props.uri)(state), + title: makeSelectTitleForUri(props.uri)(state), + nsfw: makeSelectClaimIsNsfw(props.uri)(state), + blackListedOutpoints: selectBlackListedOutpoints(state), +}); + +const perform = dispatch => ({ + resolveUri: uri => dispatch(doResolveUri(uri)), +}); + +export default connect( + select, + perform +)(ClaimPreview); diff --git a/src/ui/component/claimListItem/view.jsx b/src/ui/component/claimPreview/view.jsx similarity index 86% rename from src/ui/component/claimListItem/view.jsx rename to src/ui/component/claimPreview/view.jsx index cd0376f71..e5b7ac57c 100644 --- a/src/ui/component/claimListItem/view.jsx +++ b/src/ui/component/claimPreview/view.jsx @@ -35,7 +35,7 @@ type Props = { }>, }; -function ClaimListItem(props: Props) { +function ClaimPreview(props: Props) { const { obscureNsfw, claimIsMine, @@ -94,10 +94,10 @@ function ClaimListItem(props: Props) { if (placeholder && !claim) { return ( -
  • +
  • -
    +
  • @@ -107,16 +107,17 @@ function ClaimListItem(props: Props) { return (
  • {isChannel ? : } -
    -
    -
    +
    +
    +
    {type !== 'small' && ( @@ -127,7 +128,7 @@ function ClaimListItem(props: Props) { )}
    -
    +
    {pending &&
    Pending...
    } @@ -141,4 +142,4 @@ function ClaimListItem(props: Props) { ); } -export default withRouter(ClaimListItem); +export default withRouter(ClaimPreview); diff --git a/src/ui/component/common/file-selector.jsx b/src/ui/component/common/file-selector.jsx index 6544ae9b4..817c2412f 100644 --- a/src/ui/component/common/file-selector.jsx +++ b/src/ui/component/common/file-selector.jsx @@ -1,13 +1,6 @@ // @flow import * as React from 'react'; -// @if TARGET='app' -// $FlowFixMe import { remote } from 'electron'; -// @endif -// @if TARGET='web' -// $FlowFixMe -import { remote } from 'web/stubs'; -// @endif import Button from 'component/button'; import { FormField } from 'component/common/form'; import path from 'path'; @@ -21,6 +14,8 @@ type Props = { type: string, currentPath: ?string, onFileChosen: (string, string) => void, + label?: string, + placeholder?: string, fileLabel?: string, directoryLabel?: string, filters?: FileFilters[], @@ -83,13 +78,14 @@ class FileSelector extends React.PureComponent { input: ?HTMLInputElement; render() { - const { type, currentPath, fileLabel, directoryLabel } = this.props; + const { type, currentPath, label, fileLabel, directoryLabel, placeholder } = this.props; - const label = type === 'file' ? fileLabel || __('Choose File') : directoryLabel || __('Choose Directory'); + const buttonLabel = type === 'file' ? fileLabel || __('Choose File') : directoryLabel || __('Choose Directory'); return ( { if (this.fileInput) this.fileInput.current.select(); }} readOnly="readonly" - value={currentPath || __('No File Chosen')} - inputButton={
    + IS_WEB && ( +
    + This page is not currently supported on the web.{' '} +
    + ) ); } diff --git a/src/ui/component/errorBoundary/view.jsx b/src/ui/component/errorBoundary/view.jsx index 6e6c8d092..c3125e562 100644 --- a/src/ui/component/errorBoundary/view.jsx +++ b/src/ui/component/errorBoundary/view.jsx @@ -68,7 +68,7 @@ class ErrorBoundary extends React.Component { render() { if (this.state.hasError) { return ( -
    +
    void, claimIsMine: boolean, fileInfo: FileInfo, - viewerContainer: React.Ref, + viewerContainer: ?{ current: Node }, showFullscreen: boolean, }; diff --git a/src/ui/component/fileDownloadLink/view.jsx b/src/ui/component/fileDownloadLink/view.jsx index 5114d56a0..307e6a5c7 100644 --- a/src/ui/component/fileDownloadLink/view.jsx +++ b/src/ui/component/fileDownloadLink/view.jsx @@ -57,7 +57,7 @@ class FileDownloadLink extends React.PureComponent { } return ( - +
    ); diff --git a/src/ui/component/fileRender/view.jsx b/src/ui/component/fileRender/view.jsx index 8c0252a18..94c6adc4f 100644 --- a/src/ui/component/fileRender/view.jsx +++ b/src/ui/component/fileRender/view.jsx @@ -4,6 +4,8 @@ import React from 'react'; import LoadingScreen from 'component/common/loading-screen'; import VideoViewer from 'component/viewers/videoViewer'; +// Audio player on hold until the current player is dropped +// This component is half working // const AudioViewer = React.lazy<*>(() => // import(/* webpackChunkName: "audioViewer" */ // 'component/viewers/audioViewer') diff --git a/src/ui/component/publishAdditionalOptions/index.js b/src/ui/component/publishAdditionalOptions/index.js new file mode 100644 index 000000000..0d1481e57 --- /dev/null +++ b/src/ui/component/publishAdditionalOptions/index.js @@ -0,0 +1,46 @@ +import { connect } from 'react-redux'; +import { doResolveUri, selectBalance } from 'lbry-redux'; +import { + selectPublishFormValues, + selectIsStillEditing, + selectMyClaimForUri, + selectIsResolvingPublishUris, + selectTakeOverAmount, +} from 'redux/selectors/publish'; +import { + doResetThumbnailStatus, + doClearPublish, + doUpdatePublishForm, + doPublish, + doPrepareEdit, +} from 'redux/actions/publish'; +import { selectUnclaimedRewardValue } from 'lbryinc'; +import PublishPage from './view'; + +const select = state => ({ + ...selectPublishFormValues(state), + // The winning claim for a short lbry uri + amountNeededForTakeover: selectTakeOverAmount(state), + // My previously published claims under this short lbry uri + myClaimForUri: selectMyClaimForUri(state), + // If I clicked the "edit" button, have I changed the uri? + // Need this to make it easier to find the source on previously published content + isStillEditing: selectIsStillEditing(state), + isResolvingUri: selectIsResolvingPublishUris(state), + totalRewardValue: selectUnclaimedRewardValue(state), + balance: selectBalance(state), +}); + +const perform = dispatch => ({ + updatePublishForm: value => dispatch(doUpdatePublishForm(value)), + clearPublish: () => dispatch(doClearPublish()), + resolveUri: uri => dispatch(doResolveUri(uri)), + publish: params => dispatch(doPublish(params)), + prepareEdit: (claim, uri) => dispatch(doPrepareEdit(claim, uri)), + resetThumbnailStatus: () => dispatch(doResetThumbnailStatus()), +}); + +export default connect( + select, + perform +)(PublishPage); diff --git a/src/ui/component/publishForm/internal/license-type.jsx b/src/ui/component/publishAdditionalOptions/license-type.jsx similarity index 99% rename from src/ui/component/publishForm/internal/license-type.jsx rename to src/ui/component/publishAdditionalOptions/license-type.jsx index 6e14f7489..4d2be470c 100644 --- a/src/ui/component/publishForm/internal/license-type.jsx +++ b/src/ui/component/publishAdditionalOptions/license-type.jsx @@ -4,7 +4,7 @@ import { FormField } from 'component/common/form'; import { CC_LICENSES, COPYRIGHT, OTHER, PUBLIC_DOMAIN, NONE } from 'constants/licenses'; type Props = { - licenseType: string, + licenseType: ?string, licenseUrl: ?string, otherLicenseDescription: ?string, handleLicenseChange: (string, string) => void, diff --git a/src/ui/component/publishAdditionalOptions/view.jsx b/src/ui/component/publishAdditionalOptions/view.jsx new file mode 100644 index 000000000..b1b961159 --- /dev/null +++ b/src/ui/component/publishAdditionalOptions/view.jsx @@ -0,0 +1,80 @@ +// @flow +import React from 'react'; +import classnames from 'classnames'; +import usePersistedState from 'util/use-persisted-state'; +import { FormField } from 'component/common/form'; +import Button from 'component/button'; +import LicenseType from './license-type'; + +type Props = { + language: ?string, + name: ?string, + licenseType: ?string, + otherLicenseDescription: ?string, + licenseUrl: ?string, + disabled: boolean, + updatePublishForm: ({}) => void, +}; + +function PublishAdvanced(props: Props) { + const { language, name, licenseType, otherLicenseDescription, licenseUrl, updatePublishForm } = props; + const [hideSection, setHideSection] = usePersistedState('publish-advanced-options', true); + + function toggleHideSection() { + setHideSection(!hideSection); + } + + return ( +
    + {!hideSection && ( +
    + updatePublishForm({ language: event.target.value })} + > + + + + + + + + + + + + + + + + + updatePublishForm({ + licenseType: newLicenseType, + licenseUrl: newLicenseUrl, + }) + } + handleLicenseDescriptionChange={event => + updatePublishForm({ + otherLicenseDescription: event.target.value, + }) + } + handleLicenseUrlChange={event => updatePublishForm({ licenseUrl: event.target.value })} + /> +
    + )} + +
    +
    +
    + ); +} + +export default PublishAdvanced; diff --git a/src/ui/component/publishFile/index.js b/src/ui/component/publishFile/index.js new file mode 100644 index 000000000..5d909d94d --- /dev/null +++ b/src/ui/component/publishFile/index.js @@ -0,0 +1,21 @@ +import { connect } from 'react-redux'; +import { selectBalance } from 'lbry-redux'; +import { selectIsStillEditing, makeSelectPublishFormValue } from 'redux/selectors/publish'; +import { doUpdatePublishForm } from 'redux/actions/publish'; +import PublishPage from './view'; + +const select = state => ({ + name: makeSelectPublishFormValue('name')(state), + filePath: makeSelectPublishFormValue('filePath')(state), + isStillEditing: selectIsStillEditing(state), + balance: selectBalance(state), +}); + +const perform = dispatch => ({ + updatePublishForm: value => dispatch(doUpdatePublishForm(value)), +}); + +export default connect( + select, + perform +)(PublishPage); diff --git a/src/ui/component/publishFile/view.jsx b/src/ui/component/publishFile/view.jsx new file mode 100644 index 000000000..9b4b6a635 --- /dev/null +++ b/src/ui/component/publishFile/view.jsx @@ -0,0 +1,54 @@ +// @flow +import React from 'react'; +import { regexInvalidURI } from 'lbry-redux'; +import classnames from 'classnames'; +import FileSelector from 'component/common/file-selector'; + +type Props = { + name: ?string, + filePath: ?string, + isStillEditing: boolean, + balance: number, + updatePublishForm: ({}) => void, +}; + +function PublishFile(props: Props) { + const { name, balance, filePath, isStillEditing, updatePublishForm } = props; + + function handleFileChange(filePath: string, fileName: string) { + const publishFormParams: { filePath: string, name?: string } = { filePath }; + + if (!name) { + const parsedFileName = fileName.replace(regexInvalidURI, ''); + publishFormParams.name = parsedFileName.replace(' ', '-'); + } + + updatePublishForm(publishFormParams); + } + + return ( +
    +
    +

    {isStillEditing ? __('Edit') : __('Publish')}

    + {isStillEditing &&

    {__('You are currently editing a claim.')}

    } +
    + +
    + + {!!isStillEditing && name && ( +

    + {__("If you don't choose a file, the file from your existing claim")} + {` "${name}" `} + {__('will be used.')} +

    + )} +
    +
    + ); +} + +export default PublishFile; diff --git a/src/ui/component/publishForm/index.js b/src/ui/component/publishForm/index.js index 6b0644544..929e444ed 100644 --- a/src/ui/component/publishForm/index.js +++ b/src/ui/component/publishForm/index.js @@ -1,3 +1,45 @@ -import PublishForm from './view'; +import { connect } from 'react-redux'; +import { doResolveUri } from 'lbry-redux'; +import { + selectPublishFormValues, + selectIsStillEditing, + selectMyClaimForUri, + selectIsResolvingPublishUris, + selectTakeOverAmount, +} from 'redux/selectors/publish'; +import { + doResetThumbnailStatus, + doClearPublish, + doUpdatePublishForm, + doPublish, + doPrepareEdit, +} from 'redux/actions/publish'; +import { selectUnclaimedRewardValue } from 'lbryinc'; +import PublishPage from './view'; -export default PublishForm; +const select = state => ({ + ...selectPublishFormValues(state), + // The winning claim for a short lbry uri + amountNeededForTakeover: selectTakeOverAmount(state), + // My previously published claims under this short lbry uri + myClaimForUri: selectMyClaimForUri(state), + // If I clicked the "edit" button, have I changed the uri? + // Need this to make it easier to find the source on previously published content + isStillEditing: selectIsStillEditing(state), + isResolvingUri: selectIsResolvingPublishUris(state), + totalRewardValue: selectUnclaimedRewardValue(state), +}); + +const perform = dispatch => ({ + updatePublishForm: value => dispatch(doUpdatePublishForm(value)), + clearPublish: () => dispatch(doClearPublish()), + resolveUri: uri => dispatch(doResolveUri(uri)), + publish: params => dispatch(doPublish(params)), + prepareEdit: (claim, uri) => dispatch(doPrepareEdit(claim, uri)), + resetThumbnailStatus: () => dispatch(doResetThumbnailStatus()), +}); + +export default connect( + select, + perform +)(PublishPage); diff --git a/src/ui/component/publishForm/internal/bid-help-text.jsx b/src/ui/component/publishForm/internal/bid-help-text.jsx deleted file mode 100644 index f13b78e33..000000000 --- a/src/ui/component/publishForm/internal/bid-help-text.jsx +++ /dev/null @@ -1,38 +0,0 @@ -// @flow -import * as React from 'react'; - -type Props = { - uri: ?string, - isResolvingUri: boolean, - amountNeededForTakeover: ?number, -}; - -class BidHelpText extends React.PureComponent { - render() { - const { uri, isResolvingUri, amountNeededForTakeover } = this.props; - let bidHelpText; - - if (uri) { - if (isResolvingUri) { - bidHelpText = __('Checking the winning claim amount...'); - } else if (!amountNeededForTakeover) { - bidHelpText = __('Any amount will give you the winning bid.'); - } else { - bidHelpText = `${__('If you bid more than')} ${amountNeededForTakeover} LBC, ${__( - 'when someone navigates to' - )} ${uri} ${__('it will load your published content')}. ${__( - 'However, you can get a longer version of this URL for any bid' - )}.`; - } - } - - return ( - - {__('This LBC remains yours and the deposit can be undone at any time.')} -
    {bidHelpText}
    -
    - ); - } -} - -export default BidHelpText; diff --git a/src/ui/component/publishForm/internal/name-help-text.jsx b/src/ui/component/publishForm/internal/name-help-text.jsx deleted file mode 100644 index 2aa9a0eb8..000000000 --- a/src/ui/component/publishForm/internal/name-help-text.jsx +++ /dev/null @@ -1,50 +0,0 @@ -// @flow -import * as React from 'react'; -import Button from 'component/button'; -import { buildURI } from 'lbry-redux'; - -type Props = { - uri: ?string, - myClaimForUri: ?StreamClaim, - isStillEditing: boolean, - onEditMyClaim: (any, string) => void, -}; - -class NameHelpText extends React.PureComponent { - render() { - const { uri, myClaimForUri, onEditMyClaim, isStillEditing } = this.props; - - let nameHelpText; - - if (isStillEditing) { - nameHelpText = __( - 'You are currently editing this claim. If you change the URL, you will need to reselect a file.' - ); - } else if (uri && myClaimForUri) { - const editUri = buildURI({ - contentName: myClaimForUri.name, - claimId: myClaimForUri.claim_id, - }); - - nameHelpText = ( - - {__('You already have a claim at')} - {` ${uri} `} -
  • -

    - {isStillEditing ? __('You are currently editing a claim.') : __('What are you publishing?')}{' '} - {__('Read our')}

    -
    -
    -
    - updatePublishForm({ title: e.target.value })} - /> - - updatePublishForm({ description: text })} - /> -
    -
    - -
    -
    -

    {__('Thumbnail')}

    -

    - {(uploadThumbnailStatus === undefined && __('You should reselect your file to choose a thumbnail')) || - (uploadThumbnailStatus === THUMBNAIL_STATUSES.API_DOWN ? ( - __('Enter a URL for your thumbnail.') - ) : ( - - {__('Upload your thumbnail (.png/.jpg/.jpeg/.gif) to')}{' '} -

    - - -
    - -
    -
    -

    {__('Price')}

    -

    {__('How much will this content cost?')}

    -
    - -
    - updatePublishForm({ contentIsFree: true })} - /> - - updatePublishForm({ contentIsFree: false })} - /> - {!contentIsFree && ( - updatePublishForm({ fee: newFee })} - /> - )} - {fee && fee.currency !== 'LBC' && ( -

    - {__( - 'All content fees are charged in LBC. For non-LBC payment methods, the number of credits charged will be adjusted based on the value of LBRY credits at the time of purchase.' - )} -

    - )} -
    -
    - -
    -
    -

    {__('Anonymous or under a channel?')}

    -

    - {__('This is a username or handle that your content can be found under.')}{' '} - {__('Ex. @Marvel, @TheBeatles, @BooksByJoe')} -

    -
    - -
    - -
    -
    - -
    -
    -

    {__('Where can people find this content?')}

    -

    - {__('The LBRY URL is the exact address where people find your content (ex. lbry://myvideo).')}{' '} -

    - -
    - - - - {`lbry://${ - !channel || channel === CHANNEL_ANONYMOUS || channel === CHANNEL_NEW ? '' : `${channel}/` - }`} - - this.handleNameChange(event.target.value)} - error={nameError} - /> - -
    - -
    -
    - -
    - this.handleBidChange(parseFloat(event.target.value))} - placeholder={winningBidForClaimUri ? winningBidForClaimUri + 0.1 : 0.1} - helper={ - - } - /> -
    -
    - -
    -
    - updatePublishForm({ nsfw: !nsfw })} - /> - - updatePublishForm({ language: event.target.value })} - > - - - - - - - - - - - - - - - - - updatePublishForm({ - licenseType: newLicenseType, - licenseUrl: newLicenseUrl, - }) - } - handleLicenseDescriptionChange={event => - updatePublishForm({ - otherLicenseDescription: event.target.value, - }) - } - handleLicenseUrlChange={event => updatePublishForm({ licenseUrl: event.target.value })} - /> -
    -
    - -
    -
    - -
    -

    - {__('By continuing, you accept the')}{' '} -

    +
    + updatePublishForm({ tags: [...tags, tag] })} + onRemove={clickedTag => { + const newTags = tags.slice().filter(tag => tag.name !== clickedTag.name); + updatePublishForm({ tags: newTags }); + }} + tagsChosen={tags} + /> +
    +
    +
    + updatePublishForm({ channel })} /> +

    + {__('This is a username or handle that your content can be found under.')}{' '} + {__('Ex. @Marvel, @TheBeatles, @BooksByJoe')} +

    +
    - {!formDisabled && !formValid && this.renderFormErrors()} - - - ); - } + + + + +
    + {!formDisabled && !formValid && } + +
    +
    +

    + {__('By continuing, you accept the')}{' '} +

    +
    + + ); } export default PublishForm; diff --git a/src/ui/component/publishFormErrors/index.js b/src/ui/component/publishFormErrors/index.js new file mode 100644 index 000000000..9a1332d94 --- /dev/null +++ b/src/ui/component/publishFormErrors/index.js @@ -0,0 +1,17 @@ +import { connect } from 'react-redux'; +import { makeSelectPublishFormValue, selectIsStillEditing } from 'redux/selectors/publish'; +import PublishPage from './view'; + +const select = state => ({ + name: makeSelectPublishFormValue('name')(state), + title: makeSelectPublishFormValue('title')(state), + bid: makeSelectPublishFormValue('bid')(state), + editingUri: makeSelectPublishFormValue('editingUri')(state), + uploadThumbnailStatus: makeSelectPublishFormValue('uploadThumbnailStatus')(state), + isStillEditing: selectIsStillEditing(state), +}); + +export default connect( + select, + null +)(PublishPage); diff --git a/src/ui/component/publishFormErrors/view.jsx b/src/ui/component/publishFormErrors/view.jsx new file mode 100644 index 000000000..dc84dcd5f --- /dev/null +++ b/src/ui/component/publishFormErrors/view.jsx @@ -0,0 +1,35 @@ +// @flow +import React from 'react'; +import { THUMBNAIL_STATUSES } from 'lbry-redux'; + +type Props = { + title: ?string, + name: ?string, + bid: ?string, + editingURI: ?string, + filePath: ?string, + isStillEditing: boolean, + uploadThumbnailStatus: string, +}; + +function PublishFormErrors(props: Props) { + const { name, title, bid, editingURI, filePath, isStillEditing, uploadThumbnailStatus } = props; + + // These are extra help + // If there is an error it will be presented as an inline error as well + return ( +
    + {!title &&
    {__('A title is required')}
    } + {!name &&
    {__('A URL is required')}
    } + {!bid &&
    {__('A deposit amount is required')}
    } + {uploadThumbnailStatus === THUMBNAIL_STATUSES.IN_PROGRESS && ( +
    {__('Please wait for thumbnail to finish uploading')}
    + )} + {!!editingURI && !isStillEditing && !filePath && ( +
    {__('You need to reselect a file after changing the LBRY URL')}
    + )} +
    + ); +} + +export default PublishFormErrors; diff --git a/src/ui/component/publishName/bid-help-text.jsx b/src/ui/component/publishName/bid-help-text.jsx new file mode 100644 index 000000000..689f31dc4 --- /dev/null +++ b/src/ui/component/publishName/bid-help-text.jsx @@ -0,0 +1,32 @@ +// @flow +type Props = { + uri: ?string, + isResolvingUri: boolean, + amountNeededForTakeover: number, +}; + +function BidHelpText(props: Props) { + const { uri, isResolvingUri, amountNeededForTakeover } = props; + + let bidHelpText; + + if (uri) { + if (isResolvingUri) { + bidHelpText = __('Checking the winning claim amount...'); + } else if (!amountNeededForTakeover) { + bidHelpText = __('Any amount will give you the winning bid.'); + } else { + bidHelpText = `${__('If you bid more than')} ${amountNeededForTakeover} LBC, ${__( + 'when someone navigates to' + )} ${uri} ${__('it will load your published content')}. ${__( + 'However, you can get a longer version of this URL for any bid' + )}.`; + } + } else { + bidHelpText = __('This LBC remains yours and the deposit can be undone at any time.'); + } + + return bidHelpText; +} + +export default BidHelpText; diff --git a/src/ui/component/publishName/index.js b/src/ui/component/publishName/index.js new file mode 100644 index 000000000..98d4b835d --- /dev/null +++ b/src/ui/component/publishName/index.js @@ -0,0 +1,32 @@ +import { connect } from 'react-redux'; +import { + makeSelectPublishFormValue, + selectIsStillEditing, + selectMyClaimForUri, + selectIsResolvingPublishUris, + selectTakeOverAmount, +} from 'redux/selectors/publish'; +import { doUpdatePublishForm, doPrepareEdit } from 'redux/actions/publish'; +import { selectBalance } from 'lbry-redux'; +import PublishPage from './view'; + +const select = state => ({ + name: makeSelectPublishFormValue('name')(state), + channel: makeSelectPublishFormValue('channel')(state), + uri: makeSelectPublishFormValue('uri')(state), + isStillEditing: selectIsStillEditing(state), + isResolvingUri: selectIsResolvingPublishUris(state), + amountNeededForTakeover: selectTakeOverAmount(state), + balance: selectBalance(state), + myClaimForUri: selectMyClaimForUri(state), +}); + +const perform = dispatch => ({ + updatePublishForm: value => dispatch(doUpdatePublishForm(value)), + prepareEdit: (claim, uri) => dispatch(doPrepareEdit(claim, uri)), +}); + +export default connect( + select, + perform +)(PublishPage); diff --git a/src/ui/component/publishName/name-help-text.jsx b/src/ui/component/publishName/name-help-text.jsx new file mode 100644 index 000000000..bddf323fa --- /dev/null +++ b/src/ui/component/publishName/name-help-text.jsx @@ -0,0 +1,46 @@ +// @flow +import * as React from 'react'; +import Button from 'component/button'; +import { buildURI } from 'lbry-redux'; + +type Props = { + uri: ?string, + myClaimForUri: ?StreamClaim, + isStillEditing: boolean, + onEditMyClaim: (any, string) => void, +}; + +function NameHelpText(props: Props) { + const { uri, myClaimForUri, onEditMyClaim, isStillEditing } = props; + + let nameHelpText; + + if (isStillEditing) { + nameHelpText = __('You are currently editing this claim. If you change the URL, you will need to reselect a file.'); + } else if (uri && myClaimForUri) { + const editUri = buildURI({ + contentName: myClaimForUri.name, + claimId: myClaimForUri.claim_id, + }); + + nameHelpText = ( + + {__('You already have a claim at')} + {` ${uri} `} + ); } else { diff --git a/src/ui/constants/pages.js b/src/ui/constants/pages.js index 0354ad17d..537b62f82 100644 --- a/src/ui/constants/pages.js +++ b/src/ui/constants/pages.js @@ -20,3 +20,4 @@ export const SEARCH = 'search'; export const TRANSACTIONS = 'transactions'; export const TAGS = 'tags'; export const WALLET = 'wallet'; +export const FOLLOWING = 'following'; diff --git a/src/ui/page/file/view.jsx b/src/ui/page/file/view.jsx index a57e43271..0514b8a7d 100644 --- a/src/ui/page/file/view.jsx +++ b/src/ui/page/file/view.jsx @@ -232,9 +232,9 @@ class FilePage extends React.Component { {claimIsMine && ( -
    +

    {viewCount} {viewCount !== 1 ? __('Views') : __('View')} -

    +

    )} diff --git a/src/ui/page/tagsEdit/index.js b/src/ui/page/following/index.js similarity index 69% rename from src/ui/page/tagsEdit/index.js rename to src/ui/page/following/index.js index 7e9153c8e..97edfb98c 100644 --- a/src/ui/page/tagsEdit/index.js +++ b/src/ui/page/following/index.js @@ -1,9 +1,11 @@ import { connect } from 'react-redux'; import { selectFollowedTags } from 'lbry-redux'; +import { selectSubscriptions } from 'redux/selectors/subscriptions'; import TagsEdit from './view'; const select = state => ({ followedTags: selectFollowedTags(state), + subscribedChannels: selectSubscriptions(state), }); const perform = {}; diff --git a/src/ui/page/following/view.jsx b/src/ui/page/following/view.jsx new file mode 100644 index 000000000..9edcff43f --- /dev/null +++ b/src/ui/page/following/view.jsx @@ -0,0 +1,30 @@ +// @flow +import React from 'react'; +import Page from 'component/page'; +import TagsSelect from 'component/tagsSelect'; +import ClaimList from 'component/claimList'; + +type Props = { + subscribedChannels: Array<{ uri: string }>, +}; + +function DiscoverPage(props: Props) { + const { subscribedChannels } = props; + + return ( + +
    + +
    +
    + {__('Channels You Are Following')}} + empty={__("You aren't following any channels.")} + uris={subscribedChannels.map(({ uri }) => uri)} + /> +
    +
    + ); +} + +export default DiscoverPage; diff --git a/src/ui/page/publish/index.js b/src/ui/page/publish/index.js index 8389f1622..6ca157047 100644 --- a/src/ui/page/publish/index.js +++ b/src/ui/page/publish/index.js @@ -1,46 +1,14 @@ import { connect } from 'react-redux'; -import { doResolveUri, selectBalance } from 'lbry-redux'; -import { - selectPublishFormValues, - selectIsStillEditing, - selectMyClaimForUri, - selectIsResolvingPublishUris, - selectTakeOverAmount, -} from 'redux/selectors/publish'; -import { - doResetThumbnailStatus, - doClearPublish, - doUpdatePublishForm, - doPublish, - doPrepareEdit, -} from 'redux/actions/publish'; +import { selectBalance } from 'lbry-redux'; import { selectUnclaimedRewardValue } from 'lbryinc'; import PublishPage from './view'; const select = state => ({ - ...selectPublishFormValues(state), - // The winning claim for a short lbry uri - amountNeededForTakeover: selectTakeOverAmount(state), - // My previously published claims under this short lbry uri - myClaimForUri: selectMyClaimForUri(state), - // If I clicked the "edit" button, have I changed the uri? - // Need this to make it easier to find the source on previously published content - isStillEditing: selectIsStillEditing(state), balance: selectBalance(state), - isResolvingUri: selectIsResolvingPublishUris(state), totalRewardValue: selectUnclaimedRewardValue(state), }); -const perform = dispatch => ({ - updatePublishForm: value => dispatch(doUpdatePublishForm(value)), - clearPublish: () => dispatch(doClearPublish()), - resolveUri: uri => dispatch(doResolveUri(uri)), - publish: params => dispatch(doPublish(params)), - prepareEdit: (claim, uri) => dispatch(doPrepareEdit(claim, uri)), - resetThumbnailStatus: () => dispatch(doResetThumbnailStatus()), -}); - export default connect( select, - perform + null )(PublishPage); diff --git a/src/ui/page/publish/view.jsx b/src/ui/page/publish/view.jsx index 6903a79b4..91da03dc0 100644 --- a/src/ui/page/publish/view.jsx +++ b/src/ui/page/publish/view.jsx @@ -1,3 +1,4 @@ +// @flow import React, { Fragment } from 'react'; import PublishForm from 'component/publishForm'; import Page from 'component/page'; @@ -6,64 +7,67 @@ 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 = () => { +type Props = { + balance: number, + totalRewardValue: number, +}; + +function PublishPage(props: Props) { + const { balance, totalRewardValue } = props; + const totalRewardRounded = Math.floor(totalRewardValue / 10) * 10; + + function scrollToTop() { 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 ( - - {balance === 0 && ( - - -

    - {__( - 'LBRY uses a blockchain, which is a fancy way of saying that users (you) are in control of your data.' - )} -

    -

    - {__('Because of the blockchain, some actions require LBRY credits')} ( - - ). -

    -

    - {' '} - {__( - 'allows you to do some neat things, like paying your favorite creators for their content. And no company can stop you.' - )} -

    -
    - } - /> -
    -
    -

    {__('LBRY Credits Required')}

    -
    -

    - {__(' There are a variety of ways to get credits, including more than')}{' '} - {' '} - {__('in free rewards for participating in the LBRY beta.')} -

    -
    -
    -
    - - )} - -
    - ); } + + return ( + + {balance === 0 && ( + + +

    + {__( + 'LBRY uses a blockchain, which is a fancy way of saying that users (you) are in control of your data.' + )} +

    +

    + {__('Because of the blockchain, some actions require LBRY credits')} ( + + ). +

    +

    + {' '} + {__( + 'allows you to do some neat things, like paying your favorite creators for their content. And no company can stop you.' + )} +

    +
    + } + /> +
    +
    +

    {__('LBRY Credits Required')}

    +
    +

    + {__(' There are a variety of ways to get credits, including more than')}{' '} + {' '} + {__('in free rewards for participating in the LBRY beta.')} +

    +
    +
    +
    + + )} + +
    + ); } export default PublishPage; diff --git a/src/ui/page/search/view.jsx b/src/ui/page/search/view.jsx index 0bc39f4d2..faeec7bd4 100644 --- a/src/ui/page/search/view.jsx +++ b/src/ui/page/search/view.jsx @@ -2,7 +2,7 @@ import * as ICONS from 'constants/icons'; import React, { useEffect, Fragment } from 'react'; import { isURIValid, normalizeURI } from 'lbry-redux'; -import ClaimListItem from 'component/claimListItem'; +import ClaimPreview from 'component/claimPreview'; import ClaimList from 'component/claimList'; import Page from 'component/page'; import SearchOptions from 'component/searchOptions'; @@ -29,7 +29,6 @@ export default function SearchPage(props: Props) { useEffect(() => { if (urlQuery) { - console.log('search', urlQuery); search(urlQuery); } }, [search, urlQuery]); @@ -44,7 +43,7 @@ export default function SearchPage(props: Props) { - + )} diff --git a/src/ui/page/subscriptions/view.jsx b/src/ui/page/subscriptions/view.jsx index 28774a65d..3b1dccf75 100644 --- a/src/ui/page/subscriptions/view.jsx +++ b/src/ui/page/subscriptions/view.jsx @@ -36,7 +36,7 @@ export default function SubscriptionsPage(props: Props) { const viewingSuggestedSubs = urlParams.get('view'); function onClick() { - let url = `/$/${PAGES.SUBSCRIPTIONS}`; + let url = `/$/${PAGES.FOLLOWING}`; if (!viewingSuggestedSubs) { url += '?view=discover'; } @@ -54,6 +54,7 @@ export default function SubscriptionsPage(props: Props) { const ids = idString.split(','); const options = { channel_ids: ids, + order_by: ['release_time'], }; doClaimSearch(20, options); @@ -72,7 +73,8 @@ export default function SubscriptionsPage(props: Props) { onClick={() => onClick()} /> } - uris={viewingSuggestedSubs ? suggestedSubscriptions.map(sub => sub.uri) : uris} + // Fix the need to reverse this + uris={viewingSuggestedSubs ? suggestedSubscriptions.map(sub => sub.uri) : uris.reverse()} /> diff --git a/src/ui/page/tagsEdit/view.jsx b/src/ui/page/tagsEdit/view.jsx deleted file mode 100644 index 99bd051de..000000000 --- a/src/ui/page/tagsEdit/view.jsx +++ /dev/null @@ -1,18 +0,0 @@ -// @flow -import React from 'react'; -import Page from 'component/page'; -import TagsSelect from 'component/tagsSelect'; - -type Props = {}; - -function DiscoverPage(props: Props) { - return ( - -
    - -
    -
    - ); -} - -export default DiscoverPage; diff --git a/src/ui/redux/actions/publish.js b/src/ui/redux/actions/publish.js index 5f9f8c132..57b43d010 100644 --- a/src/ui/redux/actions/publish.js +++ b/src/ui/redux/actions/publish.js @@ -15,6 +15,7 @@ import { } from 'lbry-redux'; import { doOpenModal } from 'redux/actions/app'; import { selectosNotificationsEnabled } from 'redux/selectors/settings'; +import { selectMyClaimForUri, selectPublishFormValues } from 'redux/selectors/publish'; import { push } from 'connected-react-router'; import analytics from 'analytics'; import { formatLbryUriForWeb } from 'util/uri'; @@ -146,7 +147,7 @@ export const doPrepareEdit = (claim: StreamClaim, uri: string, fileInfo: FileLis // use same values as default state // fee will be undefined for free content fee = { - amount: 0, + amount: '0', currency: 'LBC', }, languages, @@ -159,11 +160,11 @@ export const doPrepareEdit = (claim: StreamClaim, uri: string, fileInfo: FileLis const publishData: UpdatePublishFormData = { name, channel: channelName, - bid: amount, + bid: Number(amount), contentIsFree: !fee.amount, author, description, - fee: { amount: fee.amount, currency: fee.currency }, + fee, languages, thumbnail: thumbnail ? thumbnail.url : null, title, @@ -201,10 +202,13 @@ export const doPrepareEdit = (claim: StreamClaim, uri: string, fileInfo: FileLis dispatch({ type: ACTIONS.DO_PREPARE_EDIT, data: publishData }); }; -export const doPublish = (params: PublishParams) => (dispatch: Dispatch, getState: () => {}) => { +export const doPublish = () => (dispatch: Dispatch, getState: () => {}) => { dispatch({ type: ACTIONS.PUBLISH_START }); const state = getState(); + const publishData = selectPublishFormValues(state); + const myClaimForUri = selectMyClaimForUri(state); + const myChannels = selectMyChannelClaims(state); const myClaims = selectMyClaimsWithoutChannels(state); @@ -214,8 +218,9 @@ export const doPublish = (params: PublishParams) => (dispatch: Dispatch, getStat filePath, description, language, - license, licenseUrl, + licenseType, + otherLicenseDescription, thumbnail, channel, title, @@ -223,8 +228,19 @@ export const doPublish = (params: PublishParams) => (dispatch: Dispatch, getStat fee, uri, nsfw, - claim, - } = params; + tags, + locations, + } = publishData; + + let publishingLicense; + switch (licenseType) { + case COPYRIGHT: + case OTHER: + publishingLicense = otherLicenseDescription; + break; + default: + publishingLicense = licenseType; + } // get the claim id from the channel name, we will use that instead const namedChannelClaim = myChannels.find(myChannel => myChannel.name === channel); @@ -244,29 +260,19 @@ export const doPublish = (params: PublishParams) => (dispatch: Dispatch, getStat fee_amount?: string, } = { name, - bid: creditsToString(bid), title, - license, - languages: [language], description, - tags: (claim && claim.value.tags) || [], - locations: claim && claim.value.locations, + locations, + bid: creditsToString(bid), + license: publishingLicense, + languages: [language], + tags: tags && tags.map(tag => tag.name), + license_url: licenseType === COPYRIGHT ? '' : licenseUrl, + thumbnail_url: thumbnail, }; - // Temporary solution to keep the same publish flow with the new tags api - // Eventually we will allow users to enter their own tags on publish - // `nsfw` will probably be removed - - if (licenseUrl) { - publishPayload.license_url = licenseUrl; - } - - if (thumbnail) { - publishPayload.thumbnail_url = thumbnail; - } - - if (claim && claim.value.release_time) { - publishPayload.release_time = Number(claim.value.release_time); + if (myClaimForUri && myClaimForUri.value.release_time) { + publishPayload.release_time = Number(myClaimForUri.value.release_time); } if (nsfw) { @@ -346,23 +352,25 @@ export const doCheckPendingPublishes = () => (dispatch: Dispatch, getState: GetS const checkFileList = () => { Lbry.claim_list().then(claims => { - claims.forEach(claim => { - // If it's confirmed, check if it was pending previously - if (claim.confirmations > 0 && pendingById[claim.claim_id]) { - delete pendingById[claim.claim_id]; + if (claims) { + claims.forEach(claim => { + // If it's confirmed, check if it was pending previously + if (claim.confirmations > 0 && pendingById[claim.claim_id]) { + delete pendingById[claim.claim_id]; - // If it's confirmed, check if we should notify the user - if (selectosNotificationsEnabled(getState())) { - const notif = new window.Notification('LBRY Publish Complete', { - body: `${claim.value.title} has been published to lbry://${claim.name}. Click here to view it`, - silent: false, - }); - notif.onclick = () => { - dispatch(push(formatLbryUriForWeb(claim.permanent_url))); - }; + // If it's confirmed, check if we should notify the user + if (selectosNotificationsEnabled(getState())) { + const notif = new window.Notification('LBRY Publish Complete', { + body: `${claim.value.title} has been published to lbry://${claim.name}. Click here to view it`, + silent: false, + }); + notif.onclick = () => { + dispatch(push(formatLbryUriForWeb(claim.permanent_url))); + }; + } } - } - }); + }); + } dispatch({ type: ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED, diff --git a/src/ui/redux/reducers/publish.js b/src/ui/redux/reducers/publish.js index b49049361..2749e666b 100644 --- a/src/ui/redux/reducers/publish.js +++ b/src/ui/redux/reducers/publish.js @@ -27,6 +27,7 @@ type PublishState = { bidError: ?string, otherLicenseDescription: string, licenseUrl: string, + tags: Array, }; const defaultState: PublishState = { @@ -53,6 +54,7 @@ const defaultState: PublishState = { licenseType: 'None', otherLicenseDescription: 'All rights reserved', licenseUrl: '', + tags: [], publishing: false, publishSuccess: false, publishError: undefined, diff --git a/src/ui/redux/selectors/publish.js b/src/ui/redux/selectors/publish.js index 05e88e4ed..6127c33fe 100644 --- a/src/ui/redux/selectors/publish.js +++ b/src/ui/redux/selectors/publish.js @@ -18,6 +18,12 @@ export const selectPublishFormValues = createSelector( } ); +export const makeSelectPublishFormValue = item => + createSelector( + selectState, + state => state[item] + ); + // Is the current uri the same as the uri they clicked "edit" on export const selectIsStillEditing = createSelector( selectPublishFormValues, diff --git a/src/ui/scss/component/_file-list.scss b/src/ui/scss/component/_file-list.scss index cc08e1b85..0620bbc2f 100644 --- a/src/ui/scss/component/_file-list.scss +++ b/src/ui/scss/component/_file-list.scss @@ -1,4 +1,4 @@ -.file-list__header { +.claim-list__header { display: flex; align-items: center; min-height: 4.5rem; @@ -31,12 +31,13 @@ } } -.file-list__header--small { +.claim-list__header--small { height: 3rem; + min-height: 3rem; font-size: 1em; } -.file-list__dropdown { +.claim-list__dropdown { background-position: 95% center; background-repeat: no-repeat; background-size: 1.2rem; @@ -50,8 +51,8 @@ background-color: lighten($lbry-black, 10%); } -.file-list__header, -.file-list__dropdown { +.claim-list__header, +.claim-list__dropdown { background-color: lighten($lbry-black, 10%); [data-mode='dark'] & { @@ -59,17 +60,17 @@ } } -.file-list__header-text { +.claim-list__header-text { display: flex; align-items: center; } -.file-list__header-text, -.file-list__dropdown { +.claim-list__header-text, +.claim-list__dropdown { font-size: 1.3rem; } -.file-list__alt-controls { +.claim-list__alt-controls { display: flex; align-items: center; margin-left: auto; @@ -80,7 +81,7 @@ } } -.file-list__item { +.claim-list__item { display: flex; position: relative; font-size: 1.3rem; @@ -103,12 +104,12 @@ } } -.file-list__item--injected, -.file-list__item { - border-bottom: 1px solid rgba($lbry-teal-5, 0.1); +.claim-list__item--injected, +.claim-list__item + .claim-list__item { + border-top: 1px solid rgba($lbry-teal-5, 0.1); } -.file-list__item--large { +.claim-list__item--large { @include mediaThumbHoverZoom; font-size: 1.6rem; border-bottom: 0; @@ -124,36 +125,49 @@ } } -.file-list__item-metadata { +.claim-list__pending { + cursor: pointer; + opacity: 0.6; + + &:hover { + background-color: $lbry-white; + + [data-mode='dark'] & { + background-color: lighten($lbry-black, 5%); + } + } +} + +.claim-list__item-metadata { display: flex; flex-direction: column; width: 100%; } -.file-list__item-info { +.claim-list__item-info { align-items: flex-start; } -.file-list__item-info, -.file-list__item-properties { +.claim-list__item-info, +.claim-list__item-properties { display: flex; justify-content: space-between; } -.file-list__item-properties { +.claim-list__item-properties { align-items: flex-end; } -.file-list__item-title { +.claim-list__item-title { font-weight: 600; margin-right: auto; } -.file-list__item-tags { +.claim-list__item-tags { margin-left: 0; } -.file-list__meta { +.claim-list__meta { padding: var(--spacing-medium); background-color: lighten($lbry-teal-5, 55%); } diff --git a/src/ui/scss/component/_form-field.scss b/src/ui/scss/component/_form-field.scss index 9d4c38db5..c454d45a3 100644 --- a/src/ui/scss/component/_form-field.scss +++ b/src/ui/scss/component/_form-field.scss @@ -1,16 +1,36 @@ @import '~@lbry/components/sass/form/_index.scss'; +// replace this +form { + // setting the font size here sizes everything within + &:not(:last-child) { + margin-bottom: var(--spacing-s); + } +} + +input, +select { + height: var(--spacing-l); + border: 1px solid; +} + +checkbox-element, +radio-element, +select { + cursor: pointer; +} + +textarea { + &::placeholder { + opacity: 0.4; + } +} + // lbry/components overrides and minor styles // Some items have very specific styling // This is because many styles inside `lbry/components/sass/form/` are very specific // As styles become hardened here, they _should_ slowly move over to that repo -input, -textarea, -select { - border-radius: var(--input-border-radius); -} - input-submit { align-items: center; } @@ -21,7 +41,8 @@ input[type='number'] { input[type='text'], input[type='number'], -select { +select, +textarea { padding-bottom: 0.1em; [data-mode='dark'] & { @@ -31,6 +52,14 @@ select { } } +input, +select, +textarea { + border-color: lighten($lbry-black, 20%); + border-radius: var(--input-border-radius); + border-width: 1px; +} + fieldset-section { label { width: auto; diff --git a/src/ui/scss/component/_main.scss b/src/ui/scss/component/_main.scss index 89d5c205d..3f535d262 100644 --- a/src/ui/scss/component/_main.scss +++ b/src/ui/scss/component/_main.scss @@ -5,6 +5,7 @@ padding-top: var(--header-height); padding-left: var(--spacing-large); padding-right: var(--spacing-large); + padding-bottom: var(--spacing-large); background-color: mix($lbry-white, $lbry-gray-1, 70%); display: flex; diff --git a/src/ui/scss/component/_placeholder.scss b/src/ui/scss/component/_placeholder.scss index 02d6cca55..3933c5a12 100644 --- a/src/ui/scss/component/_placeholder.scss +++ b/src/ui/scss/component/_placeholder.scss @@ -9,7 +9,7 @@ .placeholder { display: flex; - &.file-list__item-title { + &.claim-list__item-title { width: 100%; height: 3rem; }