Commentz
This commit is contained in:
@@ -45,25 +45,49 @@ if (typeof window !== "undefined") {
|
|||||||
nodes.ComfyReroute.setDefaultTextVisibility(!!localStorage["Comfy.ComfyReroute.DefaultVisibility"]);
|
nodes.ComfyReroute.setDefaultTextVisibility(!!localStorage["Comfy.ComfyReroute.DefaultVisibility"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
type QueueItem = { num: number, batchCount: number }
|
/*
|
||||||
|
* Queued prompt that hasn't been sent to the backend yet.
|
||||||
|
* TODO: Assumes the currently active graph will be serialized, needs to change
|
||||||
|
* for multiple loaded workflow support
|
||||||
|
*/
|
||||||
|
type QueueItem = {
|
||||||
|
num: number,
|
||||||
|
batchCount: number
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Represents a single workflow that can be loaded into the program from JSON.
|
||||||
|
*/
|
||||||
export type SerializedAppState = {
|
export type SerializedAppState = {
|
||||||
|
/** Program identifier, should always be "ComfyBox" */
|
||||||
createdBy: "ComfyBox",
|
createdBy: "ComfyBox",
|
||||||
|
/** Serial version, should be incremented on breaking changes */
|
||||||
version: number,
|
version: number,
|
||||||
|
/** Commit hash if found */
|
||||||
|
commitHash?: string,
|
||||||
|
/** Graph state */
|
||||||
workflow: SerializedLGraph,
|
workflow: SerializedLGraph,
|
||||||
|
/** UI state */
|
||||||
layout: SerializedLayoutState,
|
layout: SerializedLayoutState,
|
||||||
|
/** Position/offset of the canvas at the time of saving */
|
||||||
canvas: SerializedGraphCanvasState
|
canvas: SerializedGraphCanvasState
|
||||||
}
|
}
|
||||||
|
|
||||||
/** [link origin, link index] | value */
|
/** [link_origin, link_slot_index] | input_value */
|
||||||
export type SerializedPromptInput = [ComfyNodeID, number] | any
|
export type SerializedPromptInput = [ComfyNodeID, number] | any
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A single node in the prompt and its input values.
|
||||||
|
*/
|
||||||
export type SerializedPromptInputs = {
|
export type SerializedPromptInputs = {
|
||||||
/* property name -> value or link */
|
/* property name -> value or link */
|
||||||
inputs: Record<string, SerializedPromptInput>,
|
inputs: Record<string, SerializedPromptInput>,
|
||||||
class_type: string
|
class_type: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All nodes in the graph and their input values.
|
||||||
|
*/
|
||||||
export type SerializedPromptInputsAll = Record<ComfyNodeID, SerializedPromptInputs>
|
export type SerializedPromptInputsAll = Record<ComfyNodeID, SerializedPromptInputs>
|
||||||
|
|
||||||
export type SerializedPrompt = {
|
export type SerializedPrompt = {
|
||||||
@@ -71,6 +95,9 @@ export type SerializedPrompt = {
|
|||||||
output: SerializedPromptInputsAll
|
output: SerializedPromptInputsAll
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Outputs for each node.
|
||||||
|
*/
|
||||||
export type SerializedPromptOutputs = Record<ComfyNodeID, ComfyExecutionResult>
|
export type SerializedPromptOutputs = Record<ComfyNodeID, ComfyExecutionResult>
|
||||||
|
|
||||||
export type Progress = {
|
export type Progress = {
|
||||||
@@ -78,6 +105,10 @@ export type Progress = {
|
|||||||
max: number
|
max: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A combo node and the backend node that will send an updated config over, for
|
||||||
|
* refreshing lists of model files
|
||||||
|
*/
|
||||||
type BackendComboNode = {
|
type BackendComboNode = {
|
||||||
comboNode: ComfyComboNode,
|
comboNode: ComfyComboNode,
|
||||||
comfyInput: IComfyInputSlot,
|
comfyInput: IComfyInputSlot,
|
||||||
@@ -95,6 +126,7 @@ export default class ComfyApp {
|
|||||||
nodeOutputs: Record<string, any> = {};
|
nodeOutputs: Record<string, any> = {};
|
||||||
|
|
||||||
shiftDown: boolean = false;
|
shiftDown: boolean = false;
|
||||||
|
ctrlDown: boolean = false;
|
||||||
selectedGroupMoving: boolean = false;
|
selectedGroupMoving: boolean = false;
|
||||||
|
|
||||||
private queueItems: QueueItem[] = [];
|
private queueItems: QueueItem[] = [];
|
||||||
@@ -406,6 +438,7 @@ export default class ComfyApp {
|
|||||||
private addKeyboardHandler() {
|
private addKeyboardHandler() {
|
||||||
window.addEventListener("keydown", (e) => {
|
window.addEventListener("keydown", (e) => {
|
||||||
this.shiftDown = e.shiftKey;
|
this.shiftDown = e.shiftKey;
|
||||||
|
this.ctrlDown = e.ctrlKey;
|
||||||
|
|
||||||
// Queue prompt using ctrl or command + enter
|
// Queue prompt using ctrl or command + enter
|
||||||
if ((e.ctrlKey || e.metaKey) && (e.key === "Enter" || e.keyCode === 13 || e.keyCode === 10)) {
|
if ((e.ctrlKey || e.metaKey) && (e.key === "Enter" || e.keyCode === 13 || e.keyCode === 10)) {
|
||||||
@@ -414,6 +447,7 @@ export default class ComfyApp {
|
|||||||
});
|
});
|
||||||
window.addEventListener("keyup", (e) => {
|
window.addEventListener("keyup", (e) => {
|
||||||
this.shiftDown = e.shiftKey;
|
this.shiftDown = e.shiftKey;
|
||||||
|
this.ctrlDown = e.ctrlKey;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -561,7 +595,9 @@ export default class ComfyApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (get(layoutState).attrs.queuePromptButtonRunWorkflow) {
|
if (get(layoutState).attrs.queuePromptButtonRunWorkflow) {
|
||||||
this.queuePrompt(0, 1);
|
// Hold control to queue at the front
|
||||||
|
const num = this.ctrlDown ? -1 : 0;
|
||||||
|
this.queuePrompt(num, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ export class UpstreamNodeLocator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If there are non-target nodes between us and another
|
// If there are non-target nodes between us and another
|
||||||
// backend node, we have to traverse them first. This
|
// target node, we have to traverse them first. This
|
||||||
// behavior is dependent on the type of node. Reroute nodes
|
// behavior is dependent on the type of node. Reroute nodes
|
||||||
// will simply follow their single input, while branching
|
// will simply follow their single input, while branching
|
||||||
// nodes have conditional logic that determines which link
|
// nodes have conditional logic that determines which link
|
||||||
|
|||||||
@@ -312,7 +312,9 @@ export class ComfyExecuteSubgraphAction extends ComfyGraphNode {
|
|||||||
if (!app)
|
if (!app)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
app.queuePrompt(0, 1, tag);
|
// Hold control to queue at the front
|
||||||
|
const num = app.ctrlDown ? -1 : 0;
|
||||||
|
app.queuePrompt(num, 1, tag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,8 +39,10 @@ export type LayoutAttributes = {
|
|||||||
queuePromptButtonName: string,
|
queuePromptButtonName: string,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If true, clicking the "Queue Prompt" button will run the default subgraph.
|
* If true, clicking the "Queue Prompt" button will run the default
|
||||||
* Set this to false if you need special behavior before running any subgraphs.
|
* subgraph. Set this to false if you need special behavior before running
|
||||||
|
* any subgraphs, and instead use the `onDefaultQueueAction` event of the
|
||||||
|
* Comfy.QueueEvents node.
|
||||||
*/
|
*/
|
||||||
queuePromptButtonRunWorkflow: boolean,
|
queuePromptButtonRunWorkflow: boolean,
|
||||||
}
|
}
|
||||||
@@ -84,6 +86,9 @@ export type LayoutState = {
|
|||||||
*/
|
*/
|
||||||
attrs: LayoutAttributes
|
attrs: LayoutAttributes
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Increment to force Svelte to re-render the props panel
|
||||||
|
*/
|
||||||
refreshPropsPanel: Writable<number>
|
refreshPropsPanel: Writable<number>
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,7 +107,7 @@ export type Attributes = {
|
|||||||
title: string,
|
title: string,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* List of classes to apply to the component.
|
* List of CSS classes to apply to the component.
|
||||||
*/
|
*/
|
||||||
classes: string,
|
classes: string,
|
||||||
|
|
||||||
@@ -204,22 +209,22 @@ export type AttributesSpec = {
|
|||||||
values?: string[],
|
values?: string[],
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If `type` is "number", step for the slider
|
* If `type` is "number", step for the slider that edits this attribute
|
||||||
*/
|
*/
|
||||||
step?: number,
|
step?: number,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If `type` is "number", min for the slider
|
* If `type` is "number", min for the slider that edits this attribute
|
||||||
*/
|
*/
|
||||||
min?: number,
|
min?: number,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If `type` is "number", max for the slider
|
* If `type` is "number", max for the slider that edits this attribute
|
||||||
*/
|
*/
|
||||||
max?: number,
|
max?: number,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If `type` is "string", display as a textarea.
|
* If `type` is "string", display as a textarea instead of an input.
|
||||||
*/
|
*/
|
||||||
multiline?: boolean,
|
multiline?: boolean,
|
||||||
|
|
||||||
@@ -863,8 +868,9 @@ function nodeAdded(node: LGraphNode, options: LGraphAddNodeOptions) {
|
|||||||
let prevWidget = state.allItemsByNode[node.id]
|
let prevWidget = state.allItemsByNode[node.id]
|
||||||
if (prevWidget == null) {
|
if (prevWidget == null) {
|
||||||
// If a subgraph was cloned, try looking for the original widget node corresponding to the new widget node being added.
|
// If a subgraph was cloned, try looking for the original widget node corresponding to the new widget node being added.
|
||||||
// `node` is the new ComfyWidgetNode instance to copy attrs to.
|
// `node` is the new ComfyWidgetNode instance to copy layout attrs to.
|
||||||
// `options.cloneData` should contain the results of Subgraph.clone(), called "subgraphNewIDMapping".
|
// `options.cloneData` should contain the results of Subgraph.clone(), which is named "subgraphNewIDMapping" in an
|
||||||
|
// entry of the `forNode` Record.
|
||||||
// `options.cloneData` is attached to the onNodeAdded options if a node is added to a graph after being
|
// `options.cloneData` is attached to the onNodeAdded options if a node is added to a graph after being
|
||||||
// selection-cloned or pasted, as they both call clone() internally.
|
// selection-cloned or pasted, as they both call clone() internally.
|
||||||
const cloneData = options.cloneData.forNode[options.prevNodeID]
|
const cloneData = options.cloneData.forNode[options.prevNodeID]
|
||||||
@@ -879,7 +885,7 @@ function nodeAdded(node: LGraphNode, options: LGraphAddNodeOptions) {
|
|||||||
if (nodeIDInLayoutState) {
|
if (nodeIDInLayoutState) {
|
||||||
// Gottem.
|
// Gottem.
|
||||||
prevWidget = state.allItemsByNode[nodeIDInLayoutState]
|
prevWidget = state.allItemsByNode[nodeIDInLayoutState]
|
||||||
console.warn("FOUND CLONED SUBGRAPH NODE", node.id, "=>", nodeIDInLayoutState, prevWidget)
|
// console.warn("FOUND CLONED SUBGRAPH NODE", node.id, "=>", nodeIDInLayoutState, prevWidget)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,6 @@ import type { ComfyExecutionResult } from "$lib/nodes/ComfyWidgetNodes";
|
|||||||
import notify from "$lib/notify";
|
import notify from "$lib/notify";
|
||||||
import { get, writable, type Writable } from "svelte/store";
|
import { get, writable, type Writable } from "svelte/store";
|
||||||
|
|
||||||
export type QueueItem = {
|
|
||||||
name: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export type QueueEntryStatus = "success" | "error" | "interrupted" | "all_cached" | "unknown";
|
export type QueueEntryStatus = "success" | "error" | "interrupted" | "all_cached" | "unknown";
|
||||||
|
|
||||||
type QueueStateOps = {
|
type QueueStateOps = {
|
||||||
@@ -23,8 +19,13 @@ type QueueStateOps = {
|
|||||||
onExecuted: (promptID: PromptID, nodeID: ComfyNodeID, output: ComfyExecutionResult) => void
|
onExecuted: (promptID: PromptID, nodeID: ComfyNodeID, output: ComfyExecutionResult) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Single job that the backend keeps track of.
|
||||||
|
*/
|
||||||
export type QueueEntry = {
|
export type QueueEntry = {
|
||||||
/* Data preserved on page refresh */
|
/*** Data preserved on page refresh ***/
|
||||||
|
|
||||||
|
/** Priority of the prompt. -1 means to queue at the front. */
|
||||||
number: number,
|
number: number,
|
||||||
queuedAt?: Date,
|
queuedAt?: Date,
|
||||||
finishedAt?: Date,
|
finishedAt?: Date,
|
||||||
@@ -33,23 +34,34 @@ export type QueueEntry = {
|
|||||||
extraData: ComfyBoxPromptExtraData,
|
extraData: ComfyBoxPromptExtraData,
|
||||||
goodOutputs: ComfyNodeID[],
|
goodOutputs: ComfyNodeID[],
|
||||||
|
|
||||||
/* Data not sent by ComfyUI's API, lost on page refresh */
|
/*** Data not sent by ComfyUI's API, lost on page refresh ***/
|
||||||
|
|
||||||
/* Prompt outputs, collected while the prompt is still executing */
|
/* Prompt outputs, collected while the prompt is still executing */
|
||||||
outputs: SerializedPromptOutputs,
|
outputs: SerializedPromptOutputs,
|
||||||
|
/* Nodes of the workflow that have finished running so far. */
|
||||||
/* Nodes in of the workflow that have finished running so far. */
|
|
||||||
nodesRan: Set<ComfyNodeID>,
|
nodesRan: Set<ComfyNodeID>,
|
||||||
|
/* Nodes of the workflow the backend reported as cached. */
|
||||||
cachedNodes: Set<ComfyNodeID>
|
cachedNodes: Set<ComfyNodeID>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Represents a queue entry that has finished executing (suceeded or failed) and
|
||||||
|
* has been moved to the history.
|
||||||
|
*/
|
||||||
export type CompletedQueueEntry = {
|
export type CompletedQueueEntry = {
|
||||||
|
/** Corresponding entry in the queue, for the prompt/extra data */
|
||||||
entry: QueueEntry,
|
entry: QueueEntry,
|
||||||
|
/** The result of this prompt, success/failed/cached */
|
||||||
status: QueueEntryStatus,
|
status: QueueEntryStatus,
|
||||||
|
/** Message to display in the frontend */
|
||||||
message?: string,
|
message?: string,
|
||||||
|
/** Detailed error/stacktrace, perhaps inspectible with a popup */
|
||||||
error?: string,
|
error?: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Keeps track of queued and completed (history) prompts.
|
||||||
|
*/
|
||||||
export type QueueState = {
|
export type QueueState = {
|
||||||
queueRunning: Writable<QueueEntry[]>,
|
queueRunning: Writable<QueueEntry[]>,
|
||||||
queuePending: Writable<QueueEntry[]>,
|
queuePending: Writable<QueueEntry[]>,
|
||||||
@@ -57,6 +69,11 @@ export type QueueState = {
|
|||||||
queueRemaining: number | "X" | null;
|
queueRemaining: number | "X" | null;
|
||||||
runningNodeID: ComfyNodeID | null;
|
runningNodeID: ComfyNodeID | null;
|
||||||
progress: Progress | null,
|
progress: Progress | null,
|
||||||
|
/**
|
||||||
|
* If true, user pressed the "Interrupt" button in the frontend. Disable the
|
||||||
|
* button and wait until the next prompt starts running to re-enable it
|
||||||
|
* again
|
||||||
|
*/
|
||||||
isInterrupting: boolean
|
isInterrupting: boolean
|
||||||
}
|
}
|
||||||
type WritableQueueStateStore = Writable<QueueState> & QueueStateOps;
|
type WritableQueueStateStore = Writable<QueueState> & QueueStateOps;
|
||||||
@@ -159,6 +176,7 @@ function moveToCompleted(index: number, queue: Writable<QueueEntry[]>, status: Q
|
|||||||
return qc
|
return qc
|
||||||
})
|
})
|
||||||
|
|
||||||
|
state.isInterrupting = false;
|
||||||
store.set(state)
|
store.set(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user