mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-06 21:50:05 +00:00
[fix] Enable mouse gestures over video previews (#5279)
* [fix] Enable mouse gestures over video previews - fixes ctrl+scroll zoom and space+drag panning 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * [improve] Enhance code clarity in media gesture handling with descriptive constants * [clean] Remove dangling comment in handlePointer method * [improve] Use satisfies and partial mocking for better type safety in tests - Replace 'as any' with vi.mocked({partial: true}) for store mocks - Use 'satisfies Partial<Event>' for better event type checking - Remove 'not.toThrow' test as it tests default behavior - Improve test readability and type safety per review feedback * [improve] Test actual canvas existence check instead of side effects - Replace vague 'graceful handling' test with specific 'early return' test - Verify that getCanvas() is actually called to check canvas existence - Test early return behavior when canvas is null rather than just preventDefault side effect - More robust test that validates the intended logic flow * [refactor] Use localized mocking instead of global mock functions - Replace global mockGetCanvas and mockGet with in-situ vi.mocked() calls - Extract store functions directly in test cases for better locality - Follow DrJKL's suggestion for cleaner test structure - Maintains same test coverage with improved readability --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { computed } from 'vue'
|
||||
|
||||
import { app } from '@/scripts/app'
|
||||
import { useCanvasStore } from '@/stores/graphStore'
|
||||
import { useSettingStore } from '@/stores/settingStore'
|
||||
|
||||
/**
|
||||
@@ -10,6 +11,7 @@ import { useSettingStore } from '@/stores/settingStore'
|
||||
*/
|
||||
export function useCanvasInteractions() {
|
||||
const settingStore = useSettingStore()
|
||||
const { getCanvas } = useCanvasStore()
|
||||
|
||||
const isStandardNavMode = computed(
|
||||
() => settingStore.get('Comfy.Canvas.NavigationMode') === 'standard'
|
||||
@@ -37,6 +39,27 @@ export function useCanvasInteractions() {
|
||||
// Otherwise, let the component handle it normally
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles pointer events from media elements that should potentially
|
||||
* be forwarded to canvas (e.g., space+drag for panning)
|
||||
*/
|
||||
const handlePointer = (event: PointerEvent) => {
|
||||
// Check if canvas exists using established pattern
|
||||
const canvas = getCanvas()
|
||||
if (!canvas) return
|
||||
|
||||
// Check conditions for forwarding events to canvas
|
||||
const isSpacePanningDrag = canvas.read_only && event.buttons === 1 // Space key pressed + left mouse drag
|
||||
const isMiddleMousePanning = event.buttons === 4 // Middle mouse button for panning
|
||||
|
||||
if (isSpacePanningDrag || isMiddleMousePanning) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
forwardEventToCanvas(event)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards an event to the LiteGraph canvas
|
||||
*/
|
||||
@@ -54,6 +77,7 @@ export function useCanvasInteractions() {
|
||||
|
||||
return {
|
||||
handleWheel,
|
||||
handlePointer,
|
||||
forwardEventToCanvas
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { useCanvasInteractions } from '@/composables/graph/useCanvasInteractions'
|
||||
import type { LGraphNode } from '@/lib/litegraph/src/litegraph'
|
||||
import { useNodeOutputStore } from '@/stores/imagePreviewStore'
|
||||
import { fitDimensionsToNodeWidth } from '@/utils/imageUtil'
|
||||
@@ -130,6 +131,8 @@ export const useNodeVideo = (node: LGraphNode) => {
|
||||
let minHeight = DEFAULT_VIDEO_SIZE
|
||||
let minWidth = DEFAULT_VIDEO_SIZE
|
||||
|
||||
const { handleWheel, handlePointer } = useCanvasInteractions()
|
||||
|
||||
const setMinDimensions = (video: HTMLVideoElement) => {
|
||||
const { minHeight: calculatedHeight, minWidth: calculatedWidth } =
|
||||
fitDimensionsToNodeWidth(
|
||||
@@ -146,6 +149,12 @@ export const useNodeVideo = (node: LGraphNode) => {
|
||||
new Promise((resolve) => {
|
||||
const video = document.createElement('video')
|
||||
Object.assign(video, VIDEO_DEFAULT_OPTIONS)
|
||||
|
||||
// Add event listeners for canvas interactions
|
||||
video.addEventListener('wheel', handleWheel)
|
||||
video.addEventListener('pointermove', handlePointer)
|
||||
video.addEventListener('pointerdown', handlePointer)
|
||||
|
||||
video.onloadeddata = () => {
|
||||
setMinDimensions(video)
|
||||
resolve(video)
|
||||
|
||||
Reference in New Issue
Block a user