fix: dragstart singleton TabManager — JSON au lieu de String(idx)
CI / lint (push) Failing after 9s
CI / test (push) Has been skipped
CI / build (push) Has been skipped
CI / e2e (push) Has been skipped
CI / security (push) Successful in 16s
Desktop Build / build-windows (push) Has been cancelled
Desktop Build / build-linux (push) Has been cancelled

Cause: le TabManager singleton (single-pane) écrasait text/plain avec String(idx)
→ getData retournait '1' au lieu du JSON {paneId,tabId,index}
→ le drop handler PaneManager échouait sur 'missing paneId/tabId'

Fix:
- singleton dragstart: JSON.stringify({paneId:0, tabId, index}) + effectAllowed
- singleton drop: parse JSON, fallback legacy parseInt pour rétrocompatibilité
- dragover/drop inchangés (indicateurs visuels)
This commit is contained in:
2026-07-27 23:28:39 -04:00
parent fe4cb9c47c
commit 4deb54b3a3
+26 -8
View File
@@ -2267,9 +2267,11 @@ export const TabManager = {
this._showTabContextMenu(e.clientX, e.clientY, tab.id);
});
// Drag and drop
// Drag and drop — JSON format for cross-pane compatibility
el.addEventListener("dragstart", (e) => {
e.dataTransfer.setData("text/plain", String(idx));
const payload = JSON.stringify({ paneId: 0, tabId: tab.id, index: idx });
e.dataTransfer.setData("text/plain", payload);
e.dataTransfer.effectAllowed = "move";
el.classList.add("dragging");
});
el.addEventListener("dragend", () => {
@@ -2293,13 +2295,29 @@ export const TabManager = {
el.addEventListener("drop", (e) => {
e.preventDefault();
document.querySelectorAll(".tab-drop-indicator").forEach(d => d.remove());
const fromIdx = parseInt(e.dataTransfer.getData("text/plain"));
const rect = el.getBoundingClientRect();
const mid = rect.left + rect.width / 2;
const toIdx = e.clientX < mid ? idx : idx + 1;
if (fromIdx !== toIdx && fromIdx !== toIdx - 1) {
this.moveTab(fromIdx, toIdx);
const raw = e.dataTransfer.getData("text/plain");
if (!raw) return;
let dragData;
try { dragData = JSON.parse(raw); } catch (e2) {
// Legacy format: plain index string
const fromIdx = parseInt(raw);
if (isNaN(fromIdx)) return;
const rect = el.getBoundingClientRect();
const mid = rect.left + rect.width / 2;
const toIdx = e.clientX < mid ? idx : idx + 1;
if (fromIdx !== toIdx && fromIdx !== toIdx - 1)
this.moveTab(fromIdx, toIdx);
return;
}
if (dragData.paneId === 0) {
// Same pane — reorder
const rect = el.getBoundingClientRect();
const mid = rect.left + rect.width / 2;
const toIdx = e.clientX < mid ? idx : idx + 1;
if (dragData.index !== toIdx && dragData.index !== toIdx - 1)
this.moveTab(dragData.index, toIdx);
}
// Cross-pane transfers handled by PaneManager's container drop zone
});
this._tabList.appendChild(el);