Workflow title
This commit is contained in:
@@ -80,6 +80,8 @@ export type SerializedAppState = {
|
|||||||
commitHash?: string,
|
commitHash?: string,
|
||||||
/** Graph state */
|
/** Graph state */
|
||||||
workflow: SerializedLGraph,
|
workflow: SerializedLGraph,
|
||||||
|
/** Workflow name */
|
||||||
|
workflowName: string,
|
||||||
/** UI state */
|
/** UI state */
|
||||||
layout: SerializedLayoutState,
|
layout: SerializedLayoutState,
|
||||||
/** Position/offset of the canvas at the time of saving */
|
/** Position/offset of the canvas at the time of saving */
|
||||||
@@ -197,7 +199,7 @@ export default class ComfyApp {
|
|||||||
|
|
||||||
// We failed to restore a workflow so load the default
|
// We failed to restore a workflow so load the default
|
||||||
if (!restored) {
|
if (!restored) {
|
||||||
await this.initDefaultGraph();
|
await this.initDefaultWorkflow();
|
||||||
}
|
}
|
||||||
|
|
||||||
workflowState.createNewWorkflow(this.lCanvas);
|
workflowState.createNewWorkflow(this.lCanvas);
|
||||||
@@ -522,7 +524,12 @@ export default class ComfyApp {
|
|||||||
selectionState.clear();
|
selectionState.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
async initDefaultGraph() {
|
closeWorkflow(index: number) {
|
||||||
|
workflowState.closeWorkflow(this.lCanvas, index);
|
||||||
|
selectionState.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
async initDefaultWorkflow() {
|
||||||
let state = null;
|
let state = null;
|
||||||
try {
|
try {
|
||||||
const graphResponse = await fetch("/workflows/defaultWorkflow.json");
|
const graphResponse = await fetch("/workflows/defaultWorkflow.json");
|
||||||
|
|||||||
@@ -144,17 +144,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function doLoadDefault() {
|
async function doLoadDefault() {
|
||||||
var confirmed = confirm("Are you sure you want to clear the current workflow and load the default graph?");
|
var confirmed = confirm("Would you like to load the default workflow in a new tab?");
|
||||||
if (confirmed) {
|
if (confirmed) {
|
||||||
await app.initDefaultGraph();
|
await app.initDefaultWorkflow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function doClear(): void {
|
function closeWorkflow(event: Event, index: number) {
|
||||||
var confirmed = confirm("Are you sure you want to clear the current workflow?");
|
event.preventDefault();
|
||||||
if (confirmed) {
|
event.stopImmediatePropagation()
|
||||||
app.clear();
|
app.closeWorkflow(index);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -190,7 +189,11 @@
|
|||||||
<button class="workflow-tab"
|
<button class="workflow-tab"
|
||||||
class:selected={index === $workflowState.activeWorkflowIdx}
|
class:selected={index === $workflowState.activeWorkflowIdx}
|
||||||
on:click={() => app.setActiveWorkflow(index)}>
|
on:click={() => app.setActiveWorkflow(index)}>
|
||||||
{workflow.title}
|
<span class="workflow-tab-title">{workflow.title}</span>
|
||||||
|
<button class="workflow-close-button"
|
||||||
|
on:click={(e) => closeWorkflow(e, index)}>
|
||||||
|
X
|
||||||
|
</button>
|
||||||
</button>
|
</button>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
@@ -220,9 +223,6 @@
|
|||||||
<Button variant="secondary" disabled={!$alreadySetup} on:click={doLoad}>
|
<Button variant="secondary" disabled={!$alreadySetup} on:click={doLoad}>
|
||||||
Load
|
Load
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="secondary" disabled={!$alreadySetup} on:click={doClear}>
|
|
||||||
Clear
|
|
||||||
</Button>
|
|
||||||
<Button variant="secondary" disabled={!$alreadySetup} on:click={doLoadDefault}>
|
<Button variant="secondary" disabled={!$alreadySetup} on:click={doLoadDefault}>
|
||||||
Load Default
|
Load Default
|
||||||
</Button>
|
</Button>
|
||||||
@@ -371,14 +371,15 @@
|
|||||||
border-left: 1px solid var(--neutral-600);
|
border-left: 1px solid var(--neutral-600);
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: row;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
gap: var(--size-2);
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
border-right: 1px solid var(--neutral-600);
|
border-right: 1px solid var(--neutral-600);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover:not(:has(.workflow-close-button:hover)) {
|
||||||
background: var(--neutral-700);
|
background: var(--neutral-700);
|
||||||
color: var(--neutral-300);
|
color: var(--neutral-300);
|
||||||
}
|
}
|
||||||
@@ -388,6 +389,20 @@
|
|||||||
color: var(--neutral-300);
|
color: var(--neutral-300);
|
||||||
border-top-color: var(--primary-500);
|
border-top-color: var(--primary-500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> .workflow-close-button {
|
||||||
|
display:block;
|
||||||
|
width: 1.5rem;
|
||||||
|
height: 1.5rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--neutral-500);
|
||||||
|
color: var(--neutral-300);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: var(--neutral-400);
|
||||||
|
color: var(--neutral-100);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import type { SerializedAppState } from "./components/ComfyApp"
|
|||||||
const blankGraph: SerializedAppState = {
|
const blankGraph: SerializedAppState = {
|
||||||
createdBy: "ComfyBox",
|
createdBy: "ComfyBox",
|
||||||
version: 1,
|
version: 1,
|
||||||
|
workflowName: "New Workflow",
|
||||||
workflow: {
|
workflow: {
|
||||||
last_node_id: 0,
|
last_node_id: 0,
|
||||||
last_link_id: 0,
|
last_link_id: 0,
|
||||||
|
|||||||
@@ -1208,7 +1208,7 @@ function create(workflow: ComfyWorkflow): WritableLayoutStateStore {
|
|||||||
|
|
||||||
function remove(workflowID: WorkflowInstID) {
|
function remove(workflowID: WorkflowInstID) {
|
||||||
const state = get(layoutStates)
|
const state = get(layoutStates)
|
||||||
if (layoutStates[workflowID] == null)
|
if (state.all[workflowID] == null)
|
||||||
throw new Error(`No workflow with ID registered! ${workflowID}`)
|
throw new Error(`No workflow with ID registered! ${workflowID}`)
|
||||||
delete state.all[workflowID];
|
delete state.all[workflowID];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { SerializedGraphCanvasState } from '$lib/ComfyGraphCanvas';
|
import type { SerializedGraphCanvasState } from '$lib/ComfyGraphCanvas';
|
||||||
import type { LGraphCanvas, NodeID, SerializedLGraph, UUID } from '@litegraph-ts/core';
|
import { clamp, type LGraphCanvas, type NodeID, type SerializedLGraph, type UUID } from '@litegraph-ts/core';
|
||||||
import { get, writable } from 'svelte/store';
|
import { get, writable } from 'svelte/store';
|
||||||
import type { Readable, Writable } from 'svelte/store';
|
import type { Readable, Writable } from 'svelte/store';
|
||||||
import type { SerializedLayoutState, WritableLayoutStateStore } from './layoutStates';
|
import type { SerializedLayoutState, WritableLayoutStateStore } from './layoutStates';
|
||||||
@@ -87,8 +87,10 @@ export class ComfyWorkflow {
|
|||||||
|
|
||||||
stop(key: string) {
|
stop(key: string) {
|
||||||
const canvas = this.canvases[key]
|
const canvas = this.canvases[key]
|
||||||
if (canvas == null)
|
if (canvas == null) {
|
||||||
throw new Error(`This workflow is not being displayed on canvas ${key}`)
|
console.debug("This workflow is not being displayed on canvas ${key}")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.graph.detachCanvas(canvas.canvas);
|
this.graph.detachCanvas(canvas.canvas);
|
||||||
this.graph.eventBus.removeListener("afterExecute", canvas.canvasHandler)
|
this.graph.eventBus.removeListener("afterExecute", canvas.canvasHandler)
|
||||||
@@ -163,7 +165,7 @@ type WorkflowStateOps = {
|
|||||||
getWorkflow: (id: WorkflowInstID) => ComfyWorkflow | null
|
getWorkflow: (id: WorkflowInstID) => ComfyWorkflow | null
|
||||||
getWorkflowByNodeID: (id: NodeID) => ComfyWorkflow | null
|
getWorkflowByNodeID: (id: NodeID) => ComfyWorkflow | null
|
||||||
getActiveWorkflow: () => ComfyWorkflow | null
|
getActiveWorkflow: () => ComfyWorkflow | null
|
||||||
createNewWorkflow: (canvas: ComfyGraphCanvas, setActive?: boolean) => ComfyWorkflow,
|
createNewWorkflow: (canvas: ComfyGraphCanvas, title?: string, setActive?: boolean) => ComfyWorkflow,
|
||||||
openWorkflow: (canvas: ComfyGraphCanvas, data: SerializedAppState) => ComfyWorkflow,
|
openWorkflow: (canvas: ComfyGraphCanvas, data: SerializedAppState) => ComfyWorkflow,
|
||||||
closeWorkflow: (canvas: ComfyGraphCanvas, index: number) => void,
|
closeWorkflow: (canvas: ComfyGraphCanvas, index: number) => void,
|
||||||
closeAllWorkflows: (canvas: ComfyGraphCanvas) => void,
|
closeAllWorkflows: (canvas: ComfyGraphCanvas) => void,
|
||||||
@@ -196,13 +198,14 @@ function getActiveWorkflow(): ComfyWorkflow | null {
|
|||||||
return state.openedWorkflows[state.activeWorkflowIdx];
|
return state.openedWorkflows[state.activeWorkflowIdx];
|
||||||
}
|
}
|
||||||
|
|
||||||
function createNewWorkflow(canvas: ComfyGraphCanvas, setActive: boolean = false): ComfyWorkflow {
|
function createNewWorkflow(canvas: ComfyGraphCanvas, title: string = "New Workflow", setActive: boolean = false): ComfyWorkflow {
|
||||||
const workflow = new ComfyWorkflow("Workflow X");
|
const workflow = new ComfyWorkflow(title);
|
||||||
const layoutState = layoutStates.create(workflow);
|
const layoutState = layoutStates.create(workflow);
|
||||||
layoutState.initDefaultLayout();
|
layoutState.initDefaultLayout();
|
||||||
|
|
||||||
const state = get(store);
|
const state = get(store);
|
||||||
state.openedWorkflows.push(workflow);
|
state.openedWorkflows.push(workflow);
|
||||||
|
state.openedWorkflowsByID[workflow.id] = workflow;
|
||||||
|
|
||||||
if (setActive)
|
if (setActive)
|
||||||
setActiveWorkflow(canvas, state.openedWorkflows.length - 1)
|
setActiveWorkflow(canvas, state.openedWorkflows.length - 1)
|
||||||
@@ -213,11 +216,12 @@ function createNewWorkflow(canvas: ComfyGraphCanvas, setActive: boolean = false)
|
|||||||
}
|
}
|
||||||
|
|
||||||
function openWorkflow(canvas: ComfyGraphCanvas, data: SerializedAppState): ComfyWorkflow {
|
function openWorkflow(canvas: ComfyGraphCanvas, data: SerializedAppState): ComfyWorkflow {
|
||||||
const [workflow, layoutState] = ComfyWorkflow.create("Workflow X")
|
const [workflow, layoutState] = ComfyWorkflow.create(data.workflowName || "Workflow")
|
||||||
workflow.deserialize(layoutState, { graph: data.workflow, layout: data.layout })
|
workflow.deserialize(layoutState, { graph: data.workflow, layout: data.layout })
|
||||||
|
|
||||||
const state = get(store);
|
const state = get(store);
|
||||||
state.openedWorkflows.push(workflow);
|
state.openedWorkflows.push(workflow);
|
||||||
|
state.openedWorkflowsByID[workflow.id] = workflow;
|
||||||
setActiveWorkflow(canvas, state.openedWorkflows.length - 1)
|
setActiveWorkflow(canvas, state.openedWorkflows.length - 1)
|
||||||
|
|
||||||
store.set(state)
|
store.set(state)
|
||||||
@@ -237,7 +241,9 @@ function closeWorkflow(canvas: ComfyGraphCanvas, index: number) {
|
|||||||
layoutStates.remove(workflow.id)
|
layoutStates.remove(workflow.id)
|
||||||
|
|
||||||
state.openedWorkflows.splice(index, 1)
|
state.openedWorkflows.splice(index, 1)
|
||||||
setActiveWorkflow(canvas, 0);
|
delete state.openedWorkflowsByID[workflow.id]
|
||||||
|
const newIndex = clamp(state.activeWorkflowIdx, 0, state.openedWorkflows.length - 1);
|
||||||
|
setActiveWorkflow(canvas, newIndex);
|
||||||
|
|
||||||
store.set(state);
|
store.set(state);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,9 @@
|
|||||||
export let app: ComfyApp | null = null;
|
export let app: ComfyApp | null = null;
|
||||||
|
|
||||||
async function doLoadDefault() {
|
async function doLoadDefault() {
|
||||||
var confirmed = confirm("Are you sure you want to clear the current workflow and load the default graph?");
|
var confirmed = confirm("Would you like to load the default workflow in a new tab?");
|
||||||
if (confirmed) {
|
if (confirmed) {
|
||||||
await app.initDefaultGraph();
|
await app.initDefaultWorkflow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user