From abfb3eaa00803c144e474b62a6eec7573e3a72b0 Mon Sep 17 00:00:00 2001 From: Rajat Parashar Date: Wed, 23 Jun 2021 21:43:28 +0530 Subject: [PATCH 1/3] extended Drop area to report body for attachment --- src/CONST.js | 1 + src/components/TextInputFocusable/index.js | 57 ++++++++++++++++---- src/pages/home/report/ReportActionCompose.js | 11 +++- src/pages/home/report/ReportView.js | 3 +- 4 files changed, 61 insertions(+), 11 deletions(-) diff --git a/src/CONST.js b/src/CONST.js index 4e21d5b5dcb7..c59ece32612d 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -118,6 +118,7 @@ const CONST = { PERSONAL_DETAIL: 'personalDetail', }, REPORT: { + DROP_NATIVE_ID: 'report-dropzone', MAXIMUM_PARTICIPANTS: 8, ACTIONS: { LIMIT: 50, diff --git a/src/components/TextInputFocusable/index.js b/src/components/TextInputFocusable/index.js index ae979787c020..915a05a967a8 100755 --- a/src/components/TextInputFocusable/index.js +++ b/src/components/TextInputFocusable/index.js @@ -5,6 +5,7 @@ import _ from 'underscore'; import withLocalize, {withLocalizePropTypes} from '../withLocalize'; import Growl from '../../libs/Growl'; import themeColors from '../../styles/themes/default'; +import CONST from '../../CONST'; const propTypes = { /** Maximum number of lines in the text input */ @@ -74,7 +75,7 @@ const defaultProps = { isDisabled: false, autoFocus: false, forwardedRef: null, - onSelectionChange: () => { }, + onSelectionChange: () => {}, selection: { start: 0, end: 0, @@ -114,6 +115,7 @@ class TextInputFocusable extends React.Component { end: initialValue.length, }; this.saveSelection = this.saveSelection.bind(this); + this.dragNDropListener = this.dragNDropListener.bind(this); } componentDidMount() { @@ -131,10 +133,11 @@ class TextInputFocusable extends React.Component { // listeners here and unbind when the component unmounts if (this.textInput) { // Firefox will not allow dropping unless we call preventDefault on the dragover event - this.textInput.addEventListener('dragover', e => e.preventDefault()); - this.textInput.addEventListener('dragenter', this.props.onDragEnter); - this.textInput.addEventListener('dragleave', this.props.onDragLeave); - this.textInput.addEventListener('drop', this.props.onDrop); + // We listen on document to extend the Drop area beyond Composer + document.addEventListener('dragover', this.dragNDropListener); + document.addEventListener('dragenter', this.dragNDropListener); + document.addEventListener('dragleave', this.dragNDropListener); + document.addEventListener('drop', this.dragNDropListener); this.textInput.addEventListener('paste', this.checkForAttachment.bind(this)); } } @@ -158,10 +161,10 @@ class TextInputFocusable extends React.Component { componentWillUnmount() { if (this.textInput) { - this.textInput.addEventListener('dragover', e => e.preventDefault()); - this.textInput.removeEventListener('dragenter', this.props.onDragEnter); - this.textInput.removeEventListener('dragleave', this.props.onDragLeave); - this.textInput.removeEventListener('drop', this.props.onDrop); + document.removeEventListener('dragover', this.dragNDropListener); + document.removeEventListener('dragenter', this.dragNDropListener); + document.removeEventListener('dragleave', this.dragNDropListener); + document.removeEventListener('drop', this.dragNDropListener); this.textInput.removeEventListener('paste', this.checkForAttachment.bind(this)); } } @@ -182,6 +185,42 @@ class TextInputFocusable extends React.Component { return newNumberOfLines; } + /** + * Handles all types of drag-N-drop events on the composer + * + * @param {Object} e native Event + * @memberof TextInputFocusable + */ + dragNDropListener(e) { + let isOriginComposer = false; + const handler = () => { + switch (e.type) { + case 'dragover': + e.preventDefault(); + this.props.onDragEnter(e, isOriginComposer); + break; + case 'dragenter': + e.dataTransfer.dropEffect = 'copy'; + this.props.onDragEnter(e, isOriginComposer); + break; + case 'dragleave': this.props.onDragLeave(e, isOriginComposer); break; + case 'drop': this.props.onDrop(e, isOriginComposer); break; + default: break; + } + }; + + // We first check if drop target is composer so that it can be highlighted + if (this.textInput.contains(e.target)) { + isOriginComposer = true; + handler(); + return; + } + + if (document.getElementById(CONST.REPORT.DROP_NATIVE_ID).contains(e.target)) { + handler(); + } + } + /** * Keeps track of user cursor position on the Composer * diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index a495f0268678..7d5dca8d8e34 100755 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -482,7 +482,16 @@ class ReportActionCompose extends React.Component { placeholderTextColor={themeColors.placeholderText} onChangeText={this.updateComment} onKeyPress={this.triggerHotkeyActions} - onDragEnter={() => this.setState({isDraggingOver: true})} + onDragEnter={(e, isOriginComposer) => { + if (isOriginComposer) { + this.setState({isDraggingOver: true}); + } + }} + onDragOver={(e, isOriginComposer) => { + if (isOriginComposer) { + this.setState({isDraggingOver: true}); + } + }} onDragLeave={() => this.setState({isDraggingOver: false})} onDrop={(e) => { e.preventDefault(); diff --git a/src/pages/home/report/ReportView.js b/src/pages/home/report/ReportView.js index 724452f50b86..8481be201ed8 100644 --- a/src/pages/home/report/ReportView.js +++ b/src/pages/home/report/ReportView.js @@ -9,6 +9,7 @@ import KeyboardSpacer from '../../../components/KeyboardSpacer'; import styles from '../../../styles/styles'; import SwipeableView from '../../../components/SwipeableView'; import ONYXKEYS from '../../../ONYXKEYS'; +import CONST from '../../../CONST'; const propTypes = { /** The ID of the report the selected report */ @@ -29,7 +30,7 @@ const defaultProps = { }; const ReportView = ({reportID, session}) => ( - + {session.shouldShowComposeInput && ( From 6fe3151a76458f12249eaabfcedd86a5748a831d Mon Sep 17 00:00:00 2001 From: Rajat Parashar Date: Wed, 23 Jun 2021 21:49:09 +0530 Subject: [PATCH 2/3] drop over prop to textInput --- src/components/TextInputFocusable/index.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/components/TextInputFocusable/index.js b/src/components/TextInputFocusable/index.js index 915a05a967a8..25b0bf66069b 100755 --- a/src/components/TextInputFocusable/index.js +++ b/src/components/TextInputFocusable/index.js @@ -33,13 +33,16 @@ const propTypes = { /** When the input has cleared whoever owns this input should know about it */ onClear: PropTypes.func, - /** Callback to fire when a file has been dragged into the text input */ + /** Callback to fire when a file has being dragged over the text input & report body */ + onDragOver: PropTypes.func, + + /** Callback to fire when a file has been dragged into the text input & report body */ onDragEnter: PropTypes.func, - /** Callback to fire when the user is no longer dragging over the text input */ + /** Callback to fire when the user is no longer dragging over the text input & report body */ onDragLeave: PropTypes.func, - /** Callback to fire when a file is dropped on the text input */ + /** Callback to fire when a file is dropped on the text input & report body */ onDrop: PropTypes.func, /** Whether or not this TextInput is disabled. */ @@ -70,6 +73,7 @@ const defaultProps = { onClear: () => {}, style: null, onDragEnter: () => {}, + onDragOver: () => {}, onDragLeave: () => {}, onDrop: () => {}, isDisabled: false, @@ -197,7 +201,7 @@ class TextInputFocusable extends React.Component { switch (e.type) { case 'dragover': e.preventDefault(); - this.props.onDragEnter(e, isOriginComposer); + this.props.onDragOver(e, isOriginComposer); break; case 'dragenter': e.dataTransfer.dropEffect = 'copy'; From 0e81b37880bd8f878c9f10b5dd547a5f55d6d6d1 Mon Sep 17 00:00:00 2001 From: Rajat Parashar Date: Thu, 24 Jun 2021 16:13:28 +0530 Subject: [PATCH 3/3] refactor --- src/components/TextInputFocusable/index.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/TextInputFocusable/index.js b/src/components/TextInputFocusable/index.js index 25b0bf66069b..2004ed232e28 100755 --- a/src/components/TextInputFocusable/index.js +++ b/src/components/TextInputFocusable/index.js @@ -207,8 +207,12 @@ class TextInputFocusable extends React.Component { e.dataTransfer.dropEffect = 'copy'; this.props.onDragEnter(e, isOriginComposer); break; - case 'dragleave': this.props.onDragLeave(e, isOriginComposer); break; - case 'drop': this.props.onDrop(e, isOriginComposer); break; + case 'dragleave': + this.props.onDragLeave(e, isOriginComposer); + break; + case 'drop': + this.props.onDrop(e, isOriginComposer); + break; default: break; } };