mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-01-26 19:09:52 +00:00
[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:
@@ -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)
|
||||
})
|
||||
})
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user