From efff26dfcc0b3d310f44eaa20a752fb80a9d16e2 Mon Sep 17 00:00:00 2001
From: Michael Haschke <michael.haschke@eccenca.com>
Date: Thu, 12 Dec 2024 13:52:50 +0100
Subject: [PATCH] improve hook for dropzone monitoring, make it more stable by
 removing processing of unnecessary event calls

---
 CHANGELOG.md                         |  2 ++
 src/components/Application/helper.ts | 32 ++++++++++++++++++++++++++--
 2 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 650b3597..a9aec7e3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -59,6 +59,8 @@ This is a major release, and it might be not compatible with your current usage
 -   toggling on/off the `<HandleTools/>` was corrected, they kept displayed after re-entering with the cursor
 -   `<Pagination/>`
     -   change text overflow for selectors to `clip` because Firefox rendered `ellipsis` a bit too early
+-   `<ApplicationContainer />`:
+    -   `useDropzoneMonitor` helper hook process was improved so that less events are processed and the dropzone monitoring is more stable
 
 ### Changed
 
diff --git a/src/components/Application/helper.ts b/src/components/Application/helper.ts
index d449c9de..e3907da9 100644
--- a/src/components/Application/helper.ts
+++ b/src/components/Application/helper.ts
@@ -28,20 +28,48 @@ export const useApplicationHeaderOverModals = (elevate: boolean, className: stri
 export const useDropzoneMonitor = (enabledTypes: string[]) => {
     React.useEffect(() => {
         const monitor = window.document.body;
+        let timestampMonitorEnabled = 0;
+        let processDragleave: any;
 
         const addMonitor = (event: DragEvent) => {
+            // stop default, so that also no files cannot executed by browser without demand
+            event.preventDefault();
+
+            if (processDragleave) {
+                // stop removeMonitor process if it happend shortly before
+                clearTimeout(processDragleave);
+            }
+
+            // only process if monitor is not already enabled
+            if (timestampMonitorEnabled > 0) {
+                return;
+            }
+
+            // stop the event here to prevent double execution
+            event.stopImmediatePropagation();
+
+            // enable monitoring only for supported types of dragged elements
             const types = event.dataTransfer?.types || [];
             const monitorTypes = [...new Set(types.filter((type) => enabledTypes.includes(type)))];
             if (monitorTypes.length > 0 && !monitor.dataset.monitorDropzone) {
                 monitor.dataset.monitorDropzone = monitorTypes.join(" ");
             }
-            event.preventDefault();
+
+            timestampMonitorEnabled = Date.now();
         };
 
         const removeMonitor = (event: DragEvent) => {
-            if (event.type === "drop" || monitor === event.target) {
+            const removeAction = () => {
                 delete monitor.dataset.monitorDropzone;
                 event.preventDefault();
+                timestampMonitorEnabled = 0;
+            };
+
+            if (event.type === "dragleave") {
+                // use timeout function for dragleave to prevent useless removeMonitor actions
+                processDragleave = setTimeout(removeAction, 250);
+            } else {
+                removeAction();
             }
         };