From ed77f481891900eb95f5dbeafa0b71d261233633 Mon Sep 17 00:00:00 2001 From: or-else Date: Wed, 14 Dec 2022 14:26:47 -0800 Subject: [PATCH] move dnd to MessagesView, otherwise problems with layout --- css/base.css | 14 +----- src/views/messages-view.jsx | 90 ++++++++++++++++++++++++++++++++--- src/widgets/drag-and-drop.jsx | 84 -------------------------------- 3 files changed, 86 insertions(+), 102 deletions(-) delete mode 100644 src/widgets/drag-and-drop.jsx diff --git a/css/base.css b/css/base.css index c3841465..c7a9d0d8 100644 --- a/css/base.css +++ b/css/base.css @@ -2976,19 +2976,9 @@ ul.tabbar li.active > a { } /* - Drag-and-drop container. + Drag-and-drop area. */ -.drag-and-drop { - display: flex; - flex-direction: column; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; -} - -.drag-and-drop .banner { +.drag-n-drop { display: flex; border: dashed grey 0.15rem; border-radius: 1rem; diff --git a/src/views/messages-view.jsx b/src/views/messages-view.jsx index cae5f38b..d1446c6e 100644 --- a/src/views/messages-view.jsx +++ b/src/views/messages-view.jsx @@ -9,7 +9,6 @@ import CallPanel from '../widgets/call-panel.jsx'; import ChatMessage from '../widgets/chat-message.jsx'; import ContactBadges from '../widgets/contact-badges.jsx'; import DocPreview from '../widgets/doc-preview.jsx'; -import DragAndDrop from '../widgets/drag-and-drop.jsx' import ErrorPanel from '../widgets/error-panel.jsx'; import GroupSubs from '../widgets/group-subs.jsx'; import ImagePreview from '../widgets/image-preview.jsx'; @@ -117,6 +116,7 @@ class MessagesView extends React.Component { this.sendKeyPress = this.sendKeyPress.bind(this); this.subscribe = this.subscribe.bind(this); this.handleScrollReference = this.handleScrollReference.bind(this); + this.mountDnDEvents = this.mountDnDEvents.bind(this); this.handleScrollEvent = this.handleScrollEvent.bind(this); this.handleDescChange = this.handleDescChange.bind(this); this.handleSubsUpdated = this.handleSubsUpdated.bind(this); @@ -144,9 +144,22 @@ class MessagesView extends React.Component { this.handleQuoteClick = this.handleQuoteClick.bind(this); this.handleCallHangup = this.handleCallHangup.bind(this); + this.isDragEnabled = this.isDragEnabled.bind(this); + this.handleDragIn = this.handleDragIn.bind(this); + this.handleDragOut = this.handleDragOut.bind(this); + this.handleDrag = this.handleDrag.bind(this); + this.handleDrop = this.handleDrop.bind(this); + this.chatMessageRefs = {}; this.getOrCreateMessageRef = this.getOrCreateMessageRef.bind(this); + // Keeps track of the drag event. + // Need a counter b/c the browser's 'drag' events may fire multiple times + // when the user takes the mouse pointer over the container: + // for the component itself and for all nested/child elements. + this.dragCounter = 0; + this.dndRef = null; + this.readNotificationQueue = []; this.readNotificationTimer = null; @@ -166,6 +179,14 @@ class MessagesView extends React.Component { if (this.messagesScroller) { this.messagesScroller.addEventListener('scroll', this.handleScrollEvent); } + + // Drag and drop events + if (this.dndRef) { + this.dndRef.addEventListener('dragenter', this.handleDragIn); + this.dndRef.addEventListener('dragleave', this.handleDragOut); + this.dndRef.addEventListener('dragover', this.handleDrag); + this.dndRef.addEventListener('drop', this.handleDrop); + } } componentWillUnmount() { @@ -175,6 +196,14 @@ class MessagesView extends React.Component { // Flush all notifications. this.clearNotificationQueue(); + + // Drag and drop events + if (this.dndRef) { + this.dndRef.removeEventListener('dragenter', this.handleDragIn); + this.dndRef.removeEventListener('dragleave', this.handleDragOut); + this.dndRef.removeEventListener('dragover', this.handleDrag); + this.dndRef.removeEventListener('drop', this.handleDrop); + } } // Scroll last message into view on component update e.g. on message received @@ -505,6 +534,17 @@ class MessagesView extends React.Component { } } + /* Mound draf and drop events */ + mountDnDEvents(dnd) { + if (dnd) { + dnd.addEventListener('dragenter', this.handleDragIn); + dnd.addEventListener('dragleave', this.handleDragOut); + dnd.addEventListener('dragover', this.handleDrag); + dnd.addEventListener('drop', this.handleDrop); + this.dndRef = dnd; + } + } + goToLatestMessage() { this.setState({scrollPosition: 0}); if (this.messagesScroller) { @@ -1188,6 +1228,44 @@ class MessagesView extends React.Component { } } + isDragEnabled() { + return this.state.isWriter && !this.state.unconfirmed && !this.props.forwardMessage && !this.state.peerMessagingDisabled; + } + + handleDrag(e) { + e.preventDefault(); + e.stopPropagation(); + } + + handleDragIn(e) { + e.preventDefault(); + e.stopPropagation(); + this.dragCounter++; + if (e.dataTransfer.items && e.dataTransfer.items.length > 0) { + this.setState({dragging: true}); + } + } + + handleDragOut(e) { + e.preventDefault(); + e.stopPropagation(); + this.dragCounter--; + if (this.dragCounter <= 0) { + this.setState({dragging: false}); + } + } + + handleDrop(e) { + e.preventDefault(); + e.stopPropagation(); + this.setState({dragging: false}); + if (this.isDragEnabled() && e.dataTransfer.files && e.dataTransfer.files.length > 0) { + this.handleFileDrop(e.dataTransfer.files); + e.dataTransfer.clearData(); + this.dragCounter = 0; + } + } + render() { const {formatMessage} = this.props.intl; @@ -1486,14 +1564,14 @@ class MessagesView extends React.Component { onClearError={this.props.onError} /> : null} - {!this.state.unconfirmed && !this.props.forwardMessage && this.state.isWriter && !this.state.peerMessagingDisabled ? - {messagesComponent} - : messagesComponent} + {messagesComponent} + {this.state.dragging && this.isDragEnabled() ? +
{formatMessage(messages.drag_file)}
+ : null} ); } - component =
{component2}
+ component =
{component2}
} return component; } diff --git a/src/widgets/drag-and-drop.jsx b/src/widgets/drag-and-drop.jsx deleted file mode 100644 index 22b01710..00000000 --- a/src/widgets/drag-and-drop.jsx +++ /dev/null @@ -1,84 +0,0 @@ -// Drag & drop container: displays a banner on drag and calls a handler on drop. -import React from 'react'; - -export default class DragAndDrop extends React.PureComponent { - constructor(props) { - super(props); - this.state = { - // A file is being dragged over the container. - dragging: false - }; - this.dropRef = React.createRef(); - // Keeps track of the drag event. - // Need a counter b/c the browser's 'drag' events may fire multiple times - // when the user takes the mouse pointer over the container: - // for the component itself and for all nested/child elements. - this.dragCounter = 0; - - this.handleDrag = this.handleDrag.bind(this); - this.handleDragIn = this.handleDragIn.bind(this); - this.handleDragOut = this.handleDragOut.bind(this); - this.handleDrop = this.handleDrop.bind(this); - } - - componentDidMount() { - const div = this.dropRef.current; - div.addEventListener('dragenter', this.handleDragIn); - div.addEventListener('dragleave', this.handleDragOut); - div.addEventListener('dragover', this.handleDrag); - div.addEventListener('drop', this.handleDrop); - } - - componentWillUnmount() { - const div = this.dropRef.current; - div.removeEventListener('dragenter', this.handleDragIn); - div.removeEventListener('dragleave', this.handleDragOut); - div.removeEventListener('dragover', this.handleDrag); - div.removeEventListener('drop', this.handleDrop); - } - - handleDrag(e) { - e.preventDefault(); - e.stopPropagation(); - } - - handleDragIn(e) { - e.preventDefault(); - e.stopPropagation(); - this.dragCounter++; - if (e.dataTransfer.items && e.dataTransfer.items.length > 0) { - this.setState({dragging: true}); - } - } - - handleDragOut(e) { - e.preventDefault(); - e.stopPropagation(); - this.dragCounter--; - if (this.dragCounter <= 0) { - this.setState({dragging: false}); - } - } - - handleDrop(e) { - e.preventDefault(); - e.stopPropagation(); - this.setState({dragging: false}); - if (e.dataTransfer.files && e.dataTransfer.files.length > 0) { - this.props.onDrop(e.dataTransfer.files); - e.dataTransfer.clearData(); - this.dragCounter = 0; - } - } - - render() { - return ( -
- {this.state.dragging ? -
{this.props.actionPrompt}
- : null} - {this.props.children} -
- ); - } -};