From b26b031616307c30f03b74f7aefebf8f1d965f3a Mon Sep 17 00:00:00 2001 From: Sarthak Sharma <7lovesharma7@gmail.com> Date: Mon, 31 Aug 2020 23:44:32 +0530 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=80=20Feature:=20Ability=20to=20upload?= =?UTF-8?q?=20images=20to=20connect=20by=20drag=20and=20drop=20(#9992)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/javascript/article-form/actions.js | 5 +-- app/javascript/chat/chat.jsx | 41 +++++++++++++++++++++++ app/javascript/utilities/dragAndUpload.js | 9 +++++ 3 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 app/javascript/utilities/dragAndUpload.js diff --git a/app/javascript/article-form/actions.js b/app/javascript/article-form/actions.js index 96e1df48e..494dfa92f 100644 --- a/app/javascript/article-form/actions.js +++ b/app/javascript/article-form/actions.js @@ -91,8 +91,9 @@ export function generateMainImage(payload, successCb, failureCb) { if (json.error) { throw new Error(json.error); } - - return successCb(json); + const { links } = json; + const { image } = payload; + return successCb({ links, image }); }) .catch(failureCb); } diff --git a/app/javascript/chat/chat.jsx b/app/javascript/chat/chat.jsx index 21bef858e..0b97c7f44 100644 --- a/app/javascript/chat/chat.jsx +++ b/app/javascript/chat/chat.jsx @@ -8,6 +8,7 @@ import { h, Component } from 'preact'; import PropTypes from 'prop-types'; import { setupPusher } from '../utilities/connect'; import debounceAction from '../utilities/debounceAction'; +import { dragDrop } from '../utilities/dragAndUpload'; import { addSnackbarItem } from '../Snackbar'; import { conductModeration, @@ -1411,7 +1412,44 @@ export default class Chat extends Component { .getElementById('jumpback_button') .classList.remove('chatchanneljumpback__hide'); }; + handleImageDrop = (e) => { + e.preventDefault(); + const { files } = e.dataTransfer; + const messageArea = document.getElementById('messagelist'); + messageArea.classList.remove('opacity-25'); + messageArea.classList.add('opacity-100'); + dragDrop(files, this.handleImageSuccess, this.handleImageFailure); + }; + handleImageSuccess = (res) => { + const { links, image } = res; + const mLink = `![${image[0].name}](${links[0]})`; + const el = document.getElementById('messageform'); + const start = el.selectionStart; + const end = el.selectionEnd; + const text = el.value; + let before = text.substring(0, start); + before = text.substring(0, before.lastIndexOf('@') + 1); + const after = text.substring(end, text.length); + el.value = `${before + mLink} ${after}`; + el.selectionStart = start + mLink.length + 1; + el.selectionEnd = start + mLink.length + 1; + el.focus(); + }; + handleImageFailure = (e) => { + addSnackbarItem({ message: e.message, addCloseButton: true }); + }; + handleDragHover(e) { + e.preventDefault(); + const messageArea = document.getElementById('messagelist'); + messageArea.classList.add('opacity-25'); + } + handleDragExit(e) { + e.preventDefault(); + const messageArea = document.getElementById('messagelist'); + messageArea.classList.remove('opacity-25'); + messageArea.classList.add('opacity-100'); + } renderActiveChatChannel = (channelHeader) => { const { state, props } = this; @@ -1426,6 +1464,9 @@ export default class Chat extends Component { this.scroller = scroller; }} id="messagelist" + onDragOver={this.handleDragHover} + onDragExit={this.handleDragExit} + onDrop={this.handleImageDrop} > {this.renderMessages()}
diff --git a/app/javascript/utilities/dragAndUpload.js b/app/javascript/utilities/dragAndUpload.js new file mode 100644 index 000000000..7c35d47fa --- /dev/null +++ b/app/javascript/utilities/dragAndUpload.js @@ -0,0 +1,9 @@ +import { generateMainImage } from '../article-form/actions'; +import { validateFileInputs } from '../packs/validateFileInputs'; + +export function dragDrop(files, handleImageSuccess, handleImageFailure) { + if (files.length > 0 && validateFileInputs()) { + const payload = { image: files }; + generateMainImage(payload, handleImageSuccess, handleImageFailure); + } +}