From 16a715c8167d4b1c7f2692451f62c26f6711c38f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Alby?= Date: Tue, 5 Jan 2021 11:57:53 +0100 Subject: [PATCH] Merge pull request #3531 from overleaf/ta-drag-ritch-text [ReactFileTree] Contain DnD Event Listeners GitOrigin-RevId: 9d5520c3b8c1fea5c3e120f56cffddec50347f94 --- .../components/file-tree-folder-list.js | 1 + .../file-tree/contexts/file-tree-draggable.js | 39 ++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-folder-list.js b/services/web/frontend/js/features/file-tree/components/file-tree-folder-list.js index ea95e0b215..05ee3d2fa2 100644 --- a/services/web/frontend/js/features/file-tree/components/file-tree-folder-list.js +++ b/services/web/frontend/js/features/file-tree/components/file-tree-folder-list.js @@ -19,6 +19,7 @@ function FileTreeFolderList({ className={classNames('list-unstyled', classes.root)} role="tree" ref={dropRef} + dnd-container="true" > {folders.sort(compareFunction).map(folder => { return ( diff --git a/services/web/frontend/js/features/file-tree/contexts/file-tree-draggable.js b/services/web/frontend/js/features/file-tree/contexts/file-tree-draggable.js index 21017d492b..3eb793cc8a 100644 --- a/services/web/frontend/js/features/file-tree/contexts/file-tree-draggable.js +++ b/services/web/frontend/js/features/file-tree/contexts/file-tree-draggable.js @@ -14,7 +14,44 @@ import { useFileTreeActionable } from './file-tree-actionable' import { useFileTreeMutable } from './file-tree-mutable' import { useFileTreeSelectable } from '../contexts/file-tree-selectable' -const DndContext = createDndContext(HTML5Backend) +// HACK ALERT +// DnD binds drag and drop events on window and stop propagation if the dragged +// item is not a DnD element. This break other drag and drop interfaces; in +// particular in rich text. +// This is a hacky workaround to avoid calling the DnD listeners when the +// draggable or droppable element is not within a `dnd-container` element. +const ModifiedBackend = (...args) => { + function isDndChild(elt) { + if (elt.getAttribute && elt.getAttribute('dnd-container')) return true + if (!elt.parentNode) return false + return isDndChild(elt.parentNode) + } + const instance = new HTML5Backend(...args) + + const dragDropListeners = [ + 'handleTopDragStart', + 'handleTopDragStartCapture', + 'handleTopDragEndCapture', + 'handleTopDragEnter', + 'handleTopDragEnterCapture', + 'handleTopDragLeaveCapture', + 'handleTopDragOver', + 'handleTopDragOverCapture', + 'handleTopDrop', + 'handleTopDropCapture' + ] + + dragDropListeners.forEach(dragDropListener => { + const originalListener = instance[dragDropListener] + instance[dragDropListener] = (ev, ...extraArgs) => { + if (isDndChild(ev.target)) originalListener(ev, ...extraArgs) + } + }) + + return instance +} + +const DndContext = createDndContext(ModifiedBackend) const DRAGGABLE_TYPE = 'ENTITY'