docbrown/app/javascript/article-form/components/ImageUploader.jsx
Nick Taylor 653ec12300
Upgrade to Preact 10.4.4 (#8739)
Co-authored-by: Nick Taylor <nick@iamdeveloper.com>
Co-authored-by: Ridhwana <Ridhwana.Khan16@gmail.com>
2020-06-18 10:07:17 -04:00

164 lines
4.1 KiB
JavaScript

import { h, Component } from 'preact';
import { Button } from '@crayons';
import { generateMainImage } from '../actions';
import { validateFileInputs } from '../../packs/validateFileInputs';
import { ClipboardButton } from './ClipboardButton';
function isNativeAndroid() {
return (
navigator.userAgent === 'DEV-Native-android' &&
typeof AndroidBridge !== 'undefined' &&
AndroidBridge !== null
);
}
function isClipboardSupported() {
return (
typeof navigator.clipboard !== 'undefined' && navigator.clipboard !== null
);
}
const ImageIcon = () => (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
className="crayons-icon"
xmlns="http://www.w3.org/2000/svg"
role="img"
aria-labelledby="a17qec5pfhrwzk9w4kg0tp62v27qqu9t"
>
<title id="a17qec5pfhrwzk9w4kg0tp62v27qqu9t">Upload image</title>
<path d="M20 5H4v14l9.292-9.294a1 1 0 011.414 0L20 15.01V5zM2 3.993A1 1 0 012.992 3h18.016c.548 0 .992.445.992.993v16.014a1 1 0 01-.992.993H2.992A.993.993 0 012 20.007V3.993zM8 11a2 2 0 110-4 2 2 0 010 4z" />
</svg>
);
ImageIcon.displayName = 'ImageIcon';
export class ImageUploader extends Component {
state = {
insertionImageUrls: [],
uploadError: false,
uploadErrorMessage: null,
showImageCopiedMessage: false,
};
onUploadError = (error) => {
this.setState({
insertionImageUrls: [],
uploadError: true,
uploadErrorMessage: error.message,
});
};
copyText = () => {
this.imageMarkdownInput = document.getElementById(
'image-markdown-copy-link-input',
);
if (isNativeAndroid()) {
AndroidBridge.copyToClipboard(this.imageMarkdownInput.value);
this.setState({ showImageCopiedMessage: true });
} else if (isClipboardSupported()) {
navigator.clipboard
.writeText(this.imageMarkdownInput.value)
.then(() => {
this.setState({ showImageCopiedMessage: true });
})
.catch((_err) => {
this.execCopyText();
});
} else {
this.execCopyText();
}
};
handleInsertionImageUpload = (e) => {
const { files } = e.target;
this.clearUploadError();
const validFileInputs = validateFileInputs();
if (validFileInputs && files.length > 0) {
const payload = { image: files };
this.setState({ showImageCopiedMessage: false });
generateMainImage(
payload,
this.handleInsertImageUploadSuccess,
this.onUploadError,
);
}
};
handleInsertImageUploadSuccess = (response) => {
this.setState({
insertionImageUrls: response.links,
});
};
execCopyText() {
this.imageMarkdownInput.setSelectionRange(
0,
this.imageMarkdownInput.value.length,
);
document.execCommand('copy');
this.setState({ showImageCopiedMessage: true });
}
clearUploadError() {
this.setState({
uploadError: false,
uploadErrorMessage: null,
});
}
render() {
const {
insertionImageUrls,
uploadError,
uploadErrorMessage,
showImageCopiedMessage,
} = this.state;
return (
<div className="flex items-center">
<Button
className="mr-2 fw-normal"
variant="ghost"
contentType="icon-left"
icon={ImageIcon}
tabIndex="-1"
>
Upload image
<input
type="file"
id="image-upload-field"
onChange={this.handleInsertionImageUpload}
className="w-100 h-100 absolute left-0 right-0 top-0 bottom-0 overflow-hidden opacity-0 cursor-pointer"
multiple
accept="image/*"
data-max-file-size-mb="25"
tabIndex="-1"
aria-label="Upload an image"
/>
</Button>
{insertionImageUrls.length > 0 && (
<ClipboardButton
onCopy={this.copyText}
imageUrls={insertionImageUrls}
showCopyMessage={showImageCopiedMessage}
/>
)}
{uploadError && (
<span className="color-accent-danger">{uploadErrorMessage}</span>
)}
</div>
);
}
}
ImageUploader.displayName = 'ImageUploader';