diff --git a/frontend/js/pane-manager.js b/frontend/js/pane-manager.js index 8276744..3a70153 100644 --- a/frontend/js/pane-manager.js +++ b/frontend/js/pane-manager.js @@ -734,11 +734,18 @@ const PaneManager = { /** Add dragover/drop on a pane container for cross-pane transfers + drag-to-split */ _setupPaneDropZone(container, paneId) { - let _edgeZone = null; // 'right' | 'bottom' | null + let _dragCounter = 0; + + container.addEventListener('dragenter', (e) => { + const types = Array.from(e.dataTransfer.types || []); + if (!types.includes('application/obsigate-tab')) return; + _dragCounter++; + e.preventDefault(); + }); container.addEventListener('dragover', (e) => { - const raw = e.dataTransfer.types.includes('application/obsigate-tab'); - if (!raw) return; + const types = Array.from(e.dataTransfer.types || []); + if (!types.includes('application/obsigate-tab')) return; e.preventDefault(); e.dataTransfer.dropEffect = 'move'; @@ -750,37 +757,35 @@ const PaneManager = { // Clean up previous indicators container.querySelectorAll('.pane-drop-zone-indicator').forEach(d => d.remove()); - _edgeZone = null; + const tabBar = container.querySelector('.tab-bar'); + if (tabBar) tabBar.classList.remove('drop-target'); - if (isSingle) { - if (relX > rect.width * 0.75) { - _edgeZone = 'right'; - } else if (relY > rect.height * 0.75) { - _edgeZone = 'bottom'; - } - } - - if (_edgeZone) { - // Show edge zone indicator + if (isSingle && relX > rect.width * 0.72) { const indicator = document.createElement('div'); - indicator.className = 'pane-drop-zone-indicator pane-drop-zone-' + _edgeZone; + indicator.className = 'pane-drop-zone-indicator pane-drop-zone-right'; + container.appendChild(indicator); + } else if (isSingle && relY > rect.height * 0.72) { + const indicator = document.createElement('div'); + indicator.className = 'pane-drop-zone-indicator pane-drop-zone-bottom'; container.appendChild(indicator); } else { // Show tab-bar highlight for cross-pane transfer - const tabBar = container.querySelector('.tab-bar'); if (tabBar) tabBar.classList.add('drop-target'); } }); container.addEventListener('dragleave', (e) => { + _dragCounter--; + if (_dragCounter > 0) return; // Still inside container (entered a child) container.querySelectorAll('.pane-drop-zone-indicator').forEach(d => d.remove()); const tabBar = container.querySelector('.tab-bar'); if (tabBar) tabBar.classList.remove('drop-target'); - _edgeZone = null; }); container.addEventListener('drop', (e) => { e.preventDefault(); + e.stopPropagation(); + _dragCounter = 0; container.querySelectorAll('.pane-drop-zone-indicator').forEach(d => d.remove()); const tabBar = container.querySelector('.tab-bar'); if (tabBar) tabBar.classList.remove('drop-target'); @@ -789,28 +794,33 @@ const PaneManager = { if (!raw) return; try { const dragData = JSON.parse(raw); + if (dragData.paneId === paneId) return; // Same pane, let tab handler deal with it - if (_edgeZone === 'right') { - // Drag to right edge → split right with this tab + // Recalculate edge zone from drop coordinates + const rect = container.getBoundingClientRect(); + const relX = e.clientX - rect.left; + const relY = e.clientY - rect.top; + const isSingle = !this.isSplit(); + + if (isSingle && relX > rect.width * 0.72) { + // Dropped on right edge → split right with this tab this.splitRight(); - // Transfer the dragged tab to the new pane setTimeout(() => { const newPaneId = this.panes.length - 1; this.transferTab(dragData.paneId, dragData.tabId, newPaneId); - }, 100); - } else if (_edgeZone === 'bottom') { - // Drag to bottom edge → split down with this tab + }, 150); + } else if (isSingle && relY > rect.height * 0.72) { + // Dropped on bottom edge → split down with this tab this.splitDown(); setTimeout(() => { const newPaneId = this.panes.length - 1; this.transferTab(dragData.paneId, dragData.tabId, newPaneId); - }, 100); - } else if (dragData.paneId !== paneId) { - // Cross-pane transfer (dropped on tab bar or content area of another pane) + }, 150); + } else { + // Cross-pane transfer (dropped on tab bar or empty area of another pane) this.transferTab(dragData.paneId, dragData.tabId, paneId); } } catch (e2) { /* ignore */ } - _edgeZone = null; }); },