Fix list thumbnail upload #7074

Merged
saltrafael merged 3 commits from list-thumb into master 2021-09-13 17:40:31 +02:00
14 changed files with 214 additions and 344 deletions

View file

@ -51,6 +51,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Fix comment section redirection to create channel _community pr!_ ([#6557](https://github.com/lbryio/lbry-desktop/pull/6557))
- Clicking on the title of a floating player will take you back to the list ([#6921](https://github.com/lbryio/lbry-desktop/pull/6921))
- Fix floating player stopping on markdown or image files ([#7073](https://github.com/lbryio/lbry-desktop/pull/7073))
- Fix list thumbnail upload ([#7074](https://github.com/lbryio/lbry-desktop/pull/7074))
## [0.51.1] - [2021-06-26]

View file

@ -155,7 +155,7 @@
"imagesloaded": "^4.1.4",
"json-loader": "^0.5.4",
"lbry-format": "https://github.com/lbryio/lbry-format.git",
"lbry-redux": "lbryio/lbry-redux#372e559caee6af2b2d927e5d42419a71c3d15b57",
"lbry-redux": "lbryio/lbry-redux#129b0ea3faa5da69ef1b85ea9ab7777b06aa3264",
"lbryinc": "lbryio/lbryinc#0b4e41ef90d6347819dd3453f2f9398a5c1b4f36",
"lint-staged": "^7.0.2",
"localforage": "^1.7.1",

View file

@ -17,7 +17,6 @@ import {
makeSelectClaimIdsForCollectionId,
ACTIONS as LBRY_REDUX_ACTIONS,
} from 'lbry-redux';
import { doOpenModal } from 'redux/actions/app';
import CollectionForm from './view';
import { selectActiveChannelClaim, selectIncognito } from 'redux/selectors/app';
@ -44,7 +43,6 @@ const select = (state, props) => ({
});
const perform = (dispatch) => ({
openModal: (modal, props) => dispatch(doOpenModal(modal, props)),
publishCollectionUpdate: (params) => dispatch(doCollectionPublishUpdate(params)),
publishCollection: (params, collectionId) => dispatch(doCollectionPublish(params, collectionId)),
clearCollectionErrors: () => dispatch({ type: LBRY_REDUX_ACTIONS.CLEAR_COLLECTION_ERRORS }),

View file

@ -10,9 +10,9 @@ import ChannelSelector from 'component/channelSelector';
import ClaimList from 'component/claimList';
import Card from 'component/common/card';
import LbcSymbol from 'component/common/lbc-symbol';
import ThumbnailPicker from 'component/thumbnailPicker';
import SelectThumbnail from 'component/selectThumbnail';
import { useHistory } from 'react-router-dom';
import { isNameValid, regexInvalidURI } from 'lbry-redux';
import { isNameValid, regexInvalidURI, THUMBNAIL_STATUSES } from 'lbry-redux';
import { Tabs, TabList, Tab, TabPanels, TabPanel } from 'component/common/tabs';
import { FormField } from 'component/common/form';
import { handleBidChange } from 'util/publish';
@ -21,6 +21,7 @@ import { INVALID_NAME_ERROR } from 'constants/claim';
import SUPPORTED_LANGUAGES from 'constants/supported_languages';
import * as PAGES from 'constants/pages';
import analytics from 'analytics';
const LANG_NONE = 'none';
const MAX_TAG_SELECT = 5;
@ -39,23 +40,18 @@ type Props = {
tags: Array<string>,
locations: Array<string>,
languages: Array<string>,
collectionId: string,
collection: Collection,
collectionClaimIds: Array<string>,
collectionUrls: Array<string>,
publishCollectionUpdate: (CollectionUpdateParams) => Promise<any>,
updatingCollection: boolean,
updateError: string,
publishCollection: (CollectionPublishParams, string) => Promise<any>,
createError: string,
creatingCollection: boolean,
publishCollectionUpdate: (CollectionUpdateParams) => Promise<any>,
publishCollection: (CollectionPublishParams, string) => Promise<any>,
clearCollectionErrors: () => void,
onDone: (string) => void,
openModal: (
id: string,
{ onUpdate: (string) => void, assetName: string, helpText: string, currentValue: string, title: string }
) => void,
};
function CollectionForm(props: Props) {
@ -72,11 +68,8 @@ function CollectionForm(props: Props) {
locations,
languages = [],
// rest
onDone,
publishCollectionUpdate,
updateError,
updatingCollection,
publishCollection,
creatingCollection,
createError,
disabled,
@ -86,7 +79,10 @@ function CollectionForm(props: Props) {
collection,
collectionUrls,
collectionClaimIds,
publishCollectionUpdate,
publishCollection,
clearCollectionErrors,
onDone,
} = props;
const activeChannelName = activeChannelClaim && activeChannelClaim.name;
let prefix = IS_WEB ? `${DOMAIN}/` : 'lbry://';
@ -107,6 +103,11 @@ function CollectionForm(props: Props) {
const secondaryLanguage = Array.isArray(languageParam) && languageParam.length >= 2 && languageParam[1];
const collectionClaimIdsString = JSON.stringify(collectionClaimIds);
const itemError = !params.claims.length ? __('Cannot publish empty list') : '';
const thumbnailError =
(params.thumbnail_error && params.thumbnail_status !== THUMBNAIL_STATUSES.COMPLETE && __('Invalid thumbnail')) ||
(params.thumbnail_status === THUMBNAIL_STATUSES.IN_PROGRESS && __('Please wait for thumbnail to finish uploading'));
const submitError = nameError || bidError || itemError || updateError || createError || thumbnailError;
function parseName(newName) {
let INVALID_URI_CHARS = new RegExp(regexInvalidURI, 'gu');
@ -142,6 +143,8 @@ function CollectionForm(props: Props) {
function getCollectionParams() {
const collectionParams: {
thumbnail_url?: string,
thumbnail_error?: boolean,
thumbnail_status?: string,
name?: string,
description?: string,
title?: string,
@ -154,7 +157,9 @@ function CollectionForm(props: Props) {
claims: ?Array<string>,
} = {
thumbnail_url: thumbnailUrl,
name: parseName(collectionName),
description,
title: claim ? title : collectionName,
bid: String(amount || 0.001),
languages: languages ? dedupeLanguages(languages) : [],
locations: locations || [],
@ -163,32 +168,14 @@ function CollectionForm(props: Props) {
return { name: tag };
})
: [],
claim_id: String(claim && claim.claim_id),
channel_id: String(activeChannelId && parseName(collectionName)),
claims: collectionClaimIds,
};
collectionParams['name'] = parseName(collectionName);
if (activeChannelId) {
collectionParams['channel_id'] = activeChannelId;
}
if (!claim) {
collectionParams['title'] = collectionName;
}
if (claim) {
collectionParams['claim_id'] = claim.claim_id;
collectionParams['title'] = title;
}
return collectionParams;
}
React.useEffect(() => {
const collectionClaimIds = JSON.parse(collectionClaimIdsString);
setParams({ ...params, claims: collectionClaimIds });
clearCollectionErrors();
}, [collectionClaimIdsString, setParams]);
function handleLanguageChange(index, code) {
let langs = [...languageParam];
if (index === 0) {
@ -211,10 +198,6 @@ function CollectionForm(props: Props) {
setParams({ ...params, languages: langs });
}
function handleThumbnailChange(thumbnailUrl: string) {
setParams({ ...params, thumbnail_url: thumbnailUrl });
}
function handleSubmit() {
if (uri) {
publishCollectionUpdate(params).then((pendingClaim) => {
@ -235,6 +218,12 @@ function CollectionForm(props: Props) {
}
}
React.useEffect(() => {
const collectionClaimIds = JSON.parse(collectionClaimIdsString);
setParams({ ...params, claims: collectionClaimIds });
clearCollectionErrors();
}, [collectionClaimIdsString, setParams]);
React.useEffect(() => {
let nameError;
if (!name && name !== undefined) {
@ -247,17 +236,14 @@ function CollectionForm(props: Props) {
}, [name]);
React.useEffect(() => {
if (incognito) {
if (incognito && params.channel_id) {
const newParams = Object.assign({}, params);
delete newParams.channel_id;
setParams(newParams);
} else if (activeChannelId) {
} else if (activeChannelId && params.channel_id !== activeChannelId) {
setParams({ ...params, channel_id: activeChannelId });
}
}, [activeChannelId, incognito, setParams]);
const itemError = !params.claims.length ? __('Cannot publish empty list') : '';
const submitError = nameError || bidError || itemError || updateError || createError;
}, [activeChannelId, incognito, params, setParams]);
return (
<>
@ -277,11 +263,6 @@ function CollectionForm(props: Props) {
<Card
body={
<>
<fieldset-group className="fieldset-group--smushed fieldset-group--disabled-prefix">
<fieldset-section>
<label htmlFor="channel_name">{__('Channel')}</label>
</fieldset-section>
</fieldset-group>
<fieldset-group class="fieldset-group--smushed fieldset-group--disabled-prefix">
<fieldset-section>
<label htmlFor="channel_name">{__('Name')}</label>
@ -311,11 +292,15 @@ function CollectionForm(props: Props) {
value={params.title}
onChange={(e) => setParams({ ...params, title: e.target.value })}
/>
<ThumbnailPicker
inline
thumbnailParam={params.thumbnail_url}
updateThumbnailParam={handleThumbnailChange}
/>
<fieldset-section>
<SelectThumbnail
thumbnailParam={params.thumbnail_url}
thumbnailParamError={params.thumbnail_error}
thumbnailParamStatus={params.thumbnail_status}
updateThumbnailParams={setParam}
publishForm={false}
/>
</fieldset-section>
<FormField
type="markdown"
name="content_description2"
@ -436,7 +421,14 @@ function CollectionForm(props: Props) {
<div className="section__actions">
<Button
button="primary"
disabled={creatingCollection || updatingCollection || nameError || bidError || !params.claims.length}
disabled={
creatingCollection ||
updatingCollection ||
nameError ||
bidError ||
thumbnailError ||
!params.claims.length
}
label={creatingCollection || updatingCollection ? __('Submitting') : __('Submit')}
onClick={handleSubmit}
/>

View file

@ -46,10 +46,11 @@ function PublishFormErrors(props: Props) {
{!bid && <div>{__('A deposit amount is required')}</div>}
{bidError && <div>{__('Please check your deposit amount.')}</div>}
{isUploadingThumbnail && <div>{__('Please wait for thumbnail to finish uploading')}</div>}
{!isUploadingThumbnail && !thumbnail && (
{!isUploadingThumbnail && !thumbnail ? (
<div>{__('A thumbnail is required. Please upload or provide an image URL above.')}</div>
) : (
thumbnailError && !thumbnailUploaded && <div>{__('Thumbnail is invalid.')}</div>
)}
{thumbnailError && !thumbnailUploaded && <div>{__('Thumbnail is invalid.')}</div>}
{editingURI && !isStillEditing && !filePath && (
<div>{__('Please reselect a file after changing the LBRY URL')}</div>
)}

View file

@ -6,23 +6,19 @@ import {
selectFileInfosByOutpoint,
doResetThumbnailStatus,
} from 'lbry-redux';
import { doOpenModal } from 'redux/actions/app';
import PublishPage from './view';
const select = state => ({
const select = (state) => ({
...selectPublishFormValues(state),
fileInfos: selectFileInfosByOutpoint(state),
myClaimForUri: selectMyClaimForUri(state),
});
const perform = dispatch => ({
updatePublishForm: value => dispatch(doUpdatePublishForm(value)),
const perform = (dispatch) => ({
updatePublishForm: (value) => dispatch(doUpdatePublishForm(value)),
resetThumbnailStatus: () => dispatch(doResetThumbnailStatus()),
openModal: (modal, props) => dispatch(doOpenModal(modal, props)),
});
export default connect(
select,
perform
)(PublishPage);
export default connect(select, perform)(PublishPage);

View file

@ -16,168 +16,181 @@ type Props = {
thumbnail: ?string,
formDisabled: boolean,
uploadThumbnailStatus: string,
publishForm: boolean,
thumbnailPath: ?string,
thumbnailError: ?string,
thumbnailParam: ?string,
thumbnailParamError: boolean,
thumbnailParamStatus: string,
openModal: (id: string, {}) => void,
updatePublishForm: ({}) => void,
updateThumbnailParams: ({}) => void,
resetThumbnailStatus: () => void,
};
class SelectThumbnail extends React.PureComponent<Props> {
constructor() {
super();
(this: any).handleThumbnailChange = this.handleThumbnailChange.bind(this);
function SelectThumbnail(props: Props) {
const {
filePath,
fileInfos,
myClaimForUri,
formDisabled,
publishForm = true,
uploadThumbnailStatus: status,
openModal,
updatePublishForm,
thumbnailParam,
thumbnailParamStatus,
updateThumbnailParams,
thumbnailPath,
resetThumbnailStatus,
} = props;
const thumbnail = publishForm ? props.thumbnail : thumbnailParam;
const thumbnailError = publishForm ? props.thumbnailError : props.thumbnailParamError;
const accept = '.png, .jpg, .jpeg, .gif';
const manualInput = status === THUMBNAIL_STATUSES.API_DOWN || status === THUMBNAIL_STATUSES.MANUAL;
const thumbUploaded = status === THUMBNAIL_STATUSES.COMPLETE && thumbnail;
const isUrlInput = thumbnail !== ThumbnailMissingImage && thumbnail !== ThumbnailBrokenImage;
const outpoint = myClaimForUri ? `${myClaimForUri.txid}:${myClaimForUri.nout}` : undefined;
const fileInfo = outpoint ? fileInfos[outpoint] : undefined;
const downloadPath = fileInfo ? fileInfo.download_path : undefined;
const actualFilePath = filePath || downloadPath;
let isSupportedVideo = false;
if (typeof actualFilePath === 'string') {
isSupportedVideo = Lbry.getMediaType(null, actualFilePath) === 'video';
} else if (actualFilePath && actualFilePath.type) {
isSupportedVideo = actualFilePath.type.split('/')[0] === 'video';
}
handleThumbnailChange(e: SyntheticInputEvent<*>) {
const { updatePublishForm } = this.props;
function handleThumbnailChange(e: SyntheticInputEvent<*>) {
const newThumbnail = e.target.value.replace(' ', '');
updatePublishForm({
thumbnail: newThumbnail,
thumbnailError: newThumbnail.startsWith('data:image'),
});
if (updateThumbnailParams) {
updateThumbnailParams({ thumbnail_url: newThumbnail });
} else {
updatePublishForm({ thumbnail: newThumbnail });
}
}
render() {
const {
filePath,
fileInfos,
myClaimForUri,
thumbnail,
formDisabled,
uploadThumbnailStatus: status,
openModal,
updatePublishForm,
thumbnailPath,
thumbnailError,
resetThumbnailStatus,
} = this.props;
const accept = '.png, .jpg, .jpeg, .gif';
const outpoint = myClaimForUri ? `${myClaimForUri.txid}:${myClaimForUri.nout}` : undefined;
const fileInfo = outpoint ? fileInfos[outpoint] : undefined;
const downloadPath = fileInfo ? fileInfo.download_path : undefined;
const actualFilePath = filePath || downloadPath;
let isSupportedVideo = false;
if (typeof actualFilePath === 'string') {
isSupportedVideo = Lbry.getMediaType(null, actualFilePath) === 'video';
} else if (actualFilePath && actualFilePath.type) {
isSupportedVideo = actualFilePath.type.split('/')[0] === 'video';
React.useEffect(() => {
if (updateThumbnailParams && status !== thumbnailParamStatus) {
updateThumbnailParams({ thumbnail_status: status });
}
}, [status, thumbnailParamStatus, updateThumbnailParams]);
let thumbnailInputSrc;
if (!thumbnail) {
thumbnailInputSrc = ThumbnailMissingImage;
} else if (thumbnailError) {
thumbnailInputSrc = ThumbnailBrokenImage;
} else {
thumbnailInputSrc = thumbnail;
}
let thumbnailSrc;
if (!thumbnail) {
thumbnailSrc = ThumbnailMissingImage;
} else if (thumbnailError) {
thumbnailSrc =
(manualInput && ThumbnailBrokenImage) || (status !== THUMBNAIL_STATUSES.COMPLETE && ThumbnailMissingImage);
} else {
thumbnailSrc = thumbnail;
}
/*
Note:
We are using backgroundImage instead of an <img /> to zoom if the selected thumbnail isn't
the proper aspect ratio. This is to avoid blackbars on the side of images and inconsistent thumbnails
We still need to render the image to see if there is an error loading the url
*/
/*
Note:
We are using backgroundImage instead of an <img /> to zoom if the selected thumbnail isn't
the proper aspect ratio. This is to avoid blackbars on the side of images and inconsistent thumbnails
We still need to render the image to see if there is an error loading the url
*/
const thumbPreview = (
<div className="column__item thumbnail-picker__preview" style={{ backgroundImage: `url(${String(thumbnailSrc)})` }}>
{thumbUploaded && thumbnailError !== false && __('This will be visible in a few minutes.')}
<img
style={{ display: 'none' }}
src={thumbnail}
alt={__('Thumbnail Preview')}
onError={() =>
publishForm
? updatePublishForm({ thumbnailError: true })
: updateThumbnailParams({ thumbnail_error: Boolean(thumbnail) })
}
onLoad={() =>
publishForm
? updatePublishForm({ thumbnailError: !isUrlInput })
: updateThumbnailParams({ thumbnail_error: !isUrlInput })
}
/>
</div>
);
return (
<div>
{status === THUMBNAIL_STATUSES.API_DOWN || status === THUMBNAIL_STATUSES.MANUAL ? (
<div className="column">
<div className="column__item thumbnail-preview" style={{ backgroundImage: `url(${thumbnailInputSrc})` }}>
<img
style={{ display: 'none' }}
src={thumbnailInputSrc}
alt={__('Thumbnail Preview')}
onError={() => updatePublishForm({ thumbnailError: true })}
/>
</div>
return (
<>
{status !== THUMBNAIL_STATUSES.IN_PROGRESS && (
<div className="column">
{thumbPreview}
{publishForm && thumbUploaded ? (
<div className="column__item">
<FormField
type="text"
name="content_thumbnail"
label="URL"
placeholder="https://images.fbi.gov/alien"
value={thumbnail}
disabled={formDisabled}
onChange={this.handleThumbnailChange}
/>
<p>{__('Upload complete.')}</p>
<div className="section__actions">
<Button button="link" label={__('New thumbnail')} onClick={resetThumbnailStatus} />
</div>
</div>
) : (
<div className="column__item">
{manualInput ? (
<FormField
type="text"
name="content_thumbnail"
label="URL"
placeholder="https://images.fbi.gov/alien"
value={thumbnail}
disabled={formDisabled}
onChange={handleThumbnailChange}
/>
) : (
<FileSelector
currentPath={thumbnailPath}
label={__('Thumbnail')}
placeholder={__('Choose an enticing thumbnail')}
accept={accept}
onFileChosen={(file) =>
openModal(MODALS.CONFIRM_THUMBNAIL_UPLOAD, {
file,
cb: (url) => !publishForm && updateThumbnailParams({ thumbnail_url: url }),
})
}
/>
)}
<div className="card__actions">
<Button
button="link"
label={__('Use thumbnail upload tool')}
onClick={() => updatePublishForm({ uploadThumbnailStatus: THUMBNAIL_STATUSES.READY })}
label={manualInput ? __('Use thumbnail upload tool') : __('Enter a thumbnail URL')}
onClick={() =>
updatePublishForm({
uploadThumbnailStatus: manualInput ? THUMBNAIL_STATUSES.READY : THUMBNAIL_STATUSES.MANUAL,
})
}
/>
{status === THUMBNAIL_STATUSES.READY && isSupportedVideo && IS_WEB && (
// Disabled on desktop until this is resolved
// https://github.com/electron/electron/issues/20750#issuecomment-709505902
<Button
button="link"
label={__('Take a snapshot from your video')}
onClick={() => openModal(MODALS.AUTO_GENERATE_THUMBNAIL, { filePath: actualFilePath })}
/>
)}
</div>
</div>
</div>
) : (
<React.Fragment>
{status === THUMBNAIL_STATUSES.READY && (
<FileSelector
currentPath={thumbnailPath}
label={__('Thumbnail')}
placeholder={__('Choose an enticing thumbnail')}
accept={accept}
onFileChosen={(file) => openModal(MODALS.CONFIRM_THUMBNAIL_UPLOAD, { file })}
/>
)}
{status === THUMBNAIL_STATUSES.COMPLETE && thumbnail && (
<div className="column column--space-between">
<div className="column__item thumbnail-preview" style={{ backgroundImage: `url(${thumbnail})` }}>
{(thumbnailError !== false) && __('This will be visible in a few minutes.')}
<img
style={{ display: 'none' }}
src={thumbnail}
alt={__('Thumbnail Preview')}
onError={() => updatePublishForm({ thumbnailError: true })}
onLoad={() => updatePublishForm({ thumbnailError: false })}
/>
</div>
<div className="column__item">
<p>{__('Upload complete.')}</p>
<div className="section__actions">
<Button button="link" label={__('New thumbnail')} onClick={resetThumbnailStatus} />
</div>
</div>
</div>
)}
</React.Fragment>
)}
{status === THUMBNAIL_STATUSES.READY && (
<div className="section__actions">
<Button
button="link"
label={__('Enter a thumbnail URL')}
onClick={() => updatePublishForm({ uploadThumbnailStatus: THUMBNAIL_STATUSES.MANUAL })}
/>
{isSupportedVideo && IS_WEB && (
// Disabled on desktop until this is resolved
// https://github.com/electron/electron/issues/20750#issuecomment-709505902
<Button
button="link"
label={__('Take a snapshot from your video')}
onClick={() => openModal(MODALS.AUTO_GENERATE_THUMBNAIL, { filePath: actualFilePath })}
/>
)}
</div>
)}
)}
</div>
)}
{status === THUMBNAIL_STATUSES.IN_PROGRESS && <p>{__('Uploading thumbnail')}...</p>}
{status !== THUMBNAIL_STATUSES.COMPLETE && (
<p className="help">
{status === THUMBNAIL_STATUSES.API_DOWN
? __('Enter a URL for your thumbnail.')
: __('Upload your thumbnail to %domain%. Recommended size is 16:9.', { domain: DOMAIN })}
</p>
)}
</div>
);
}
{status === THUMBNAIL_STATUSES.IN_PROGRESS && <p>{__('Uploading thumbnail')}...</p>}
{!thumbUploaded && (
<p className="help">
{manualInput
? __('Enter a URL for your thumbnail.')
: __('Upload your thumbnail to %domain%. Recommended size is 16:9.', { domain: DOMAIN })}
</p>
)}
</>
);
}
export default SelectThumbnail;

View file

@ -1,13 +0,0 @@
import { connect } from 'react-redux';
import ThumbnailPicker from './view';
import { makeSelectThumbnailForUri } from 'lbry-redux';
const select = (state, props) => ({
thumbnailForUri: makeSelectThumbnailForUri(props.uri)(state),
});
// const perform = dispatch => ({
// });
export default connect(select)(ThumbnailPicker);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -1,116 +0,0 @@
// @flow
import * as React from 'react';
import Card from 'component/common/card';
import ThumbnailMissingImage from './thumbnail-missing.png';
import SelectAsset from 'component/selectAsset';
type Props = {
// uploadThumbnailStatus: string,
thumbnailParam: string,
thumbnailForUri: string,
updateThumbnailParam: (string) => void,
inline?: boolean,
};
const ThumbnailPicker = (props: Props) => {
const { thumbnailForUri, thumbnailParam, updateThumbnailParam, inline } = props;
// uploadThumbnailStatus
// {status === THUMBNAIL_STATUSES.API_DOWN || status === THUMBNAIL_STATUSES.MANUAL ? (
// {status === THUMBNAIL_STATUSES.READY && (
// {status === THUMBNAIL_STATUSES.COMPLETE && thumbnail && (
const [thumbError, setThumbError] = React.useState(false); // possibly existing URL
const updateThumb = (thumb: string) => {
setThumbError(false);
updateThumbnailParam(thumb);
};
if (inline) {
return (
<fieldset-section>
<label>{__('Thumbnail')}</label>
<div className="column">
{thumbError && (
<div
className="column__item thumbnail-picker__preview"
style={{ backgroundImage: `url(${ThumbnailMissingImage})` }}
/>
)}
{!thumbError && (
<div
className="column__item thumbnail-picker__preview"
style={{ backgroundImage: `url(${thumbnailParam || thumbnailForUri})` }}
>
<img
style={{ display: 'none' }}
src={thumbnailParam || thumbnailForUri}
alt={__('Thumbnail Preview')}
onError={() => {
if (thumbnailParam) {
setThumbError(true);
}
}}
/>
</div>
)}
<div className="column__item">
{/* if upload */}
<SelectAsset
inline
onUpdate={updateThumb}
currentValue={thumbnailParam}
assetName={'Image'}
recommended={__('(16:9)')}
/>
</div>
</div>
</fieldset-section>
);
}
return (
<div>
<Card
body={
<div className="column">
{thumbError && (
<div
className="column__item thumbnail-preview"
style={{ backgroundImage: `url(${ThumbnailMissingImage})` }}
/>
)}
{!thumbError && (
<div
className="column__item thumbnail-preview"
style={{ backgroundImage: `url(${thumbnailParam || thumbnailForUri})` }}
>
<img
style={{ display: 'none' }}
src={thumbnailParam || thumbnailForUri}
alt={__('Thumbnail Preview')}
onError={() => {
if (thumbnailParam) {
setThumbError(true);
}
}}
/>
</div>
)}
<div className="column__item">
{/* if upload */}
<SelectAsset
inline
onUpdate={updateThumb}
currentValue={thumbnailParam}
assetName={'Thumbnail'}
recommended={__('(16:9)')}
/>
</div>
</div>
}
/>
</div>
);
};
export default ThumbnailPicker;

View file

@ -3,13 +3,10 @@ import { doHideModal } from 'redux/actions/app';
import { doUploadThumbnail, doUpdatePublishForm } from 'lbry-redux';
import ModalConfirmThumbnailUpload from './view';
const perform = dispatch => ({
const perform = (dispatch) => ({
closeModal: () => dispatch(doHideModal()),
upload: file => dispatch(doUploadThumbnail(null, file, null, null, file.path)),
updatePublishForm: value => dispatch(doUpdatePublishForm(value)),
upload: (file, cb) => dispatch(doUploadThumbnail(null, file, null, null, file.path, cb)),
updatePublishForm: (value) => dispatch(doUpdatePublishForm(value)),
});
export default connect(
null,
perform
)(ModalConfirmThumbnailUpload);
export default connect(null, perform)(ModalConfirmThumbnailUpload);

View file

@ -4,17 +4,18 @@ import { Modal } from 'modal/modal';
import { DOMAIN } from 'config';
type Props = {
upload: WebFile => void,
file: WebFile,
upload: (WebFile, (string) => void) => void,
cb: (string) => void,
closeModal: () => void,
updatePublishForm: ({}) => void,
};
class ModalConfirmThumbnailUpload extends React.PureComponent<Props> {
upload() {
const { upload, updatePublishForm, closeModal, file } = this.props;
const { upload, updatePublishForm, cb, closeModal, file } = this.props;
if (file) {
upload(file);
upload(file, cb);
updatePublishForm({ thumbnailPath: file.path });
closeModal();
}

View file

@ -10139,9 +10139,9 @@ lazy-val@^1.0.4:
yargs "^13.2.2"
zstd-codec "^0.1.1"
lbry-redux@lbryio/lbry-redux#372e559caee6af2b2d927e5d42419a71c3d15b57:
lbry-redux@lbryio/lbry-redux#129b0ea3faa5da69ef1b85ea9ab7777b06aa3264:
version "0.0.1"
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/372e559caee6af2b2d927e5d42419a71c3d15b57"
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/129b0ea3faa5da69ef1b85ea9ab7777b06aa3264"
dependencies:
"@ungap/from-entries" "^0.2.1"
proxy-polyfill "0.1.6"