move dnd to MessagesView, otherwise problems with layout

This commit is contained in:
or-else
2022-12-14 14:26:47 -08:00
parent ed3107405f
commit ed77f48189
3 changed files with 86 additions and 102 deletions
+2 -12
View File
@@ -2976,19 +2976,9 @@ ul.tabbar li.active > a {
} }
/* /*
Drag-and-drop container. Drag-and-drop area.
*/ */
.drag-and-drop { .drag-n-drop {
display: flex;
flex-direction: column;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.drag-and-drop .banner {
display: flex; display: flex;
border: dashed grey 0.15rem; border: dashed grey 0.15rem;
border-radius: 1rem; border-radius: 1rem;
+84 -6
View File
@@ -9,7 +9,6 @@ import CallPanel from '../widgets/call-panel.jsx';
import ChatMessage from '../widgets/chat-message.jsx'; import ChatMessage from '../widgets/chat-message.jsx';
import ContactBadges from '../widgets/contact-badges.jsx'; import ContactBadges from '../widgets/contact-badges.jsx';
import DocPreview from '../widgets/doc-preview.jsx'; import DocPreview from '../widgets/doc-preview.jsx';
import DragAndDrop from '../widgets/drag-and-drop.jsx'
import ErrorPanel from '../widgets/error-panel.jsx'; import ErrorPanel from '../widgets/error-panel.jsx';
import GroupSubs from '../widgets/group-subs.jsx'; import GroupSubs from '../widgets/group-subs.jsx';
import ImagePreview from '../widgets/image-preview.jsx'; import ImagePreview from '../widgets/image-preview.jsx';
@@ -117,6 +116,7 @@ class MessagesView extends React.Component {
this.sendKeyPress = this.sendKeyPress.bind(this); this.sendKeyPress = this.sendKeyPress.bind(this);
this.subscribe = this.subscribe.bind(this); this.subscribe = this.subscribe.bind(this);
this.handleScrollReference = this.handleScrollReference.bind(this); this.handleScrollReference = this.handleScrollReference.bind(this);
this.mountDnDEvents = this.mountDnDEvents.bind(this);
this.handleScrollEvent = this.handleScrollEvent.bind(this); this.handleScrollEvent = this.handleScrollEvent.bind(this);
this.handleDescChange = this.handleDescChange.bind(this); this.handleDescChange = this.handleDescChange.bind(this);
this.handleSubsUpdated = this.handleSubsUpdated.bind(this); this.handleSubsUpdated = this.handleSubsUpdated.bind(this);
@@ -144,9 +144,22 @@ class MessagesView extends React.Component {
this.handleQuoteClick = this.handleQuoteClick.bind(this); this.handleQuoteClick = this.handleQuoteClick.bind(this);
this.handleCallHangup = this.handleCallHangup.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.chatMessageRefs = {};
this.getOrCreateMessageRef = this.getOrCreateMessageRef.bind(this); 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.readNotificationQueue = [];
this.readNotificationTimer = null; this.readNotificationTimer = null;
@@ -166,6 +179,14 @@ class MessagesView extends React.Component {
if (this.messagesScroller) { if (this.messagesScroller) {
this.messagesScroller.addEventListener('scroll', this.handleScrollEvent); 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() { componentWillUnmount() {
@@ -175,6 +196,14 @@ class MessagesView extends React.Component {
// Flush all notifications. // Flush all notifications.
this.clearNotificationQueue(); 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 // 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() { goToLatestMessage() {
this.setState({scrollPosition: 0}); this.setState({scrollPosition: 0});
if (this.messagesScroller) { 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() { render() {
const {formatMessage} = this.props.intl; const {formatMessage} = this.props.intl;
@@ -1486,14 +1564,14 @@ class MessagesView extends React.Component {
onClearError={this.props.onError} /> onClearError={this.props.onError} />
: null} : null}
<LoadSpinner show={this.state.fetchingMessages} /> <LoadSpinner show={this.state.fetchingMessages} />
{!this.state.unconfirmed && !this.props.forwardMessage && this.state.isWriter && !this.state.peerMessagingDisabled ? {messagesComponent}
<DragAndDrop actionPrompt={this.props.intl.formatMessage(messages.drag_file)} {this.state.dragging && this.isDragEnabled() ?
onDrop={this.handleFileDrop} >{messagesComponent}</DragAndDrop> <div className="drag-n-drop">{formatMessage(messages.drag_file)}</div>
: messagesComponent} : null}
</> </>
); );
} }
component = <div id="topic-view">{component2}</div> component = <div id="topic-view" ref={this.mountDnDEvents}>{component2}</div>
} }
return component; return component;
} }
-84
View File
@@ -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 (
<div className="drag-and-drop" ref={this.dropRef}>
{this.state.dragging ?
<div className="banner">{this.props.actionPrompt}</div>
: null}
{this.props.children}
</div>
);
}
};