Skip to content

Commit 1234e1c

Browse files
authored
Support Right Click -> Save for animated webp (#6095)
Allow for Right Click -> Save Image to work for the "SaveAnimatedWEBP" node. Fixing this revealed other existing issues: - Attempting to resize the node causes runaway scaling - Right clicking on the image directly causes a browser context menu without a save option. Significant rewriting has been performed to resolve both of these issues. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-6095-Support-Right-Click-Save-for-animated-webp-28e6d73d3650818e85a2ec58c38c2aae) by [Unito](https://www.unito.io)
1 parent 984ebef commit 1234e1c

File tree

2 files changed

+33
-32
lines changed

2 files changed

+33
-32
lines changed

src/composables/node/useNodeAnimatedImage.ts

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import type { LGraphNode } from '@/lib/litegraph/src/litegraph'
2-
import type { IWidget } from '@/lib/litegraph/src/types/widgets'
2+
import { useCanvasInteractions } from '@/renderer/core/canvas/useCanvasInteractions'
33
import { ANIM_PREVIEW_WIDGET } from '@/scripts/app'
4-
import { createImageHost } from '@/scripts/ui/imagePreview'
5-
import { fitDimensionsToNodeWidth } from '@/utils/imageUtil'
4+
import { isDOMWidget } from '@/scripts/domWidget'
65

76
/**
87
* Composable for handling animated image previews in nodes
@@ -20,38 +19,38 @@ export function useNodeAnimatedImage() {
2019
(w) => w.name === ANIM_PREVIEW_WIDGET
2120
)
2221

22+
node.imgs[0].classList.value = 'block size-full object-contain'
2323
if (widgetIdx > -1) {
2424
// Replace content in existing widget
25-
const widget = node.widgets[widgetIdx] as IWidget & {
26-
options: { host: ReturnType<typeof createImageHost> }
27-
}
28-
widget.options.host.updateImages(node.imgs)
25+
const widget = node.widgets[widgetIdx]
26+
if (!isDOMWidget(widget)) return
27+
widget.element.replaceChildren(node.imgs[0])
2928
} else {
3029
// Create new widget
31-
const host = createImageHost(node)
32-
// @ts-expect-error host is not a standard DOM widget option.
33-
const widget = node.addDOMWidget(ANIM_PREVIEW_WIDGET, 'img', host.el, {
34-
host,
35-
// @ts-expect-error `getHeight` of image host returns void instead of number.
36-
getHeight: host.getHeight,
37-
onDraw: host.onDraw,
30+
const element = document.createElement('div')
31+
element.appendChild(node.imgs[0])
32+
const widget = node.addDOMWidget(ANIM_PREVIEW_WIDGET, 'img', element, {
3833
hideOnZoom: false
39-
}) as IWidget & {
40-
options: { host: ReturnType<typeof createImageHost> }
41-
}
34+
})
35+
node.overIndex = 0
36+
37+
// Add event listeners for canvas interactions
38+
const { handleWheel, handlePointer, forwardEventToCanvas } =
39+
useCanvasInteractions()
40+
node.imgs[0].style.pointerEvents = 'none'
41+
element.addEventListener('wheel', handleWheel)
42+
element.addEventListener('pointermove', handlePointer)
43+
element.addEventListener('pointerup', handlePointer)
44+
element.addEventListener(
45+
'pointerdown',
46+
(e) => {
47+
return e.button !== 2 ? handlePointer(e) : forwardEventToCanvas(e)
48+
},
49+
true
50+
)
51+
4252
widget.serialize = false
4353
widget.serializeValue = () => undefined
44-
widget.options.host.updateImages(node.imgs)
45-
widget.computeLayoutSize = () => {
46-
const img = widget.options.host.getCurrentImage()
47-
if (!img) return { minHeight: 0, minWidth: 0 }
48-
49-
return fitDimensionsToNodeWidth(
50-
img.naturalWidth,
51-
img.naturalHeight,
52-
node.size?.[0] || 0
53-
)
54-
}
5554
}
5655
}
5756

src/scripts/ui/imagePreview.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
2+
13
import { app } from '../app'
24
import { $el } from '../ui'
35

@@ -48,8 +50,8 @@ export function calculateImageGrid(
4850
return { cellWidth, cellHeight, cols, rows, shiftX }
4951
}
5052

51-
// @ts-expect-error fixme ts strict error
52-
export function createImageHost(node) {
53+
/** @knipIgnoreUnusedButUsedByCustomNodes */
54+
export function createImageHost(node: LGraphNode) {
5355
const el = $el('div.comfy-img-preview')
5456
// @ts-expect-error fixme ts strict error
5557
let currentImgs
@@ -108,8 +110,8 @@ export function createImageHost(node) {
108110
}
109111
el.replaceChildren(...imgs)
110112
currentImgs = imgs
111-
node.onResize(node.size)
112-
node.graph.setDirtyCanvas(true, true)
113+
node.onResize?.(node.size)
114+
node.graph?.setDirtyCanvas(true, true)
113115
}
114116
},
115117
getHeight() {

0 commit comments

Comments
 (0)