From 57e87aace0d4bbd2740de32d38aa5aeb233d3b8e Mon Sep 17 00:00:00 2001 From: Eugene Fox Date: Fri, 18 Jul 2025 21:01:28 +0300 Subject: [PATCH] chore: minor dnd collision detection improvements --- .../sidepanel/utils/dnd/collisionDetector.ts | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/entrypoints/sidepanel/utils/dnd/collisionDetector.ts b/entrypoints/sidepanel/utils/dnd/collisionDetector.ts index b175d20..7e4ec75 100644 --- a/entrypoints/sidepanel/utils/dnd/collisionDetector.ts +++ b/entrypoints/sidepanel/utils/dnd/collisionDetector.ts @@ -33,9 +33,11 @@ export function collisionDetector(vertical?: boolean): CollisionDetection if (activeItem.item.type === "collection") { + // If we drag a collection, we should ignore other items, like tabs or groups if (droppableItem.item.type !== "collection") continue; + // Using distance between centers value = distanceBetween(centerOfRectangle(rect), centerRect); collisions.push({ id, data: { droppableContainer, value } }); continue; @@ -44,14 +46,20 @@ export function collisionDetector(vertical?: boolean): CollisionDetection const intersectionRatio: number = getIntersectionRatio(rect, collisionRect); const intersectionCoefficient: number = intersectionRatio / getMaxIntersectionRatio(rect, collisionRect); + // Dragging a tab or a group over a collection if (droppableItem.item.type === "collection") { + // Ignoring collection, if the tab or the group is inside that collection if (activeItem.indices.length === 2 && activeItem.indices[0] === droppableItem.indices[0]) continue; - if (intersectionCoefficient < 0.7 && activeItem.item.type === "tab") + // Ignoring collection if we're dragging a tab or a group that doesn't belong to the collection, + // but intersection ratio is less than 0.7 + if (intersectionCoefficient < 0.7) continue; + // If we're dragging a tab, that's inside a group that belongs to the collection, + // we substract the group's intersection from the collection's one if (activeItem.indices.length === 3 && activeItem.indices[0] === droppableItem.indices[0]) { const [collectionId, groupId] = activeItem.indices; @@ -62,16 +70,23 @@ export function collisionDetector(vertical?: boolean): CollisionDetection value = 1 / (intersectionRatio - getIntersectionRatio(groupRect, collisionRect)); } + // Otherwise, use intersection ratio + // At this point we're dragging either: + // - a group, that doesn't belong to the collection + // - a tab, that either belongs to the collection's group, or has intersection coefficient >= .7 else { - value = 1 / intersectionRatio; + value = 2 / intersectionRatio; } } + // If we're dragging a tab or a group over another group's dropzone else if (droppableItem.item.type === "group" && (id as string).endsWith("_dropzone")) { + // Ignore, if we're dragging a group if (activeItem.item.type === "group") continue; + // Ignore, if we're dragging a tab, that's inside the group if ( activeItem.indices.length === 3 && activeItem.indices[0] === droppableItem.indices[0] && @@ -79,11 +94,15 @@ export function collisionDetector(vertical?: boolean): CollisionDetection ) continue; + // Ignore, if coefficient is less than .5 + // (at this point we're dragging a tab, that's outside of the group's dropzone) if (intersectionCoefficient < 0.5) continue; + // Use intersection between the tab and the group's dropzone value = 1 / intersectionRatio; } + // We're dragging a group or a tab over its sibling else if (activeItem.indices.length === droppableItem.indices.length) { if (activeItem.indices[0] !== droppableItem.indices[0]) @@ -92,9 +111,22 @@ export function collisionDetector(vertical?: boolean): CollisionDetection if (activeItem.indices.length === 3 && activeItem.indices[1] !== droppableItem.indices[1]) continue; + // Ignore pinned groups if (droppableItem.item.type === "group" && droppableItem.item.pinned === true) continue; + const collectionRect: ClientRect | undefined = droppableRects.get(activeItem.indices[0].toString()); + + if (!collectionRect) + continue; + + const collectionIntersectionRatio: number = getIntersectionRatio(collectionRect, collisionRect); + const collectionIntersectionCoefficient: number = collectionIntersectionRatio / getMaxIntersectionRatio(collectionRect, collisionRect); + + // Ignore if we are outside of the home collection + if (collectionIntersectionCoefficient < 0.7) + continue; + if (activeItem.item.type === "tab" && droppableItem.item.type === "tab") { value = distanceBetween(centerOfRectangle(rect), centerRect);