Workflow saving/loading

This commit is contained in:
space-nuko
2023-05-06 21:39:21 -05:00
parent 2a2d04803b
commit da65d1b439
6 changed files with 78 additions and 18 deletions

View File

@@ -21,6 +21,7 @@
import queueState from "$lib/stores/queueState";
import ComfyUnlockUIButton from "./ComfyUnlockUIButton.svelte";
import ComfyGraphView from "./ComfyGraphView.svelte";
import { download } from "$lib/utils";
export let app: ComfyApp = undefined;
let imageViewer: ImageViewer;
@@ -32,6 +33,7 @@
let resizeTimeout: NodeJS.Timeout | null;
let hasShownUIHelpToast: boolean = false;
let uiTheme: string = "";
let fileInput: HTMLInputElement = undefined;
let debugLayout: boolean = false;
@@ -100,6 +102,43 @@
if (!app?.lGraph)
return;
const promptFilename = false; // TODO
let filename = "workflow.json";
if (promptFilename) {
filename = prompt("Save workflow as:", filename);
if (!filename) return;
if (!filename.toLowerCase().endsWith(".json")) {
filename += ".json";
}
}
else {
const date = new Date();
const formattedDate = date.toISOString().replace(/:/g, '-').replace(/\.\d{3}/g, '').replace('T', '_').replace("Z", "");
filename = `workflow-${formattedDate}.json`
}
const indent = 2
const json = JSON.stringify(app.serialize(), null, indent)
download(filename, json, "application/json")
}
function doLoad(): void {
if (!app?.lGraph || !fileInput)
return;
fileInput.click();
}
function loadWorkflow(): void {
app.handleFile(fileInput.files[0]);
}
function doSaveLocal(): void {
if (!app?.lGraph)
return;
app.saveStateToLocalStorage();
toast.push("Saved to local storage.")
//
@@ -109,13 +148,6 @@
// download(`workflow-${formattedDate}.json`, JSON.stringify(app.serialize()), "application/json")
}
function doReset(): void {
var confirmed = confirm("Are you sure you want to clear the current workflow?");
if (confirmed) {
app.reset();
}
}
async function doLoadDefault(): void {
var confirmed = confirm("Are you sure you want to clear the current workflow and load the default graph?");
if (confirmed) {
@@ -123,6 +155,13 @@
}
}
function doClear(): void {
var confirmed = confirm("Are you sure you want to clear the current workflow?");
if (confirmed) {
app.clear();
}
}
$: if ($uiState.uiUnlocked && !hasShownUIHelpToast) {
hasShownUIHelpToast = true;
toast.push("Right-click to open context menu.")
@@ -222,8 +261,14 @@
<Button variant="secondary" on:click={doSave}>
Save
</Button>
<Button variant="secondary" on:click={doReset}>
Reset
<Button variant="secondary" on:click={doSaveLocal}>
Save Local
</Button>
<Button variant="secondary" on:click={doLoad}>
Load
</Button>
<Button variant="secondary" on:click={doClear}>
Clear
</Button>
<Button variant="secondary" on:click={doLoadDefault}>
Load Default
@@ -255,6 +300,7 @@
</div>
</div>
<LightboxModal />
<input bind:this={fileInput} id="comfy-file-input" type="file" accept=".json" on:change={loadWorkflow} />
</div>
<SvelteToast options={toastOptions} />
@@ -358,4 +404,8 @@
span.left {
right: 0px;
}
#comfy-file-input {
display: none;
}
</style>

View File

@@ -404,7 +404,7 @@ export default class ComfyApp {
}
}
reset() {
clear() {
this.clean();
const blankGraph: SerializedLGraph = {
@@ -634,16 +634,21 @@ export default class ComfyApp {
if (file.type === "image/png") {
const pngInfo = await getPngMetadata(file);
if (pngInfo) {
if (pngInfo.workflow) {
this.loadGraphData(JSON.parse(pngInfo.workflow));
if (pngInfo.comfyBoxConfig) {
this.deserialize(JSON.parse(pngInfo.comfyBoxConfig));
} else if (pngInfo.parameters) {
importA1111(this.lGraph, pngInfo.parameters, this.api);
throw "TODO import A111 import!"
// importA1111(this.lGraph, pngInfo.parameters, this.api);
}
else {
console.error("No metadata found in image file.", pngInfo)
toast.push("No metadata found in image file.")
}
}
} else if (file.type === "application/json" || file.name.endsWith(".json")) {
const reader = new FileReader();
reader.onload = () => {
this.loadGraphData(JSON.parse(reader.result as string));
this.deserialize(JSON.parse(reader.result as string));
};
reader.readAsText(file);
}

View File

@@ -33,7 +33,8 @@ export default class ComfyValueControl extends ComfyGraphNode {
{ name: "step", type: "number" }
],
outputs: [
{ name: "value", type: "*" }
{ name: "value", type: "*" },
{ name: "changed", type: BuiltInSlotType.EVENT }
],
}
@@ -93,6 +94,7 @@ export default class ComfyValueControl extends ComfyGraphNode {
v = clamp(v, min, max)
this.setProperty("value", v)
this.triggerSlot(1, v)
this.setOutputData(0, v)
console.debug("ValueControl", v, this.properties)

View File

@@ -101,7 +101,7 @@ export abstract class ComfyWidgetNode<T = any> extends ComfyGraphNode {
if (this.changedIndex !== null && this.outputs.length >= this.changedIndex) {
const changedOutput = this.outputs[this.changedIndex]
if (changedOutput.type === BuiltInSlotType.EVENT)
this.triggerSlot(this.changedIndex, "changed")
this.triggerSlot(this.changedIndex, get(this.value))
}
}

View File

@@ -790,7 +790,10 @@ function initDefaultLayout() {
currentSelection: [],
currentSelectionNodes: [],
isMenuOpen: false,
isConfiguring: false
isConfiguring: false,
attrs: {
defaultSubgraph: ""
}
})
const root = addContainer(null, { direction: "horizontal", title: "" });