Merge pull request #1755 from lbryio/verify-thumbnail-url
Validate thumbnails
This commit is contained in:
commit
1d9282e1b8
10 changed files with 135 additions and 57 deletions
|
@ -12,7 +12,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
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
BIN
static/img/no-thumbnail.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
|
@ -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"
|
||||||
|
|
Loading…
Reference in a new issue