From 6cf480094d50a58d4619c18af77c4659c125d49e Mon Sep 17 00:00:00 2001 From: Thales <> Date: Sun, 10 May 2026 00:29:25 +0100 Subject: [PATCH] fix(ui): fix drag-and-drop on Windows WebView2 and catalog rail layout - Set dragDropEnabled: false in tauri.conf.json so WebView2 doesn't intercept OS-level drag events, allowing HTML5 dragover/drop to fire - Fix catalog-rail background not filling full panel height by adding grid-template-rows: 1fr and explicit grid-column/row placement on rail and main, preventing catalog-main from wrapping to an implicit row in the collapsed state - Restore dropOnFolder and getDraggedTrackId to accept explicit trackId and text/plain fallback for cross-origin dataTransfer in WebView2 - Add wireRailLibraryDrop so tracks can be dragged from trash back to library by dropping on the Library rail button --- desktop/src-tauri/tauri.conf.json | 3 +- static/css/widgets.css | 8 +++++ static/js/catalog.js | 56 +++++++++++++++++++++++++++---- 3 files changed, 60 insertions(+), 7 deletions(-) diff --git a/desktop/src-tauri/tauri.conf.json b/desktop/src-tauri/tauri.conf.json index ed8d2b2..0071b98 100644 --- a/desktop/src-tauri/tauri.conf.json +++ b/desktop/src-tauri/tauri.conf.json @@ -17,7 +17,8 @@ "height": 900, "minWidth": 1440, "minHeight": 900, - "backgroundColor": "#050b10" + "backgroundColor": "#050b10", + "dragDropEnabled": false } ], "security": { diff --git a/static/css/widgets.css b/static/css/widgets.css index 488bdbc..483cdcb 100644 --- a/static/css/widgets.css +++ b/static/css/widgets.css @@ -337,6 +337,10 @@ .catalog { display: grid !important; grid-template-columns: 72px minmax(0, 1fr); + grid-template-rows: 1fr; + align-items: stretch !important; + height: 100% !important; + min-height: 0 !important; gap: 0 !important; padding: 0 !important; border-radius: 12px !important; @@ -345,6 +349,8 @@ } .catalog-rail { + grid-column: 1; + grid-row: 1; display: flex; flex-direction: column; align-items: stretch; @@ -428,6 +434,8 @@ } .catalog-main { + grid-column: 2; + grid-row: 1; display: flex; flex-direction: column; gap: 10px; diff --git a/static/js/catalog.js b/static/js/catalog.js index d6911bd..984fb3c 100644 --- a/static/js/catalog.js +++ b/static/js/catalog.js @@ -452,7 +452,9 @@ function isTrackDragEvent(event) { } function getDraggedTrackId(event) { - return event?.dataTransfer?.getData(TRACK_DRAG_TYPE) || dragId; + return event?.dataTransfer?.getData(TRACK_DRAG_TYPE) + || event?.dataTransfer?.getData("text/plain") + || dragId; } function startDrag(trackId, itemEl, event) { @@ -473,16 +475,17 @@ function endDrag(itemEl) { document.getElementById("lanes")?.classList.remove("library-drop-target"); } -function dropOnFolder(folderId) { - if (!dragId) return; +function dropOnFolder(folderId, trackId) { + const id = trackId ?? dragId; + if (!id) return; // Remove from current folder for (const f of folders) { - const idx = f.items.indexOf(dragId); + const idx = f.items.indexOf(id); if (idx !== -1) { f.items.splice(idx, 1); break; } } // Add to target folder const target = folders.find((f) => f.id === folderId); - if (target && !target.items.includes(dragId)) target.items.push(dragId); + if (target && !target.items.includes(id)) target.items.push(id); saveState(); render(); } @@ -549,6 +552,46 @@ function wireRailTrashDrop() { }); } +function restoreTrackFromTrash(trackId) { + if (!tracks[trackId]) return; + const trash = getTrashFolder(); + if (!trash?.items.includes(trackId)) return; + trash.items = trash.items.filter((id) => id !== trackId); + let target = folders.find((f) => f.id !== TRASH_ID); + if (!target) { + target = makeFolder({ id: `f-${Date.now()}`, name: "Unsorted" }); + folders.unshift(target); + } + if (!target.items.includes(trackId)) target.items.push(trackId); + saveState(); + render(); +} + +function wireRailLibraryDrop() { + const btn = document.querySelector(".rail-library"); + if (!btn || btn.dataset.dropReady === "1") return; + btn.dataset.dropReady = "1"; + + btn.addEventListener("dragover", (e) => { + if (!isTrackDragEvent(e) || catalogView !== "trash") return; + e.preventDefault(); + e.dataTransfer.dropEffect = "move"; + btn.classList.add("drop-target"); + }); + btn.addEventListener("dragleave", (e) => { + if (!btn.contains(e.relatedTarget)) btn.classList.remove("drop-target"); + }); + btn.addEventListener("drop", (e) => { + btn.classList.remove("drop-target"); + if (catalogView !== "trash") return; + const trackId = getDraggedTrackId(e); + if (!trackId || !tracks[trackId]) return; + e.preventDefault(); + restoreTrackFromTrash(trackId); + setCatalogView("library"); + }); +} + function isTextEditingTarget(target) { return Boolean(target?.closest?.("input, textarea, select, [contenteditable='true'], .folder-editor")); } @@ -716,7 +759,7 @@ function renderFolder(folder) { el.addEventListener("drop", (e) => { e.preventDefault(); el.classList.remove("drop-target"); - dropOnFolder(folder.id); + dropOnFolder(folder.id, getDraggedTrackId(e)); }); return el; @@ -956,6 +999,7 @@ export function initCatalog() { wireWidgets(); wireMainPanelDrop(); wireRailTrashDrop(); + wireRailLibraryDrop(); wireLibraryDeleteKeys(); wireAboutDialog(); setDisplayedVersion(currentVersion);