fix: allow URI drops to bubble from Vue nodes to document handler

Remove unconditional .stop on @drop in LGraphNode.vue so URI-list
drags (e.g. <img> elements) can reach the document-level fallback in
app.ts. stopPropagation is now called only when onDragDrop returns
true (file drop handled). Also made handleDrop synchronous since
onDragDrop returns a plain boolean.
This commit is contained in:
bymyself
2026-03-05 22:44:25 -08:00
parent 1ee75332b3
commit 7a74661e57
2 changed files with 56 additions and 8 deletions

View File

@@ -13,7 +13,13 @@ import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
import { setActivePinia } from 'pinia'
const mockData = vi.hoisted(() => ({
mockExecuting: false
mockExecuting: false,
mockLgraphNode: null as Record<string, unknown> | null
}))
vi.mock('@/utils/graphTraversalUtil', () => ({
getLocatorIdFromNodeData: vi.fn(() => 'test-node-123'),
getNodeByLocatorId: vi.fn(() => mockData.mockLgraphNode)
}))
vi.mock('@/renderer/core/layout/transform/useTransformState', () => {
@@ -293,4 +299,48 @@ describe('LGraphNode', () => {
expect(wrapper.find('[role="button"][aria-label]').exists()).toBe(true)
})
})
describe('handleDrop', () => {
it('should stop propagation when onDragDrop returns true', async () => {
const onDragDrop = vi.fn().mockReturnValue(true)
mockData.mockLgraphNode = {
onDragDrop,
onDragOver: vi.fn(),
isSubgraphNode: () => false
}
const wrapper = mountLGraphNode({ nodeData: mockNodeData })
const parentListener = vi.fn()
wrapper.element.parentElement?.addEventListener('drop', parentListener)
wrapper.element.dispatchEvent(
new Event('drop', { bubbles: true, cancelable: true })
)
expect(onDragDrop).toHaveBeenCalled()
expect(parentListener).not.toHaveBeenCalled()
})
it('should not stop propagation when onDragDrop returns false', async () => {
const onDragDrop = vi.fn().mockReturnValue(false)
mockData.mockLgraphNode = {
onDragDrop,
onDragOver: vi.fn(),
isSubgraphNode: () => false
}
const wrapper = mountLGraphNode({ nodeData: mockNodeData })
const parentListener = vi.fn()
wrapper.element.parentElement?.addEventListener('drop', parentListener)
wrapper.element.dispatchEvent(
new Event('drop', { bubbles: true, cancelable: true })
)
expect(onDragDrop).toHaveBeenCalled()
expect(parentListener).toHaveBeenCalled()
})
})
})

View File

@@ -33,7 +33,7 @@
@contextmenu="handleContextMenu"
@dragover.prevent="handleDragOver"
@dragleave="handleDragLeave"
@drop.stop.prevent="handleDrop"
@drop.prevent="handleDrop"
>
<!-- Selection/Execution Outline Overlay -->
<AppOutput
@@ -825,15 +825,13 @@ function handleDragLeave() {
isDraggingOver.value = false
}
async function handleDrop(event: DragEvent) {
function handleDrop(event: DragEvent) {
isDraggingOver.value = false
const node = lgraphNode.value
if (!node || !node.onDragDrop) {
return
}
if (!node?.onDragDrop) return
// Forward the drop event to the litegraph node's onDragDrop callback
await node.onDragDrop(event)
const handled = node.onDragDrop(event)
if (handled) event.stopPropagation()
}
</script>