Config default templates

This commit is contained in:
space-nuko
2023-05-25 17:38:30 -05:00
parent 2a0662592a
commit 220be38a0b
6 changed files with 89 additions and 35 deletions

View File

@@ -1,7 +1,9 @@
{
"comfyUIHostname": "localhost",
"comfyUIPort": 8188,
"alwaysStripUserState": false,
"promptForWorkflowName": false,
"confirmWhenUnloadingUnsavedChanges": true
"comfyUIHostname": "localhost",
"comfyUIPort": 8188,
"alwaysStripUserState": false,
"promptForWorkflowName": false,
"confirmWhenUnloadingUnsavedChanges": true,
"builtInTemplates": ["ControlNet", "LoRA x5", "Model Loader", "Positive_Negative", "Seed Randomizer"],
"cacheBuiltInResources": true
}

View File

@@ -338,7 +338,6 @@ export function serializeTemplate(canvas: ComfyGraphCanvas, template: ComfyBoxTe
uiState.update(s => { s.forceSaveUserState = null; return s; });
nodes = relocateNodes(nodes);
nodes = removeTags(nodes);
[nodes, links] = pruneDetachedLinks(nodes, links);
const svg = renderSvg(canvas, graph, TEMPLATE_SVG_PADDING);
@@ -378,29 +377,21 @@ export function extractTemplateJSONFromSVG(svg: string): string | null {
/*
* Credit goes to pythongosssss for this format
*/
export function deserializeTemplateFromSVG(file: File): Promise<SerializedComfyBoxTemplate> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = async () => {
const svg = reader.result as string;
let template = null;
let templateJSON = extractTemplateJSONFromSVG(svg);
if (templateJSON)
template = JSON.parse(templateJSON);
export function deserializeTemplateFromSVG(svg: string): SerializedComfyBoxTemplate | null {
let template = null;
let templateJSON = extractTemplateJSONFromSVG(svg);
if (templateJSON)
template = JSON.parse(templateJSON);
if (!isSerializedComfyBoxTemplate(template)) {
reject("Invalid template format!")
}
else {
template.svg = svg;
resolve(template)
}
};
reader.readAsText(file);
});
if (!isSerializedComfyBoxTemplate(template)) {
return null;
}
else {
template.svg = svg;
return template;
}
}
export function createTemplate(nodes: LGraphNode[]): ComfyBoxTemplateResult {
if (nodes.length === 0) {
return {

View File

@@ -29,7 +29,7 @@ import queueState from "$lib/stores/queueState";
import selectionState from "$lib/stores/selectionState";
import uiState from "$lib/stores/uiState";
import workflowState, { ComfyBoxWorkflow, type WorkflowAttributes, type WorkflowInstID } from "$lib/stores/workflowState";
import type { SerializedPromptOutput } from "$lib/utils";
import { readFileToText, type SerializedPromptOutput } from "$lib/utils";
import { basename, capitalize, download, graphToGraphVis, jsonToJsObject, promptToGraphVis, range } from "$lib/utils";
import { tick } from "svelte";
import { type SvelteComponentDev } from "svelte/internal";
@@ -264,9 +264,9 @@ export default class ComfyApp {
*/
async loadConfig() {
try {
const config = await fetch(`/config.json`);
const state = await config.json() as ConfigState;
configState.set(state);
const config = await fetch(`/config.json`, { cache: "no-store" });
const newConfig = await config.json() as ConfigState;
configState.set({ ...get(configState), ...newConfig });
}
catch (error) {
console.error(`Failed to load config`, error)
@@ -274,7 +274,44 @@ export default class ComfyApp {
}
async loadBuiltInTemplates(): Promise<SerializedComfyBoxTemplate[]> {
return []
const builtInTemplates = get(configState).builtInTemplates
const options: RequestInit = get(configState).cacheBuiltInResources ? {} : { cache: "no-store" }
const promises = builtInTemplates.map(basename => {
return fetch(`/templates/${basename}.svg`, options)
.then(res => res.text())
.catch(error => error)
})
const [templates, error] = await Promise.all(promises).then((results) => {
const templates: SerializedComfyBoxTemplate[] = []
const errors: string[] = []
for (const r of results) {
if (r instanceof Error) {
errors.push(r.toString())
}
else {
// bare filename of image
const svg = r as string;
const templateAndSvg = deserializeTemplateFromSVG(svg)
if (templateAndSvg == null) {
errors.push("Invalid SVG template format")
}
templates.push(templateAndSvg)
}
}
let error = null;
if (errors && errors.length > 0)
error = "Error(s) loading builtin templates:\n" + errors.join("\n");
return [templates, error]
})
if (error)
notify(error, { type: "error" })
return templates;
}
resizeCanvas() {
@@ -786,7 +823,8 @@ export default class ComfyApp {
async initDefaultWorkflow(name: string = "defaultWorkflow", options?: OpenWorkflowOptions) {
let state = null;
try {
const graphResponse = await fetch(`/workflows/${name}.json`);
const options: RequestInit = get(configState).cacheBuiltInResources ? {} : { cache: "no-store" }
const graphResponse = await fetch(`/workflows/${name}.json`, options);
state = await graphResponse.json() as SerializedAppState;
}
catch (error) {
@@ -1061,7 +1099,12 @@ export default class ComfyApp {
};
reader.readAsText(file);
} else if (file.type === "image/svg+xml" || file.name.endsWith(".svg")) {
const templateAndSvg = await deserializeTemplateFromSVG(file);
const svg = await readFileToText(file);
const templateAndSvg = deserializeTemplateFromSVG(svg);
if (templateAndSvg == null) {
notify("Invalid SVG template format!", { type: "error" })
return;
}
const importTemplate = () => {
try {

View File

@@ -89,7 +89,7 @@
for (const r of results) {
if (r instanceof Error) {
errors.push(r.cause)
errors.push(r.toString())
}
else {
// bare filename of image

View File

@@ -17,6 +17,12 @@ export type ConfigState = {
/** When closing the tab, open the confirmation window if there's unsaved changes */
confirmWhenUnloadingUnsavedChanges: boolean,
/** Basenames of templates that can be loaded from public/templates. Saves LocalStorage space. */
builtInTemplates: string[],
/** Cache loading of built-in resources to save network use */
cacheBuiltInResources: boolean
}
type ConfigStateOps = {
@@ -30,7 +36,9 @@ const store: Writable<ConfigState> = writable(
comfyUIPort: 8188,
alwaysStripUserState: false,
promptForWorkflowName: false,
confirmWhenUnloadingUnsavedChanges: true
confirmWhenUnloadingUnsavedChanges: true,
builtInTemplates: [],
cacheBuiltInResources: true,
})
function getBackendURL(): string {

View File

@@ -598,3 +598,13 @@ export function calcNodesBoundingBox(nodes: SerializedLGraphNode[]): Vector4 {
return [min_x, min_y, max_x, max_y];
}
export async function readFileToText(file: File): Promise<string> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = async () => {
resolve(reader.result as string);
};
reader.readAsText(file);
})
}