Validate thumbnails #1755

Merged
daovist merged 6 commits from verify-thumbnail-url into master 2018-07-19 17:12:11 +02:00
10 changed files with 135 additions and 57 deletions

View file

@ -10,7 +10,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
### Added ### Added
* Added 3D file viewer for OBJ & STL file types ([#1558](https://github.com/lbryio/lbry-desktop/pull/1558)) * Added 3D file viewer for OBJ & STL file types ([#1558](https://github.com/lbryio/lbry-desktop/pull/1558))
* Added thumbnail preview on publish page ([#1755](https://github.com/lbryio/lbry-desktop/pull/1755))
### Changed ### Changed

View file

@ -9,7 +9,7 @@ type Props = {
type: string, type: string,
currentPath: ?string, currentPath: ?string,
onFileChosen: (string, string) => void, onFileChosen: (string, string) => void,
fileLabel: ?string, fileLabel?: string,
directoryLabel?: string, directoryLabel?: string,
}; };
@ -56,7 +56,7 @@ class FileSelector extends React.PureComponent<Props> {
type === 'file' ? fileLabel || __('Choose File') : directoryLabel || __('Choose Directory'); type === 'file' ? fileLabel || __('Choose File') : directoryLabel || __('Choose Directory');
return ( return (
<FormRow verticallyCentered padded> <FormRow verticallyCentered>
<Button button="primary" onClick={() => this.handleButtonClick()} label={label} /> <Button button="primary" onClick={() => this.handleButtonClick()} label={label} />
<input <input
webkitdirectory="true" webkitdirectory="true"

View file

@ -73,8 +73,8 @@ class PublishForm extends React.PureComponent<Props> {
} }
componentWillMount() { componentWillMount() {
const { isStillEditing, thumbnail } = this.props; const { thumbnail } = this.props;
if (!isStillEditing || !thumbnail) { if (!thumbnail) {
this.props.resetThumbnailStatus(); this.props.resetThumbnailStatus();
} }
} }
@ -356,14 +356,17 @@ class PublishForm extends React.PureComponent<Props> {
/> />
</div> </div>
)} )}
<FileSelector currentPath={filePath} onFileChosen={this.handleFileChange} /> <div className="card__content">
{!!isStillEditing && ( <FileSelector currentPath={filePath} onFileChosen={this.handleFileChange} />
<p className="card__content card__subtitle"> {!!isStillEditing &&
{__("If you don't choose a file, the file from your existing claim")} name && (
{` "${name}" `} <p className="card__content card__subtitle">
{__('will be used.')} {__("If you don't choose a file, the file from your existing claim")}
</p> {` "${name}" `}
)} {__('will be used.')}
</p>
)}
</div>
</section> </section>
<div className={classnames({ 'card--disabled': formDisabled })}> <div className={classnames({ 'card--disabled': formDisabled })}>
<section className="card card--section"> <section className="card card--section">
@ -400,10 +403,9 @@ class PublishForm extends React.PureComponent<Props> {
__('Enter a URL for your thumbnail.') __('Enter a URL for your thumbnail.')
) : ( ) : (
<React.Fragment> <React.Fragment>
{__( {__('Upload your thumbnail (.png/.jpg/.jpeg/.gif) to')}{' '}
'Upload your thumbnail (.png/.jpg/.jpeg/.gif) to spee.ch, or enter the URL manually. Learn more about spee.ch ' <Button button="link" label={__('spee.ch')} href="https://spee.ch/about" />.{' '}
)} {__('Recommended size: 800x450 (16:9)')}
<Button button="link" label={__('here')} href="https://spee.ch/about" />.
</React.Fragment> </React.Fragment>
)} )}
</div> </div>

View file

@ -1,9 +1,10 @@
// @flow // @flow
import { THUMBNAIL_STATUSES, MODALS } from 'lbry-redux'; import { THUMBNAIL_STATUSES, MODALS } from 'lbry-redux';
import React from 'react'; import * as React from 'react';
import { FormField, FormRow } from 'component/common/form'; import { FormField } from 'component/common/form';
import FileSelector from 'component/common/file-selector'; import FileSelector from 'component/common/file-selector';
import Button from 'component/button'; import Button from 'component/button';
import Native from 'native';
type Props = { type Props = {
thumbnail: ?string, thumbnail: ?string,
@ -15,7 +16,29 @@ type Props = {
resetThumbnailStatus: () => void, resetThumbnailStatus: () => void,
}; };
class SelectThumbnail extends React.PureComponent<Props> { type State = {
thumbnailError: boolean,
};
class SelectThumbnail extends React.PureComponent<Props, State> {
constructor() {
super();
this.state = {
thumbnailError: false,
};
(this: any).handleThumbnailChange = this.handleThumbnailChange.bind(this);
}
handleThumbnailChange(e: SyntheticInputEvent<*>) {
const { updatePublishForm } = this.props;
const newThumbnail = e.target.value.replace(' ', '');
updatePublishForm({ thumbnail: newThumbnail });
this.setState({ thumbnailError: false });
}
render() { render() {
const { const {
thumbnail, thumbnail,
@ -26,25 +49,47 @@ class SelectThumbnail extends React.PureComponent<Props> {
thumbnailPath, thumbnailPath,
resetThumbnailStatus, resetThumbnailStatus,
} = this.props; } = this.props;
const { thumbnailError } = this.state;
const thumbnailSrc =
!thumbnail || thumbnailError ? Native.imagePath('no-thumbnail.png') : thumbnail;
return ( return (
<div> <div className="card__content">
{status === THUMBNAIL_STATUSES.API_DOWN || status === THUMBNAIL_STATUSES.MANUAL ? ( {status === THUMBNAIL_STATUSES.API_DOWN || status === THUMBNAIL_STATUSES.MANUAL ? (
<FormRow padded> <div className="column">
<FormField <img
stretch src={thumbnailSrc}
type="text" className="column__item thumbnail-preview"
name="content_thumbnail" alt={__('Thumbnail Preview')}
label={__('URL')} onError={() => {
placeholder="http://spee.ch/mylogo" this.setState({ thumbnailError: true });
value={thumbnail} }}
disabled={formDisabled}
onChange={e => updatePublishForm({ thumbnail: e.target.value })}
/> />
</FormRow> <div className="column__item">
<FormField
className="input--thumbnail"
type="text"
name="content_thumbnail"
label="URL"
placeholder="http://spee.ch/mylogo"
value={thumbnail}
disabled={formDisabled}
onChange={this.handleThumbnailChange}
/>
<div className="card__actions">
<Button
button="link"
label={__('Use thumbnail upload tool')}
onClick={() =>
updatePublishForm({ uploadThumbnailStatus: THUMBNAIL_STATUSES.READY })
}
/>
</div>
</div>
</div>
) : ( ) : (
<div className="form-row--padded"> <React.Fragment>
{(status === THUMBNAIL_STATUSES.READY || status === THUMBNAIL_STATUSES.COMPLETE) && ( {status === THUMBNAIL_STATUSES.READY && (
<FileSelector <FileSelector
currentPath={thumbnailPath} currentPath={thumbnailPath}
fileLabel={__('Choose Thumbnail')} fileLabel={__('Choose Thumbnail')}
@ -52,18 +97,31 @@ class SelectThumbnail extends React.PureComponent<Props> {
/> />
)} )}
{status === THUMBNAIL_STATUSES.COMPLETE && ( {status === THUMBNAIL_STATUSES.COMPLETE && (
<div> <div className="column column--space-between">
<p> <img
Upload complete. View it{' '} className="column__item thumbnail-preview"
<Button button="link" href={thumbnail} label={__('here')} />. src={thumbnail}
</p> alt={__('Thumbnail Preview')}
<Button button="link" label={__('New thumbnail')} onClick={resetThumbnailStatus} /> />
<div className="column__item">
<p>
Upload complete.{' '}
<Button button="link" href={thumbnail} label={__('View it on spee.ch')} />.
</p>
<div className="card__actions">
<Button
button="link"
label={__('New thumbnail')}
onClick={resetThumbnailStatus}
/>
</div>
</div>
</div> </div>
)} )}
</div> </React.Fragment>
)} )}
<div className="card__actions"> {status === THUMBNAIL_STATUSES.READY && (
{status === THUMBNAIL_STATUSES.READY && ( <div className="card__actions">
<Button <Button
button="link" button="link"
label={__('Or enter a URL manually')} label={__('Or enter a URL manually')}
@ -71,15 +129,8 @@ class SelectThumbnail extends React.PureComponent<Props> {
updatePublishForm({ uploadThumbnailStatus: THUMBNAIL_STATUSES.MANUAL }) updatePublishForm({ uploadThumbnailStatus: THUMBNAIL_STATUSES.MANUAL })
} }
/> />
)} </div>
{status === THUMBNAIL_STATUSES.MANUAL && ( )}
<Button
button="link"
label={__('Use thumbnail upload tool')}
onClick={() => updatePublishForm({ uploadThumbnailStatus: THUMBNAIL_STATUSES.READY })}
/>
)}
</div>
{status === THUMBNAIL_STATUSES.IN_PROGRESS && <p>{__('Uploading thumbnail')}...</p>} {status === THUMBNAIL_STATUSES.IN_PROGRESS && <p>{__('Uploading thumbnail')}...</p>}
</div> </div>

View file

@ -153,7 +153,6 @@ dd {
p { p {
font-family: 'metropolis-medium'; font-family: 'metropolis-medium';
padding: $spacing-vertical * 1/3 0;
} }
.page { .page {
@ -302,6 +301,14 @@ p {
opacity: 0.5; opacity: 0.5;
} }
.column {
display: flex;
.column__item:not(:first-child) {
padding-left: $spacing-width * 2/3;
}
}
.truncated-text { .truncated-text {
//display: inline-block; //display: inline-block;
display: -webkit-box; display: -webkit-box;
@ -361,3 +368,9 @@ p {
margin-top: $spacing-vertical * 2/3; margin-top: $spacing-vertical * 2/3;
} }
} }
.thumbnail-preview {
height: var(--thumbnail-preview-height);
width: var(--thumbnail-preview-width);
border: var(--thumbnail-preview-border);
}

View file

@ -179,4 +179,10 @@ $large-breakpoint: 1921px;
// /* Animation :) */ // /* Animation :) */
--animation-duration: 0.3s; --animation-duration: 0.3s;
--animation-style: cubic-bezier(0.55, 0, 0.1, 1); --animation-style: cubic-bezier(0.55, 0, 0.1, 1);
/* Image */
--thumbnail-preview-height: 100px;
--thumbnail-preview-width: 177px;
// This will awlways white, it looks fine on light mode
--thumbnail-preview-border: 1px solid var(--color-white);
} }

View file

@ -255,6 +255,12 @@
right: $spacing-vertical; right: $spacing-vertical;
} }
.card__actions-bottom-corner {
position: absolute;
bottom: $spacing-vertical;
right: $spacing-vertical;
}
.card__actions--end { .card__actions--end {
justify-content: flex-end; justify-content: flex-end;
} }

View file

@ -67,8 +67,8 @@
width: 35px; width: 35px;
} }
input.paginate-channel { input.input--thumbnail {
width: 35px; width: 400px;
} }
&.form-field--auto-height { &.form-field--auto-height {

BIN
static/img/no-thumbnail.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -5221,9 +5221,9 @@ lazy-val@^1.0.3:
version "1.0.3" version "1.0.3"
resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.3.tgz#bb97b200ef00801d94c317e29dc6ed39e31c5edc" resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.3.tgz#bb97b200ef00801d94c317e29dc6ed39e31c5edc"
lbry-redux@lbryio/lbry-redux#177ef2c1916f9672e713267500e447d671ae1bc3: lbry-redux@lbryio/lbry-redux#e0909b08647a790d155f3189b9f9bf0b3e55bd17:
version "0.0.1" version "0.0.1"
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/177ef2c1916f9672e713267500e447d671ae1bc3" resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/e0909b08647a790d155f3189b9f9bf0b3e55bd17"
dependencies: dependencies:
proxy-polyfill "0.1.6" proxy-polyfill "0.1.6"
reselect "^3.0.0" reselect "^3.0.0"