[fix] Prevent drag activation during Vue node resize (#7064)

## Summary
- Add isResizingVueNodes flag to layoutStore
- Set flag in useNodeResize during resize operation
- Check flag in useNodePointerInteractions to skip drag activation

Fixes a bug where resizing a Vue node after selecting it would
incorrectly trigger drag logic, causing the node to teleport.


┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7064-fix-Prevent-drag-activation-during-Vue-node-resize-2bb6d73d365081a2ad0ad4c7be76afee)
by [Unito](https://www.unito.io)

---------

Co-authored-by: DrJKL <DrJKL0424@gmail.com>
This commit is contained in:
Christian Byrne
2025-11-30 20:23:30 -08:00
committed by GitHub
parent d76c59cb14
commit dfe098897a
5 changed files with 65 additions and 0 deletions

View File

@@ -0,0 +1,54 @@
import {
comfyExpect as expect,
comfyPageFixture as test
} from '../../../../fixtures/ComfyPage'
test.describe('Vue Node Resizing', () => {
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.setSetting('Comfy.VueNodes.Enabled', true)
await comfyPage.vueNodes.waitForNodes()
})
test('should resize node without position drift after selecting', async ({
comfyPage
}) => {
// Get a Vue node fixture
const node = await comfyPage.vueNodes.getFixtureByTitle('Load Checkpoint')
const initialBox = await node.boundingBox()
if (!initialBox) throw new Error('Node bounding box not found')
// Select the node first (this was causing the bug)
await node.header.click()
await comfyPage.page.waitForTimeout(100) // Brief pause after selection
// Get position after selection
const selectedBox = await node.boundingBox()
if (!selectedBox)
throw new Error('Node bounding box not found after select')
// Verify position unchanged after selection
expect(selectedBox.x).toBeCloseTo(initialBox.x, 1)
expect(selectedBox.y).toBeCloseTo(initialBox.y, 1)
// Now resize from bottom-right corner
const resizeStartX = selectedBox.x + selectedBox.width - 5
const resizeStartY = selectedBox.y + selectedBox.height - 5
await comfyPage.page.mouse.move(resizeStartX, resizeStartY)
await comfyPage.page.mouse.down()
await comfyPage.page.mouse.move(resizeStartX + 50, resizeStartY + 30)
await comfyPage.page.mouse.up()
// Get final position and size
const finalBox = await node.boundingBox()
if (!finalBox) throw new Error('Node bounding box not found after resize')
// Position should NOT have changed (the bug was position drift)
expect(finalBox.x).toBeCloseTo(initialBox.x, 1)
expect(finalBox.y).toBeCloseTo(initialBox.y, 1)
// Size should have increased
expect(finalBox.width).toBeGreaterThan(initialBox.width)
expect(finalBox.height).toBeGreaterThan(initialBox.height)
})
})

View File

@@ -138,6 +138,8 @@ class LayoutStoreImpl implements LayoutStore {
// Vue dragging state for selection toolbox (public ref for direct mutation)
public isDraggingVueNodes = ref(false)
// Vue resizing state to prevent drag from activating during resize
public isResizingVueNodes = ref(false)
constructor() {
// Initialize Yjs data structures

View File

@@ -92,12 +92,14 @@ const mockData = vi.hoisted(() => {
vi.mock('@/renderer/core/layout/store/layoutStore', () => {
const isDraggingVueNodes = ref(false)
const isResizingVueNodes = ref(false)
const fakeNodeLayoutRef = ref(mockData.fakeNodeLayout)
const getNodeLayoutRef = vi.fn(() => fakeNodeLayoutRef)
const setSource = vi.fn()
return {
layoutStore: {
isDraggingVueNodes,
isResizingVueNodes,
getNodeLayoutRef,
setSource
}

View File

@@ -63,6 +63,9 @@ export function useNodePointerInteractions(
function onPointermove(event: PointerEvent) {
if (forwardMiddlePointerIfNeeded(event)) return
// Don't activate drag while resizing
if (layoutStore.isResizingVueNodes.value) return
const nodeId = toValue(nodeIdRef)
if (nodeManager.value?.getNode(nodeId)?.flags?.pinned) {

View File

@@ -2,6 +2,7 @@ import { useEventListener } from '@vueuse/core'
import { ref } from 'vue'
import type { Point, Size } from '@/renderer/core/layout/types'
import { layoutStore } from '@/renderer/core/layout/store/layoutStore'
import { useNodeSnap } from '@/renderer/extensions/vueNodes/composables/useNodeSnap'
import { useShiftKeySync } from '@/renderer/extensions/vueNodes/composables/useShiftKeySync'
import { useTransformState } from '@/renderer/core/layout/transform/useTransformState'
@@ -55,6 +56,8 @@ export function useNodeResize(
// Capture pointer to ensure we get all move/up events
target.setPointerCapture(event.pointerId)
// Mark as resizing to prevent drag from activating
layoutStore.isResizingVueNodes.value = true
isResizing.value = true
resizeStartPointer.value = { x: event.clientX, y: event.clientY }
resizeStartSize.value = startSize
@@ -93,6 +96,7 @@ export function useNodeResize(
const handlePointerUp = (upEvent: PointerEvent) => {
if (isResizing.value) {
isResizing.value = false
layoutStore.isResizingVueNodes.value = false
resizeStartPointer.value = null
resizeStartSize.value = null