Fork of KJNodes' Ideogram 4 Prompt Builder with stores, multi-select, scene save/load, live background preview, and separate width/height outputs. Co-authored-by: Cursor <cursoragent@cursor.com>
93 lines
2.8 KiB
JavaScript
93 lines
2.8 KiB
JavaScript
/** Shared helpers between the enhanced builder nodes. */
|
|
|
|
import { nodeClassName } from "./utility.js";
|
|
|
|
const { app } = window.comfyAPI.app;
|
|
|
|
export const BUILDER_CLASS = "Ideogram4PromptBuilderKJEnhancedByAE";
|
|
export const PREVIEW_UPDATE_CLASS = "Ideogram4PromptBuilderKJPreviewUpdateByAE";
|
|
const STORE_API = "/byae/ideogram/stores";
|
|
|
|
const EMPTY_STORES = () => ({ characters: {}, objects: {}, scenes: {} });
|
|
|
|
export async function loadStores() {
|
|
try {
|
|
const resp = await fetch(STORE_API);
|
|
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
|
|
const data = await resp.json();
|
|
return {
|
|
characters: data.characters || {},
|
|
objects: data.objects || {},
|
|
scenes: data.scenes || {},
|
|
};
|
|
} catch (e) {
|
|
console.warn("ByAE Ideogram: failed to load stores", e);
|
|
return EMPTY_STORES();
|
|
}
|
|
}
|
|
|
|
export async function saveStoreEntry(bucket, name, data) {
|
|
const resp = await fetch(`${STORE_API}/${bucket}/${encodeURIComponent(name)}`, {
|
|
method: "PUT",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify(data),
|
|
});
|
|
if (!resp.ok) {
|
|
let msg = `HTTP ${resp.status}`;
|
|
try {
|
|
const err = await resp.json();
|
|
if (err?.error) msg = err.error;
|
|
} catch (e) { /* ignore */ }
|
|
throw new Error(msg);
|
|
}
|
|
}
|
|
|
|
export function findBuildersOnGraph(graph) {
|
|
if (!graph?._nodes) return [];
|
|
return graph._nodes.filter((n) => nodeClassName(n) === BUILDER_CLASS);
|
|
}
|
|
|
|
let _bgPushListenerInstalled = false;
|
|
|
|
/** Listen for server push when Preview BG Update writes a temp file. */
|
|
export function installBgUpdateListener() {
|
|
if (_bgPushListenerInstalled) return;
|
|
_bgPushListenerInstalled = true;
|
|
const { api } = window.comfyAPI.api;
|
|
api.addEventListener("byae_ideogram_bg_updated", ({ detail }) => {
|
|
if (!detail?.guid) return;
|
|
const graph = app.graph;
|
|
if (!graph?._nodes) return;
|
|
for (const node of findBuildersOnGraph(graph)) {
|
|
const guid = node.properties?.byae_bg_guid;
|
|
if (guid && guid === detail.guid) {
|
|
node.byaeApplyBgUpdate?.(detail);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
let _queueHooksInstalled = false;
|
|
|
|
/** Inject internal editor fields into the workflow prompt (no native backing widgets). */
|
|
export function installBuilderQueueHooks() {
|
|
if (_queueHooksInstalled) return;
|
|
_queueHooksInstalled = true;
|
|
const orig = app.graphToPrompt?.bind(app);
|
|
if (!orig) return;
|
|
app.graphToPrompt = async function (...args) {
|
|
const builders = findBuildersOnGraph(app.graph);
|
|
for (const n of builders) n.byaePersistState?.();
|
|
const res = await orig(...args);
|
|
if (!res?.output) return res;
|
|
for (const n of builders) {
|
|
const patch = n.byaeGetPromptInputs?.();
|
|
if (!patch) continue;
|
|
const key = String(n.id);
|
|
if (!res.output[key]) continue;
|
|
res.output[key].inputs = { ...(res.output[key].inputs || {}), ...patch };
|
|
}
|
|
return res;
|
|
};
|
|
}
|