From ec0a53f76582dac143e04474c06c8cc5d333a55d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20K=C5=82osko?= Date: Thu, 25 Apr 2024 16:11:59 +0200 Subject: [PATCH] Fix file drag-and-drop on Safari (#2582) --- assets/js/hooks/session.js | 12 ++++++++++++ assets/js/lib/utils.js | 4 ++++ 2 files changed, 16 insertions(+) diff --git a/assets/js/hooks/session.js b/assets/js/hooks/session.js index c70f8bfe6..e1baf8e56 100644 --- a/assets/js/hooks/session.js +++ b/assets/js/hooks/session.js @@ -9,6 +9,7 @@ import { isElementInViewport, isElementHidden, pop, + isSafari, } from "../lib/utils"; import { parseHookProps } from "../lib/attribute"; import KeyBuffer from "../lib/key_buffer"; @@ -738,6 +739,17 @@ const Session = { }); this.el.addEventListener("dragleave", (event) => { + // The related target should point to the newly entered element, + // and be null when the cursor leaves the window. However, in + // Safari the related target is always null (1), so we ignore + // the leave event altogether. The side effect is that dropping + // the file outside the window will keep the drop areas open and + // require page refresh to hide them, but the workaround is not + // worth its complexity, hence we accept this edge case. + // + // (1): https://stackoverflow.com/a/71744945 + if (isSafari()) return; + if (!this.el.contains(event.relatedTarget)) { stopDragging(); } diff --git a/assets/js/lib/utils.js b/assets/js/lib/utils.js index 92a4c2c94..e58c53989 100644 --- a/assets/js/lib/utils.js +++ b/assets/js/lib/utils.js @@ -331,3 +331,7 @@ export function wait(milliseconds) { setTimeout(() => resolve(), milliseconds); }); } + +export function isSafari() { + return /^((?!chrome|android).)*safari/i.test(navigator.userAgent); +}