mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-23 22:25:05 +00:00
Backport of #11493 to `core/1.44` Automatically created by backport workflow. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-12129-backport-core-1-44-fix-Load-Image-preview-retains-deleted-asset-FE-230-35d6d73d36508157ada3db9f8416e113) by [Unito](https://www.unito.io) Co-authored-by: Dante <bunggl@naver.com>
66 lines
2.4 KiB
TypeScript
66 lines
2.4 KiB
TypeScript
import type {
|
|
LGraph,
|
|
LGraphNode,
|
|
Subgraph
|
|
} from '@/lib/litegraph/src/litegraph'
|
|
import { collectAllNodes } from '@/utils/graphTraversalUtil'
|
|
|
|
/**
|
|
* Clear cached Load Image / Load Video preview state on any node whose widget
|
|
* value matches one of the given values. Covers:
|
|
* - the canvas renderer cache (`node.imgs`, `node.videoContainer`)
|
|
* - the Vue preview source — must be cleared via `removeOutputsForNode`
|
|
* so the Pinia reactive ref (`nodeOutputStore.nodeOutputs.value`) updates,
|
|
* not just the legacy `app.nodeOutputs` mirror
|
|
*
|
|
* Comparison is full-string against the widget value as stored — callers must
|
|
* provide the canonical widget-value variants for each deleted asset (e.g.
|
|
* `foo.png`, `foo.png [output]`, `sub/foo.png [output]`, `<asset_hash>`). This
|
|
* avoids false matches when two distinct assets share a basename across
|
|
* input/output sources.
|
|
*
|
|
* Walks the full graph hierarchy via `collectAllNodes`, so Load Image / Load
|
|
* Video nodes inside subgraphs are also matched.
|
|
*
|
|
* FE-230 — invoked after successful asset deletion so the Load Image / Load
|
|
* Video node preview does not keep displaying a thumbnail for an asset that
|
|
* no longer exists.
|
|
*/
|
|
export function clearNodePreviewCacheForValues(
|
|
rootGraph: LGraph | Subgraph,
|
|
deletedValues: ReadonlySet<string>,
|
|
removeOutputsForNode: (node: LGraphNode) => void
|
|
): void {
|
|
if (deletedValues.size === 0) return
|
|
for (const node of findNodesReferencingValues(rootGraph, deletedValues)) {
|
|
removeOutputsForNode(node)
|
|
node.imgs = undefined
|
|
node.videoContainer = undefined
|
|
node.graph?.setDirtyCanvas(true)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Walk the graph hierarchy and yield each leaf node whose widget value matches
|
|
* one of `deletedValues`. Used by both the preview-clearing path and the
|
|
* missing-media-marking path so the two stay in lockstep.
|
|
*
|
|
* Skips subgraph wrapper nodes — only their interior nodes are inspected.
|
|
*/
|
|
export function findNodesReferencingValues(
|
|
rootGraph: LGraph | Subgraph,
|
|
deletedValues: ReadonlySet<string>
|
|
): LGraphNode[] {
|
|
if (deletedValues.size === 0) return []
|
|
const matches: LGraphNode[] = []
|
|
for (const node of collectAllNodes(rootGraph)) {
|
|
if (!node.widgets?.length) continue
|
|
if (node.isSubgraphNode?.()) continue
|
|
const referencesDeleted = node.widgets.some(
|
|
(w) => typeof w.value === 'string' && deletedValues.has(w.value)
|
|
)
|
|
if (referencesDeleted) matches.push(node)
|
|
}
|
|
return matches
|
|
}
|