Make node locate race-safe and graph-switch-aware

This commit is contained in:
Dariusz L
2026-06-22 00:18:41 +02:00
parent 8d63fb8f2a
commit ff95a2bd1e
+46 -3
View File
@@ -238,13 +238,16 @@ export const lifecycleGraphMethods = {
/**
* Locate and focus a node in the ComfyUI canvas
*/
locateNodeInGraph(nodeId, options = {}) {
async locateNodeInGraph(nodeId, options = {}) {
try {
if (!app?.graph) {
this.showNotification('Cannot locate node - graph not available', 'error');
return;
}
const locateToken = `${Date.now()}-${Math.random().toString(36).slice(2)}`;
this._locateRequestToken = locateToken;
const locateOptions = typeof options === 'string'
? { subgraphId: options }
: (options || {});
@@ -255,7 +258,15 @@ export const lifecycleGraphMethods = {
return;
}
this.activateGraphForLocate(target);
await this.activateGraphForLocate(target);
await this.waitForLocateGraphReady(target.graph);
if (this._locateRequestToken !== locateToken) return;
if (app.canvas?.graph !== target.graph) {
this.setActiveCanvasGraph(target.graph);
await this.waitForLocateGraphReady(target.graph);
if (this._locateRequestToken !== locateToken) return;
}
const node = target.node;
const graph = target.graph || node.graph || app.canvas?.graph || app.graph;
@@ -311,6 +322,34 @@ export const lifecycleGraphMethods = {
}
},
waitForLocateGraphReady(graph, { settleFrames = 3, timeoutMs = 600 } = {}) {
return new Promise(resolve => {
const start = performance.now();
let stableFrames = 0;
const tick = () => {
if (app?.canvas?.graph === graph) {
stableFrames += 1;
if (stableFrames >= settleFrames) {
resolve(true);
return;
}
} else {
stableFrames = 0;
}
if (performance.now() - start >= timeoutMs) {
resolve(false);
return;
}
requestAnimationFrame(tick);
};
requestAnimationFrame(tick);
});
},
findLocateTarget(nodeId, options = {}) {
const rootGraph = app?.graph;
if (!rootGraph) return null;
@@ -452,7 +491,7 @@ export const lifecycleGraphMethods = {
return walk(rootGraph, []) || fallback;
},
activateGraphForLocate(target) {
async activateGraphForLocate(target) {
const canvas = app?.canvas;
if (!canvas || !target?.graph) return false;
@@ -460,18 +499,22 @@ export const lifecycleGraphMethods = {
for (const step of path) {
if (step.parentGraph && canvas.graph !== step.parentGraph) {
this.setActiveCanvasGraph(step.parentGraph);
await this.waitForLocateGraphReady(step.parentGraph, { settleFrames: 2, timeoutMs: 500 });
}
if (step.node?.subgraph && canvas.graph !== step.node.subgraph) {
const opened = this.openSubgraphNodeForLocate(step.node);
await this.waitForLocateGraphReady(step.node.subgraph, { settleFrames: 2, timeoutMs: 500 });
if (!opened || canvas.graph !== step.node.subgraph) {
this.setActiveCanvasGraph(step.node.subgraph);
await this.waitForLocateGraphReady(step.node.subgraph, { settleFrames: 2, timeoutMs: 500 });
}
}
}
if (canvas.graph !== target.graph) {
this.setActiveCanvasGraph(target.graph);
await this.waitForLocateGraphReady(target.graph, { settleFrames: 2, timeoutMs: 500 });
}
return canvas.graph === target.graph;