fix(terminal): add collision detection for terminal drag and drop reordering (#985)

* fix(terminal): add collision detection for terminal drag and drop reordering

Add closestCenter collision detection to DndContext to fix terminal
drag and drop swapping not detecting valid drop targets. The default
rectIntersection algorithm required too much overlap for grid layouts.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(terminal): handle file drops when closestCenter returns sortable ID

Address PR review feedback:
- Fix file drop handling to work when closestCenter collision detection
  returns the sortable ID instead of the droppable ID
- Add terminals to useCallback dependency array to prevent stale state

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Andy
2026-01-12 23:45:15 +01:00
committed by AndyMik90
parent 74ed4320d9
commit 1701160b8a
@@ -12,7 +12,8 @@ import {
PointerSensor,
KeyboardSensor,
useSensor,
useSensors
useSensors,
closestCenter,
} from '@dnd-kit/core';
import {
SortableContext,
@@ -292,17 +293,22 @@ export function TerminalGrid({ projectPath, onNewTaskClick, isActive = false }:
// Handle file drop on terminal
const overId = over.id.toString();
if (overId.startsWith('terminal-')) {
const terminalId = overId.replace('terminal-', '');
let terminalId: string | null = null;
if (activeData?.path) {
// Quote the path if it contains spaces
const quotedPath = activeData.path.includes(' ') ? `"${activeData.path}"` : activeData.path;
// Insert the file path into the terminal with a trailing space
window.electronAPI.sendTerminalInput(terminalId, quotedPath + ' ');
}
if (overId.startsWith('terminal-')) {
terminalId = overId.replace('terminal-', '');
} else if (terminals.some(t => t.id === overId)) {
// closestCenter might return the sortable ID instead of droppable ID
terminalId = overId;
}
}, [reorderTerminals]);
if (terminalId && activeData?.path) {
// Quote the path if it contains spaces
const quotedPath = activeData.path.includes(' ') ? `"${activeData.path}"` : activeData.path;
// Insert the file path into the terminal with a trailing space
window.electronAPI.sendTerminalInput(terminalId, quotedPath + ' ');
}
}, [reorderTerminals, terminals]);
// Calculate grid layout based on number of terminals
const gridLayout = useMemo(() => {
@@ -358,6 +364,7 @@ export function TerminalGrid({ projectPath, onNewTaskClick, isActive = false }:
return (
<DndContext
sensors={sensors}
collisionDetection={closestCenter}
onDragStart={handleDragStart}
onDragEnd={handleDragEnd}
>