2018-04-02 18:39:00 +02:00
|
|
|
// @flow
|
2018-10-29 18:23:53 +01:00
|
|
|
import * as MODALS from 'constants/modal_types';
|
2021-10-17 10:36:14 +02:00
|
|
|
import * as THUMBNAIL_STATUSES from 'constants/thumbnail_upload_statuses';
|
|
|
|
import Lbry from 'lbry';
|
2022-01-13 06:10:55 +01:00
|
|
|
import { DOMAIN, THUMBNAIL_CDN_SIZE_LIMIT_BYTES } from 'config';
|
2018-07-18 17:46:21 +02:00
|
|
|
import * as React from 'react';
|
|
|
|
import { FormField } from 'component/common/form';
|
2018-04-02 18:39:00 +02:00
|
|
|
import FileSelector from 'component/common/file-selector';
|
2018-06-08 06:05:45 +02:00
|
|
|
import Button from 'component/button';
|
2019-03-05 05:46:57 +01:00
|
|
|
import ThumbnailMissingImage from './thumbnail-missing.png';
|
|
|
|
import ThumbnailBrokenImage from './thumbnail-broken.png';
|
2018-04-02 18:39:00 +02:00
|
|
|
|
|
|
|
type Props = {
|
2019-05-21 23:18:11 +02:00
|
|
|
filePath: ?string,
|
2019-08-29 17:19:37 +02:00
|
|
|
fileInfos: { [string]: FileListItem },
|
|
|
|
myClaimForUri: ?StreamClaim,
|
2018-04-02 18:39:00 +02:00
|
|
|
thumbnail: ?string,
|
|
|
|
formDisabled: boolean,
|
|
|
|
uploadThumbnailStatus: string,
|
2018-06-08 06:05:45 +02:00
|
|
|
thumbnailPath: ?string,
|
2021-04-21 05:31:54 +02:00
|
|
|
thumbnailError: ?string,
|
2021-09-13 17:40:31 +02:00
|
|
|
thumbnailParam: ?string,
|
|
|
|
thumbnailParamError: boolean,
|
|
|
|
thumbnailParamStatus: string,
|
2019-01-08 00:29:40 +01:00
|
|
|
openModal: (id: string, {}) => void,
|
2018-04-02 18:39:00 +02:00
|
|
|
updatePublishForm: ({}) => void,
|
2021-09-13 17:40:31 +02:00
|
|
|
updateThumbnailParams: ({}) => void,
|
2018-06-08 06:05:45 +02:00
|
|
|
resetThumbnailStatus: () => void,
|
2018-04-02 18:39:00 +02:00
|
|
|
};
|
|
|
|
|
2021-09-13 17:40:31 +02:00
|
|
|
function SelectThumbnail(props: Props) {
|
|
|
|
const {
|
|
|
|
filePath,
|
|
|
|
fileInfos,
|
|
|
|
myClaimForUri,
|
|
|
|
formDisabled,
|
|
|
|
uploadThumbnailStatus: status,
|
|
|
|
openModal,
|
|
|
|
updatePublishForm,
|
|
|
|
thumbnailParam,
|
|
|
|
thumbnailParamStatus,
|
|
|
|
updateThumbnailParams,
|
|
|
|
thumbnailPath,
|
|
|
|
resetThumbnailStatus,
|
|
|
|
} = props;
|
2018-07-18 17:46:21 +02:00
|
|
|
|
2021-09-15 16:11:01 +02:00
|
|
|
const publishForm = !updateThumbnailParams;
|
2021-09-13 17:40:31 +02:00
|
|
|
const thumbnail = publishForm ? props.thumbnail : thumbnailParam;
|
|
|
|
const thumbnailError = publishForm ? props.thumbnailError : props.thumbnailParamError;
|
2018-07-18 17:46:21 +02:00
|
|
|
|
2021-09-13 17:40:31 +02:00
|
|
|
const accept = '.png, .jpg, .jpeg, .gif';
|
2022-07-11 16:12:37 +02:00
|
|
|
const manualInput = status === THUMBNAIL_STATUSES.MANUAL;
|
2021-09-13 17:40:31 +02:00
|
|
|
const thumbUploaded = status === THUMBNAIL_STATUSES.COMPLETE && thumbnail;
|
|
|
|
const isUrlInput = thumbnail !== ThumbnailMissingImage && thumbnail !== ThumbnailBrokenImage;
|
2018-07-18 17:46:21 +02:00
|
|
|
|
2021-09-13 17:40:31 +02:00
|
|
|
const outpoint = myClaimForUri ? `${myClaimForUri.txid}:${myClaimForUri.nout}` : undefined;
|
|
|
|
const fileInfo = outpoint ? fileInfos[outpoint] : undefined;
|
|
|
|
const downloadPath = fileInfo ? fileInfo.download_path : undefined;
|
2019-03-05 05:46:57 +01:00
|
|
|
|
2021-09-13 17:40:31 +02:00
|
|
|
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';
|
|
|
|
}
|
2019-03-05 05:46:57 +01:00
|
|
|
|
2021-09-13 17:40:31 +02:00
|
|
|
function handleThumbnailChange(e: SyntheticInputEvent<*>) {
|
|
|
|
const newThumbnail = e.target.value.replace(' ', '');
|
2019-08-29 17:19:37 +02:00
|
|
|
|
2021-09-13 17:40:31 +02:00
|
|
|
if (updateThumbnailParams) {
|
|
|
|
updateThumbnailParams({ thumbnail_url: newThumbnail });
|
|
|
|
} else {
|
|
|
|
updatePublishForm({ thumbnail: newThumbnail });
|
2019-10-07 22:02:32 +02:00
|
|
|
}
|
2021-09-13 17:40:31 +02:00
|
|
|
}
|
2019-05-21 23:18:11 +02:00
|
|
|
|
2021-09-13 17:40:31 +02:00
|
|
|
React.useEffect(() => {
|
|
|
|
if (updateThumbnailParams && status !== thumbnailParamStatus) {
|
|
|
|
updateThumbnailParams({ thumbnail_status: status });
|
2019-03-05 05:46:57 +01:00
|
|
|
}
|
2021-09-13 17:40:31 +02:00
|
|
|
}, [status, thumbnailParamStatus, updateThumbnailParams]);
|
|
|
|
|
|
|
|
let thumbnailSrc;
|
|
|
|
if (!thumbnail) {
|
|
|
|
thumbnailSrc = ThumbnailMissingImage;
|
|
|
|
} else if (thumbnailError) {
|
|
|
|
thumbnailSrc =
|
|
|
|
(manualInput && ThumbnailBrokenImage) || (status !== THUMBNAIL_STATUSES.COMPLETE && ThumbnailMissingImage);
|
|
|
|
} else {
|
|
|
|
thumbnailSrc = thumbnail;
|
|
|
|
}
|
2018-07-18 17:46:21 +02:00
|
|
|
|
2021-09-13 17:40:31 +02:00
|
|
|
/*
|
|
|
|
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)})` }}>
|
2021-11-30 02:32:36 +01:00
|
|
|
{thumbUploaded &&
|
|
|
|
thumbnailError !== false &&
|
|
|
|
__('This will be visible in a few minutes after you submit this form.')}
|
2021-09-13 17:40:31 +02:00
|
|
|
<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>
|
|
|
|
);
|
2018-09-02 03:49:12 +02:00
|
|
|
|
2021-09-13 17:40:31 +02:00
|
|
|
return (
|
|
|
|
<>
|
2022-06-03 15:28:12 +02:00
|
|
|
<h2 className="card__title">{__('Thumbnail')}</h2>
|
2021-09-13 17:40:31 +02:00
|
|
|
{status !== THUMBNAIL_STATUSES.IN_PROGRESS && (
|
2022-06-03 15:28:12 +02:00
|
|
|
<div className="column card--thumbnail">
|
|
|
|
{thumbPreview}
|
|
|
|
{publishForm && thumbUploaded ? (
|
|
|
|
<div className="column__item">
|
|
|
|
<p>{__('Upload complete.')}</p>
|
|
|
|
<div className="section__actions">
|
|
|
|
<Button button="link" label={__('New thumbnail')} onClick={resetThumbnailStatus} />
|
2021-09-13 17:40:31 +02:00
|
|
|
</div>
|
2022-06-03 15:28:12 +02:00
|
|
|
</div>
|
|
|
|
) : (
|
|
|
|
<div className="column__item">
|
|
|
|
{manualInput ? (
|
|
|
|
<>
|
2022-02-11 19:50:55 +01:00
|
|
|
<FormField
|
|
|
|
type="text"
|
|
|
|
name="content_thumbnail"
|
|
|
|
placeholder="https://images.fbi.gov/alien"
|
|
|
|
value={thumbnail}
|
|
|
|
disabled={formDisabled}
|
|
|
|
onChange={handleThumbnailChange}
|
|
|
|
/>
|
2022-06-03 15:28:12 +02:00
|
|
|
{!thumbUploaded && <p className="help">{__('Enter a URL for your thumbnail.')}</p>}
|
|
|
|
</>
|
|
|
|
) : (
|
|
|
|
<>
|
2022-02-11 19:50:55 +01:00
|
|
|
<FileSelector
|
|
|
|
currentPath={thumbnailPath}
|
|
|
|
placeholder={__('Choose an enticing thumbnail')}
|
|
|
|
accept={accept}
|
|
|
|
onFileChosen={(file) =>
|
|
|
|
openModal(MODALS.CONFIRM_THUMBNAIL_UPLOAD, {
|
|
|
|
file,
|
|
|
|
cb: (url) => !publishForm && updateThumbnailParams({ thumbnail_url: url }),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
/>
|
2022-06-03 15:28:12 +02:00
|
|
|
{!thumbUploaded && (
|
|
|
|
<p className="help">
|
|
|
|
{__('Upload your thumbnail to %domain%. Recommended ratio is 16:9, %max_size%MB max.', {
|
|
|
|
domain: DOMAIN,
|
|
|
|
max_size: THUMBNAIL_CDN_SIZE_LIMIT_BYTES / (1024 * 1024),
|
|
|
|
})}
|
|
|
|
</p>
|
|
|
|
)}
|
|
|
|
</>
|
|
|
|
)}
|
|
|
|
<div className="card__actions">
|
|
|
|
<Button
|
|
|
|
button="link"
|
|
|
|
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
|
2021-09-13 17:40:31 +02:00
|
|
|
<Button
|
|
|
|
button="link"
|
2022-06-03 15:28:12 +02:00
|
|
|
label={__('Take a snapshot from your video')}
|
|
|
|
onClick={() => openModal(MODALS.AUTO_GENERATE_THUMBNAIL, { filePath: actualFilePath })}
|
2021-08-26 16:51:53 +02:00
|
|
|
/>
|
2022-06-03 15:28:12 +02:00
|
|
|
)}
|
2019-03-05 05:46:57 +01:00
|
|
|
</div>
|
2022-06-03 15:28:12 +02:00
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
</div>
|
2021-09-13 17:40:31 +02:00
|
|
|
)}
|
2018-04-02 18:39:00 +02:00
|
|
|
|
2022-07-11 16:12:37 +02:00
|
|
|
{status === THUMBNAIL_STATUSES.IN_PROGRESS && (
|
|
|
|
<div className="column card--thumbnail">
|
|
|
|
<p>{__('Uploading thumbnail')}...</p>
|
|
|
|
</div>
|
|
|
|
)}
|
2021-09-13 17:40:31 +02:00
|
|
|
</>
|
|
|
|
);
|
2018-04-02 18:39:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
export default SelectThumbnail;
|