/* global Runtime */ import { h, Component, Fragment } from 'preact'; import PropTypes from 'prop-types'; import { addSnackbarItem } from '../../Snackbar'; import { generateMainImage } from '../actions'; import { validateFileInputs } from '../../packs/validateFileInputs'; import { onDragOver, onDragExit } from './dragAndDropHelpers'; import { Button } from '@crayons'; import { Spinner } from '@crayons/Spinner/Spinner'; import { DragAndDropZone } from '@utilities/dragAndDrop'; export class ArticleCoverImage extends Component { state = { uploadError: false, uploadErrorMessage: null, uploadingImage: false, }; onImageUploadSuccess = (...args) => { this.props.onMainImageUrlChange(...args); this.setState({ uploadingImage: false }); }; handleMainImageUpload = (event) => { event.preventDefault(); this.setState({ uploadingImage: true }); this.clearUploadError(); if (validateFileInputs()) { const { files: image } = event.dataTransfer || event.target; const payload = { image }; generateMainImage(payload, this.onImageUploadSuccess, this.onUploadError); } }; clearUploadError = () => { this.setState({ uploadError: false, uploadErrorMessage: null, }); }; onUploadError = (error) => { this.setState({ uploadingImage: false, uploadError: true, uploadErrorMessage: error.message, }); }; useNativeUpload = () => { return Runtime.isNativeIOS('imageUpload'); }; initNativeImagePicker = (e) => { e.preventDefault(); window.webkit.messageHandlers.imageUpload.postMessage({ id: 'native-cover-image-upload-message', ratio: `${100.0 / 42.0}`, }); }; handleNativeMessage = (e) => { const message = JSON.parse(e.target.value); switch (message.action) { case 'uploading': this.setState({ uploadingImage: true }); this.clearUploadError(); break; case 'error': this.setState({ uploadingImage: false, uploadError: true, uploadErrorMessage: message.error, }); break; case 'success': this.props.onMainImageUrlChange({ links: [message.link] }); this.setState({ uploadingImage: false }); break; } }; triggerMainImageRemoval = (e) => { e.preventDefault(); const { onMainImageUrlChange } = this.props; onMainImageUrlChange({ links: [], }); }; onDropImage = (event) => { onDragExit(event); if (event.dataTransfer.files.length > 1) { addSnackbarItem({ message: 'Only one image can be dropped at a time.', addCloseButton: true, }); return; } this.handleMainImageUpload(event); }; render() { const { mainImage } = this.props; const { uploadError, uploadErrorMessage, uploadingImage } = this.state; const uploadLabel = mainImage ? 'Change' : 'Add a cover image'; // When the component is rendered in an environment that supports a native // image picker for image upload we want to add the aria-label attr and the // onClick event to the UI button. This event will kick off the native UX. // The props are unwrapped (using spread operator) in the button below const extraProps = this.useNativeUpload() ? { onClick: this.initNativeImagePicker, 'aria-label': 'Upload cover image', } : {}; return (
{!uploadingImage && mainImage && ( Post cover )}
{uploadingImage ? ( Uploading... ) : ( {mainImage && ( )} )} {this.useNativeUpload() && ( )}
{uploadError && (

{uploadErrorMessage}

)}
); } } ArticleCoverImage.propTypes = { mainImage: PropTypes.string.isRequired, onMainImageUrlChange: PropTypes.func.isRequired, }; ArticleCoverImage.displayName = 'ArticleCoverImage';