Workflow saving/loading
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -790,7 +790,10 @@ function initDefaultLayout() {
|
||||
currentSelection: [],
|
||||
currentSelectionNodes: [],
|
||||
isMenuOpen: false,
|
||||
isConfiguring: false
|
||||
isConfiguring: false,
|
||||
attrs: {
|
||||
defaultSubgraph: ""
|
||||
}
|
||||
})
|
||||
|
||||
const root = addContainer(null, { direction: "horizontal", title: "" });
|
||||
|
||||
Reference in New Issue
Block a user