ui.js 16 KB
Newer Older
1
2
import { api } from "./api.js";
import { ComfyDialog as _ComfyDialog } from "./ui/dialog.js";
pythongosssss's avatar
pythongosssss committed
3
import { toggleSwitch } from "./ui/toggleSwitch.js";
4
5
6
import { ComfySettingsDialog } from "./ui/settings.js";

export const ComfyDialog = _ComfyDialog;
pythongosssss's avatar
pythongosssss committed
7

pythongosssss's avatar
pythongosssss committed
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
 * 
 * @param { string } tag HTML Element Tag and optional classes e.g. div.class1.class2
 * @param { string | Element | Element[] | {
 * 	 parent?: Element,
 *   $?: (el: Element) => void, 
 *   dataset?: DOMStringMap,
 *   style?: CSSStyleDeclaration,
 * 	 for?: string
 * } | undefined } propsOrChildren 
 * @param { Element[] | undefined } [children]
 * @returns 
 */
Jairo Correa's avatar
Jairo Correa committed
21
export function $el(tag, propsOrChildren, children) {
pythongosssss's avatar
pythongosssss committed
22
23
	const split = tag.split(".");
	const element = document.createElement(split.shift());
reaper47's avatar
reaper47 committed
24
25
26
27
	if (split.length > 0) {
		element.classList.add(...split);
	}

pythongosssss's avatar
pythongosssss committed
28
	if (propsOrChildren) {
pythongosssss's avatar
pythongosssss committed
29
30
31
32
33
		if (typeof propsOrChildren === "string") {
			propsOrChildren = { textContent: propsOrChildren };
		} else if (propsOrChildren instanceof Element) {
			propsOrChildren = [propsOrChildren];
		}
pythongosssss's avatar
pythongosssss committed
34
35
36
		if (Array.isArray(propsOrChildren)) {
			element.append(...propsOrChildren);
		} else {
reaper47's avatar
reaper47 committed
37
			const {parent, $: cb, dataset, style} = propsOrChildren;
pythongosssss's avatar
pythongosssss committed
38
39
			delete propsOrChildren.parent;
			delete propsOrChildren.$;
40
41
			delete propsOrChildren.dataset;
			delete propsOrChildren.style;
pythongosssss's avatar
pythongosssss committed
42

reaper47's avatar
reaper47 committed
43
44
45
46
			if (Object.hasOwn(propsOrChildren, "for")) {
				element.setAttribute("for", propsOrChildren.for)
			}

47
48
49
50
51
52
			if (style) {
				Object.assign(element.style, style);
			}

			if (dataset) {
				Object.assign(element.dataset, dataset);
pythongosssss's avatar
pythongosssss committed
53
54
			}

pythongosssss's avatar
pythongosssss committed
55
56
			Object.assign(element, propsOrChildren);
			if (children) {
pythongosssss's avatar
pythongosssss committed
57
				element.append(...(children instanceof Array ? children : [children]));
pythongosssss's avatar
pythongosssss committed
58
59
60
61
62
63
64
65
66
67
68
69
70
71
			}

			if (parent) {
				parent.append(element);
			}

			if (cb) {
				cb(element);
			}
		}
	}
	return element;
}

72
function dragElement(dragEl, settings) {
73
74
75
76
77
78
	var posDiffX = 0,
		posDiffY = 0,
		posStartX = 0,
		posStartY = 0,
		newPosX = 0,
		newPosY = 0;
79
	if (dragEl.getElementsByClassName("drag-handle")[0]) {
Jairo Correa's avatar
Jairo Correa committed
80
		// if present, the handle is where you move the DIV from:
81
		dragEl.getElementsByClassName("drag-handle")[0].onmousedown = dragMouseDown;
Jairo Correa's avatar
Jairo Correa committed
82
83
84
85
86
	} else {
		// otherwise, move the DIV from anywhere inside the DIV:
		dragEl.onmousedown = dragMouseDown;
	}

pythongosssss's avatar
pythongosssss committed
87
88
89
90
91
	// When the element resizes (e.g. view queue) ensure it is still in the windows bounds
	const resizeObserver = new ResizeObserver(() => {
		ensureInBounds();
	}).observe(dragEl);

92
	function ensureInBounds() {
pythongosssss's avatar
pythongosssss committed
93
		if (dragEl.classList.contains("comfy-menu-manual-pos")) {
pythongosssss's avatar
pythongosssss committed
94
95
			newPosX = Math.min(document.body.clientWidth - dragEl.clientWidth, Math.max(0, dragEl.offsetLeft));
			newPosY = Math.min(document.body.clientHeight - dragEl.clientHeight, Math.max(0, dragEl.offsetTop));
96

pythongosssss's avatar
pythongosssss committed
97
98
			positionElement();
		}
pythongosssss's avatar
pythongosssss committed
99
	}
100
101
102
103
104
105
106
107
108
109
110
111
112

	function positionElement() {
		const halfWidth = document.body.clientWidth / 2;
		const anchorRight = newPosX + dragEl.clientWidth / 2 > halfWidth;

		// set the element's new position:
		if (anchorRight) {
			dragEl.style.left = "unset";
			dragEl.style.right = document.body.clientWidth - newPosX - dragEl.clientWidth + "px";
		} else {
			dragEl.style.left = newPosX + "px";
			dragEl.style.right = "unset";
		}
113

pythongosssss's avatar
pythongosssss committed
114
115
		dragEl.style.top = newPosY + "px";
		dragEl.style.bottom = "unset";
116
117
118
119
120

		if (savePos) {
			localStorage.setItem(
				"Comfy.MenuPosition",
				JSON.stringify({
pythongosssss's avatar
pythongosssss committed
121
122
					x: dragEl.offsetLeft,
					y: dragEl.offsetTop,
123
124
125
126
127
128
129
130
131
				})
			);
		}
	}

	function restorePos() {
		let pos = localStorage.getItem("Comfy.MenuPosition");
		if (pos) {
			pos = JSON.parse(pos);
pythongosssss's avatar
pythongosssss committed
132
133
134
			newPosX = pos.x;
			newPosY = pos.y;
			positionElement();
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
			ensureInBounds();
		}
	}

	let savePos = undefined;
	settings.addSetting({
		id: "Comfy.MenuPosition",
		name: "Save menu position",
		type: "boolean",
		defaultValue: savePos,
		onChange(value) {
			if (savePos === undefined && value) {
				restorePos();
			}
			savePos = value;
		},
	});
reaper47's avatar
reaper47 committed
152

Jairo Correa's avatar
Jairo Correa committed
153
154
155
156
	function dragMouseDown(e) {
		e = e || window.event;
		e.preventDefault();
		// get the mouse cursor position at startup:
157
158
		posStartX = e.clientX;
		posStartY = e.clientY;
Jairo Correa's avatar
Jairo Correa committed
159
160
161
162
163
164
165
166
		document.onmouseup = closeDragElement;
		// call a function whenever the cursor moves:
		document.onmousemove = elementDrag;
	}

	function elementDrag(e) {
		e = e || window.event;
		e.preventDefault();
167
168
169

		dragEl.classList.add("comfy-menu-manual-pos");

Jairo Correa's avatar
Jairo Correa committed
170
		// calculate the new cursor position:
171
172
173
174
		posDiffX = e.clientX - posStartX;
		posDiffY = e.clientY - posStartY;
		posStartX = e.clientX;
		posStartY = e.clientY;
175
176
177
178
179

		newPosX = Math.min(document.body.clientWidth - dragEl.clientWidth, Math.max(0, dragEl.offsetLeft + posDiffX));
		newPosY = Math.min(document.body.clientHeight - dragEl.clientHeight, Math.max(0, dragEl.offsetTop + posDiffY));

		positionElement();
Jairo Correa's avatar
Jairo Correa committed
180
181
	}

182
	window.addEventListener("resize", () => {
183
		ensureInBounds();
184
185
	});

Jairo Correa's avatar
Jairo Correa committed
186
187
188
189
190
191
192
	function closeDragElement() {
		// stop moving when mouse button is released:
		document.onmouseup = null;
		document.onmousemove = null;
	}
}

pythongosssss's avatar
pythongosssss committed
193
class ComfyList {
pythongosssss's avatar
pythongosssss committed
194
195
	#type;
	#text;
196
	#reverse;
pythongosssss's avatar
pythongosssss committed
197

198
	constructor(text, type, reverse) {
pythongosssss's avatar
pythongosssss committed
199
200
		this.#text = text;
		this.#type = type || text.toLowerCase();
201
		this.#reverse = reverse || false;
pythongosssss's avatar
pythongosssss committed
202
		this.element = $el("div.comfy-list");
pythongosssss's avatar
pythongosssss committed
203
204
205
206
207
208
209
210
		this.element.style.display = "none";
	}

	get visible() {
		return this.element.style.display !== "none";
	}

	async load() {
pythongosssss's avatar
pythongosssss committed
211
212
213
214
215
216
217
		const items = await api.getItems(this.#type);
		this.element.replaceChildren(
			...Object.keys(items).flatMap((section) => [
				$el("h4", {
					textContent: section,
				}),
				$el("div.comfy-list-items", [
218
					...(this.#reverse ? items[section].reverse() : items[section]).map((item) => {
pythongosssss's avatar
pythongosssss committed
219
220
221
222
223
						// Allow items to specify a custom remove action (e.g. for interrupt current prompt)
						const removeAction = item.remove || {
							name: "Delete",
							cb: () => api.deleteItem(this.#type, item.prompt[1]),
						};
reaper47's avatar
reaper47 committed
224
						return $el("div", {textContent: item.prompt[0] + ": "}, [
pythongosssss's avatar
pythongosssss committed
225
226
							$el("button", {
								textContent: "Load",
pythongosssss's avatar
pythongosssss committed
227
228
								onclick: async () => {
									await app.loadGraphData(item.prompt[3].extra_pnginfo.workflow);
pythongosssss's avatar
pythongosssss committed
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
									if (item.outputs) {
										app.nodeOutputs = item.outputs;
									}
								},
							}),
							$el("button", {
								textContent: removeAction.name,
								onclick: async () => {
									await removeAction.cb();
									await this.update();
								},
							}),
						]);
					}),
				]),
			]),
			$el("div.comfy-list-actions", [
				$el("button", {
					textContent: "Clear " + this.#text,
					onclick: async () => {
						await api.clearItems(this.#type);
						await this.load();
					},
				}),
reaper47's avatar
reaper47 committed
253
				$el("button", {textContent: "Refresh", onclick: () => this.load()}),
pythongosssss's avatar
pythongosssss committed
254
255
			])
		);
pythongosssss's avatar
pythongosssss committed
256
257
258
259
260
261
262
263
264
265
	}

	async update() {
		if (this.visible) {
			await this.load();
		}
	}

	async show() {
		this.element.style.display = "block";
pythongosssss's avatar
pythongosssss committed
266
267
		this.button.textContent = "Close";

pythongosssss's avatar
pythongosssss committed
268
269
270
271
272
		await this.load();
	}

	hide() {
		this.element.style.display = "none";
comfyanonymous's avatar
comfyanonymous committed
273
		this.button.textContent = "View " + this.#text;
pythongosssss's avatar
pythongosssss committed
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
	}

	toggle() {
		if (this.visible) {
			this.hide();
			return false;
		} else {
			this.show();
			return true;
		}
	}
}

export class ComfyUI {
	constructor(app) {
		this.app = app;
		this.dialog = new ComfyDialog();
291
		this.settings = new ComfySettingsDialog(app);
pythongosssss's avatar
pythongosssss committed
292

m957ymj75urz's avatar
m957ymj75urz committed
293
		this.batchCount = 1;
comfyanonymous's avatar
comfyanonymous committed
294
		this.lastQueueSize = 0;
pythongosssss's avatar
pythongosssss committed
295
		this.queue = new ComfyList("Queue");
296
		this.history = new ComfyList("History", "history", true);
pythongosssss's avatar
pythongosssss committed
297

pythongosssss's avatar
pythongosssss committed
298
299
300
301
		api.addEventListener("status", () => {
			this.queue.update();
			this.history.update();
		});
pythongosssss's avatar
pythongosssss committed
302

303
304
305
306
307
308
		const confirmClear = this.settings.addSetting({
			id: "Comfy.ConfirmClear",
			name: "Require confirmation when clearing workflow",
			type: "boolean",
			defaultValue: true,
		});
309

310
311
312
313
314
315
316
		const promptFilename = this.settings.addSetting({
			id: "Comfy.PromptFilename",
			name: "Prompt for filename when saving workflow",
			type: "boolean",
			defaultValue: true,
		});

317
318
319
		/**
		 * file format for preview
		 *
320
		 * format;quality
321
322
		 *
		 * ex)
323
		 * webp;50 -> webp, quality 50
324
325
326
327
328
329
		 * jpeg;80 -> rgb, jpeg, quality 80
		 *
		 * @type {string}
		 */
		const previewImage = this.settings.addSetting({
			id: "Comfy.PreviewFormat",
reaper47's avatar
reaper47 committed
330
331
			name: "When displaying a preview in the image widget, convert it to a lightweight image, e.g. webp, jpeg, webp;50, etc.",
			type: "text",
332
333
334
			defaultValue: "",
		});

335
336
337
338
339
340
341
		this.settings.addSetting({
			id: "Comfy.DisableSliders",
			name: "Disable sliders.",
			type: "boolean",
			defaultValue: false,
		});

342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
		this.settings.addSetting({
			id: "Comfy.DisableFloatRounding",
			name: "Disable rounding floats (requires page reload).",
			type: "boolean",
			defaultValue: false,
		});

		this.settings.addSetting({
			id: "Comfy.FloatRoundingPrecision",
			name: "Decimal places [0 = auto] (requires page reload).",
			type: "slider",
			attrs: {
				min: 0,
				max: 6,
				step: 1,
			},
			defaultValue: 0,
		});

pythongosssss's avatar
pythongosssss committed
361
		const fileInput = $el("input", {
362
			id: "comfy-file-input",
pythongosssss's avatar
pythongosssss committed
363
			type: "file",
364
			accept: ".json,image/png,.latent,.safetensors,image/webp",
reaper47's avatar
reaper47 committed
365
			style: {display: "none"},
pythongosssss's avatar
pythongosssss committed
366
367
368
369
			parent: document.body,
			onchange: () => {
				app.handleFile(fileInput.files[0]);
			},
pythongosssss's avatar
pythongosssss committed
370
		});
pythongosssss's avatar
pythongosssss committed
371

pythongosssss's avatar
pythongosssss committed
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
		const autoQueueModeEl = toggleSwitch(
			"autoQueueMode",
			[
				{ text: "instant", tooltip: "A new prompt will be queued as soon as the queue reaches 0" },
				{ text: "change", tooltip: "A new prompt will be queued when the queue is at 0 and the graph is/has changed" },
			],
			{
				onChange: (value) => {
					this.autoQueueMode = value.item.value;
				},
			}
		);
		autoQueueModeEl.style.display = "none";

		api.addEventListener("graphChanged", () => {
			if (this.autoQueueMode === "change") {
				if (this.lastQueueSize === 0) {
					this.graphHasChanged = false;
					app.queuePrompt(0, this.batchCount);
				} else {
					this.graphHasChanged = true;
				}
			}
		});

reaper47's avatar
reaper47 committed
397
398
399
400
401
402
403
404
405
		this.menuContainer = $el("div.comfy-menu", {parent: document.body}, [
			$el("div.drag-handle", {
				style: {
					overflow: "hidden",
					position: "relative",
					width: "100%",
					cursor: "default"
				}
			}, [
Jairo Correa's avatar
Jairo Correa committed
406
				$el("span.drag-handle"),
reaper47's avatar
reaper47 committed
407
408
				$el("span", {$: (q) => (this.queueSize = q)}),
				$el("button.comfy-settings-btn", {textContent: "⚙️", onclick: () => this.settings.show()}),
pythongosssss's avatar
pythongosssss committed
409
			]),
410
			$el("button.comfy-queue-btn", {
411
				id: "queue-button",
412
413
414
				textContent: "Queue Prompt",
				onclick: () => app.queuePrompt(0, this.batchCount),
			}),
m957ymj75urz's avatar
m957ymj75urz committed
415
			$el("div", {}, [
reaper47's avatar
reaper47 committed
416
				$el("label", {innerHTML: "Extra options"}, [
417
418
419
420
421
422
					$el("input", {
						type: "checkbox",
						onchange: (i) => {
							document.getElementById("extraOptions").style.display = i.srcElement.checked ? "block" : "none";
							this.batchCount = i.srcElement.checked ? document.getElementById("batchCountInputRange").value : 1;
							document.getElementById("autoQueueCheckbox").checked = false;
pythongosssss's avatar
pythongosssss committed
423
							this.autoQueueEnabled = false;
424
425
426
						},
					}),
				]),
m957ymj75urz's avatar
m957ymj75urz committed
427
			]),
reaper47's avatar
reaper47 committed
428
			$el("div", {id: "extraOptions", style: {width: "100%", display: "none"}}, [
429
430
431
				$el("div",[

					$el("label", {innerHTML: "Batch count"}),
432
433
434
435
436
					$el("input", {
						id: "batchCountInputNumber",
						type: "number",
						value: this.batchCount,
						min: "1",
reaper47's avatar
reaper47 committed
437
						style: {width: "35%", "margin-left": "0.4em"},
438
						oninput: (i) => {
m957ymj75urz's avatar
m957ymj75urz committed
439
							this.batchCount = i.target.value;
440
441
							document.getElementById("batchCountInputRange").value = this.batchCount;
						},
m957ymj75urz's avatar
m957ymj75urz committed
442
					}),
443
444
445
446
447
448
					$el("input", {
						id: "batchCountInputRange",
						type: "range",
						min: "1",
						max: "100",
						value: this.batchCount,
m957ymj75urz's avatar
m957ymj75urz committed
449
450
						oninput: (i) => {
							this.batchCount = i.srcElement.value;
451
452
							document.getElementById("batchCountInputNumber").value = i.srcElement.value;
						},
453
454
455
456
457
458
					}),		
				]),
				$el("div",[
					$el("label",{
						for:"autoQueueCheckbox",
						innerHTML: "Auto Queue"
459
460
461
462
463
					}),
					$el("input", {
						id: "autoQueueCheckbox",
						type: "checkbox",
						checked: false,
464
						title: "Automatically queue prompt when the queue size hits 0",
pythongosssss's avatar
pythongosssss committed
465
466
467
468
						onchange: (e) => {
							this.autoQueueEnabled = e.target.checked;
							autoQueueModeEl.style.display = this.autoQueueEnabled ? "" : "none";
						}
m957ymj75urz's avatar
m957ymj75urz committed
469
					}),
pythongosssss's avatar
pythongosssss committed
470
					autoQueueModeEl
471
				])
m957ymj75urz's avatar
m957ymj75urz committed
472
			]),
pythongosssss's avatar
pythongosssss committed
473
			$el("div.comfy-menu-btns", [
reaper47's avatar
reaper47 committed
474
475
476
477
478
				$el("button", {
					id: "queue-front-button",
					textContent: "Queue Front",
					onclick: () => app.queuePrompt(-1, this.batchCount)
				}),
pythongosssss's avatar
pythongosssss committed
479
480
				$el("button", {
					$: (b) => (this.queue.button = b),
481
					id: "comfy-view-queue-button",
pythongosssss's avatar
pythongosssss committed
482
483
484
485
486
487
488
489
					textContent: "View Queue",
					onclick: () => {
						this.history.hide();
						this.queue.toggle();
					},
				}),
				$el("button", {
					$: (b) => (this.history.button = b),
490
					id: "comfy-view-history-button",
pythongosssss's avatar
pythongosssss committed
491
492
493
494
495
496
497
498
499
500
					textContent: "View History",
					onclick: () => {
						this.queue.hide();
						this.history.toggle();
					},
				}),
			]),
			this.queue.element,
			this.history.element,
			$el("button", {
501
				id: "comfy-save-button",
pythongosssss's avatar
pythongosssss committed
502
503
				textContent: "Save",
				onclick: () => {
504
505
506
507
508
509
510
511
					let filename = "workflow.json";
					if (promptFilename.value) {
						filename = prompt("Save workflow as:", filename);
						if (!filename) return;
						if (!filename.toLowerCase().endsWith(".json")) {
							filename += ".json";
						}
					}
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
					app.graphToPrompt().then(p=>{
						const json = JSON.stringify(p.workflow, null, 2); // convert the data to a JSON string
						const blob = new Blob([json], {type: "application/json"});
						const url = URL.createObjectURL(blob);
						const a = $el("a", {
							href: url,
							download: filename,
							style: {display: "none"},
							parent: document.body,
						});
						a.click();
						setTimeout(function () {
							a.remove();
							window.URL.revokeObjectURL(url);
						}, 0);
pythongosssss's avatar
pythongosssss committed
527
528
529
					});
				},
			}),
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
			$el("button", {
				id: "comfy-dev-save-api-button",
				textContent: "Save (API Format)",
				style: {width: "100%", display: "none"},
				onclick: () => {
					let filename = "workflow_api.json";
					if (promptFilename.value) {
						filename = prompt("Save workflow (API) as:", filename);
						if (!filename) return;
						if (!filename.toLowerCase().endsWith(".json")) {
							filename += ".json";
						}
					}
					app.graphToPrompt().then(p=>{
						const json = JSON.stringify(p.output, null, 2); // convert the data to a JSON string
						const blob = new Blob([json], {type: "application/json"});
						const url = URL.createObjectURL(blob);
						const a = $el("a", {
							href: url,
							download: filename,
							style: {display: "none"},
							parent: document.body,
						});
						a.click();
						setTimeout(function () {
							a.remove();
							window.URL.revokeObjectURL(url);
						}, 0);
					});
				},
			}),
reaper47's avatar
reaper47 committed
561
562
563
564
565
566
567
568
569
570
571
572
573
			$el("button", {id: "comfy-load-button", textContent: "Load", onclick: () => fileInput.click()}),
			$el("button", {
				id: "comfy-refresh-button",
				textContent: "Refresh",
				onclick: () => app.refreshComboInNodes()
			}),
			$el("button", {id: "comfy-clipspace-button", textContent: "Clipspace", onclick: () => app.openClipspace()}),
			$el("button", {
				id: "comfy-clear-button", textContent: "Clear", onclick: () => {
					if (!confirmClear.value || confirm("Clear workflow?")) {
						app.clean();
						app.graph.clear();
					}
574
				}
reaper47's avatar
reaper47 committed
575
576
			}),
			$el("button", {
pythongosssss's avatar
pythongosssss committed
577
				id: "comfy-load-default-button", textContent: "Load Default", onclick: async () => {
reaper47's avatar
reaper47 committed
578
					if (!confirmClear.value || confirm("Load default workflow?")) {
pythongosssss's avatar
pythongosssss committed
579
						await app.loadGraphData()
reaper47's avatar
reaper47 committed
580
					}
581
				}
reaper47's avatar
reaper47 committed
582
			}),
pythongosssss's avatar
pythongosssss committed
583
		]);
pythongosssss's avatar
pythongosssss committed
584

585
586
587
588
589
590
591
592
		const devMode = this.settings.addSetting({
			id: "Comfy.DevMode",
			name: "Enable Dev mode Options",
			type: "boolean",
			defaultValue: false,
			onChange: function(value) { document.getElementById("comfy-dev-save-api-button").style.display = value ? "block" : "none"},
		});

593
		dragElement(this.menuContainer, this.settings);
Jairo Correa's avatar
Jairo Correa committed
594

reaper47's avatar
reaper47 committed
595
		this.setStatus({exec_info: {queue_remaining: "X"}});
pythongosssss's avatar
pythongosssss committed
596
597
598
599
	}

	setStatus(status) {
		this.queueSize.textContent = "Queue size: " + (status ? status.exec_info.queue_remaining : "ERR");
comfyanonymous's avatar
comfyanonymous committed
600
		if (status) {
601
602
603
			if (
				this.lastQueueSize != 0 &&
				status.exec_info.queue_remaining == 0 &&
pythongosssss's avatar
pythongosssss committed
604
605
606
				this.autoQueueEnabled &&
				(this.autoQueueMode === "instant" || this.graphHasChanged) &&
				!app.lastExecutionError
607
			) {
comfyanonymous's avatar
comfyanonymous committed
608
				app.queuePrompt(0, this.batchCount);
pythongosssss's avatar
pythongosssss committed
609
610
				status.exec_info.queue_remaining += this.batchCount;
				this.graphHasChanged = false;
comfyanonymous's avatar
comfyanonymous committed
611
			}
612
			this.lastQueueSize = status.exec_info.queue_remaining;
comfyanonymous's avatar
comfyanonymous committed
613
		}
pythongosssss's avatar
pythongosssss committed
614
615
	}
}