diff --git a/src/ui/component/publishForm/view.jsx b/src/ui/component/publishForm/view.jsx index fe28b57fd..c7cfe67d3 100644 --- a/src/ui/component/publishForm/view.jsx +++ b/src/ui/component/publishForm/view.jsx @@ -407,6 +407,7 @@ class PublishForm extends React.PureComponent { { render() { const { + filePath, thumbnail, formDisabled, uploadThumbnailStatus: status, @@ -61,6 +64,8 @@ class SelectThumbnail extends React.PureComponent { const { thumbnailError } = this.state; + const isSupportedVideo = getMediaType(null, filePath) === 'video'; + let thumbnailSrc; if (!thumbnail) { thumbnailSrc = ThumbnailMissingImage; @@ -141,9 +146,16 @@ class SelectThumbnail extends React.PureComponent {
)} diff --git a/src/ui/constants/modal_types.js b/src/ui/constants/modal_types.js index 533b0d5fa..8cd8ee674 100644 --- a/src/ui/constants/modal_types.js +++ b/src/ui/constants/modal_types.js @@ -3,6 +3,7 @@ export const CONFIRM_EXTERNAL_RESOURCE = 'confirm_external_resource'; export const INCOMPATIBLE_DAEMON = 'incompatible_daemon'; export const FILE_TIMEOUT = 'file_timeout'; export const DOWNLOADING = 'downloading'; +export const AUTO_GENERATE_THUMBNAIL = 'auto_generate_thumbnail'; export const AUTO_UPDATE_DOWNLOADED = 'auto_update_downloaded'; export const AUTO_UPDATE_CONFIRM = 'auto_update_confirm'; export const ERROR = 'error'; diff --git a/src/ui/modal/modalAutoGenerateThumbnail/index.js b/src/ui/modal/modalAutoGenerateThumbnail/index.js new file mode 100644 index 000000000..f1d3234bc --- /dev/null +++ b/src/ui/modal/modalAutoGenerateThumbnail/index.js @@ -0,0 +1,16 @@ +import { connect } from 'react-redux'; +import { doHideModal } from 'redux/actions/app'; +import { doUploadThumbnail } from 'redux/actions/publish'; +import { doToast } from 'lbry-redux'; +import ModalAutoGenerateThumbnail from './view'; + +const perform = dispatch => ({ + closeModal: () => dispatch(doHideModal()), + upload: buffer => dispatch(doUploadThumbnail(null, buffer)), + showToast: options => dispatch(doToast(options)), +}); + +export default connect( + null, + perform +)(ModalAutoGenerateThumbnail); diff --git a/src/ui/modal/modalAutoGenerateThumbnail/view.jsx b/src/ui/modal/modalAutoGenerateThumbnail/view.jsx new file mode 100644 index 000000000..0bff3d631 --- /dev/null +++ b/src/ui/modal/modalAutoGenerateThumbnail/view.jsx @@ -0,0 +1,84 @@ +// @flow +import React, { useRef } from 'react'; +import { Modal } from 'modal/modal'; + +type Props = { + upload: Buffer => void, + filePath: string, + closeModal: () => void, + showToast: ({}) => void, +}; + +function ModalAutoGenerateThumbnail(props: Props) { + const { closeModal, filePath, upload, showToast } = props; + const playerRef = useRef(); + + let src = filePath.replace(/\\/g, '/'); + src = src[0] !== '/' ? `/${src}` : src; + src = encodeURI(`file://${src}`).replace(/[?#]/g, encodeURIComponent); + + function uploadImage() { + const imageBuffer = captureSnapshot(); + if (imageBuffer) { + upload(imageBuffer); + closeModal(); + } else { + onError(); + } + } + + function captureSnapshot(): ?Buffer { + const player = playerRef.current; + if (!player) { + return; + } + + const canvas = document.createElement('canvas'); + canvas.width = player.videoWidth; + canvas.height = player.videoHeight; + const context = canvas.getContext('2d'); + context.drawImage(player, 0, 0, canvas.width, canvas.height); + const dataURL = canvas.toDataURL(); + const rawData = dataURL.replace(/data:image\/\w+;base64,/i, ''); + canvas.remove(); + return Buffer.from(rawData, 'base64'); + } + + function resize(): void { + const player = playerRef.current; + if (!player) { + return; + } + + console.log('resized'); + + const fixedWidth = 450; + const videoWidth = player.videoWidth; + const videoHeight = player.videoHeight; + player.width = fixedWidth; + player.height = Math.floor(videoHeight * (fixedWidth / videoWidth)); + } + + function onError(): void { + showToast({ isError: true, message: __("Something didn't work. Please try again.") }); + } + + return ( + +
+

{__('Pause at any time to select a thumbnail from your video')}.

+
+
+ ); +} + +export default ModalAutoGenerateThumbnail; diff --git a/src/ui/modal/modalRouter/view.jsx b/src/ui/modal/modalRouter/view.jsx index 1c8d7fc13..af910c611 100644 --- a/src/ui/modal/modalRouter/view.jsx +++ b/src/ui/modal/modalRouter/view.jsx @@ -4,6 +4,7 @@ import * as MODALS from 'constants/modal_types'; import ModalError from 'modal/modalError'; import ModalAuthFailure from 'modal/modalAuthFailure'; import ModalDownloading from 'modal/modalDownloading'; +import ModalAutoGenerateThumbnail from 'modal/modalAutoGenerateThumbnail'; import ModalAutoUpdateDownloaded from 'modal/modalAutoUpdateDownloaded'; import ModalAutoUpdateConfirm from 'modal/modalAutoUpdateConfirm'; import ModalUpgrade from 'modal/modalUpgrade'; @@ -51,6 +52,8 @@ function ModalRouter(props: Props) { return ; case MODALS.DOWNLOADING: return ; + case MODALS.AUTO_GENERATE_THUMBNAIL: + return ; case MODALS.AUTO_UPDATE_DOWNLOADED: return ; case MODALS.AUTO_UPDATE_CONFIRM: diff --git a/src/ui/redux/actions/publish.js b/src/ui/redux/actions/publish.js index 7d3ffba27..4c40575b3 100644 --- a/src/ui/redux/actions/publish.js +++ b/src/ui/redux/actions/publish.js @@ -68,10 +68,22 @@ export const doUpdatePublishForm = (publishFormValue: UpdatePublishFormData) => data: { ...publishFormValue }, }); -export const doUploadThumbnail = (filePath: string) => (dispatch: Dispatch) => { - const thumbnail = fs.readFileSync(filePath); - const fileExt = path.extname(filePath); - const fileName = path.basename(filePath); +export const doUploadThumbnail = (filePath: string, thumbnailBuffer: Uint8Array) => (dispatch: Dispatch) => { + let thumbnail, fileExt, fileName, fileType; + + if (filePath) { + thumbnail = fs.readFileSync(filePath); + fileExt = path.extname(filePath); + fileName = path.basename(filePath); + fileType = `image/${fileExt.slice(1)}`; + } else if (thumbnailBuffer) { + thumbnail = thumbnailBuffer; + fileExt = '.png'; + fileName = 'thumbnail.png'; + fileType = 'image/png'; + } else { + return null; + } const makeid = () => { let text = ''; @@ -102,7 +114,7 @@ export const doUploadThumbnail = (filePath: string) => (dispatch: Dispatch) => { const data = new FormData(); const name = makeid(); - const file = new File([thumbnail], fileName, { type: `image/${fileExt.slice(1)}` }); + const file = new File([thumbnail], fileName, { type: fileType }); data.append('name', name); data.append('file', file);