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); this._showTabContextMenu(e.clientX, e.clientY, tab.id);
}); });
// Drag and drop // Drag and drop — JSON format for cross-pane compatibility
el.addEventListener("dragstart", (e) => { 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.classList.add("dragging");
}); });
el.addEventListener("dragend", () => { el.addEventListener("dragend", () => {
@@ -2293,13 +2295,29 @@ export const TabManager = {
el.addEventListener("drop", (e) => { el.addEventListener("drop", (e) => {
e.preventDefault(); e.preventDefault();
document.querySelectorAll(".tab-drop-indicator").forEach(d => d.remove()); document.querySelectorAll(".tab-drop-indicator").forEach(d => d.remove());
const fromIdx = parseInt(e.dataTransfer.getData("text/plain")); const raw = e.dataTransfer.getData("text/plain");
const rect = el.getBoundingClientRect(); if (!raw) return;
const mid = rect.left + rect.width / 2; let dragData;
const toIdx = e.clientX < mid ? idx : idx + 1; try { dragData = JSON.parse(raw); } catch (e2) {
if (fromIdx !== toIdx && fromIdx !== toIdx - 1) { // Legacy format: plain index string
this.moveTab(fromIdx, toIdx); 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); this._tabList.appendChild(el);