7372 lines
255 KiB
JavaScript
7372 lines
255 KiB
JavaScript
import { $ as e, At as t, Bt as n, Dt as r, Et as i, Ft as a, Lt as o, Mt as s, Nt as c, Ot as l, P as u, Pt as d, Tt as f, U as p, Ut as m, Vt as h, Wt as g, X as _, Xt as v, Yt as y, Zt as b, an as x, at as S, ct as ee, dt as C, et as te, ft as w, in as T, it as ne, j as re, jt as ie, k as ae, kt as oe, nt as E, ot as se, pt as ce, qt as D, rt as le, st as ue, t as de, tt as fe, ut as pe, wt as me, z as he, zt as ge } from "./floatingViewerManager-DwwPSNFX.js";
|
|
import { A as _e, E as ve, G as ye, M as be, O as xe, a as O, c as Se, d as Ce, dt as we, f as Te, l as Ee, m as De, o as k, p as A, s as Oe, u as ke, v as Ae, w as je } from "./events-C6W1gWsG.js";
|
|
import { $ as j, C as M, D as N, E as P, F as Me, G as Ne, H as Pe, L as F, O as Fe, P as Ie, Q as Le, T as Re, V as ze, W as Be, a as Ve, at as I, b as He, c as Ue, ct as L, d as We, f as Ge, g as Ke, h as qe, i as Je, k as Ye, l as Xe, m as Ze, n as Qe, o as $e, ot as et, p as tt, r as nt, s as rt, st as R, t as it, u as at, v as ot, w as z, x as B, y as st, z as V } from "./mjr-primevue-CJ2E0Gsv.js";
|
|
import { n as ct, r as lt, t as ut } from "./mjr-vue-vendor-DRftM6R3.js";
|
|
import { a as dt, i as ft, n as pt, o as mt, r as ht, t as gt } from "./geninfoParser-5vKgjqjD.js";
|
|
//#region ui/utils/events.ts
|
|
function _t(e, t, { target: n = null, warnPrefix: r = "[Majoor]" } = {}) {
|
|
let i = n || (typeof window < "u" ? window : null);
|
|
if (!i || typeof i.dispatchEvent != "function") return !1;
|
|
try {
|
|
return i.dispatchEvent(new CustomEvent(e, { detail: t }));
|
|
} catch (t) {
|
|
try {
|
|
console.warn(`${r} Failed to dispatch event: ${e}`, t);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
return !1;
|
|
}
|
|
}
|
|
//#endregion
|
|
//#region ui/app/settings/settingsUtils.ts
|
|
var H = (e, t) => {
|
|
if (typeof e == "boolean") return e;
|
|
if (typeof e == "string") {
|
|
let t = e.trim().toLowerCase();
|
|
if ([
|
|
"1",
|
|
"true",
|
|
"yes",
|
|
"on"
|
|
].includes(t)) return !0;
|
|
if ([
|
|
"0",
|
|
"false",
|
|
"no",
|
|
"off"
|
|
].includes(t)) return !1;
|
|
}
|
|
return !!t;
|
|
}, U = (e, t) => {
|
|
let n = Number(e);
|
|
return Number.isFinite(n) ? n : Number(t);
|
|
}, vt = (e, t, n) => {
|
|
let r = typeof e == "string" ? e.trim() : String(e ?? "");
|
|
return t.includes(r) ? r : n;
|
|
}, yt = (e) => e === "__proto__" || e === "prototype" || e === "constructor", bt = (e, t) => {
|
|
let n = { ...e };
|
|
return !t || typeof t != "object" || Object.keys(t).forEach((r) => {
|
|
if (yt(r)) return;
|
|
let i = t[r];
|
|
i && typeof i == "object" && !Array.isArray(i) ? n[r] = bt(e[r] || {}, i) : i !== void 0 && (n[r] = i);
|
|
}), n;
|
|
}, xt = Object.freeze({
|
|
small: 80,
|
|
medium: 120,
|
|
large: 180
|
|
}), St = Object.freeze([
|
|
"small",
|
|
"medium",
|
|
"large"
|
|
]), Ct = (e, t) => Math.max(60, Math.min(600, Math.round(U(e, t)))), wt = (e = {}) => {
|
|
let t = Number(e?.minSize);
|
|
if (Number.isFinite(t)) return Ct(t, k.GRID_MIN_SIZE);
|
|
let n = vt(String(e?.minSizePreset || "").toLowerCase(), St, "");
|
|
return n ? xt[n] : Ct(e?.minSize, k.GRID_MIN_SIZE);
|
|
}, Tt = (e = {}) => Ct(e?.minSize, k.FEED_GRID_MIN_SIZE), Et = (e) => {
|
|
let t = Math.round(U(e, k.GRID_MIN_SIZE));
|
|
return t <= 100 ? "small" : t >= 150 ? "large" : "medium";
|
|
}, Dt = async (e, t = "Majoor", n = {}) => {
|
|
let r = jt();
|
|
if (r && typeof r.alert == "function") try {
|
|
await r.alert({
|
|
title: String(t || "Majoor"),
|
|
message: String(e || "")
|
|
});
|
|
return;
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
let i = Mt();
|
|
if (i) try {
|
|
let n = String(e || "");
|
|
typeof i.addAlert == "function" ? i.addAlert(n) : i.add({
|
|
severity: "info",
|
|
summary: String(t || "Majoor"),
|
|
detail: n,
|
|
life: 5e3
|
|
});
|
|
return;
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
if (n?.native !== !1) {
|
|
let n = Nt();
|
|
if (n) try {
|
|
n.show(Pt(e, t));
|
|
try {
|
|
n.element?.style?.setProperty?.("z-index", "1100");
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
return;
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
}
|
|
let a = zt();
|
|
if (!a) {
|
|
try {
|
|
window.alert(e);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
return;
|
|
}
|
|
return new Promise((n) => {
|
|
let r = new a();
|
|
Ut(r);
|
|
let i = W("div", { style: {
|
|
display: "flex",
|
|
flexDirection: "column",
|
|
gap: "18px",
|
|
padding: "18px 20px 18px 20px"
|
|
} }, [
|
|
W("div", { style: {
|
|
display: "flex",
|
|
alignItems: "center",
|
|
justifyContent: "flex-start"
|
|
} }, [W("div", {
|
|
textContent: t,
|
|
style: {
|
|
fontWeight: "700",
|
|
fontSize: "30px",
|
|
color: "rgba(255,255,255,0.96)",
|
|
lineHeight: "1.2"
|
|
}
|
|
})]),
|
|
W("div", {
|
|
textContent: String(e || ""),
|
|
style: {
|
|
fontSize: "22px",
|
|
color: "rgba(255,255,255,0.86)",
|
|
whiteSpace: "pre-wrap",
|
|
lineHeight: "1.45"
|
|
}
|
|
}),
|
|
W("div", { style: {
|
|
display: "flex",
|
|
justifyContent: "flex-end",
|
|
gap: "10px"
|
|
} }, [W("button", {
|
|
textContent: A("dialog.confirm", "Confirm"),
|
|
onclick: () => {
|
|
try {
|
|
r.close();
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
n();
|
|
},
|
|
style: {
|
|
padding: "10px 16px",
|
|
borderRadius: "10px",
|
|
border: "1px solid rgba(17,132,255,0.75)",
|
|
background: "#1184ff",
|
|
color: "rgba(255,255,255,0.98)",
|
|
fontWeight: "600",
|
|
cursor: "pointer"
|
|
}
|
|
})])
|
|
]);
|
|
try {
|
|
r.show(i), setTimeout(() => Wt(r), 0);
|
|
} catch {
|
|
try {
|
|
window.alert(e);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
n();
|
|
}
|
|
});
|
|
}, Ot = async (e, t = "Majoor") => {
|
|
let n = jt();
|
|
if (n) try {
|
|
let r = {
|
|
title: String(t || A("dialog.confirm", "Confirm")),
|
|
message: String(e || "")
|
|
};
|
|
return !!(typeof n.confirm == "function" && await n.confirm(r));
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
let r = zt();
|
|
if (!r) try {
|
|
return window.confirm(e);
|
|
} catch {
|
|
return !1;
|
|
}
|
|
return new Promise((n) => {
|
|
let i = new r();
|
|
Ut(i);
|
|
let a = (e) => {
|
|
try {
|
|
i.close();
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
n(!!e);
|
|
}, o = W("div", { style: {
|
|
display: "flex",
|
|
flexDirection: "column",
|
|
gap: "18px",
|
|
padding: "18px 20px 18px 20px"
|
|
} }, [
|
|
W("div", { style: {
|
|
display: "flex",
|
|
alignItems: "center",
|
|
justifyContent: "flex-start"
|
|
} }, [W("div", {
|
|
textContent: t,
|
|
style: {
|
|
fontWeight: "700",
|
|
fontSize: "30px",
|
|
color: "rgba(255,255,255,0.96)",
|
|
lineHeight: "1.2"
|
|
}
|
|
})]),
|
|
W("div", {
|
|
textContent: String(e || ""),
|
|
style: {
|
|
fontSize: "22px",
|
|
color: "rgba(255,255,255,0.86)",
|
|
whiteSpace: "pre-wrap",
|
|
lineHeight: "1.45"
|
|
}
|
|
}),
|
|
W("div", { style: {
|
|
display: "flex",
|
|
justifyContent: "flex-end",
|
|
gap: "10px"
|
|
} }, [W("button", {
|
|
textContent: A("dialog.cancel", "Cancel"),
|
|
onclick: () => a(!1),
|
|
style: {
|
|
padding: "10px 16px",
|
|
borderRadius: "10px",
|
|
border: "1px solid rgba(255,255,255,0.18)",
|
|
background: "rgba(255,255,255,0.06)",
|
|
color: "rgba(255,255,255,0.85)",
|
|
fontWeight: "600",
|
|
cursor: "pointer"
|
|
}
|
|
}), W("button", {
|
|
textContent: A("dialog.confirm", "Confirm"),
|
|
onclick: () => a(!0),
|
|
style: {
|
|
padding: "10px 16px",
|
|
borderRadius: "10px",
|
|
border: "1px solid rgba(17,132,255,0.75)",
|
|
background: "#1184ff",
|
|
color: "rgba(255,255,255,0.98)",
|
|
fontWeight: "600",
|
|
cursor: "pointer"
|
|
}
|
|
})])
|
|
]);
|
|
try {
|
|
i.show(o), setTimeout(() => Wt(i), 0);
|
|
} catch {
|
|
try {
|
|
n(!!window.confirm(e));
|
|
} catch {
|
|
n(!1);
|
|
}
|
|
}
|
|
});
|
|
}, kt = async (e, t = "", n = "Majoor") => {
|
|
let r = jt();
|
|
if (r) try {
|
|
let i = {
|
|
title: String(n || A("dialog.prompt", "Prompt")),
|
|
message: String(e || ""),
|
|
defaultValue: String(t ?? "")
|
|
}, a = typeof r.prompt == "function" ? await r.prompt(i) : null;
|
|
return a == null ? null : String(a);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
let i = zt();
|
|
if (!i) try {
|
|
return window.prompt(e, t);
|
|
} catch {
|
|
return null;
|
|
}
|
|
return new Promise((r) => {
|
|
let a = new i();
|
|
Ut(a);
|
|
let o = (e) => {
|
|
try {
|
|
a.close();
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
r(e ?? null);
|
|
}, s = W("input", {
|
|
type: "text",
|
|
value: String(t ?? ""),
|
|
style: {
|
|
width: "100%",
|
|
padding: "10px 10px",
|
|
borderRadius: "10px",
|
|
border: "1px solid rgba(255,255,255,0.12)",
|
|
background: "rgba(0,0,0,0.25)",
|
|
color: "rgba(255,255,255,0.9)",
|
|
outline: "none",
|
|
boxSizing: "border-box"
|
|
},
|
|
onkeydown: (e) => {
|
|
e.key === "Enter" && o(s.value), e.key === "Escape" && o(null), e.stopPropagation();
|
|
}
|
|
}), c = W("div", { style: {
|
|
display: "flex",
|
|
flexDirection: "column",
|
|
gap: "12px",
|
|
padding: "16px"
|
|
} }, [
|
|
W("div", {
|
|
textContent: n,
|
|
style: {
|
|
fontWeight: "600",
|
|
fontSize: "14px",
|
|
color: "rgba(255,255,255,0.95)"
|
|
}
|
|
}),
|
|
W("div", {
|
|
textContent: String(e || ""),
|
|
style: {
|
|
fontSize: "13px",
|
|
color: "rgba(255,255,255,0.80)",
|
|
whiteSpace: "pre-wrap",
|
|
lineHeight: "1.4"
|
|
}
|
|
}),
|
|
s,
|
|
W("div", { style: {
|
|
display: "flex",
|
|
justifyContent: "flex-end",
|
|
gap: "10px"
|
|
} }, [W("button", {
|
|
textContent: A("dialog.cancel", "Cancel"),
|
|
onclick: () => o(null),
|
|
style: {
|
|
padding: "8px 12px",
|
|
borderRadius: "8px",
|
|
border: "1px solid rgba(255,255,255,0.12)",
|
|
background: "rgba(0,0,0,0.25)",
|
|
color: "rgba(255,255,255,0.85)",
|
|
cursor: "pointer"
|
|
}
|
|
}), W("button", {
|
|
textContent: A("dialog.ok", "OK"),
|
|
onclick: () => o(s.value),
|
|
style: {
|
|
padding: "8px 12px",
|
|
borderRadius: "8px",
|
|
border: "1px solid rgba(95,179,255,0.45)",
|
|
background: "rgba(95,179,255,0.18)",
|
|
color: "rgba(255,255,255,0.95)",
|
|
cursor: "pointer"
|
|
}
|
|
})])
|
|
]);
|
|
try {
|
|
a.show(c), setTimeout(() => Wt(a), 0), setTimeout(() => {
|
|
try {
|
|
s.focus(), s.select();
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
}, 0);
|
|
} catch {
|
|
try {
|
|
r(window.prompt(e, t));
|
|
} catch {
|
|
r(null);
|
|
}
|
|
}
|
|
});
|
|
}, At = () => {
|
|
try {
|
|
return _e()?.ui || null;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}, jt = () => {
|
|
let e = (e) => !!e && (typeof e.alert == "function" || typeof e.confirm == "function" || typeof e.prompt == "function");
|
|
try {
|
|
let t = ve();
|
|
if (e(t)) return t;
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
return null;
|
|
}, Mt = () => {
|
|
try {
|
|
let e = xe();
|
|
if (e && typeof e.add == "function") return e;
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
return null;
|
|
}, Nt = () => {
|
|
try {
|
|
let e = At();
|
|
if (e?.dialog && typeof e.dialog.show == "function") return e.dialog;
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
return null;
|
|
}, Pt = (e, t = "Majoor") => {
|
|
let n = String(e ?? ""), r = String(t ?? "").trim();
|
|
return !r || r.toLowerCase() === "majoor" ? n : `${r}<br><br>${n}`;
|
|
}, Ft = new Set(/* @__PURE__ */ "abort.blur.change.click.close.contextmenu.dblclick.dragend.dragenter.dragleave.dragover.dragstart.drop.error.focus.input.keydown.keypress.keyup.load.mousedown.mouseenter.mouseleave.mousemove.mouseout.mouseover.mouseup.reset.resize.scroll.select.submit.touchcancel.touchend.touchmove.touchstart.transitionend.unload.wheel".split(".")), It = new Set([
|
|
"__proto__",
|
|
"constructor",
|
|
"prototype",
|
|
"innerHTML",
|
|
"outerHTML",
|
|
"srcdoc",
|
|
"__defineGetter__",
|
|
"__defineSetter__",
|
|
"__lookupGetter__",
|
|
"__lookupSetter__"
|
|
]), Lt = new Set([
|
|
"id",
|
|
"name",
|
|
"value",
|
|
"type",
|
|
"checked",
|
|
"disabled",
|
|
"placeholder",
|
|
"title",
|
|
"textContent",
|
|
"htmlFor",
|
|
"role",
|
|
"tabIndex"
|
|
]), Rt = (e, t = {}, n = []) => {
|
|
let r = document.createElement(e);
|
|
return Object.entries(t || {}).forEach(([e, t]) => {
|
|
let n = String(e || "");
|
|
if (!(!n || It.has(n))) {
|
|
if (e === "style" && t && typeof t == "object") {
|
|
Object.assign(r.style, t);
|
|
return;
|
|
}
|
|
if (e === "className") {
|
|
r.className = String(t);
|
|
return;
|
|
}
|
|
if (n.startsWith("on")) {
|
|
if (typeof t == "function") {
|
|
let e = n.slice(2).toLowerCase();
|
|
Ft.has(e) && r.addEventListener(e, t);
|
|
}
|
|
return;
|
|
}
|
|
if (Lt.has(n)) try {
|
|
r[n] = t;
|
|
return;
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
try {
|
|
r.setAttribute(n, String(t));
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
}
|
|
}), (Array.isArray(n) ? n : [n]).filter(Boolean).forEach((e) => {
|
|
try {
|
|
r.appendChild(e);
|
|
} catch {
|
|
r.appendChild(document.createTextNode(String(e)));
|
|
}
|
|
}), r;
|
|
}, W = (e, t, n) => {
|
|
let r = At();
|
|
if (r?.$el) try {
|
|
return r.$el(e, t, n);
|
|
} catch {}
|
|
return Rt(e, t, n);
|
|
}, zt = () => At()?.ComfyDialog || null, Bt = 999999, Vt = 560, Ht = 12, Ut = (e) => {
|
|
try {
|
|
e.element.style.zIndex = String(Bt), e.element.style.width = `${Vt}px`, e.element.style.padding = "0", e.element.style.backgroundColor = "var(--comfy-menu-bg, #131722)", e.element.style.border = "1px solid rgba(255,255,255,0.14)", e.element.style.borderRadius = `${Ht}px`, e.element.style.boxSizing = "border-box", e.element.style.overflow = "hidden", e.element.style.boxShadow = "0 18px 48px rgba(0,0,0,0.48)";
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
}, Wt = (e) => {
|
|
try {
|
|
let t = e?.element;
|
|
if (!t) return;
|
|
let n = t.querySelectorAll("button,[role='button']");
|
|
for (let e of n) {
|
|
let t = String(e?.textContent || "").trim().toLowerCase(), n = String(e?.getAttribute?.("aria-label") || "").trim().toLowerCase();
|
|
if (t === "close" || n === "close") try {
|
|
e.style.display = "none";
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
}
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
}, G = {
|
|
debug: {
|
|
safeCall: k.DEBUG_SAFE_CALL,
|
|
safeListeners: k.DEBUG_SAFE_LISTENERS,
|
|
viewer: k.DEBUG_VIEWER
|
|
},
|
|
grid: {
|
|
pageSize: k.DEFAULT_PAGE_SIZE,
|
|
minSize: k.GRID_MIN_SIZE,
|
|
minSizePreset: Et(k.GRID_MIN_SIZE),
|
|
gap: k.GRID_GAP,
|
|
showExtBadge: k.GRID_SHOW_BADGES_EXTENSION,
|
|
showRatingBadge: k.GRID_SHOW_BADGES_RATING,
|
|
showTagsBadge: k.GRID_SHOW_BADGES_TAGS,
|
|
showDetails: k.GRID_SHOW_DETAILS,
|
|
showFilename: k.GRID_SHOW_DETAILS_FILENAME,
|
|
showDate: k.GRID_SHOW_DETAILS_DATE,
|
|
showDimensions: k.GRID_SHOW_DETAILS_DIMENSIONS,
|
|
showGenTime: k.GRID_SHOW_DETAILS_GENTIME,
|
|
showHoverInfo: k.GRID_SHOW_HOVER_INFO,
|
|
showWorkflowDot: k.GRID_SHOW_WORKFLOW_DOT,
|
|
workflowGroupBy: k.WORKFLOW_GRID_GROUP_BY,
|
|
videoAutoplayMode: k.GRID_VIDEO_AUTOPLAY_MODE,
|
|
starColor: k.BADGE_STAR_COLOR,
|
|
badgeImageColor: k.BADGE_IMAGE_COLOR,
|
|
badgeVideoColor: k.BADGE_VIDEO_COLOR,
|
|
badgeAudioColor: k.BADGE_AUDIO_COLOR,
|
|
badgeModel3dColor: k.BADGE_MODEL3D_COLOR,
|
|
badgeDuplicateAlertColor: k.BADGE_DUPLICATE_ALERT_COLOR
|
|
},
|
|
infiniteScroll: {
|
|
enabled: k.INFINITE_SCROLL_ENABLED,
|
|
rootMargin: k.INFINITE_SCROLL_ROOT_MARGIN,
|
|
threshold: k.INFINITE_SCROLL_THRESHOLD,
|
|
bottomGapPx: k.BOTTOM_GAP_PX
|
|
},
|
|
siblings: { hidePngSiblings: !0 },
|
|
autoScan: { onStartup: k.AUTO_SCAN_ON_STARTUP },
|
|
scan: { fastMode: !0 },
|
|
watcher: {
|
|
enabled: !0,
|
|
debounceMs: k.WATCHER_DEBOUNCE_MS,
|
|
dedupeTtlMs: k.WATCHER_DEDUPE_TTL_MS,
|
|
maxPending: 500,
|
|
minSize: 100,
|
|
maxSize: 4294967296
|
|
},
|
|
safety: { confirmDeletion: !0 },
|
|
status: { pollInterval: k.STATUS_POLL_INTERVAL },
|
|
viewer: {
|
|
allowPanAtZoom1: k.VIEWER_ALLOW_PAN_AT_ZOOM_1,
|
|
disableWebGL: k.VIEWER_DISABLE_WEBGL_VIDEO,
|
|
pauseDuringExecution: k.VIEWER_PAUSE_DURING_EXECUTION,
|
|
floatingPauseDuringExecution: k.FLOATING_VIEWER_PAUSE_DURING_EXECUTION,
|
|
mfvLiveDefault: k.MFV_LIVE_DEFAULT,
|
|
mfvPreviewDefault: k.MFV_PREVIEW_DEFAULT,
|
|
videoGradeThrottleFps: k.VIEWER_VIDEO_GRADE_THROTTLE_FPS,
|
|
scopesFps: k.VIEWER_SCOPES_FPS,
|
|
metaTtlMs: k.VIEWER_META_TTL_MS,
|
|
metaMaxEntries: k.VIEWER_META_MAX_ENTRIES,
|
|
mfvSidebarPosition: "right",
|
|
mfvPreviewMethod: k.MFV_PREVIEW_METHOD,
|
|
ltxavRgbFallback: !1
|
|
},
|
|
rtHydrate: {
|
|
concurrency: k.RT_HYDRATE_CONCURRENCY,
|
|
queueMax: k.RT_HYDRATE_QUEUE_MAX,
|
|
seenMax: k.RT_HYDRATE_SEEN_MAX,
|
|
pruneBudget: k.RT_HYDRATE_PRUNE_BUDGET,
|
|
seenTtlMs: k.RT_HYDRATE_SEEN_TTL_MS
|
|
},
|
|
observability: {
|
|
enabled: !1,
|
|
runtimeDashboardMode: "autoHide30",
|
|
verboseErrors: !1,
|
|
verboseRouteRegistrationLogs: !1,
|
|
verboseStartupLogs: !1
|
|
},
|
|
feed: {
|
|
minSize: k.FEED_GRID_MIN_SIZE,
|
|
showInfo: k.FEED_SHOW_INFO,
|
|
showFilename: k.FEED_SHOW_FILENAME,
|
|
showDimensions: k.FEED_SHOW_DIMENSIONS,
|
|
showDate: k.FEED_SHOW_DATE,
|
|
showGenTime: k.FEED_SHOW_GENTIME,
|
|
showWorkflowDot: k.FEED_SHOW_WORKFLOW_DOT,
|
|
showExtBadge: k.FEED_SHOW_BADGES_EXTENSION,
|
|
showRatingBadge: k.FEED_SHOW_BADGES_RATING,
|
|
showTagsBadge: k.FEED_SHOW_BADGES_TAGS
|
|
},
|
|
sidebar: {
|
|
position: "right",
|
|
showPreviewThumb: !0,
|
|
widthPx: 360
|
|
},
|
|
probeBackend: { mode: "auto" },
|
|
i18n: { followComfyLanguage: !0 },
|
|
metadataFallback: {
|
|
image: !0,
|
|
media: !0
|
|
},
|
|
paths: {
|
|
outputDirectory: "",
|
|
indexDirectory: "",
|
|
workflowRoots: ""
|
|
},
|
|
db: {
|
|
timeoutMs: 5e3,
|
|
maxConnections: 10,
|
|
queryTimeoutMs: 1e3
|
|
},
|
|
ratingTagsSync: { enabled: !0 },
|
|
cache: { tagsTTLms: 3e4 },
|
|
search: { maxResults: k.SEARCH_DEFAULT_LIMIT },
|
|
ai: {
|
|
vectorSearchEnabled: !0,
|
|
vectorCaptionOnIndex: !1,
|
|
verboseAiLogs: !1
|
|
},
|
|
executionGrouping: { enabled: k.EXECUTION_GROUPING_ENABLED },
|
|
workflowMinimap: {
|
|
enabled: k.WORKFLOW_MINIMAP_ENABLED,
|
|
nodeColors: !0,
|
|
showLinks: !0,
|
|
showGroups: !0,
|
|
renderBypassState: !0,
|
|
renderErrorState: !0,
|
|
showViewport: !0,
|
|
showNodeLabels: !1,
|
|
size: "comfortable"
|
|
},
|
|
ui: {
|
|
cardHoverColor: k.UI_CARD_HOVER_COLOR,
|
|
cardSelectionColor: k.UI_CARD_SELECTION_COLOR,
|
|
ratingColor: k.UI_RATING_COLOR,
|
|
tagColor: k.UI_TAG_COLOR
|
|
},
|
|
security: {
|
|
safeMode: !1,
|
|
allowWrite: !0,
|
|
allowRemoteWrite: !0,
|
|
allowDelete: !0,
|
|
allowRename: !0,
|
|
allowOpenInFolder: !0,
|
|
allowResetIndex: !0,
|
|
apiToken: "",
|
|
tokenConfigured: !1,
|
|
tokenHint: ""
|
|
}
|
|
}, K = () => {
|
|
try {
|
|
let e = De.get(x);
|
|
if (!e) return { ...G };
|
|
let t = JSON.parse(e), n = t && typeof t == "object" && Number.isInteger(t.version) && t.data && typeof t.data == "object";
|
|
if (!n && !(t && typeof t == "object" && !Array.isArray(t))) return { ...G };
|
|
if (n && Number(t.version) > 1) return console.warn("[Majoor] settings schema version is newer than this build, using defaults"), { ...G };
|
|
let r = n ? t.data : t, i = new Set(/* @__PURE__ */ "debug.grid.infiniteScroll.siblings.autoScan.scan.watcher.status.viewer.rtHydrate.observability.feed.sidebar.probeBackend.i18n.paths.db.ratingTagsSync.cache.search.ai.executionGrouping.workflowMinimap.ui.security.safety".split(".")), a = {};
|
|
if (r && typeof r == "object") for (let [e, t] of Object.entries(r)) i.has(e) && (a[e] = t);
|
|
let o = bt(G, a);
|
|
if (!n) try {
|
|
q(o);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
return o;
|
|
} catch (e) {
|
|
return console.warn("[Majoor] settings load failed, using defaults", e), { ...G };
|
|
}
|
|
}, q = (e) => {
|
|
try {
|
|
let t = JSON.parse(JSON.stringify(e || {}));
|
|
t?.security && typeof t.security == "object" && (t.security.apiToken = "");
|
|
let n = {
|
|
version: 1,
|
|
data: t
|
|
};
|
|
if (!De.set("mjrSettings", JSON.stringify(n))) throw Error("SettingsStore rejected the write");
|
|
} catch (e) {
|
|
console.warn("[Majoor] settings save failed", e);
|
|
try {
|
|
let e = Date.now();
|
|
e - (Number(window?._mjrSettingsSaveFailAt || 0) || 0) > 3e4 && (window._mjrSettingsSaveFailAt = e, Dt(A("dialog.settingsSaveFailed", "Majoor: Failed to save settings (browser storage full or blocked).")));
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
try {
|
|
_t("mjr-settings-save-failed", { error: String(e?.message || e || "") }, { warnPrefix: "[Majoor]" });
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
}
|
|
}, J = (e) => {
|
|
let t = Number(k.MAX_PAGE_SIZE) || 2e3;
|
|
O.DEFAULT_PAGE_SIZE = Math.max(50, Math.min(t, Number(e.grid?.pageSize) || k.DEFAULT_PAGE_SIZE)), O.AUTO_SCAN_ON_STARTUP = !!e.autoScan?.onStartup, O.EXECUTION_GROUPING_ENABLED = !!(e.executionGrouping?.enabled ?? k.EXECUTION_GROUPING_ENABLED), O.STATUS_POLL_INTERVAL = Math.max(1e3, Number(e.status?.pollInterval) || k.STATUS_POLL_INTERVAL), O.DEBUG_SAFE_CALL = !!e.debug?.safeCall, O.DEBUG_SAFE_LISTENERS = !!e.debug?.safeListeners, O.DEBUG_VIEWER = !!e.debug?.viewer, O.GRID_MIN_SIZE = wt(e.grid), O.FEED_GRID_MIN_SIZE = Tt(e.feed), O.GRID_GAP = Math.max(0, Math.min(40, Math.round(U(e.grid?.gap, k.GRID_GAP)))), O.GRID_SHOW_BADGES_EXTENSION = !!(e.grid?.showExtBadge ?? k.GRID_SHOW_BADGES_EXTENSION), O.GRID_SHOW_BADGES_RATING = !!(e.grid?.showRatingBadge ?? k.GRID_SHOW_BADGES_RATING), O.GRID_SHOW_BADGES_TAGS = !!(e.grid?.showTagsBadge ?? k.GRID_SHOW_BADGES_TAGS), O.GRID_SHOW_DETAILS = !!(e.grid?.showDetails ?? k.GRID_SHOW_DETAILS), O.GRID_SHOW_DETAILS_FILENAME = !!(e.grid?.showFilename ?? k.GRID_SHOW_DETAILS_FILENAME), O.GRID_SHOW_DETAILS_DATE = !!(e.grid?.showDate ?? k.GRID_SHOW_DETAILS_DATE), O.GRID_SHOW_DETAILS_DIMENSIONS = !!(e.grid?.showDimensions ?? k.GRID_SHOW_DETAILS_DIMENSIONS), O.GRID_SHOW_DETAILS_GENTIME = !!(e.grid?.showGenTime ?? k.GRID_SHOW_DETAILS_GENTIME), O.GRID_SHOW_HOVER_INFO = !!(e.grid?.showHoverInfo ?? k.GRID_SHOW_HOVER_INFO), O.GRID_SHOW_WORKFLOW_DOT = !!(e.grid?.showWorkflowDot ?? k.GRID_SHOW_WORKFLOW_DOT);
|
|
{
|
|
let t = String(e.grid?.workflowGroupBy ?? k.WORKFLOW_GRID_GROUP_BY).toLowerCase();
|
|
O.WORKFLOW_GRID_GROUP_BY = [
|
|
"none",
|
|
"task",
|
|
"model",
|
|
"category"
|
|
].includes(t) ? t : k.WORKFLOW_GRID_GROUP_BY;
|
|
}
|
|
O.FEED_SHOW_INFO = !!(e.feed?.showInfo ?? k.FEED_SHOW_INFO), O.FEED_SHOW_FILENAME = !!(e.feed?.showFilename ?? k.FEED_SHOW_FILENAME), O.FEED_SHOW_DIMENSIONS = !!(e.feed?.showDimensions ?? k.FEED_SHOW_DIMENSIONS), O.FEED_SHOW_DATE = !!(e.feed?.showDate ?? k.FEED_SHOW_DATE), O.FEED_SHOW_GENTIME = !!(e.feed?.showGenTime ?? k.FEED_SHOW_GENTIME), O.FEED_SHOW_WORKFLOW_DOT = !!(e.feed?.showWorkflowDot ?? k.FEED_SHOW_WORKFLOW_DOT), O.FEED_SHOW_BADGES_EXTENSION = !!(e.feed?.showExtBadge ?? k.FEED_SHOW_BADGES_EXTENSION), O.FEED_SHOW_BADGES_RATING = !!(e.feed?.showRatingBadge ?? k.FEED_SHOW_BADGES_RATING), O.FEED_SHOW_BADGES_TAGS = !!(e.feed?.showTagsBadge ?? k.FEED_SHOW_BADGES_TAGS);
|
|
{
|
|
let t = e.grid?.videoAutoplayMode ?? k.GRID_VIDEO_AUTOPLAY_MODE;
|
|
t ??= e.grid?.videoHoverAutoplay === !1 ? "off" : "hover", t === !0 && (t = "hover"), t === !1 && (t = "off"), t !== "hover" && t !== "always" && t !== "off" && (t = "hover"), O.GRID_VIDEO_AUTOPLAY_MODE = t;
|
|
}
|
|
let n = (e, t) => {
|
|
let n = String(e || "").trim();
|
|
return /^[0-9a-fA-F]{6}$/.test(n) && (n = `#${n}`), /^#[0-9a-fA-F]{3,8}$/.test(n) ? n : t;
|
|
};
|
|
O.BADGE_STAR_COLOR = n(e.grid?.starColor, k.BADGE_STAR_COLOR), O.BADGE_IMAGE_COLOR = n(e.grid?.badgeImageColor, k.BADGE_IMAGE_COLOR), O.BADGE_VIDEO_COLOR = n(e.grid?.badgeVideoColor, k.BADGE_VIDEO_COLOR), O.BADGE_AUDIO_COLOR = n(e.grid?.badgeAudioColor, k.BADGE_AUDIO_COLOR), O.BADGE_MODEL3D_COLOR = n(e.grid?.badgeModel3dColor, k.BADGE_MODEL3D_COLOR), O.BADGE_DUPLICATE_ALERT_COLOR = n(e.grid?.badgeDuplicateAlertColor, k.BADGE_DUPLICATE_ALERT_COLOR), O.UI_CARD_HOVER_COLOR = n(e.ui?.cardHoverColor, k.UI_CARD_HOVER_COLOR), O.UI_CARD_SELECTION_COLOR = n(e.ui?.cardSelectionColor, k.UI_CARD_SELECTION_COLOR), O.UI_RATING_COLOR = n(e.ui?.ratingColor, k.UI_RATING_COLOR), O.UI_TAG_COLOR = n(e.ui?.tagColor, k.UI_TAG_COLOR);
|
|
try {
|
|
let e = Array.from(document.querySelectorAll(".mjr-assets-manager"));
|
|
for (let t of e) t.style.setProperty("--mjr-star-active", O.BADGE_STAR_COLOR), t.style.setProperty("--mjr-badge-image", O.BADGE_IMAGE_COLOR), t.style.setProperty("--mjr-badge-video", O.BADGE_VIDEO_COLOR), t.style.setProperty("--mjr-badge-audio", O.BADGE_AUDIO_COLOR), t.style.setProperty("--mjr-badge-model3d", O.BADGE_MODEL3D_COLOR), t.style.setProperty("--mjr-badge-duplicate-alert", O.BADGE_DUPLICATE_ALERT_COLOR), t.style.setProperty("--mjr-card-hover-color", O.UI_CARD_HOVER_COLOR), t.style.setProperty("--mjr-card-selection-color", O.UI_CARD_SELECTION_COLOR), t.style.setProperty("--mjr-rating-color", O.UI_RATING_COLOR), t.style.setProperty("--mjr-tag-color", O.UI_TAG_COLOR);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
O.INFINITE_SCROLL_ENABLED = !!e.infiniteScroll?.enabled, O.INFINITE_SCROLL_ROOT_MARGIN = String(e.infiniteScroll?.rootMargin || k.INFINITE_SCROLL_ROOT_MARGIN), O.INFINITE_SCROLL_THRESHOLD = Math.max(0, Math.min(1, U(e.infiniteScroll?.threshold, k.INFINITE_SCROLL_THRESHOLD))), O.BOTTOM_GAP_PX = Math.max(0, Math.min(5e3, Math.round(U(e.infiniteScroll?.bottomGapPx, k.BOTTOM_GAP_PX)))), O.VIEWER_ALLOW_PAN_AT_ZOOM_1 = !!e.viewer?.allowPanAtZoom1, O.VIEWER_DISABLE_WEBGL_VIDEO = !!e.viewer?.disableWebGL, O.VIEWER_PAUSE_DURING_EXECUTION = !!(e.viewer?.pauseDuringExecution ?? k.VIEWER_PAUSE_DURING_EXECUTION), O.FLOATING_VIEWER_PAUSE_DURING_EXECUTION = !!(e.viewer?.floatingPauseDuringExecution ?? k.FLOATING_VIEWER_PAUSE_DURING_EXECUTION), O.MFV_LIVE_DEFAULT = e.viewer?.mfvLiveDefault ?? k.MFV_LIVE_DEFAULT, O.MFV_PREVIEW_DEFAULT = e.viewer?.mfvPreviewDefault ?? k.MFV_PREVIEW_DEFAULT, O.MFV_LIVE_AUTO_OPEN = !1, O.MFV_PREVIEW_AUTO_OPEN = !1, O.MFV_NODE_STREAM_AUTO_OPEN = !1;
|
|
{
|
|
let t = String(e.viewer?.mfvPreviewMethod || k.MFV_PREVIEW_METHOD).toLowerCase();
|
|
O.MFV_PREVIEW_METHOD = [
|
|
"default",
|
|
"auto",
|
|
"latent2rgb",
|
|
"taesd",
|
|
"none"
|
|
].includes(t) ? t : k.MFV_PREVIEW_METHOD;
|
|
}
|
|
{
|
|
let t = String(e.viewer?.mfvSidebarPosition || "right").toLowerCase();
|
|
O.MFV_SIDEBAR_POSITION = [
|
|
"left",
|
|
"right",
|
|
"bottom"
|
|
].includes(t) ? t : "right";
|
|
}
|
|
O.VIEWER_VIDEO_GRADE_THROTTLE_FPS = Math.max(1, Math.min(60, Math.round(U(e.viewer?.videoGradeThrottleFps, k.VIEWER_VIDEO_GRADE_THROTTLE_FPS)))), O.VIEWER_SCOPES_FPS = Math.max(1, Math.min(60, Math.round(U(e.viewer?.scopesFps, k.VIEWER_SCOPES_FPS)))), O.VIEWER_META_TTL_MS = Math.max(1e3, Math.min(10 * 6e4, Math.round(U(e.viewer?.metaTtlMs, k.VIEWER_META_TTL_MS)))), O.VIEWER_META_MAX_ENTRIES = Math.max(50, Math.min(5e3, Math.round(U(e.viewer?.metaMaxEntries, k.VIEWER_META_MAX_ENTRIES)))), O.WORKFLOW_MINIMAP_ENABLED = !!(e.workflowMinimap?.enabled ?? k.WORKFLOW_MINIMAP_ENABLED), O.RT_HYDRATE_CONCURRENCY = Math.max(1, Math.min(16, Math.round(U(e.rtHydrate?.concurrency, k.RT_HYDRATE_CONCURRENCY)))), O.RT_HYDRATE_QUEUE_MAX = Math.max(10, Math.min(5e3, Math.round(U(e.rtHydrate?.queueMax, k.RT_HYDRATE_QUEUE_MAX)))), O.RT_HYDRATE_SEEN_MAX = Math.max(1e3, Math.min(2e5, Math.round(U(e.rtHydrate?.seenMax, k.RT_HYDRATE_SEEN_MAX)))), O.RT_HYDRATE_PRUNE_BUDGET = Math.max(10, Math.min(1e4, Math.round(U(e.rtHydrate?.pruneBudget, k.RT_HYDRATE_PRUNE_BUDGET)))), O.RT_HYDRATE_SEEN_TTL_MS = Math.max(5e3, Math.min(360 * 6e4, Math.round(U(e.rtHydrate?.seenTtlMs, k.RT_HYDRATE_SEEN_TTL_MS)))), O.DELETE_CONFIRMATION = !!e.safety?.confirmDeletion, O.DEBUG_VERBOSE_ERRORS = !!e.observability?.verboseErrors, O.WATCHER_MAX_PENDING = Math.max(10, Math.min(5e3, Math.round(U(e.watcher?.maxPending, 500)))), O.WATCHER_MIN_SIZE = Math.max(0, Math.min(1e6, Math.round(U(e.watcher?.minSize, 100)))), O.WATCHER_MAX_SIZE = Math.max(1e5, Math.min(17179869184, Math.round(U(e.watcher?.maxSize, 4294967296)))), O.DB_TIMEOUT_MS = Math.max(1e3, Math.min(3e4, Math.round(U(e.db?.timeoutMs, 5e3)))), O.DB_MAX_CONNECTIONS = Math.max(1, Math.min(100, Math.round(U(e.db?.maxConnections, 10)))), O.DB_QUERY_TIMEOUT_MS = Math.max(500, Math.min(1e4, Math.round(U(e.db?.queryTimeoutMs, 1e3)))), O.SEARCH_REQUEST_LIMIT = Math.max(10, Math.min(k.MAX_PAGE_SIZE || 2e3, Math.round(U(e.search?.maxResults, k.SEARCH_DEFAULT_LIMIT))));
|
|
};
|
|
async function Gt() {
|
|
try {
|
|
let e = await ue();
|
|
if (!e?.ok) return;
|
|
let t = e.data?.prefs;
|
|
if (!t || typeof t != "object") return;
|
|
let n = K();
|
|
if (n.security = n.security || {}, n.security.safeMode = H(t.safe_mode, n.security.safeMode), n.security.allowWrite = H(t.allow_write, n.security.allowWrite), n.security.requireAuth = H(t.require_auth, n.security.requireAuth), n.security.allowRemoteWrite = H(t.allow_remote_write, n.security.allowRemoteWrite), n.security.allowInsecureTokenTransport = H(t.allow_insecure_token_transport, n.security.allowInsecureTokenTransport), n.security.allowDelete = H(t.allow_delete, n.security.allowDelete), n.security.allowRename = H(t.allow_rename, n.security.allowRename), n.security.allowOpenInFolder = H(t.allow_open_in_folder, n.security.allowOpenInFolder), n.security.allowResetIndex = H(t.allow_reset_index, n.security.allowResetIndex), n.security.tokenConfigured = H(t.token_configured, n.security.tokenConfigured), n.security.tokenHint = String(t.token_hint || "").trim(), !String(n.security.apiToken || "").trim()) try {
|
|
let e = await p(), t = String(e?.data?.token || "").trim();
|
|
e?.ok && t && (n.security.apiToken = t);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
q(n), J(n), _t("mjr-settings-changed", { key: "security" }, { warnPrefix: "[Majoor]" });
|
|
} catch (e) {
|
|
console.warn("[Majoor] failed to sync backend security settings", e);
|
|
}
|
|
}
|
|
async function Kt() {
|
|
try {
|
|
let e = await pe();
|
|
if (!e?.ok) return;
|
|
let t = e.data?.prefs;
|
|
if (!t || typeof t != "object") return;
|
|
let n = K();
|
|
n.ai = n.ai || {}, n.ai.vectorSearchEnabled = H(t.enabled, n.ai.vectorSearchEnabled ?? !0), n.ai.vectorCaptionOnIndex = H(t.caption_on_index ?? t.captionOnIndex, n.ai.vectorCaptionOnIndex ?? !1), q(n), J(n), _t("mjr-settings-changed", { key: "ai.vectorSearch" }, { warnPrefix: "[Majoor]" });
|
|
} catch (e) {
|
|
console.warn("[Majoor] failed to sync backend vector search settings", e);
|
|
}
|
|
}
|
|
async function qt() {
|
|
try {
|
|
let t = await e();
|
|
if (!t?.ok) return;
|
|
let n = t.data?.prefs;
|
|
if (!n || typeof n != "object") return;
|
|
let r = K();
|
|
r.executionGrouping = r.executionGrouping || {}, r.executionGrouping.enabled = H(n.enabled, r.executionGrouping.enabled ?? k.EXECUTION_GROUPING_ENABLED), q(r), J(r), _t("mjr-settings-changed", { key: "executionGrouping.enabled" }, { warnPrefix: "[Majoor]" });
|
|
} catch (e) {
|
|
console.warn("[Majoor] failed to sync backend execution grouping settings", e);
|
|
}
|
|
}
|
|
//#endregion
|
|
//#region ui/app/settings/settingsRuntime.ts
|
|
var Jt = "mjr-runtime-status-dashboard", Yt = "__mjr_write_token", Xt = 3e4;
|
|
function Zt() {
|
|
try {
|
|
let e = K(), t = String(e?.observability?.runtimeDashboardMode || G.observability.runtimeDashboardMode);
|
|
return [
|
|
"autoHide30",
|
|
"always",
|
|
"hidden"
|
|
].includes(t) ? t : "autoHide30";
|
|
} catch {
|
|
return "autoHide30";
|
|
}
|
|
}
|
|
function Qt() {
|
|
try {
|
|
document.getElementById(Jt)?.remove?.();
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
}
|
|
function $t() {
|
|
try {
|
|
window.__MJR_RUNTIME_STATUS_HIDE_TIMEOUT__ && (clearTimeout(window.__MJR_RUNTIME_STATUS_HIDE_TIMEOUT__), window.__MJR_RUNTIME_STATUS_HIDE_TIMEOUT__ = null);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
}
|
|
function en() {
|
|
try {
|
|
return String(sessionStorage?.getItem?.(Yt) || "").trim();
|
|
} catch {
|
|
return "";
|
|
}
|
|
}
|
|
function tn(e, t) {
|
|
let n = t === "auth" ? "__mjrAuthLine" : "__mjrMetricsLine";
|
|
if (e?.[n]) return e[n];
|
|
let r = document.createElement("div");
|
|
return r.style.whiteSpace = "nowrap", r.style.lineHeight = "1.35", t === "auth" && (r.style.marginTop = "4px", r.style.fontWeight = "600"), e.appendChild(r), e[n] = r, r;
|
|
}
|
|
function nn(e) {
|
|
let t = en(), n = String(e?.token_hint || "").trim() || (t ? `...${t.slice(-4)}` : ""), r = e?.allow_write !== !1, i = e?.require_auth === !0, a = e?.token_configured === !0;
|
|
return r ? t ? {
|
|
text: A("runtime.writeAuthActive", "Write auth: active {tokenHint}", { tokenHint: n || "(session)" }),
|
|
color: "#7ee0a0"
|
|
} : i && a ? {
|
|
text: A("runtime.writeAuthMissing", "Write auth: missing in this browser {tokenHint}", { tokenHint: n || "(server token configured)" }),
|
|
color: "#f1c36d"
|
|
} : i ? {
|
|
text: A("runtime.writeAuthRequired", "Write auth: required"),
|
|
color: "#f1c36d"
|
|
} : e && typeof e == "object" ? {
|
|
text: A("runtime.writeAuthNotRequired", "Write auth: not required"),
|
|
color: "#8fd0ff"
|
|
} : {
|
|
text: A("runtime.writeAuthUnknown", "Write auth: unknown"),
|
|
color: "#c8ced8"
|
|
} : {
|
|
text: A("runtime.writeAuthBlocked", "Write auth: writes blocked by server"),
|
|
color: "#ff9b9b"
|
|
};
|
|
}
|
|
function rn() {
|
|
try {
|
|
if (Zt() === "hidden" || window.__MJR_RUNTIME_STATUS_HIDDEN__) return Qt(), null;
|
|
let e = document.querySelector(".mjr-assets-manager.mjr-am-container"), t = document.getElementById(Jt);
|
|
if (!e) {
|
|
try {
|
|
t?.remove?.();
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
return null;
|
|
}
|
|
try {
|
|
let t = String(getComputedStyle(e).position || "").toLowerCase();
|
|
(!t || t === "static") && (e.style.position = "relative");
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
let n = document.getElementById(Jt);
|
|
return n ? n.parentElement !== e && e.appendChild(n) : (n = document.createElement("div"), n.id = Jt, n.style.position = "absolute", n.style.bottom = "10px", n.style.right = "10px", n.style.zIndex = "9999", n.style.padding = "6px 10px", n.style.borderRadius = "10px", n.style.border = "1px solid rgba(255,255,255,0.16)", n.style.background = "rgba(0,0,0,0.45)", n.style.backdropFilter = "blur(4px)", n.style.color = "var(--content-fg, #fff)", n.style.fontSize = "11px", n.style.pointerEvents = "none", n.style.display = "flex", n.style.flexDirection = "column", e.appendChild(n)), n;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
async function an() {
|
|
let e = rn();
|
|
if (!e) return !1;
|
|
let t = tn(e, "metrics"), n = tn(e, "auth");
|
|
try {
|
|
let [r, i] = await Promise.all([se(), ue()]), a = A("runtime.unavailable", "Runtime: unavailable");
|
|
if (!r?.ok || !r?.data) t.textContent = a;
|
|
else {
|
|
let e = r.data.db || {}, n = r.data.index || {}, i = r.data.watcher || {}, o = Number(e.active_connections || 0), s = Number(n.enrichment_queue_length || 0), c = Number(i.pending_files || 0);
|
|
t.textContent = A("runtime.metricsLine", "DB active: {active} | Enrich Q: {enrichQ} | Watcher pending: {pending}", {
|
|
active: o,
|
|
enrichQ: s,
|
|
pending: c
|
|
}), a = A("runtime.metricsTitle", "Runtime Metrics\nDB active connections: {active}\nEnrichment queue: {enrichQ}\nWatcher pending files: {pending}", {
|
|
active: o,
|
|
enrichQ: s,
|
|
pending: c
|
|
});
|
|
}
|
|
let o = nn(i?.data?.prefs || null);
|
|
return n.textContent = o.text, n.style.color = o.color, e.title = `${a}\n${o.text}`, !0;
|
|
} catch {
|
|
return t.textContent = A("runtime.unavailable", "Runtime: unavailable"), n.textContent = A("runtime.writeAuthUnknown", "Write auth: unknown"), n.style.color = "#c8ced8", e.title = `${A("runtime.unavailable", "Runtime: unavailable")}\n${n.textContent}`, !0;
|
|
}
|
|
}
|
|
function on() {
|
|
try {
|
|
let e = Zt();
|
|
if (e === "hidden") {
|
|
window.__MJR_RUNTIME_STATUS_HIDDEN__ = !0, $t(), Qt();
|
|
return;
|
|
}
|
|
window.__MJR_RUNTIME_STATUS_SETTINGS_LISTENER__ || (window.__MJR_RUNTIME_STATUS_SETTINGS_LISTENER__ = (e) => {
|
|
if (e?.detail?.key !== "observability.runtimeDashboardMode") return;
|
|
let t = Zt();
|
|
window.__MJR_RUNTIME_STATUS_HIDDEN__ = t === "hidden", $t(), Qt(), t !== "hidden" && on();
|
|
}, window.addEventListener?.("mjr-settings-changed", window.__MJR_RUNTIME_STATUS_SETTINGS_LISTENER__)), window.__MJR_RUNTIME_STATUS_HIDDEN__ = !1, $t(), e === "autoHide30" && (window.__MJR_RUNTIME_STATUS_HIDE_TIMEOUT__ = setTimeout(() => {
|
|
window.__MJR_RUNTIME_STATUS_HIDDEN__ = !0, Qt();
|
|
}, Xt)), an().catch(() => {}), window.__MJR_RUNTIME_STATUS_INFLIGHT__ ?? (window.__MJR_RUNTIME_STATUS_INFLIGHT__ = !1), window.__MJR_RUNTIME_STATUS_MISS_COUNT__ ?? (window.__MJR_RUNTIME_STATUS_MISS_COUNT__ = 0), window.__MJR_RUNTIME_STATUS_INTERVAL__ || (window.__MJR_RUNTIME_STATUS_INTERVAL__ = setInterval(() => {
|
|
window.__MJR_RUNTIME_STATUS_INFLIGHT__ || (window.__MJR_RUNTIME_STATUS_INFLIGHT__ = !0, an().then((e) => {
|
|
if (e) {
|
|
window.__MJR_RUNTIME_STATUS_MISS_COUNT__ = 0;
|
|
return;
|
|
}
|
|
window.__MJR_RUNTIME_STATUS_MISS_COUNT__ = Number(window.__MJR_RUNTIME_STATUS_MISS_COUNT__ || 0) + 1;
|
|
}).catch(() => {}).finally(() => {
|
|
window.__MJR_RUNTIME_STATUS_INFLIGHT__ = !1;
|
|
}));
|
|
}, 1e4));
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
}
|
|
//#endregion
|
|
//#region ui/utils/debounce.ts
|
|
var sn = 300;
|
|
function cn(e, t = sn) {
|
|
let n, r = (...r) => {
|
|
clearTimeout(n), n = setTimeout(() => e(...r), t);
|
|
};
|
|
return r.cancel = () => {
|
|
clearTimeout(n);
|
|
}, r.flush = (...t) => {
|
|
clearTimeout(n), e(...t);
|
|
}, r;
|
|
}
|
|
//#endregion
|
|
//#region ui/app/settings/settingsGrid.ts
|
|
var Y = "Majoor", ln = "Majoor Assets Manager";
|
|
function un(e, t, n) {
|
|
let r = (e, t) => [
|
|
ln,
|
|
e,
|
|
t
|
|
], i = (e) => [
|
|
ln,
|
|
A("cat.cards", "Cards"),
|
|
e
|
|
], a = (e) => [
|
|
ln,
|
|
A("cat.badges", "Badges"),
|
|
e
|
|
], o = (e) => [
|
|
ln,
|
|
A("cat.badges", "Badges"),
|
|
e
|
|
], s = (e, t) => {
|
|
let n = String(e || "").trim();
|
|
return /^[0-9a-fA-F]{6}$/.test(n) && (n = `#${n}`), /^#[0-9a-fA-F]{6}$/.test(n) ? n.toUpperCase() : t;
|
|
};
|
|
t.grid?.minSizePreset || (t.grid = t.grid || {}, t.grid.minSizePreset = Et(t.grid.minSize), q(t)), e({
|
|
id: `${Y}.Cards.ThumbSize`,
|
|
category: i(A("setting.grid.cardSize.group", "Card size")),
|
|
name: A("setting.grid.cardSize.name", "Majoor: Card Size"),
|
|
tooltip: A("setting.grid.cardSize.desc", "Choose the card size preset used by the grid layout."),
|
|
type: "combo",
|
|
defaultValue: (() => {
|
|
let e = vt(String(t.grid?.minSizePreset || "").toLowerCase(), St, Et(t.grid?.minSize)), n = {
|
|
small: A("setting.grid.cardSize.small", "Small"),
|
|
medium: A("setting.grid.cardSize.medium", "Medium"),
|
|
large: A("setting.grid.cardSize.large", "Large")
|
|
};
|
|
return n[e] || n.medium;
|
|
})(),
|
|
options: [
|
|
A("setting.grid.cardSize.small", "Small"),
|
|
A("setting.grid.cardSize.medium", "Medium"),
|
|
A("setting.grid.cardSize.large", "Large")
|
|
],
|
|
onChange: (e) => {
|
|
let r = String(e || "").trim().toLowerCase(), i = A("setting.grid.cardSize.small", "Small").toLowerCase(), a = A("setting.grid.cardSize.medium", "Medium").toLowerCase(), o = A("setting.grid.cardSize.large", "Large").toLowerCase(), s = "medium";
|
|
r === i || r === "small" || r === "petit" ? s = "small" : r === o || r === "large" || r === "grand" ? s = "large" : (r === a || r === "medium" || r === "moyen") && (s = "medium"), t.grid.minSizePreset = s, t.grid.minSize = xt[s], q(t), J(t), n("grid.minSizePreset");
|
|
}
|
|
}), e({
|
|
id: `${Y}.Cards.CustomThumbSize`,
|
|
category: i(A("setting.grid.cardSize.group", "Card size")),
|
|
name: "Majoor: Custom Card Size (px)",
|
|
tooltip: "Set the minimum card width used by the main grid layout (60-600 px).",
|
|
type: "number",
|
|
defaultValue: Math.max(60, Math.min(600, Number(t.grid?.minSize) || 120)),
|
|
attrs: {
|
|
min: 60,
|
|
max: 600,
|
|
step: 10
|
|
},
|
|
onChange: (e) => {
|
|
let r = Math.max(60, Math.min(600, Math.round(Number(e) || 120)));
|
|
t.grid.minSize = r, t.grid.minSizePreset = Et(r), q(t), J(t), n("grid.minSize");
|
|
}
|
|
}), e({
|
|
id: `${Y}.Grid.ShowDetails`,
|
|
category: i("Show card details"),
|
|
name: "Show metadata panel",
|
|
tooltip: "Show the bottom details panel on asset cards (filename, date, etc.)",
|
|
type: "boolean",
|
|
defaultValue: !!t.grid?.showDetails,
|
|
onChange: (e) => {
|
|
t.grid.showDetails = !!e, q(t), J(t), n("grid.showDetails");
|
|
}
|
|
}), e({
|
|
id: `${Y}.Grid.ShowFilename`,
|
|
category: i("Show filename"),
|
|
name: "Show filename",
|
|
tooltip: "Display filename in details panel",
|
|
type: "boolean",
|
|
defaultValue: !!t.grid?.showFilename,
|
|
onChange: (e) => {
|
|
t.grid.showFilename = !!e, q(t), J(t), n("grid.showFilename");
|
|
}
|
|
}), e({
|
|
id: `${Y}.Grid.ShowDate`,
|
|
category: i("Show date/time"),
|
|
name: "Show date/time",
|
|
tooltip: "Display date and time in details panel",
|
|
type: "boolean",
|
|
defaultValue: !!t.grid?.showDate,
|
|
onChange: (e) => {
|
|
t.grid.showDate = !!e, q(t), J(t), n("grid.showDate");
|
|
}
|
|
}), e({
|
|
id: `${Y}.Grid.ShowDimensions`,
|
|
category: i("Show dimensions"),
|
|
name: "Show dimensions",
|
|
tooltip: "Display resolution (WxH) in details panel",
|
|
type: "boolean",
|
|
defaultValue: !!t.grid?.showDimensions,
|
|
onChange: (e) => {
|
|
t.grid.showDimensions = !!e, q(t), J(t), n("grid.showDimensions");
|
|
}
|
|
}), e({
|
|
id: `${Y}.Grid.ShowGenTime`,
|
|
category: i("Show generation time"),
|
|
name: "Show generation time",
|
|
tooltip: "Display seconds taken to generate the asset (if available)",
|
|
type: "boolean",
|
|
defaultValue: !!(t.grid?.showGenTime ?? k.GRID_SHOW_DETAILS_GENTIME),
|
|
onChange: (e) => {
|
|
t.grid.showGenTime = !!e, q(t), J(t), n("grid.showGenTime");
|
|
}
|
|
}), e({
|
|
id: `${Y}.Grid.ShowHoverInfo`,
|
|
category: i("Show prompt on hover"),
|
|
name: "Show prompt on hover",
|
|
tooltip: "Show positive prompt and generation time as a tooltip overlay when hovering over a card thumbnail. Does not block video play-on-hover.",
|
|
type: "boolean",
|
|
defaultValue: !!(t.grid?.showHoverInfo ?? k.GRID_SHOW_HOVER_INFO),
|
|
onChange: (e) => {
|
|
t.grid.showHoverInfo = !!e, q(t), J(t), n("grid.showHoverInfo");
|
|
}
|
|
}), e({
|
|
id: `${Y}.Grid.ShowWorkflowDot`,
|
|
category: i("Show workflow dot"),
|
|
name: "Show workflow indicator",
|
|
tooltip: "Display the green dot indicating workflow metadata availability (bottom right of card)",
|
|
type: "boolean",
|
|
defaultValue: !!t.grid?.showWorkflowDot,
|
|
onChange: (e) => {
|
|
t.grid.showWorkflowDot = !!e, q(t), J(t), n("grid.showWorkflowDot");
|
|
}
|
|
}), e({
|
|
id: `${Y}.Grid.ShowExtBadge`,
|
|
category: a("Show format badges"),
|
|
name: "Show format badges",
|
|
tooltip: "Display format badges (e.g. JPG, MP4) on thumbnails",
|
|
type: "boolean",
|
|
defaultValue: !!t.grid?.showExtBadge,
|
|
onChange: (e) => {
|
|
t.grid.showExtBadge = !!e, q(t), J(t), n("grid.showExtBadge");
|
|
}
|
|
}), e({
|
|
id: `${Y}.Grid.ShowRatingBadge`,
|
|
category: a("Show rating badges"),
|
|
name: "Show ratings",
|
|
tooltip: "Display star ratings on thumbnails",
|
|
type: "boolean",
|
|
defaultValue: !!t.grid?.showRatingBadge,
|
|
onChange: (e) => {
|
|
t.grid.showRatingBadge = !!e, q(t), J(t), n("grid.showRatingBadge");
|
|
}
|
|
}), e({
|
|
id: `${Y}.Grid.ShowTagsBadge`,
|
|
category: a("Show tags badges"),
|
|
name: "Show tags",
|
|
tooltip: "Display a small indicator if an asset has tags",
|
|
type: "boolean",
|
|
defaultValue: !!t.grid?.showTagsBadge,
|
|
onChange: (e) => {
|
|
t.grid.showTagsBadge = !!e, q(t), J(t), n("grid.showTagsBadge");
|
|
}
|
|
}), e({
|
|
id: `${Y}.Badges.StarColor`,
|
|
category: o(A("setting.starColor", "Star color")),
|
|
name: A("setting.starColor", "Majoor: Star color"),
|
|
tooltip: A("setting.starColor.tooltip", "Color of rating stars on thumbnails (hex, e.g. #FFD45A)"),
|
|
type: "color",
|
|
defaultValue: s(t.grid?.starColor, k.BADGE_STAR_COLOR),
|
|
onChange: (e) => {
|
|
t.grid.starColor = s(e, k.BADGE_STAR_COLOR), q(t), J(t), n("grid.starColor");
|
|
}
|
|
}), e({
|
|
id: `${Y}.Badges.ImageColor`,
|
|
category: o(A("setting.badgeImageColor", "Image badge color")),
|
|
name: A("setting.badgeImageColor", "Majoor: Image badge color"),
|
|
tooltip: A("setting.badgeImageColor.tooltip", "Color for image badges: PNG, JPG, WEBP, GIF, BMP, TIF (hex)"),
|
|
type: "color",
|
|
defaultValue: s(t.grid?.badgeImageColor, k.BADGE_IMAGE_COLOR),
|
|
onChange: (e) => {
|
|
t.grid.badgeImageColor = s(e, k.BADGE_IMAGE_COLOR), q(t), J(t), n("grid.badgeImageColor");
|
|
}
|
|
}), e({
|
|
id: `${Y}.Badges.VideoColor`,
|
|
category: o(A("setting.badgeVideoColor", "Video badge color")),
|
|
name: A("setting.badgeVideoColor", "Majoor: Video badge color"),
|
|
tooltip: A("setting.badgeVideoColor.tooltip", "Color for video badges: MP4, WEBM, MOV, AVI, MKV (hex)"),
|
|
type: "color",
|
|
defaultValue: s(t.grid?.badgeVideoColor, k.BADGE_VIDEO_COLOR),
|
|
onChange: (e) => {
|
|
t.grid.badgeVideoColor = s(e, k.BADGE_VIDEO_COLOR), q(t), J(t), n("grid.badgeVideoColor");
|
|
}
|
|
}), e({
|
|
id: `${Y}.Badges.AudioColor`,
|
|
category: o(A("setting.badgeAudioColor", "Audio badge color")),
|
|
name: A("setting.badgeAudioColor", "Majoor: Audio badge color"),
|
|
tooltip: A("setting.badgeAudioColor.tooltip", "Color for audio badges: MP3, WAV, OGG, FLAC (hex)"),
|
|
type: "color",
|
|
defaultValue: s(t.grid?.badgeAudioColor, k.BADGE_AUDIO_COLOR),
|
|
onChange: (e) => {
|
|
t.grid.badgeAudioColor = s(e, k.BADGE_AUDIO_COLOR), q(t), J(t), n("grid.badgeAudioColor");
|
|
}
|
|
}), e({
|
|
id: `${Y}.Badges.Model3dColor`,
|
|
category: o(A("setting.badgeModel3dColor", "3D model badge color")),
|
|
name: A("setting.badgeModel3dColor", "Majoor: 3D model badge color"),
|
|
tooltip: A("setting.badgeModel3dColor.tooltip", "Color for 3D model badges: OBJ, FBX, GLB, GLTF (hex)"),
|
|
type: "color",
|
|
defaultValue: s(t.grid?.badgeModel3dColor, k.BADGE_MODEL3D_COLOR),
|
|
onChange: (e) => {
|
|
t.grid.badgeModel3dColor = s(e, k.BADGE_MODEL3D_COLOR), q(t), J(t), n("grid.badgeModel3dColor");
|
|
}
|
|
}), e({
|
|
id: `${Y}.Badges.DuplicateAlertColor`,
|
|
category: o(A("setting.badgeDuplicateAlertColor", "Duplicate alert badge color")),
|
|
name: A("setting.badgeDuplicateAlertColor", "Majoor: Duplicate alert badge color"),
|
|
tooltip: A("setting.badgeDuplicateAlertColor.tooltip", "Color for duplicate extension badges (PNG+, JPG+, etc)."),
|
|
type: "color",
|
|
defaultValue: s(t.grid?.badgeDuplicateAlertColor, k.BADGE_DUPLICATE_ALERT_COLOR),
|
|
onChange: (e) => {
|
|
t.grid.badgeDuplicateAlertColor = s(e, k.BADGE_DUPLICATE_ALERT_COLOR), q(t), J(t), n("grid.badgeDuplicateAlertColor");
|
|
}
|
|
}), e({
|
|
id: `${Y}.Grid.PageSize`,
|
|
category: r(A("cat.grid"), A("setting.grid.pagesize.name").replace("Majoor: ", "")),
|
|
name: A("setting.grid.pagesize.name"),
|
|
tooltip: A("setting.grid.pagesize.desc"),
|
|
type: "number",
|
|
defaultValue: t.grid.pageSize,
|
|
attrs: {
|
|
min: 50,
|
|
max: Number(O.MAX_PAGE_SIZE) || 2e3,
|
|
step: 50
|
|
},
|
|
onChange: (e) => {
|
|
let r = Number(O.MAX_PAGE_SIZE) || 2e3;
|
|
t.grid.pageSize = Math.max(50, Math.min(r, Number(e) || k.DEFAULT_PAGE_SIZE)), q(t), J(t), n("grid.pageSize");
|
|
}
|
|
}), e({
|
|
id: `${Y}.Grid.WorkflowGroupBy`,
|
|
category: r(A("cat.grid"), "Workflow grouping"),
|
|
name: "Workflow grid grouping",
|
|
tooltip: "In Workflow scope, insert titled separators and group cards by Task, Model, or Category.",
|
|
type: "combo",
|
|
defaultValue: (() => {
|
|
let e = String(t.grid?.workflowGroupBy || k.WORKFLOW_GRID_GROUP_BY).trim().toLowerCase(), n = {
|
|
none: "None",
|
|
task: "Task",
|
|
model: "Model",
|
|
category: "Category"
|
|
};
|
|
return n[e] || n.none;
|
|
})(),
|
|
options: [
|
|
"None",
|
|
"Task",
|
|
"Model",
|
|
"Category"
|
|
],
|
|
onChange: (e) => {
|
|
let r = {
|
|
None: "none",
|
|
Task: "task",
|
|
Model: "model",
|
|
Category: "category"
|
|
}[String(e || "")] || "none";
|
|
t.grid = t.grid || {}, t.grid.workflowGroupBy = r, q(t), J(t), n("grid.workflowGroupBy");
|
|
}
|
|
}), e({
|
|
id: `${Y}.InfiniteScroll.Enabled`,
|
|
category: r(A("cat.grid"), A("setting.nav.infinite.name").replace("Majoor: ", "")),
|
|
name: A("setting.nav.infinite.name"),
|
|
tooltip: A("setting.nav.infinite.desc"),
|
|
type: "boolean",
|
|
defaultValue: !!t.infiniteScroll?.enabled,
|
|
onChange: (e) => {
|
|
t.infiniteScroll = t.infiniteScroll || {}, t.infiniteScroll.enabled = !!e, q(t), J(t), n("infiniteScroll.enabled");
|
|
}
|
|
}), e({
|
|
id: `${Y}.Sidebar.Position`,
|
|
category: r(A("cat.grid"), A("setting.sidebar.pos.name").replace("Majoor: ", "")),
|
|
name: A("setting.sidebar.pos.name"),
|
|
tooltip: A("setting.sidebar.pos.desc"),
|
|
type: "combo",
|
|
defaultValue: t.sidebar?.position || "right",
|
|
options: ["left", "right"],
|
|
onChange: (e) => {
|
|
t.sidebar = t.sidebar || {}, t.sidebar.position = e === "left" ? "left" : "right", q(t), n("sidebar.position");
|
|
}
|
|
}), e({
|
|
id: `${Y}.Sidebar.ShowPreviewThumb`,
|
|
category: r(A("cat.grid"), "Sidebar preview"),
|
|
name: "Show sidebar preview thumb",
|
|
tooltip: "Show/hide the large media preview at the top of the sidebar metadata panel.",
|
|
type: "boolean",
|
|
defaultValue: !!(t.sidebar?.showPreviewThumb ?? !0),
|
|
onChange: (e) => {
|
|
t.sidebar = t.sidebar || {}, t.sidebar.showPreviewThumb = !!e, q(t), n("sidebar.showPreviewThumb");
|
|
}
|
|
}), e({
|
|
id: `${Y}.Sidebar.WidthPx`,
|
|
category: r(A("cat.grid"), "Sidebar width"),
|
|
name: "Sidebar width (px)",
|
|
tooltip: "Set the details sidebar width in pixels (240-640).",
|
|
type: "number",
|
|
defaultValue: Math.max(240, Math.min(640, Number(t.sidebar?.widthPx) || 360)),
|
|
attrs: {
|
|
min: 240,
|
|
max: 640,
|
|
step: 10
|
|
},
|
|
onChange: (e) => {
|
|
t.sidebar = t.sidebar || {}, t.sidebar.widthPx = Math.max(240, Math.min(640, Math.round(Number(e) || 360))), q(t), n("sidebar.widthPx");
|
|
}
|
|
}), e({
|
|
id: `${Y}.General.HideSiblings`,
|
|
category: r(A("cat.grid"), A("setting.siblings.hide.name").replace("Majoor: ", "")),
|
|
name: A("setting.siblings.hide.name"),
|
|
tooltip: A("setting.siblings.hide.desc"),
|
|
type: "boolean",
|
|
defaultValue: !!t.siblings?.hidePngSiblings,
|
|
onChange: (e) => {
|
|
t.siblings = t.siblings || {}, t.siblings.hidePngSiblings = !!e, q(t), n("siblings.hidePngSiblings");
|
|
}
|
|
}), e({
|
|
id: `${Y}.Grid.VideoAutoplayMode`,
|
|
category: r(A("cat.grid"), A("setting.grid.videoAutoplayMode.name", "Video autoplay").replace("Majoor: ", "")),
|
|
name: A("setting.grid.videoAutoplayMode.name", "Majoor: Video autoplay"),
|
|
tooltip: A("setting.grid.videoAutoplayMode.desc", "Controls video thumbnail playback in the grid. Off: static frame. Hover: play on mouse hover. Always: loop while visible."),
|
|
type: "combo",
|
|
defaultValue: (() => {
|
|
let e = t.grid?.videoAutoplayMode;
|
|
e ??= t.grid?.videoHoverAutoplay === !1 ? "off" : "hover", e === !0 && (e = "hover"), e === !1 && (e = "off"), e !== "hover" && e !== "always" && e !== "off" && (e = "hover");
|
|
let n = {
|
|
off: A("setting.grid.videoAutoplayMode.off", "Off"),
|
|
hover: A("setting.grid.videoAutoplayMode.hover", "Hover"),
|
|
always: A("setting.grid.videoAutoplayMode.always", "Always")
|
|
};
|
|
return n[e] || n.off;
|
|
})(),
|
|
options: [
|
|
A("setting.grid.videoAutoplayMode.off", "Off"),
|
|
A("setting.grid.videoAutoplayMode.hover", "Hover"),
|
|
A("setting.grid.videoAutoplayMode.always", "Always")
|
|
],
|
|
onChange: (e) => {
|
|
let r = {
|
|
[A("setting.grid.videoAutoplayMode.off", "Off")]: "off",
|
|
[A("setting.grid.videoAutoplayMode.hover", "Hover")]: "hover",
|
|
[A("setting.grid.videoAutoplayMode.always", "Always")]: "always"
|
|
}[e] || "off";
|
|
t.grid = t.grid || {}, t.grid.videoAutoplayMode = r, delete t.grid.videoHoverAutoplay, q(t), J(t), n("grid.videoAutoplayMode");
|
|
}
|
|
}), e({
|
|
id: `${Y}.Cards.HoverColor`,
|
|
category: i("Hover color"),
|
|
name: "Majoor: Card hover color",
|
|
tooltip: "Background tint used when hovering a card (hex, e.g. #3D3D3D).",
|
|
type: "color",
|
|
defaultValue: s(t.ui?.cardHoverColor, k.UI_CARD_HOVER_COLOR),
|
|
onChange: (e) => {
|
|
t.ui = t.ui || {}, t.ui.cardHoverColor = s(e, k.UI_CARD_HOVER_COLOR), q(t), J(t), n("ui.cardHoverColor");
|
|
}
|
|
}), e({
|
|
id: `${Y}.Cards.SelectionColor`,
|
|
category: i("Selection color"),
|
|
name: "Majoor: Card selection color",
|
|
tooltip: "Outline/accent color used for selected cards (hex, e.g. #4A90E2).",
|
|
type: "color",
|
|
defaultValue: s(t.ui?.cardSelectionColor, k.UI_CARD_SELECTION_COLOR),
|
|
onChange: (e) => {
|
|
t.ui = t.ui || {}, t.ui.cardSelectionColor = s(e, k.UI_CARD_SELECTION_COLOR), q(t), J(t), n("ui.cardSelectionColor");
|
|
}
|
|
}), e({
|
|
id: `${Y}.Badges.RatingColor`,
|
|
category: a("Rating color"),
|
|
name: "Majoor: Rating badge color",
|
|
tooltip: "Color used for rating badge text/accent (hex, e.g. #FF9500).",
|
|
type: "color",
|
|
defaultValue: s(t.ui?.ratingColor, k.UI_RATING_COLOR),
|
|
onChange: (e) => {
|
|
t.ui = t.ui || {}, t.ui.ratingColor = s(e, k.UI_RATING_COLOR), q(t), J(t), n("ui.ratingColor");
|
|
}
|
|
}), e({
|
|
id: `${Y}.Badges.TagColor`,
|
|
category: a("Tag color"),
|
|
name: "Majoor: Tags badge color",
|
|
tooltip: "Color used for tags badge text/accent (hex, e.g. #4A90E2).",
|
|
type: "color",
|
|
defaultValue: s(t.ui?.tagColor, k.UI_TAG_COLOR),
|
|
onChange: (e) => {
|
|
t.ui = t.ui || {}, t.ui.tagColor = s(e, k.UI_TAG_COLOR), q(t), J(t), n("ui.tagColor");
|
|
}
|
|
});
|
|
}
|
|
//#endregion
|
|
//#region ui/app/settings/settingsViewer.ts
|
|
var dn = "Majoor", fn = "Majoor Assets Manager";
|
|
function pn(e, t, n) {
|
|
let r = (e, t) => [
|
|
fn,
|
|
e,
|
|
t
|
|
], i = (e) => r(A("cat.viewer", "Viewer"), e), a = (e) => r(A("cat.floatingViewer", "Floating Viewer"), e);
|
|
e({
|
|
id: `${dn}.Viewer.AllowPanAtZoom1`,
|
|
category: i(A("setting.viewer.pan.name").replace("Majoor: ", "")),
|
|
name: A("setting.viewer.pan.name"),
|
|
tooltip: A("setting.viewer.pan.desc"),
|
|
type: "boolean",
|
|
defaultValue: !!t.viewer?.allowPanAtZoom1,
|
|
onChange: (e) => {
|
|
t.viewer = t.viewer || {}, t.viewer.allowPanAtZoom1 = !!e, q(t), J(t), n("viewer.allowPanAtZoom1");
|
|
}
|
|
}), e({
|
|
id: `${dn}.Viewer.DisableWebGL`,
|
|
category: i("Disable WebGL Video"),
|
|
name: "Disable WebGL Video",
|
|
tooltip: "Use CPU rendering (Canvas 2D) for video playback. Fixes 'black screen' issues on incompatible hardware/browsers.",
|
|
type: "boolean",
|
|
defaultValue: !!t.viewer?.disableWebGL,
|
|
onChange: (e) => {
|
|
t.viewer = t.viewer || {}, t.viewer.disableWebGL = !!e, q(t), J(t), n("viewer.disableWebGL");
|
|
}
|
|
}), e({
|
|
id: `${dn}.Viewer.PauseDuringExecution`,
|
|
category: i(A("setting.viewer.pauseExecution.name").replace("Majoor: ", "")),
|
|
name: A("setting.viewer.pauseExecution.name"),
|
|
tooltip: A("setting.viewer.pauseExecution.desc"),
|
|
type: "boolean",
|
|
defaultValue: !!t.viewer?.pauseDuringExecution,
|
|
onChange: (e) => {
|
|
t.viewer = t.viewer || {}, t.viewer.pauseDuringExecution = !!e, q(t), J(t), n("viewer.pauseDuringExecution");
|
|
}
|
|
}), e({
|
|
id: `${dn}.Viewer.FloatingPauseDuringExecution`,
|
|
category: a(A("setting.viewer.floatingPauseExecution.name").replace("Majoor: ", "")),
|
|
name: A("setting.viewer.floatingPauseExecution.name"),
|
|
tooltip: A("setting.viewer.floatingPauseExecution.desc"),
|
|
type: "boolean",
|
|
defaultValue: !!t.viewer?.floatingPauseDuringExecution,
|
|
onChange: (e) => {
|
|
t.viewer = t.viewer || {}, t.viewer.floatingPauseDuringExecution = !!e, q(t), J(t), n("viewer.floatingPauseDuringExecution");
|
|
}
|
|
}), e({
|
|
id: `${dn}.Viewer.MfvLiveDefault`,
|
|
category: a(A("setting.viewer.mfvLiveDefault.name").replace("Majoor: ", "")),
|
|
name: A("setting.viewer.mfvLiveDefault.name"),
|
|
tooltip: A("setting.viewer.mfvLiveDefault.desc"),
|
|
type: "boolean",
|
|
defaultValue: !!(t.viewer?.mfvLiveDefault ?? k.MFV_LIVE_DEFAULT),
|
|
onChange: (e) => {
|
|
t.viewer = t.viewer || {}, t.viewer.mfvLiveDefault = !!e, q(t), J(t), n("viewer.mfvLiveDefault");
|
|
}
|
|
}), e({
|
|
id: `${dn}.Viewer.MfvPreviewDefault`,
|
|
category: a(A("setting.viewer.mfvPreviewDefault.name").replace("Majoor: ", "")),
|
|
name: A("setting.viewer.mfvPreviewDefault.name"),
|
|
tooltip: A("setting.viewer.mfvPreviewDefault.desc"),
|
|
type: "boolean",
|
|
defaultValue: !!(t.viewer?.mfvPreviewDefault ?? k.MFV_PREVIEW_DEFAULT),
|
|
onChange: (e) => {
|
|
t.viewer = t.viewer || {}, t.viewer.mfvPreviewDefault = !!e, q(t), J(t), n("viewer.mfvPreviewDefault");
|
|
}
|
|
}), e({
|
|
id: `${dn}.Viewer.MfvSidebarPosition`,
|
|
category: a("Node Parameters sidebar position"),
|
|
name: "Node Parameters sidebar position",
|
|
tooltip: "Position of the Node Parameters sidebar in the Floating Viewer (right, left, or bottom).",
|
|
type: "combo",
|
|
defaultValue: t.viewer?.mfvSidebarPosition || "right",
|
|
options: [
|
|
"right",
|
|
"left",
|
|
"bottom"
|
|
],
|
|
onChange: (e) => {
|
|
let r = [
|
|
"left",
|
|
"right",
|
|
"bottom"
|
|
].includes(e) ? e : "right";
|
|
t.viewer = t.viewer || {}, t.viewer.mfvSidebarPosition = r, q(t), J(t), n("viewer.mfvSidebarPosition");
|
|
}
|
|
}), e({
|
|
id: `${dn}.Viewer.MfvPreviewMethod`,
|
|
category: a(A("setting.viewer.mfvPreviewMethod.name").replace("Majoor: ", "")),
|
|
name: A("setting.viewer.mfvPreviewMethod.name"),
|
|
tooltip: A("setting.viewer.mfvPreviewMethod.desc"),
|
|
type: "combo",
|
|
defaultValue: t.viewer?.mfvPreviewMethod || k.MFV_PREVIEW_METHOD,
|
|
options: [
|
|
"taesd",
|
|
"latent2rgb",
|
|
"auto",
|
|
"default",
|
|
"none"
|
|
],
|
|
onChange: (e) => {
|
|
let r = [
|
|
"taesd",
|
|
"latent2rgb",
|
|
"auto",
|
|
"default",
|
|
"none"
|
|
].includes(e) ? e : k.MFV_PREVIEW_METHOD;
|
|
t.viewer = t.viewer || {}, t.viewer.mfvPreviewMethod = r, q(t), J(t), n("viewer.mfvPreviewMethod");
|
|
}
|
|
}), e({
|
|
id: `${dn}.Viewer.LtxavRgbFallback`,
|
|
category: a("LTXAV preview fallback"),
|
|
name: "Majoor: LTXAV RGB Preview Fallback (experimental)",
|
|
tooltip: "Reuse LTXV RGB projection for LTXAV when native latent preview is unavailable. Experimental; quality may be approximate.",
|
|
type: "boolean",
|
|
defaultValue: !!t.viewer?.ltxavRgbFallback,
|
|
onChange: async (e) => {
|
|
let r = !!e, i = !!t.viewer?.ltxavRgbFallback;
|
|
t.viewer = t.viewer || {}, t.viewer.ltxavRgbFallback = r, q(t), J(t), n("viewer.ltxavRgbFallback");
|
|
try {
|
|
let e = await l(r);
|
|
if (!e?.ok) throw Error(e?.error || "Failed to update LTXAV RGB preview fallback setting");
|
|
} catch (e) {
|
|
t.viewer.ltxavRgbFallback = i, q(t), J(t), n("viewer.ltxavRgbFallback"), v(e?.message || "Failed to update LTXAV RGB preview fallback setting", "error");
|
|
}
|
|
}
|
|
});
|
|
try {
|
|
E().then((e) => {
|
|
if (!e?.ok) return;
|
|
let r = !!e?.data?.prefs?.enabled, i = K();
|
|
i.viewer = i.viewer || {}, !!i.viewer.ltxavRgbFallback !== r && (i.viewer.ltxavRgbFallback = r, Object.assign(t, i), q(i), J(i), n("viewer.ltxavRgbFallback"));
|
|
}).catch(() => {});
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
((r, a, o, s) => {
|
|
e({
|
|
id: `${dn}.WorkflowMinimap.${r}`,
|
|
category: i(A(o).replace("Majoor: ", "")),
|
|
name: A(o),
|
|
tooltip: A(s),
|
|
type: "boolean",
|
|
defaultValue: !!t.workflowMinimap?.[a],
|
|
onChange: (e) => {
|
|
t.workflowMinimap = t.workflowMinimap || {}, t.workflowMinimap[a] = !!e, q(t), n(`workflowMinimap.${a}`);
|
|
}
|
|
});
|
|
})("Enabled", "enabled", "setting.minimap.enabled.name", "setting.minimap.enabled.desc");
|
|
}
|
|
//#endregion
|
|
//#region ui/app/settings/settingsScanning.ts
|
|
var mn = "Majoor", hn = "Majoor Assets Manager";
|
|
function gn(e, t, r) {
|
|
let i = (e, t) => [
|
|
hn,
|
|
e,
|
|
t
|
|
];
|
|
e({
|
|
id: `${mn}.ExecutionGrouping.Enabled`,
|
|
category: i(A("cat.scanning"), "Execution grouping"),
|
|
name: "Execution job/stack grouping",
|
|
tooltip: "Enable or disable all live job_id / stack_id tracking, grouping, and stack finalization logic.",
|
|
type: "boolean",
|
|
defaultValue: !!(t.executionGrouping?.enabled ?? k.EXECUTION_GROUPING_ENABLED),
|
|
onChange: async (e) => {
|
|
let n = !!(t.executionGrouping?.enabled ?? k.EXECUTION_GROUPING_ENABLED), i = !!e;
|
|
t.executionGrouping = t.executionGrouping || {}, t.executionGrouping.enabled = i, q(t), J(t), r("executionGrouping.enabled");
|
|
try {
|
|
let e = await f(i);
|
|
if (!e?.ok) throw Error(e?.error || "Failed to update execution grouping setting");
|
|
t.executionGrouping.enabled = !!e?.data?.prefs?.enabled, q(t), J(t), r("executionGrouping.enabled");
|
|
} catch (e) {
|
|
t.executionGrouping.enabled = n, q(t), J(t), r("executionGrouping.enabled"), v(e?.message || "Failed to update execution grouping setting", "error");
|
|
}
|
|
}
|
|
}), e({
|
|
id: `${mn}.AutoScan.OnStartup`,
|
|
category: i(A("cat.scanning"), A("setting.scan.startup.name").replace("Majoor: ", "")),
|
|
name: A("setting.scan.startup.name"),
|
|
tooltip: A("setting.scan.startup.desc"),
|
|
type: "boolean",
|
|
defaultValue: !!t.autoScan?.onStartup,
|
|
onChange: (e) => {
|
|
t.autoScan = t.autoScan || {}, t.autoScan.onStartup = !!e, q(t), J(t), r("autoScan.onStartup");
|
|
}
|
|
}), e({
|
|
id: `${mn}.Scan.FastMode`,
|
|
category: i(A("cat.scanning"), "Scan mode"),
|
|
name: "Fast scan mode",
|
|
tooltip: "Use fast scan mode for manual backfill scans (skip heavier metadata work during scan).",
|
|
type: "boolean",
|
|
defaultValue: !!(t.scan?.fastMode ?? !0),
|
|
onChange: (e) => {
|
|
t.scan = t.scan || {}, t.scan.fastMode = !!e, q(t), r("scan.fastMode");
|
|
}
|
|
}), e({
|
|
id: `${mn}.RtHydrate.Concurrency`,
|
|
category: i(A("cat.scanning"), "Hydration"),
|
|
name: "Hydrate Concurrency",
|
|
tooltip: "Maximum concurrent hydration requests for rating/tags.",
|
|
type: "number",
|
|
defaultValue: Number(t.rtHydrate?.concurrency || k.RT_HYDRATE_CONCURRENCY || 5),
|
|
attrs: {
|
|
min: 1,
|
|
max: 20,
|
|
step: 1
|
|
},
|
|
onChange: (e) => {
|
|
t.rtHydrate = t.rtHydrate || {}, t.rtHydrate.concurrency = Math.max(1, Math.min(20, Math.round(U(e, k.RT_HYDRATE_CONCURRENCY || 5)))), q(t), J(t), r("rtHydrate.concurrency");
|
|
}
|
|
});
|
|
let a = (e, t, n, r) => {
|
|
let i = Math.round(U(e, t));
|
|
return Math.max(n, Math.min(r, i));
|
|
}, o = (e = {}) => {
|
|
let n = [];
|
|
if (t.watcher = t.watcher || {}, typeof e.debounce_ms == "number") {
|
|
let r = Math.max(50, Math.min(5e3, Math.round(e.debounce_ms)));
|
|
t.watcher.debounceMs !== r && (t.watcher.debounceMs = r, n.push("watcher.debounceMs"));
|
|
}
|
|
if (typeof e.dedupe_ttl_ms == "number") {
|
|
let r = Math.max(100, Math.min(3e4, Math.round(e.dedupe_ttl_ms)));
|
|
t.watcher.dedupeTtlMs !== r && (t.watcher.dedupeTtlMs = r, n.push("watcher.dedupeTtlMs"));
|
|
}
|
|
n.length && (q(t), n.forEach((e) => r(e)));
|
|
}, s = async () => {
|
|
try {
|
|
let e = await C();
|
|
if (!e?.ok) return;
|
|
o(e.data || {});
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
};
|
|
e({
|
|
id: `${mn}.Watcher.Enabled`,
|
|
category: i(A("cat.scanning"), A("setting.watcher.enabled.label", "Enable watcher")),
|
|
name: A("setting.watcher.name"),
|
|
tooltip: A("setting.watcher.desc") + " (env: MJR_ENABLE_WATCHER)",
|
|
type: "boolean",
|
|
defaultValue: !!t.watcher?.enabled,
|
|
onChange: async (e) => {
|
|
t.watcher = t.watcher || {}, t.watcher.enabled = !!e, q(t), r("watcher.enabled");
|
|
try {
|
|
let n = await ge(!!e);
|
|
n?.ok || (t.watcher.enabled = !e, q(t), r("watcher.enabled"), v(n?.error || A("toast.failedToggleWatcher", "Failed to toggle watcher"), "error"));
|
|
} catch {
|
|
t.watcher.enabled = !e, q(t), r("watcher.enabled");
|
|
}
|
|
}
|
|
}), e({
|
|
id: `${mn}.Watcher.DebounceDelay`,
|
|
category: i(A("cat.scanning"), A("setting.watcher.debounce.label", "Watcher debounce delay")),
|
|
name: A("setting.watcher.debounce.name"),
|
|
tooltip: A("setting.watcher.debounce.desc") + " (env: MJR_WATCHER_DEBOUNCE_MS)",
|
|
type: "number",
|
|
defaultValue: t.watcher?.debounceMs ?? k.WATCHER_DEBOUNCE_MS,
|
|
attrs: {
|
|
min: 50,
|
|
max: 6e4,
|
|
step: 50
|
|
},
|
|
onChange: async (e) => {
|
|
let i = k.WATCHER_DEBOUNCE_MS, o = a(e, i, 50, 6e4), s = t.watcher?.debounceMs ?? i;
|
|
if (o !== s) {
|
|
t.watcher = t.watcher || {}, t.watcher.debounceMs = o, q(t);
|
|
try {
|
|
let e = await n({ debounce_ms: o });
|
|
if (!e?.ok) throw Error(e?.error || A("setting.watcher.debounce.error"));
|
|
let i = Math.round(Number(e?.data?.debounce_ms ?? o));
|
|
t.watcher.debounceMs = i, q(t), r("watcher.debounceMs");
|
|
} catch (e) {
|
|
t.watcher.debounceMs = s, q(t), r("watcher.debounceMs"), v(e?.message || A("setting.watcher.debounce.error"), "error");
|
|
}
|
|
}
|
|
}
|
|
}), e({
|
|
id: `${mn}.Watcher.DedupeWindow`,
|
|
category: i(A("cat.scanning"), A("setting.watcher.dedupe.label", "Watcher dedupe window")),
|
|
name: A("setting.watcher.dedupe.name"),
|
|
tooltip: A("setting.watcher.dedupe.desc") + " (env: MJR_WATCHER_DEDUPE_TTL_MS)",
|
|
type: "number",
|
|
defaultValue: t.watcher?.dedupeTtlMs ?? k.WATCHER_DEDUPE_TTL_MS,
|
|
attrs: {
|
|
min: 100,
|
|
max: 12e4,
|
|
step: 100
|
|
},
|
|
onChange: async (e) => {
|
|
let i = k.WATCHER_DEDUPE_TTL_MS, o = a(e, i, 100, 12e4), s = t.watcher?.dedupeTtlMs ?? i;
|
|
if (o !== s) {
|
|
t.watcher = t.watcher || {}, t.watcher.dedupeTtlMs = o, q(t);
|
|
try {
|
|
let e = await n({ dedupe_ttl_ms: o });
|
|
if (!e?.ok) throw Error(e?.error || A("setting.watcher.dedupe.error"));
|
|
let i = Math.round(Number(e?.data?.dedupe_ttl_ms ?? o));
|
|
t.watcher.dedupeTtlMs = i, q(t), r("watcher.dedupeTtlMs");
|
|
} catch (e) {
|
|
t.watcher.dedupeTtlMs = s, q(t), r("watcher.dedupeTtlMs"), v(e?.message || A("setting.watcher.dedupe.error"), "error");
|
|
}
|
|
}
|
|
}
|
|
}), e({
|
|
id: `${mn}.Watcher.MaxPending`,
|
|
category: i(A("cat.scanning"), "Watcher queue"),
|
|
name: "Watcher: max pending files",
|
|
tooltip: "Maximum number of pending watcher files kept in memory.",
|
|
type: "number",
|
|
defaultValue: Number(t.watcher?.maxPending ?? 500),
|
|
attrs: {
|
|
min: 10,
|
|
max: 5e3,
|
|
step: 10
|
|
},
|
|
onChange: (e) => {
|
|
t.watcher = t.watcher || {}, t.watcher.maxPending = Math.max(10, Math.min(5e3, Math.round(U(e, 500)))), q(t), J(t), r("watcher.maxPending");
|
|
}
|
|
}), e({
|
|
id: `${mn}.Watcher.MinSize`,
|
|
category: i(A("cat.scanning"), "Watcher file size"),
|
|
name: "Watcher: min size (bytes)",
|
|
tooltip: "Minimum file size indexed by watcher.",
|
|
type: "number",
|
|
defaultValue: Number(t.watcher?.minSize ?? 100),
|
|
attrs: {
|
|
min: 0,
|
|
max: 1e6,
|
|
step: 100
|
|
},
|
|
onChange: (e) => {
|
|
t.watcher = t.watcher || {}, t.watcher.minSize = Math.max(0, Math.min(1e6, Math.round(U(e, 100)))), q(t), J(t), r("watcher.minSize");
|
|
}
|
|
}), e({
|
|
id: `${mn}.Watcher.MaxSize`,
|
|
category: i(A("cat.scanning"), "Watcher file size"),
|
|
name: "Watcher: max size (bytes)",
|
|
tooltip: "Maximum file size indexed by watcher.",
|
|
type: "number",
|
|
defaultValue: Number(t.watcher?.maxSize ?? 4294967296),
|
|
attrs: {
|
|
min: 1e5,
|
|
max: 17179869184,
|
|
step: 1e5
|
|
},
|
|
onChange: (e) => {
|
|
t.watcher = t.watcher || {}, t.watcher.maxSize = Math.max(1e5, Math.min(17179869184, Math.round(U(e, 4294967296)))), q(t), J(t), r("watcher.maxSize");
|
|
}
|
|
});
|
|
try {
|
|
s().catch(() => {});
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
e({
|
|
id: `${mn}.RatingTagsSync.Enabled`,
|
|
category: i(A("cat.scanning"), A("setting.sync.rating.name").replace("Majoor: ", "")),
|
|
name: A("setting.sync.rating.name"),
|
|
tooltip: A("setting.sync.rating.desc"),
|
|
type: "boolean",
|
|
defaultValue: !!t.ratingTagsSync?.enabled,
|
|
onChange: (e) => {
|
|
t.ratingTagsSync = t.ratingTagsSync || {}, t.ratingTagsSync.enabled = !!e, q(t), r("ratingTagsSync.enabled");
|
|
}
|
|
});
|
|
}
|
|
//#endregion
|
|
//#region ui/app/settings/settingsFeed.ts
|
|
var _n = "Majoor", vn = "Majoor Assets Manager";
|
|
function yn(e, t, n) {
|
|
let r = (e) => [
|
|
vn,
|
|
A("cat.feed", "Generated Feed"),
|
|
e
|
|
], i = () => {
|
|
t.feed = t.feed || {};
|
|
};
|
|
e({
|
|
id: `${_n}.Feed.CardSize`,
|
|
category: r("Card size"),
|
|
name: "Feed card size (px)",
|
|
tooltip: "Set the minimum card width used by the Generated Feed layout (60-600 px).",
|
|
type: "number",
|
|
defaultValue: Math.max(60, Math.min(600, Number(t.feed?.minSize) || 120)),
|
|
attrs: {
|
|
min: 60,
|
|
max: 600,
|
|
step: 10
|
|
},
|
|
onChange: (e) => {
|
|
i(), t.feed.minSize = Math.max(60, Math.min(600, Math.round(Number(e) || 120))), q(t), J(t), n("feed.minSize");
|
|
}
|
|
}), e({
|
|
id: `${_n}.Feed.ShowInfo`,
|
|
category: r("Show info section"),
|
|
name: "Show card info section",
|
|
tooltip: "Show or hide the entire info section (filename, metadata, dots) below thumbnails in the Generated Feed.",
|
|
type: "boolean",
|
|
defaultValue: !!(t.feed?.showInfo ?? k.FEED_SHOW_INFO),
|
|
onChange: (e) => {
|
|
i(), t.feed.showInfo = !!e, q(t), J(t), n("feed.showInfo");
|
|
}
|
|
}), e({
|
|
id: `${_n}.Feed.ShowFilename`,
|
|
category: r("Show filename"),
|
|
name: "Show filename",
|
|
tooltip: "Display the filename on feed cards.",
|
|
type: "boolean",
|
|
defaultValue: !!(t.feed?.showFilename ?? k.FEED_SHOW_FILENAME),
|
|
onChange: (e) => {
|
|
i(), t.feed.showFilename = !!e, q(t), J(t), n("feed.showFilename");
|
|
}
|
|
}), e({
|
|
id: `${_n}.Feed.ShowDimensions`,
|
|
category: r("Show dimensions"),
|
|
name: "Show dimensions",
|
|
tooltip: "Display resolution (WxH) and duration on feed cards.",
|
|
type: "boolean",
|
|
defaultValue: !!(t.feed?.showDimensions ?? k.FEED_SHOW_DIMENSIONS),
|
|
onChange: (e) => {
|
|
i(), t.feed.showDimensions = !!e, q(t), J(t), n("feed.showDimensions");
|
|
}
|
|
}), e({
|
|
id: `${_n}.Feed.ShowDate`,
|
|
category: r("Show date/time"),
|
|
name: "Show date/time",
|
|
tooltip: "Display date and time on feed cards.",
|
|
type: "boolean",
|
|
defaultValue: !!(t.feed?.showDate ?? k.FEED_SHOW_DATE),
|
|
onChange: (e) => {
|
|
i(), t.feed.showDate = !!e, q(t), J(t), n("feed.showDate");
|
|
}
|
|
}), e({
|
|
id: `${_n}.Feed.ShowGenTime`,
|
|
category: r("Show generation time"),
|
|
name: "Show generation time",
|
|
tooltip: "Display the generation time badge on feed cards.",
|
|
type: "boolean",
|
|
defaultValue: !!(t.feed?.showGenTime ?? k.FEED_SHOW_GENTIME),
|
|
onChange: (e) => {
|
|
i(), t.feed.showGenTime = !!e, q(t), J(t), n("feed.showGenTime");
|
|
}
|
|
}), e({
|
|
id: `${_n}.Feed.ShowWorkflowDot`,
|
|
category: r("Show workflow dot"),
|
|
name: "Show workflow indicator",
|
|
tooltip: "Display the workflow availability dot on feed cards.",
|
|
type: "boolean",
|
|
defaultValue: !!(t.feed?.showWorkflowDot ?? k.FEED_SHOW_WORKFLOW_DOT),
|
|
onChange: (e) => {
|
|
i(), t.feed.showWorkflowDot = !!e, q(t), J(t), n("feed.showWorkflowDot");
|
|
}
|
|
}), e({
|
|
id: `${_n}.Feed.ShowExtBadge`,
|
|
category: r("Show format badges"),
|
|
name: "Show format badges",
|
|
tooltip: "Display format badges (e.g. JPG, MP4) on feed card thumbnails.",
|
|
type: "boolean",
|
|
defaultValue: !!(t.feed?.showExtBadge ?? k.FEED_SHOW_BADGES_EXTENSION),
|
|
onChange: (e) => {
|
|
i(), t.feed.showExtBadge = !!e, q(t), J(t), n("feed.showExtBadge");
|
|
}
|
|
}), e({
|
|
id: `${_n}.Feed.ShowRatingBadge`,
|
|
category: r("Show rating badges"),
|
|
name: "Show ratings",
|
|
tooltip: "Display star ratings on feed card thumbnails.",
|
|
type: "boolean",
|
|
defaultValue: !!(t.feed?.showRatingBadge ?? k.FEED_SHOW_BADGES_RATING),
|
|
onChange: (e) => {
|
|
i(), t.feed.showRatingBadge = !!e, q(t), J(t), n("feed.showRatingBadge");
|
|
}
|
|
}), e({
|
|
id: `${_n}.Feed.ShowTagsBadge`,
|
|
category: r("Show tags badges"),
|
|
name: "Show tags",
|
|
tooltip: "Display tag indicators on feed card thumbnails.",
|
|
type: "boolean",
|
|
defaultValue: !!(t.feed?.showTagsBadge ?? k.FEED_SHOW_BADGES_TAGS),
|
|
onChange: (e) => {
|
|
i(), t.feed.showTagsBadge = !!e, q(t), J(t), n("feed.showTagsBadge");
|
|
}
|
|
});
|
|
}
|
|
//#endregion
|
|
//#region ui/app/settings/settingsSecurity.ts
|
|
var bn = "Majoor", xn = "Majoor Assets Manager", Sn = 16, Cn = {
|
|
safeMode: !1,
|
|
allowWrite: !0,
|
|
allowDelete: !0,
|
|
allowRename: !0,
|
|
allowOpenInFolder: !0,
|
|
allowResetIndex: !0
|
|
};
|
|
function wn(e) {
|
|
return !!e;
|
|
}
|
|
function Tn(e, t) {
|
|
return wn(e) === wn(t);
|
|
}
|
|
function En(e) {
|
|
return typeof e == "string" ? e.trim() : "";
|
|
}
|
|
function Dn(e) {
|
|
let t = String(e || "").trim().toLowerCase();
|
|
return t === "localhost" || t === "127.0.0.1" || t === "::1";
|
|
}
|
|
function On() {
|
|
return globalThis.location || globalThis.window?.location || null;
|
|
}
|
|
function kn() {
|
|
let e = On();
|
|
if (!e) return !1;
|
|
let t = String(e.protocol || "").toLowerCase(), n = String(e.hostname || "").trim();
|
|
return t === "http:" && !Dn(n);
|
|
}
|
|
function An(e) {
|
|
let t = globalThis.crypto;
|
|
if (!t?.getRandomValues) throw Error("Secure token generation requires crypto.getRandomValues().");
|
|
return t.getRandomValues(e);
|
|
}
|
|
function jn(e) {
|
|
let t = Math.max(4, Number(e) || 0), n = new Uint8Array(t);
|
|
return An(n), Array.from(n, (e) => e.toString(16).padStart(2, "0")).join("");
|
|
}
|
|
function Mn() {
|
|
return `mjr_${jn(18)}`;
|
|
}
|
|
function Nn(e) {
|
|
return String(e?.apiToken || "").trim().length >= Sn && H(e?.allowWrite, !0) && H(e?.requireAuth, !1) && !H(e?.allowRemoteWrite, !1);
|
|
}
|
|
function Pn(e) {
|
|
let t = String((e && typeof e == "object" ? e : {}).apiToken || "").trim();
|
|
return {
|
|
apiToken: t.length >= Sn ? t : Mn(),
|
|
allowWrite: !0,
|
|
requireAuth: !0,
|
|
allowRemoteWrite: !1,
|
|
allowInsecureTokenTransport: kn()
|
|
};
|
|
}
|
|
function Fn(e) {
|
|
let t = e || {};
|
|
return {
|
|
safe_mode: H(t.safeMode, !1),
|
|
allow_write: H(t.allowWrite, !0),
|
|
require_auth: H(t.requireAuth, !1),
|
|
allow_remote_write: H(t.allowRemoteWrite, !1),
|
|
allow_insecure_token_transport: H(t.allowInsecureTokenTransport, !1),
|
|
allow_delete: H(t.allowDelete, !0),
|
|
allow_rename: H(t.allowRename, !0),
|
|
allow_open_in_folder: H(t.allowOpenInFolder, !0),
|
|
allow_reset_index: H(t.allowResetIndex, !0),
|
|
...String(t.apiToken || "").trim() ? { api_token: String(t.apiToken || "").trim() } : {}
|
|
};
|
|
}
|
|
function In(e) {
|
|
return c(Fn(e));
|
|
}
|
|
function Ln(e) {
|
|
let t = String(e?.security?.tokenHint || "").trim();
|
|
return t ? A("setting.sec.token.placeholderConfigured", "Token configured on server ({tokenHint}). Leave blank to keep the current server token.", { tokenHint: t }) : e?.security?.tokenConfigured ? A("setting.sec.token.placeholderConfiguredGeneric", "Token configured on server. Leave blank to keep the current server token.") : A("setting.sec.token.placeholder", "Auto-generated for this browser session.");
|
|
}
|
|
function Rn(e, t, n) {
|
|
let r = (e, t) => [
|
|
xn,
|
|
e,
|
|
t
|
|
];
|
|
e({
|
|
id: `${bn}.Safety.ConfirmDeletion`,
|
|
category: r(A("cat.security"), "Confirm before deleting"),
|
|
name: "Confirm before deleting",
|
|
tooltip: "Show a confirmation dialog before deleting files. Disabling this allows instant deletion.",
|
|
type: "boolean",
|
|
defaultValue: t.safety?.confirmDeletion !== !1,
|
|
onChange: (e) => {
|
|
Tn(t.safety?.confirmDeletion !== !1, e) || (t.safety = t.safety || {}, t.safety.confirmDeletion = !!e, q(t), J(t), n("safety.confirmDeletion"));
|
|
}
|
|
});
|
|
let i = (i, a, o, s = "cat.security") => {
|
|
e({
|
|
id: `${bn}.Security.${i}`,
|
|
category: r(A(s), A(a).replace("Majoor: ", "")),
|
|
name: A(a),
|
|
tooltip: A(o),
|
|
type: "boolean",
|
|
defaultValue: H(t.security?.[i], Cn[i] ?? !1),
|
|
onChange: (e) => {
|
|
if (!Tn(t.security?.[i], e)) {
|
|
t.security = t.security || {}, t.security[i] = !!e, q(t), n(`security.${i}`);
|
|
try {
|
|
In(t.security).then((e) => {
|
|
e?.ok && e.data?.prefs ? Gt() : e && e.ok === !1 && console.warn("[Majoor] backend security settings update failed", e.error || e);
|
|
}).catch(() => {});
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
};
|
|
i("safeMode", "setting.sec.safe.name", "setting.sec.safe.desc"), i("allowWrite", "setting.sec.write.name", "setting.sec.write.desc"), i("allowDelete", "setting.sec.del.name", "setting.sec.del.desc"), i("allowRename", "setting.sec.ren.name", "setting.sec.ren.desc"), i("allowOpenInFolder", "setting.sec.open.name", "setting.sec.open.desc"), i("allowResetIndex", "setting.sec.reset.name", "setting.sec.reset.desc"), e({
|
|
id: `${bn}.Security.RemoteLanPreset`,
|
|
category: r(A("cat.remote"), A("setting.sec.remoteLanPreset.name").replace("Majoor: ", "")),
|
|
name: A("setting.sec.remoteLanPreset.name"),
|
|
tooltip: A("setting.sec.remoteLanPreset.desc"),
|
|
type: "boolean",
|
|
defaultValue: Nn(t.security),
|
|
onChange: (e) => {
|
|
if (t.security = t.security || {}, Tn(t.security.remoteLanPreset, e)) return;
|
|
if (t.security.remoteLanPreset = !!e, !e) {
|
|
q(t), n("security.remoteLanPreset");
|
|
return;
|
|
}
|
|
let r;
|
|
try {
|
|
r = Pn(t.security);
|
|
} catch (e) {
|
|
v(e?.message || A("toast.remoteLanPresetFailed", "Failed to apply the recommended remote LAN setup."), "error");
|
|
return;
|
|
}
|
|
Object.assign(t.security, r), t.security.tokenConfigured = !0, t.security.tokenHint = String(r.apiToken || "").trim() ? `...${String(r.apiToken).trim().slice(-4)}` : "", r.apiToken && y(r.apiToken), q(t), n("security.remoteLanPreset"), n("security.apiToken"), n("security.allowWrite"), n("security.requireAuth"), n("security.allowRemoteWrite"), n("security.allowInsecureTokenTransport");
|
|
try {
|
|
In(t.security).then((e) => {
|
|
e?.ok && e.data?.prefs ? (Gt(), v(A("toast.remoteLanPresetApplied", "Recommended remote LAN setup applied. This browser session is now authorized for Majoor write operations."), "success")) : e && e.ok === !1 && (v(e.error || A("toast.remoteLanPresetFailed", "Failed to apply the recommended remote LAN setup."), "error"), console.warn("[Majoor] backend remote LAN preset update failed", e.error || e));
|
|
}).catch((e) => {
|
|
v(e?.message || A("toast.remoteLanPresetFailed", "Failed to apply the recommended remote LAN setup."), "error");
|
|
});
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
}
|
|
}), e({
|
|
id: `${bn}.Security.ApiToken`,
|
|
category: r(A("cat.remote"), A("setting.sec.token.name").replace("Majoor: ", "")),
|
|
name: A("setting.sec.token.name", "Majoor: API Token"),
|
|
tooltip: A("setting.sec.token.desc", "Store the API token used for write operations. Majoor sends it via X-MJR-Token and Authorization headers."),
|
|
type: "text",
|
|
defaultValue: t.security?.apiToken || "",
|
|
attrs: { placeholder: Ln(t) },
|
|
onChange: (e) => {
|
|
t.security = t.security || {};
|
|
let r = En(e);
|
|
if (En(t.security.apiToken) !== r && (t.security.apiToken = r, t.security.apiToken && (t.security.tokenConfigured = !0, t.security.tokenHint = `...${t.security.apiToken.slice(-4)}`, y(t.security.apiToken)), q(t), n("security.apiToken"), t.security.apiToken)) try {
|
|
c({ api_token: t.security.apiToken }).then((e) => {
|
|
e?.ok && e.data?.prefs ? Gt() : e && e.ok === !1 && console.warn("[Majoor] backend token update failed", e.error || e);
|
|
}).catch(() => {});
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
}
|
|
}), i("requireAuth", "setting.sec.requireAuth.name", "setting.sec.requireAuth.desc", "cat.remote"), i("allowRemoteWrite", "setting.sec.remote.name", "setting.sec.remote.desc", "cat.remote"), i("allowInsecureTokenTransport", "setting.sec.insecureTransport.name", "setting.sec.insecureTransport.desc", "cat.remote");
|
|
}
|
|
//#endregion
|
|
//#region ui/app/settings/settingsAdvanced.ts
|
|
var X = "Majoor", zn = "Majoor Assets Manager";
|
|
function Bn(e, n, a, c) {
|
|
let l = (e, t) => [
|
|
zn,
|
|
e,
|
|
t
|
|
], u = String(n.paths?.outputDirectory || ""), f = null, p = 0, m = null;
|
|
e({
|
|
id: `${X}.Paths.OutputDirectory`,
|
|
category: l(A("cat.advanced"), "Paths / Output"),
|
|
name: "Majoor: Generation Output Directory",
|
|
tooltip: "Override the ComfyUI generation output directory used by Majoor (equivalent to --output-directory). Leave empty to keep the current backend default.",
|
|
type: "text",
|
|
defaultValue: String(n.paths?.outputDirectory || ""),
|
|
attrs: { placeholder: "D:\\\\____COMFY_OUTPUTS" },
|
|
onChange: async (e) => {
|
|
let r = String(e || "").trim();
|
|
n.paths = n.paths || {}, n.paths.outputDirectory = r, q(n);
|
|
try {
|
|
f &&= (clearTimeout(f), null);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
f = setTimeout(async () => {
|
|
f = null;
|
|
let e = ++p;
|
|
try {
|
|
m?.abort?.();
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
m = typeof AbortController < "u" ? new AbortController() : null;
|
|
try {
|
|
let i = await t(r, m ? { signal: m.signal } : {});
|
|
if (e !== p) return;
|
|
if (!i?.ok) throw Error(i?.error || A("toast.failedSetOutputDirectory", "Failed to set output directory"));
|
|
let o = String(i?.data?.output_directory || r).trim();
|
|
n.paths.outputDirectory = o, u = o, q(n), a("paths.outputDirectory");
|
|
} catch (t) {
|
|
if (e !== p || String(t?.name || "") === "AbortError" || String(t?.code || "") === "ABORTED") return;
|
|
n.paths.outputDirectory = u, q(n), a("paths.outputDirectory"), v(t?.message || A("toast.failedSetOutputDirectory", "Failed to set output directory"), "error");
|
|
}
|
|
}, 700);
|
|
}
|
|
});
|
|
try {
|
|
ne().then((e) => {
|
|
if (!e?.ok) return;
|
|
let t = String(e?.data?.output_directory || "").trim();
|
|
n.paths = n.paths || {}, n.paths.outputDirectory !== t && (n.paths.outputDirectory = t, u = t, q(n), a("paths.outputDirectory"));
|
|
}).catch(() => {});
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
let g = String(n.paths?.indexDirectory || ""), y = null, x = 0, C = null;
|
|
e({
|
|
id: `${X}.Paths.IndexDirectory`,
|
|
category: l(A("cat.advanced"), "Paths / Index"),
|
|
name: "Majoor: Index Database Directory",
|
|
tooltip: "Override the Majoor index database directory. Use this to keep the SQLite index on a different local disk. Requires restart.",
|
|
type: "text",
|
|
defaultValue: String(n.paths?.indexDirectory || ""),
|
|
attrs: { placeholder: "D:\\MajoorIndex" },
|
|
onChange: async (e) => {
|
|
let t = String(e || "").trim();
|
|
n.paths = n.paths || {}, n.paths.indexDirectory = t, q(n);
|
|
try {
|
|
y &&= (clearTimeout(y), null);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
y = setTimeout(async () => {
|
|
y = null;
|
|
let e = ++x;
|
|
try {
|
|
C?.abort?.();
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
C = typeof AbortController < "u" ? new AbortController() : null;
|
|
try {
|
|
let i = await r(t, C ? { signal: C.signal } : {});
|
|
if (e !== x) return;
|
|
if (!i?.ok) throw Error(i?.error || A("toast.failedSetIndexDirectory", "Failed to set index directory"));
|
|
let o = String(i?.data?.index_directory || t).trim(), s = o !== g;
|
|
n.paths.indexDirectory = o, g = o, q(n), a("paths.indexDirectory"), s && v(A("toast.indexDirectorySavedRestart", "Index directory saved. Restart ComfyUI to apply."), "success", void 0, { history: { trackId: "settings:index-directory-saved" } });
|
|
} catch (t) {
|
|
if (e !== x || String(t?.name || "") === "AbortError" || String(t?.code || "") === "ABORTED") return;
|
|
n.paths.indexDirectory = g, q(n), a("paths.indexDirectory"), v(t?.message || A("toast.failedSetIndexDirectory", "Failed to set index directory"), "error");
|
|
}
|
|
}, 700);
|
|
}
|
|
});
|
|
try {
|
|
fe().then((e) => {
|
|
if (!e?.ok) return;
|
|
let t = String(e?.data?.index_directory || "").trim();
|
|
n.paths = n.paths || {}, n.paths.indexDirectory !== t && (n.paths.indexDirectory = t, g = t, q(n), a("paths.indexDirectory"));
|
|
}).catch(() => {});
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
let w = String(n.paths?.workflowRoots || ""), T = null, re = 0, ae = null;
|
|
e({
|
|
id: `${X}.Paths.WorkflowRoots`,
|
|
category: l(A("cat.advanced"), "Paths / Workflows"),
|
|
name: "Majoor: Workflow Roots",
|
|
tooltip: "Folders scanned by the Workflow tab. Use one folder per line, or separate folders with semicolons. Leave empty to use ComfyUI defaults and MJR_AM_WORKFLOW_DIRECTORY.",
|
|
type: "text",
|
|
defaultValue: String(n.paths?.workflowRoots || ""),
|
|
attrs: { placeholder: "D:\\\\ComfyUI\\\\user\\\\default\\\\workflows" },
|
|
onChange: async (e) => {
|
|
let t = String(e || "").trim();
|
|
n.paths = n.paths || {}, n.paths.workflowRoots = t, q(n);
|
|
try {
|
|
T &&= (clearTimeout(T), null);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
T = setTimeout(async () => {
|
|
T = null;
|
|
let e = ++re;
|
|
try {
|
|
ae?.abort?.();
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
ae = typeof AbortController < "u" ? new AbortController() : null;
|
|
try {
|
|
let r = await o(t, ae ? { signal: ae.signal } : {});
|
|
if (e !== re) return;
|
|
if (!r?.ok) throw Error(r?.error || A("toast.failedSetWorkflowRoots", "Failed to set workflow roots"));
|
|
let i = String(r?.data?.workflow_roots_text || t).trim();
|
|
n.paths.workflowRoots = i, w = i, q(n), a("paths.workflowRoots"), v(A("toast.workflowRootsSaved", "Workflow roots saved"), "success", 1800);
|
|
} catch (t) {
|
|
if (e !== re || String(t?.name || "") === "AbortError" || String(t?.code || "") === "ABORTED") return;
|
|
n.paths.workflowRoots = w, q(n), a("paths.workflowRoots"), v(t?.message || A("toast.failedSetWorkflowRoots", "Failed to set workflow roots"), "error");
|
|
}
|
|
}, 700);
|
|
}
|
|
});
|
|
try {
|
|
ce().then((e) => {
|
|
if (!e?.ok) return;
|
|
let t = String(e?.data?.workflow_roots_text || "").trim();
|
|
n.paths = n.paths || {}, n.paths.workflowRoots !== t && (n.paths.workflowRoots = t, w = t, q(n), a("paths.workflowRoots"));
|
|
}).catch(() => {});
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
let E = Se().map((e) => e.code), se = ["auto", ...E];
|
|
e({
|
|
id: `${X}.Language`,
|
|
category: l(A("cat.advanced"), A("setting.language.name", "Language")),
|
|
name: A("setting.language.name", "Majoor: Language"),
|
|
tooltip: "Use auto to detect and follow ComfyUI language. Or choose a fixed language for Majoor only.",
|
|
type: "combo",
|
|
defaultValue: n.i18n?.followComfyLanguage ? "auto" : Oe(),
|
|
options: se,
|
|
onChange: (e) => {
|
|
if (n.i18n = n.i18n || {}, e === "auto") {
|
|
n.i18n.followComfyLanguage = !0, ke(!0), Ee(c), q(n), a("language");
|
|
return;
|
|
}
|
|
E.includes(e) && (n.i18n.followComfyLanguage = !1, ke(!1), Ce(e), q(n), a("language"));
|
|
}
|
|
}), e({
|
|
id: `${X}.ProbeBackend.Mode`,
|
|
category: l(A("cat.advanced"), A("setting.probe.mode.name").replace("Majoor: ", "")),
|
|
name: A("setting.probe.mode.name"),
|
|
tooltip: A("setting.probe.mode.desc") + " (env: MAJOOR_MEDIA_PROBE_BACKEND)",
|
|
type: "combo",
|
|
defaultValue: n.probeBackend?.mode || G.probeBackend.mode,
|
|
options: [
|
|
"auto",
|
|
"exiftool",
|
|
"ffprobe",
|
|
"both"
|
|
],
|
|
onChange: (e) => {
|
|
let t = vt(e, [
|
|
"auto",
|
|
"exiftool",
|
|
"ffprobe",
|
|
"both"
|
|
], G.probeBackend.mode);
|
|
n.probeBackend = n.probeBackend || {}, n.probeBackend.mode = t, q(n), J(n), a("probeBackend.mode"), ie(t).catch(() => {});
|
|
}
|
|
}), e({
|
|
id: `${X}.MetadataFallback.Image`,
|
|
category: l(A("cat.advanced"), "Metadata"),
|
|
name: "Majoor: Metadata Fallback (Images)",
|
|
tooltip: "Enable Pillow fallback when ExifTool is missing or fails.",
|
|
type: "boolean",
|
|
defaultValue: n.metadataFallback?.image ?? G.metadataFallback.image,
|
|
onChange: async (e) => {
|
|
let t = !!e, r = !!(n.metadataFallback?.image ?? G.metadataFallback.image);
|
|
n.metadataFallback = n.metadataFallback || {}, n.metadataFallback.image = t, q(n), a("metadataFallback.image");
|
|
try {
|
|
let e = await oe({
|
|
image: t,
|
|
media: n.metadataFallback?.media ?? G.metadataFallback.media
|
|
});
|
|
if (!e?.ok) throw Error(e?.error || A("toast.failedUpdateMetadataFallback", "Failed to update metadata fallback settings"));
|
|
} catch (e) {
|
|
n.metadataFallback.image = r, q(n), a("metadataFallback.image"), v(e?.message || A("toast.failedUpdateMetadataFallback", "Failed to update metadata fallback settings"), "error");
|
|
}
|
|
}
|
|
}), e({
|
|
id: `${X}.MetadataFallback.Media`,
|
|
category: l(A("cat.advanced"), "Metadata"),
|
|
name: "Majoor: Metadata Fallback (Audio/Video)",
|
|
tooltip: "Enable hachoir fallback when ffprobe is missing or fails.",
|
|
type: "boolean",
|
|
defaultValue: n.metadataFallback?.media ?? G.metadataFallback.media,
|
|
onChange: async (e) => {
|
|
let t = !!e, r = !!(n.metadataFallback?.media ?? G.metadataFallback.media);
|
|
n.metadataFallback = n.metadataFallback || {}, n.metadataFallback.media = t, q(n), a("metadataFallback.media");
|
|
try {
|
|
let e = await oe({
|
|
image: n.metadataFallback?.image ?? G.metadataFallback.image,
|
|
media: t
|
|
});
|
|
if (!e?.ok) throw Error(e?.error || A("toast.failedUpdateMetadataFallback", "Failed to update metadata fallback settings"));
|
|
} catch (e) {
|
|
n.metadataFallback.media = r, q(n), a("metadataFallback.media"), v(e?.message || A("toast.failedUpdateMetadataFallback", "Failed to update metadata fallback settings"), "error");
|
|
}
|
|
}
|
|
});
|
|
try {
|
|
le().then((e) => {
|
|
if (!e?.ok || !e?.data?.prefs) return;
|
|
let t = e.data.prefs || {}, r = !!(t.image ?? G.metadataFallback.image), i = !!(t.media ?? G.metadataFallback.media);
|
|
n.metadataFallback = n.metadataFallback || {};
|
|
let o = !1;
|
|
n.metadataFallback.image !== r && (n.metadataFallback.image = r, o = !0), n.metadataFallback.media !== i && (n.metadataFallback.media = i, o = !0), o && (q(n), a("metadataFallback"));
|
|
}).catch(() => {});
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
e({
|
|
id: `${X}.Db.Timeout`,
|
|
category: l(A("cat.advanced"), "Database"),
|
|
name: "DB Timeout (ms)",
|
|
tooltip: "Client-side DB timeout preference (stored locally).",
|
|
type: "number",
|
|
defaultValue: Number(n.db?.timeoutMs || 5e3),
|
|
attrs: {
|
|
min: 1e3,
|
|
max: 3e4,
|
|
step: 1e3
|
|
},
|
|
onChange: (e) => {
|
|
n.db = n.db || {}, n.db.timeoutMs = Math.max(1e3, Math.min(3e4, Math.round(U(e, 5e3)))), q(n), J(n), a("db.timeoutMs");
|
|
}
|
|
}), e({
|
|
id: `${X}.Db.MaxConnections`,
|
|
category: l(A("cat.advanced"), "Database"),
|
|
name: "DB Max Connections",
|
|
tooltip: "Client-side DB max connections preference (stored locally).",
|
|
type: "number",
|
|
defaultValue: Number(n.db?.maxConnections || 10),
|
|
attrs: {
|
|
min: 1,
|
|
max: 100,
|
|
step: 1
|
|
},
|
|
onChange: (e) => {
|
|
n.db = n.db || {}, n.db.maxConnections = Math.max(1, Math.min(100, Math.round(U(e, 10)))), q(n), J(n), a("db.maxConnections");
|
|
}
|
|
}), e({
|
|
id: `${X}.Db.QueryTimeout`,
|
|
category: l(A("cat.advanced"), "Database"),
|
|
name: "DB Query Timeout (ms)",
|
|
tooltip: "Client-side DB query timeout preference (stored locally).",
|
|
type: "number",
|
|
defaultValue: Number(n.db?.queryTimeoutMs || 1e3),
|
|
attrs: {
|
|
min: 500,
|
|
max: 1e4,
|
|
step: 500
|
|
},
|
|
onChange: (e) => {
|
|
n.db = n.db || {}, n.db.queryTimeoutMs = Math.max(500, Math.min(1e4, Math.round(U(e, 1e3)))), q(n), J(n), a("db.queryTimeoutMs");
|
|
}
|
|
}), e({
|
|
id: `${X}.Observability.Enabled`,
|
|
category: l(A("cat.advanced"), A("setting.obs.enabled.name").replace("Majoor: ", "")),
|
|
name: A("setting.obs.enabled.name"),
|
|
tooltip: A("setting.obs.enabled.desc"),
|
|
type: "boolean",
|
|
defaultValue: !!n.observability?.enabled,
|
|
onChange: (e) => {
|
|
n.observability = n.observability || {}, n.observability.enabled = !!e, q(n), J(n), a("observability.enabled");
|
|
}
|
|
}), e({
|
|
id: `${X}.Observability.RuntimeDashboardMode`,
|
|
category: l(A("cat.advanced"), "Runtime metrics badge"),
|
|
name: "Majoor: Runtime metrics badge",
|
|
tooltip: "Controls the small DB/enrichment/watcher metrics badge in the Assets Manager panel.",
|
|
type: "combo",
|
|
defaultValue: n.observability?.runtimeDashboardMode || G.observability.runtimeDashboardMode,
|
|
options: [
|
|
"autoHide30",
|
|
"always",
|
|
"hidden"
|
|
],
|
|
onChange: (e) => {
|
|
let t = vt(e, [
|
|
"autoHide30",
|
|
"always",
|
|
"hidden"
|
|
], G.observability.runtimeDashboardMode);
|
|
n.observability = n.observability || {}, n.observability.runtimeDashboardMode = t, q(n), a("observability.runtimeDashboardMode");
|
|
}
|
|
}), e({
|
|
id: `${X}.Observability.VerboseErrors`,
|
|
category: l(A("cat.advanced"), "Verbose error logging"),
|
|
name: "Verbose error logging",
|
|
tooltip: "Show detailed error messages in toasts and console. Useful for debugging.",
|
|
type: "boolean",
|
|
defaultValue: !!n.observability?.verboseErrors,
|
|
onChange: (e) => {
|
|
n.observability = n.observability || {}, n.observability.verboseErrors = !!e, q(n), J(n), a("observability.verboseErrors");
|
|
}
|
|
}), e({
|
|
id: `${X}.Observability.VerboseRouteRegistrationLogs`,
|
|
category: l(A("cat.advanced"), "Logs"),
|
|
name: "Majoor: Verbose route registration logs",
|
|
tooltip: "When disabled, Majoor prints a compact startup summary instead of listing every registered API route. Takes effect on the next backend restart.",
|
|
type: "boolean",
|
|
defaultValue: !!(n.observability?.verboseRouteRegistrationLogs ?? G.observability?.verboseRouteRegistrationLogs ?? !1),
|
|
onChange: async (e) => {
|
|
let t = !!e, r = !!(n.observability?.verboseRouteRegistrationLogs ?? G.observability?.verboseRouteRegistrationLogs ?? !1);
|
|
n.observability = n.observability || {}, n.observability.verboseRouteRegistrationLogs = t, q(n), a("observability.verboseRouteRegistrationLogs");
|
|
try {
|
|
let e = await s(t);
|
|
if (!e?.ok) throw Error(e?.error || "Failed to update route logging settings");
|
|
} catch (e) {
|
|
n.observability.verboseRouteRegistrationLogs = r, q(n), a("observability.verboseRouteRegistrationLogs"), v(e?.message || "Failed to update route logging settings", "error");
|
|
}
|
|
}
|
|
}), (async () => {
|
|
try {
|
|
let e = !!(await S())?.data?.prefs?.enabled;
|
|
n.observability = n.observability || {}, n.observability.verboseRouteRegistrationLogs !== e && (n.observability.verboseRouteRegistrationLogs = e, q(n), a("observability.verboseRouteRegistrationLogs"));
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
})(), e({
|
|
id: `${X}.Observability.VerboseStartupLogs`,
|
|
category: l(A("cat.advanced"), "Logs"),
|
|
name: "Majoor: Verbose startup logs",
|
|
tooltip: "When disabled, Majoor suppresses most informational bootstrap logs during backend startup while keeping warnings and errors. Takes effect on the next backend restart.",
|
|
type: "boolean",
|
|
defaultValue: !!(n.observability?.verboseStartupLogs ?? G.observability?.verboseStartupLogs ?? !1),
|
|
onChange: async (e) => {
|
|
let t = !!e, r = !!(n.observability?.verboseStartupLogs ?? G.observability?.verboseStartupLogs ?? !1);
|
|
n.observability = n.observability || {}, n.observability.verboseStartupLogs = t, q(n), a("observability.verboseStartupLogs");
|
|
try {
|
|
let e = await d(t);
|
|
if (!e?.ok) throw Error(e?.error || "Failed to update startup logging settings");
|
|
} catch (e) {
|
|
n.observability.verboseStartupLogs = r, q(n), a("observability.verboseStartupLogs"), v(e?.message || "Failed to update startup logging settings", "error");
|
|
}
|
|
}
|
|
}), (async () => {
|
|
try {
|
|
let e = !!(await ee())?.data?.prefs?.enabled;
|
|
n.observability = n.observability || {}, n.observability.verboseStartupLogs !== e && (n.observability.verboseStartupLogs = e, q(n), a("observability.verboseStartupLogs"));
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
})();
|
|
{
|
|
let t = "HuggingFace Token", r = "", o = null, s = 0, c = !!n.ai?.huggingFaceTokenVisible, u = () => {
|
|
try {
|
|
let e = Array.from(document.querySelectorAll("input[data-mjr-hf-token=\"1\"]"));
|
|
for (let t of e) try {
|
|
t.type = c ? "text" : "password";
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
}, d = (e) => {
|
|
try {
|
|
let t = String(e || "").trim();
|
|
if (!t) return;
|
|
let n = Array.from(document.querySelectorAll("input[data-mjr-hf-token=\"1\"]"));
|
|
for (let e of n) try {
|
|
e.placeholder = t;
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
};
|
|
e({
|
|
id: `${X}.AI.HuggingFaceTokenVisible`,
|
|
category: l(A("cat.advanced"), t),
|
|
name: "Show HuggingFace token",
|
|
tooltip: "Show or hide the HuggingFace token while editing.",
|
|
type: "boolean",
|
|
defaultValue: c,
|
|
onChange: (e) => {
|
|
let t = !!e;
|
|
c = t, n.ai = n.ai || {}, n.ai.huggingFaceTokenVisible = t, q(n), a("ai.huggingFaceTokenVisible"), setTimeout(u, 0);
|
|
}
|
|
}), e({
|
|
id: `${X}.AI.HuggingFaceToken`,
|
|
category: l(A("cat.advanced"), t),
|
|
name: "HuggingFace Token",
|
|
tooltip: [
|
|
"Optional token for HuggingFace Hub downloads (higher rate limits).",
|
|
"Saved server-side and used by CLIP model loading.",
|
|
"Leave empty to clear the stored token."
|
|
].join("\n"),
|
|
type: "text",
|
|
defaultValue: "",
|
|
attrs: {
|
|
placeholder: "Paste HuggingFace token (hf_...)",
|
|
type: c ? "text" : "password",
|
|
autocomplete: "new-password",
|
|
name: "mjr_huggingface_token",
|
|
"data-mjr-hf-token": "1"
|
|
},
|
|
onChange: (e) => {
|
|
let t = String(e || "").trim();
|
|
if (t !== r) {
|
|
try {
|
|
o &&= (clearTimeout(o), null);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
o = setTimeout(async () => {
|
|
o = null;
|
|
let e = ++s;
|
|
try {
|
|
let n = await i(t);
|
|
if (e !== s) return;
|
|
if (!n?.ok) throw Error(n?.error || "Failed to update HuggingFace token");
|
|
r = t, a("ai.huggingFaceToken"), t ? v("HuggingFace token saved", "success") : v("HuggingFace token cleared", "success", void 0, { noHistory: !0 });
|
|
} catch (t) {
|
|
if (e !== s) return;
|
|
v(t?.message || "Failed to update HuggingFace token", "error");
|
|
}
|
|
}, 900);
|
|
}
|
|
}
|
|
}), setTimeout(u, 0), (async () => {
|
|
try {
|
|
let e = (await te())?.data?.prefs || {}, t = !!e?.has_token, n = String(e?.token_hint || "").trim();
|
|
d(t ? `Configured ${n || "(saved)"}` : "Paste HuggingFace token (hf_...)");
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
})(), e({
|
|
id: `${X}.AI.VerboseLogs`,
|
|
category: l(A("cat.advanced"), t),
|
|
name: "Majoor: Verbose AI logs",
|
|
tooltip: "Enable detailed HuggingFace/SigLIP2/X-CLIP logs and progress bars during model download/loading.",
|
|
type: "boolean",
|
|
defaultValue: !!(n.ai?.verboseAiLogs ?? G.ai?.verboseAiLogs ?? !1),
|
|
onChange: async (e) => {
|
|
let t = !!e, r = !!(n.ai?.verboseAiLogs ?? G.ai?.verboseAiLogs ?? !1);
|
|
n.ai = n.ai || {}, n.ai.verboseAiLogs = t, q(n), a("ai.verboseAiLogs");
|
|
try {
|
|
let e = await me(t);
|
|
if (!e?.ok) throw Error(e?.error || "Failed to update AI logging settings");
|
|
} catch (e) {
|
|
n.ai.verboseAiLogs = r, q(n), a("ai.verboseAiLogs"), v(e?.message || "Failed to update AI logging settings", "error");
|
|
}
|
|
}
|
|
}), (async () => {
|
|
try {
|
|
let e = !!(await _())?.data?.prefs?.enabled;
|
|
n.ai = n.ai || {}, n.ai.verboseAiLogs !== e && (n.ai.verboseAiLogs = e, q(n), a("ai.verboseAiLogs"));
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
})();
|
|
}
|
|
e({
|
|
id: `${X}.AI.VectorStats`,
|
|
category: l(A("cat.advanced"), "AI / Vector Search"),
|
|
name: "Vector Index Status",
|
|
tooltip: "Current status of the SigLIP2/X-CLIP vector index used for semantic search",
|
|
type: "text",
|
|
defaultValue: "Loading vector status..."
|
|
}), (async () => {
|
|
try {
|
|
let e = await D();
|
|
e?.ok ? console.debug?.("[Majoor] Vector status:", `${e.data?.total || 0} assets indexed | Model: ${e.data?.model || "N/A"}`) : console.debug?.("[Majoor] Vector status unavailable");
|
|
} catch (e) {
|
|
console.debug?.("[Majoor] Vector status fetch failed", e);
|
|
}
|
|
})(), e({
|
|
id: `${X}.AI.VectorBackfillAction`,
|
|
category: l(A("cat.advanced"), "AI / Vector Search"),
|
|
name: "Vector Index Action",
|
|
tooltip: [
|
|
"Compute CLIP embeddings for all assets that don't have them yet.",
|
|
"This is required for AI semantic search to work.",
|
|
"",
|
|
"Choose 'Run backfill now' to start indexing.",
|
|
"This may take several minutes for large libraries.",
|
|
"",
|
|
"Note: New assets are indexed automatically during scanning."
|
|
].join("\n"),
|
|
type: "combo",
|
|
defaultValue: "Idle",
|
|
options: ["Idle", "Run backfill now"],
|
|
onChange: async (e) => {
|
|
if (String(e || "") !== "Run backfill now") return;
|
|
let t = { history: {
|
|
trackId: "vector-backfill:advanced-settings",
|
|
title: "Vector Backfill",
|
|
source: "all",
|
|
operation: "vector_backfill",
|
|
forceStore: !0
|
|
} };
|
|
try {
|
|
v(A("toast.vectorBackfillStarting", "Starting vector backfill... This may take a while."), "info", void 0, { history: {
|
|
...t.history,
|
|
status: "started",
|
|
detail: "Starting vector backfill... This may take a while."
|
|
} });
|
|
let e = await h(64, { onProgress: (e) => {
|
|
let n = String(e?.status || "running").toLowerCase() || "running", r = e?.progress || e?.result || {}, i = Number(r?.candidates ?? r?.processed ?? 0), a = Number(r?.indexed ?? 0), o = Number(r?.skipped ?? 0), s = Number(r?.errors ?? 0), c = Math.max(i, a + o + s), l = c > 0 ? Math.round((a + o + s) / c * 100) : null, u = n === "queued" ? "Vector backfill queued" : `Candidates ${i}, indexed ${a}, skipped ${o}, errors ${s}`;
|
|
b({
|
|
summary: "Vector Backfill",
|
|
detail: u
|
|
}, n === "failed" ? "error" : n === "succeeded" ? "success" : "info", 0, { history: {
|
|
...t.history,
|
|
status: n,
|
|
detail: u,
|
|
progress: {
|
|
current: a + o + s,
|
|
total: c,
|
|
percent: l,
|
|
indexed: a,
|
|
skipped: o,
|
|
errors: s,
|
|
label: n
|
|
}
|
|
} });
|
|
} });
|
|
if (e?.ok) {
|
|
let n = e.data || {}, r = String(n?.status || "").toLowerCase(), i = !!n?.pending || [
|
|
"queued",
|
|
"running",
|
|
"pending"
|
|
].includes(r), a = n?.progress || {}, o = Number(n?.processed ?? a?.candidates ?? 0), s = Number(n?.indexed ?? a?.indexed ?? 0), c = Number(n?.skipped ?? a?.skipped ?? 0);
|
|
if (i) {
|
|
let e = String(n?.job_id || "").trim();
|
|
v(A("toast.vectorBackfillRunning", "Vector backfill still running in background{job}.", { job: e ? ` (job ${e.slice(0, 8)})` : "" }), "info", void 0, { history: {
|
|
...t.history,
|
|
status: "running",
|
|
detail: `Vector backfill still running in background${e ? ` (${e.slice(0, 8)})` : ""}.`,
|
|
progress: {
|
|
current: s + c,
|
|
total: Math.max(o, s + c),
|
|
percent: Math.max(o, s + c) > 0 ? Math.round((s + c) / Math.max(o, s + c) * 100) : null,
|
|
indexed: s,
|
|
skipped: c,
|
|
label: "running"
|
|
}
|
|
} });
|
|
} else v(A("toast.vectorBackfillComplete", "Vector backfill complete! Processed: {processed}, Indexed: {indexed}, Skipped: {skipped}", {
|
|
processed: o,
|
|
indexed: s,
|
|
skipped: c
|
|
}), "success", void 0, { history: {
|
|
...t.history,
|
|
status: "succeeded",
|
|
detail: `Processed ${o}, indexed ${s}, skipped ${c}`,
|
|
progress: {
|
|
current: o,
|
|
total: o,
|
|
percent: o > 0 ? 100 : null,
|
|
indexed: s,
|
|
skipped: c,
|
|
label: "done"
|
|
}
|
|
} });
|
|
try {
|
|
let e = await D();
|
|
e?.ok && console.debug?.("[Majoor] Vector stats after backfill:", e.data);
|
|
} catch (e) {
|
|
console.debug?.("[Majoor] Failed to refresh vector stats:", e);
|
|
}
|
|
} else throw Error(e?.error || A("toast.vectorBackfillFailedGeneric", "Backfill failed"));
|
|
} catch (e) {
|
|
let n = e?.message || String(e || A("status.unknown", "unknown"));
|
|
v(A("toast.vectorBackfillFailedDetail", "Vector backfill failed: {error}", { error: n }), "error", void 0, { history: {
|
|
...t.history,
|
|
status: "failed",
|
|
detail: n
|
|
} }), console.error("[Majoor] Vector backfill error:", e);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
//#endregion
|
|
//#region ui/app/settings/settingsSearch.ts
|
|
var Vn = "Majoor", Hn = "Majoor Assets Manager";
|
|
function Un(e, t, n) {
|
|
let r = (e, t) => [
|
|
Hn,
|
|
e,
|
|
t
|
|
];
|
|
e({
|
|
id: `${Vn}.AI.VectorSearchEnabled`,
|
|
category: r(A("cat.search", "Search"), "AI"),
|
|
name: A("setting.ai.vector.enabled.name", "Enable AI semantic search"),
|
|
tooltip: A("setting.ai.vector.enabled.desc", "Enable/disable AI vector search features (SigLIP2/X-CLIP: description search, prompt alignment, AI tag suggestions, smart collections)."),
|
|
type: "boolean",
|
|
defaultValue: !!(t.ai?.vectorSearchEnabled ?? !0),
|
|
onChange: async (e) => {
|
|
t.ai = t.ai || {};
|
|
let r = !!(t.ai.vectorSearchEnabled ?? !0), i = !!e;
|
|
t.ai.vectorSearchEnabled = i, q(t), J(t), n("ai.vectorSearchEnabled");
|
|
try {
|
|
let e = await a(i);
|
|
if (!e?.ok) {
|
|
t.ai.vectorSearchEnabled = r, q(t), J(t), n("ai.vectorSearchEnabled"), v(e?.error || "Failed to update AI vector search setting", "error");
|
|
return;
|
|
}
|
|
v(i ? "AI semantic search enabled" : "AI semantic search disabled", "info", 2200);
|
|
} catch (e) {
|
|
t.ai.vectorSearchEnabled = r, q(t), J(t), n("ai.vectorSearchEnabled"), v(e?.message || "Failed to update AI vector search setting", "error");
|
|
}
|
|
}
|
|
}), e({
|
|
id: `${Vn}.AI.VectorCaptionOnIndex`,
|
|
category: r(A("cat.search", "Search"), "AI"),
|
|
name: A("setting.ai.vector.captionOnIndex.name", "Generate AI captions during indexing"),
|
|
tooltip: A("setting.ai.vector.captionOnIndex.desc", "Allow automatic vector indexing and backfill to run Florence-2 captions for image assets. This is slower and can use significant VRAM/CPU; leave it off for faster grid startup."),
|
|
type: "boolean",
|
|
defaultValue: !!(t.ai?.vectorCaptionOnIndex ?? !1),
|
|
onChange: async (e) => {
|
|
t.ai = t.ai || {};
|
|
let r = !!(t.ai.vectorCaptionOnIndex ?? !1), i = !!e;
|
|
t.ai.vectorCaptionOnIndex = i, q(t), J(t), n("ai.vectorCaptionOnIndex");
|
|
try {
|
|
let e = await a({ caption_on_index: i });
|
|
if (!e?.ok) {
|
|
t.ai.vectorCaptionOnIndex = r, q(t), J(t), n("ai.vectorCaptionOnIndex"), v(e?.error || "Failed to update AI caption indexing setting", "error");
|
|
return;
|
|
}
|
|
i && v("AI captions during indexing enabled", "info", 2600);
|
|
} catch (e) {
|
|
t.ai.vectorCaptionOnIndex = r, q(t), J(t), n("ai.vectorCaptionOnIndex"), v(e?.message || "Failed to update AI caption indexing setting", "error");
|
|
}
|
|
}
|
|
}), e({
|
|
id: `${Vn}.Search.MaxResults`,
|
|
category: r(A("cat.search", "Search")),
|
|
name: A("setting.search.maxResults.name", "Max search results (client)"),
|
|
tooltip: A("setting.search.maxResults.desc", "Maximum number of results requested per search. The backend still enforces MAJOOR_SEARCH_MAX_LIMIT; increase that env var if you need a higher hard cap."),
|
|
type: "number",
|
|
defaultValue: Number(t.search?.maxResults || k.SEARCH_DEFAULT_LIMIT),
|
|
attrs: {
|
|
min: 10,
|
|
max: k.MAX_PAGE_SIZE || 2e3,
|
|
step: 1
|
|
},
|
|
onChange: (e) => {
|
|
t.search = t.search || {}, t.search.maxResults = Math.max(10, Math.min(k.MAX_PAGE_SIZE || 2e3, Number(e) || k.SEARCH_DEFAULT_LIMIT)), q(t), J(t), n("search.maxResults");
|
|
}
|
|
}), e({
|
|
id: `${Vn}.EnvVars.Reference`,
|
|
category: r(A("cat.advanced"), "Environment variables"),
|
|
name: "Environment variables reference",
|
|
tooltip: [
|
|
"Set these env vars before starting ComfyUI to override defaults:",
|
|
"",
|
|
"MAJOOR_OUTPUT_DIRECTORY - Override output root directory",
|
|
"MAJOOR_EXIFTOOL_PATH - Path to exiftool binary",
|
|
"MAJOOR_FFPROBE_PATH - Path to ffprobe binary",
|
|
"MAJOOR_MEDIA_PROBE_BACKEND - Probe mode: auto|exiftool|ffprobe|both",
|
|
"MAJOOR_EXIFTOOL_TIMEOUT - ExifTool timeout in seconds (default: 15)",
|
|
"MAJOOR_FFPROBE_TIMEOUT - FFprobe timeout in seconds (default: 10)",
|
|
"MAJOOR_DB_TIMEOUT - Database timeout in seconds (default: 30)",
|
|
"MAJOOR_DB_MAX_CONNECTIONS - Max DB connections (default: 8)",
|
|
"MAJOOR_METADATA_CACHE_MAX - Metadata cache max entries (default: 100000)",
|
|
"MAJOOR_METADATA_EXTRACT_CONCURRENCY - Parallel metadata workers (default: 1)",
|
|
"MJR_ENABLE_WATCHER - Enable file watcher: 1|0 (default: 1)",
|
|
"MJR_WATCHER_DEBOUNCE_MS - Watcher debounce delay in ms (default: 3000)",
|
|
"MJR_WATCHER_DEDUPE_TTL_MS - Watcher dedupe window in ms (default: 3000)",
|
|
"MJR_WATCHER_MAX_FILE_SIZE_BYTES - Max file size to index (default: 512MB)",
|
|
"MJR_WATCHER_FLUSH_MAX_FILES - Max files per flush batch (default: 256)",
|
|
"MJR_WATCHER_PENDING_MAX - Max pending watcher queue (default: 5000)",
|
|
"MJR_AM_ENABLE_VECTOR_SEARCH - Enable AI vector/semantic search: 1|0 (default: 1)",
|
|
"MJR_AM_VECTOR_CAPTION_ON_INDEX - Generate Florence captions during vector indexing: 1|0 (default: 0)",
|
|
"MAJOOR_SEARCH_MAX_LIMIT - Max search results (default: 500)",
|
|
"MAJOOR_BG_SCAN_ON_LIST - Scan on directory list: 0|1 (default: 0)"
|
|
].join("\n"),
|
|
type: "text",
|
|
defaultValue: "Hover for full list of environment variables"
|
|
});
|
|
}
|
|
//#endregion
|
|
//#region ui/app/settings/SettingsPanel.ts
|
|
var Wn = "Majoor Assets Manager", Gn = /^\s*Majoor:\s*/i, Kn = Object.freeze({
|
|
ASSETS_PANEL: "Assets Panel",
|
|
GENERATED_FEED: "Generated Feed",
|
|
VIEWER: "Viewer & Floating Viewer",
|
|
INDEXING: "Indexing & Watcher",
|
|
SEARCH_AI: "Search & AI",
|
|
GENERAL: "General",
|
|
ADVANCED: "Advanced",
|
|
SECURITY: "Security"
|
|
}), qn = new Set([
|
|
"grid.starColor",
|
|
"grid.badgeImageColor",
|
|
"grid.badgeVideoColor",
|
|
"grid.badgeAudioColor",
|
|
"grid.badgeModel3dColor",
|
|
"grid.badgeDuplicateAlertColor",
|
|
"ui.cardHoverColor",
|
|
"ui.cardSelectionColor",
|
|
"ui.ratingColor",
|
|
"ui.tagColor"
|
|
]), Jn = "Majoor.General.ResetAllSettings", Yn = "mjr-settings-reset-btn", Xn = null, Zn = null;
|
|
function Qn(e) {
|
|
let t = String(e || "").trim();
|
|
return t ? /^Majoor\.(Safety|Security)\./.test(t) ? Kn.SECURITY : /^Majoor\.(Paths|ProbeBackend|MetadataFallback|Db|Observability)\./.test(t) || t === "Majoor.EnvVars.Reference" || t === "Majoor.AI.HuggingFaceTokenVisible" || t === "Majoor.AI.HuggingFaceToken" || t === "Majoor.AI.VerboseLogs" || t === "Majoor.AI.VectorStats" || t === "Majoor.AI.VectorBackfillAction" ? Kn.ADVANCED : /^Majoor\.(Viewer|WorkflowMinimap)\./.test(t) ? Kn.VIEWER : /^Majoor\.Feed\./.test(t) ? Kn.GENERATED_FEED : /^Majoor\.(AutoScan|Scan|Watcher|ExecutionGrouping|RatingTagsSync)\./.test(t) ? Kn.INDEXING : t === "Majoor.RtHydrate.Concurrency" ? Kn.ADVANCED : t === "Majoor.AI.VectorSearchEnabled" || t === "Majoor.AI.VectorCaptionOnIndex" || /^Majoor\.Search\./.test(t) ? Kn.SEARCH_AI : /^Majoor\.(Grid|Cards|Badges|Sidebar|InfiniteScroll|General)\./.test(t) ? Kn.ASSETS_PANEL : Kn.GENERAL : Kn.GENERAL;
|
|
}
|
|
function $n(e) {
|
|
let t = Array.isArray(e?.category) ? e.category.filter(Boolean) : [], n = Qn(e?.id), r = String(t[1] || t[0] || "").trim(), i = String(t[2] || "").trim(), a = String(e?.name || "").replace(Gn, "").trim();
|
|
return [
|
|
Wn,
|
|
n,
|
|
i || r || a || n
|
|
];
|
|
}
|
|
var er = !1, tr = null, nr = null, rr = !1, ir = /* @__PURE__ */ new Set();
|
|
function ar(e) {
|
|
if (!e || typeof e != "object") return null;
|
|
let t = { ...e };
|
|
try {
|
|
typeof t.name == "string" && (t.name = t.name.replace(Gn, "").trim());
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
try {
|
|
t.category = $n(t);
|
|
} catch {
|
|
t.category = [Wn, Kn.GENERAL];
|
|
}
|
|
return !t.tooltip && typeof t.name == "string" && t.name.trim() && (t.tooltip = t.name.trim()), t;
|
|
}
|
|
function or(e, t, n) {
|
|
let r = String(t?.id || "").trim();
|
|
if (!r || ir.has(r)) return !1;
|
|
ir.add(r);
|
|
try {
|
|
return ye(e, r, n);
|
|
} finally {
|
|
ir.delete(r);
|
|
}
|
|
}
|
|
function sr(e, t) {
|
|
if (!t || typeof t != "object") return t;
|
|
let n = { ...t };
|
|
or(e, n, n.defaultValue);
|
|
let r = n.onChange;
|
|
return n.onChange = (t, ...i) => {
|
|
if (or(e, n, t), typeof r == "function") return r(t, ...i);
|
|
n.defaultValue = t;
|
|
}, n;
|
|
}
|
|
function cr(e) {
|
|
try {
|
|
return JSON.parse(JSON.stringify(e || {}));
|
|
} catch {
|
|
return { ...G };
|
|
}
|
|
}
|
|
function lr(e, t, n, { wrapForComfy: r = !0 } = {}) {
|
|
let i = [], a = (e) => {
|
|
let n = ar(e);
|
|
n && i.push(r ? sr(t, n) : n);
|
|
};
|
|
return un(a, e, n), yn(a, e, n), pn(a, e, n), gn(a, e, n), Rn(a, e, n), Bn(a, e, n, t), Un(a, e, n), i;
|
|
}
|
|
function ur(e, t) {
|
|
if (e === t) return !0;
|
|
try {
|
|
return JSON.stringify(e) === JSON.stringify(t);
|
|
} catch {
|
|
return !1;
|
|
}
|
|
}
|
|
function dr(e) {
|
|
return e ? e.querySelector(".form-input") || e.querySelector(".p-inputgroup") || e.querySelector(".setting-input") || e.querySelector("[class*='input']") : null;
|
|
}
|
|
function fr(e, t) {
|
|
let n = document.createElement("button");
|
|
return n.type = "button", n.className = Yn, n.textContent = e, n.title = t, n.style.marginLeft = "8px", n.style.minWidth = e.length > 2 ? "auto" : "24px", n.style.height = "24px", n.style.padding = e.length > 2 ? "0 10px" : "0", n.style.borderRadius = "6px", n.style.border = "1px solid var(--border-color, #555)", n.style.background = "var(--comfy-input-bg, #2b2b2b)", n.style.color = "var(--input-text, inherit)", n.style.cursor = "pointer", n.style.fontSize = "12px", n.style.lineHeight = "22px", n.style.flexShrink = "0", n;
|
|
}
|
|
function pr(e, t, n) {
|
|
String(e?.id || "").trim() && (or(n, e, t), typeof e?.onChange == "function" && e.onChange(t));
|
|
}
|
|
function mr(e, t, n, r) {
|
|
let i = !ur(be(r, t.id, t.defaultValue), n);
|
|
e.disabled = !i, e.style.opacity = i ? "1" : "0.45";
|
|
}
|
|
function hr() {
|
|
if (typeof document > "u" || !Zn) return;
|
|
let { app: e, definitions: t, defaultValues: n } = Zn, r = document.querySelector(`[data-setting-id="${Jn}"]`), i = dr(r);
|
|
if (r && i && !r.getAttribute("data-mjr-reset-injected")) {
|
|
r.setAttribute("data-mjr-reset-injected", "true"), i.innerHTML = "";
|
|
let a = fr("Reset all settings", "Reset all Majoor settings to defaults");
|
|
a.onclick = (r) => {
|
|
r.preventDefault(), r.stopPropagation();
|
|
for (let r of t) r.id !== Jn && n.has(r.id) && pr(r, n.get(r.id), e);
|
|
hr();
|
|
}, i.appendChild(a);
|
|
}
|
|
for (let r of t) {
|
|
if (!r?.id || r.id === Jn || !n.has(r.id)) continue;
|
|
let t = document.querySelector(`[data-setting-id="${r.id}"]`);
|
|
if (!t || t.getAttribute("data-mjr-reset-injected")) continue;
|
|
let i = dr(t);
|
|
if (!i) continue;
|
|
t.setAttribute("data-mjr-reset-injected", "true");
|
|
let a = fr("Reset", "Reset this setting to default");
|
|
mr(a, r, n.get(r.id), e), a.onclick = (t) => {
|
|
t.preventDefault(), t.stopPropagation();
|
|
let i = n.get(r.id);
|
|
pr(r, i, e), mr(a, r, i, e);
|
|
}, i.appendChild(a);
|
|
}
|
|
}
|
|
function gr(e, t, n) {
|
|
typeof document > "u" || typeof MutationObserver > "u" || (Zn = {
|
|
app: e,
|
|
definitions: t,
|
|
defaultValues: new Map(n.filter((e) => e?.id && e.id !== Jn).map((e) => [e.id, e.defaultValue]))
|
|
}, hr(), !Xn && (Xn = new MutationObserver(() => hr()), Xn.observe(document.body, {
|
|
childList: !0,
|
|
subtree: !0
|
|
})));
|
|
}
|
|
function _r(e, t, { initRuntime: n = !1 } = {}) {
|
|
if (nr) typeof t == "function" && nr.onAppliedListeners.add(t), e && !nr.app && (nr.app = e);
|
|
else {
|
|
let n = K();
|
|
n.i18n = n.i18n || {}, typeof n.i18n.followComfyLanguage == "boolean" ? ke(!!n.i18n.followComfyLanguage) : (n.i18n.followComfyLanguage = !0, ke(!0), q(n));
|
|
let r = /* @__PURE__ */ new Set();
|
|
typeof t == "function" && r.add(t);
|
|
let i = /* @__PURE__ */ new Set(), a = /* @__PURE__ */ new Set(), o = () => {
|
|
if (!i.size) return;
|
|
let e = Array.from(i);
|
|
i.clear();
|
|
for (let t of e) _t("mjr-settings-changed", { key: t }, { warnPrefix: "[Majoor]" });
|
|
}, s = () => {
|
|
if (!a.size) return;
|
|
let e = Array.from(a);
|
|
a.clear();
|
|
for (let t of e) _t("mjr-settings-changed", { key: t }, { warnPrefix: "[Majoor]" });
|
|
}, c = cn(o, 120), l = cn(s, 450), u = (e) => {
|
|
typeof e == "string" && i.add(e), c();
|
|
}, d = (e) => {
|
|
typeof e == "string" && a.add(e), l();
|
|
}, f = () => {
|
|
let e = K();
|
|
Object.assign(n, e), J(n), u("storage");
|
|
}, p = (e) => {
|
|
!e || e.key !== "mjrSettings" || e.newValue !== e.oldValue && f();
|
|
};
|
|
if (!er) {
|
|
if (tr && typeof window < "u") try {
|
|
window.removeEventListener("storage", tr);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
try {
|
|
window.addEventListener("storage", p), er = !0, tr = p;
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
}
|
|
nr = {
|
|
app: e,
|
|
notifyApplied: (e) => {
|
|
for (let t of r) try {
|
|
t(n, e);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
qn.has(String(e || "")) ? d(e) : u(e);
|
|
},
|
|
onAppliedListeners: r,
|
|
refreshFromStorage: f,
|
|
settings: n
|
|
};
|
|
}
|
|
if (n && !rr) {
|
|
let t = e || nr.app, n = nr.settings;
|
|
Ee(t), J(n), Te(t), Gt(), Kt(), qt(), n?.watcher && typeof n.watcher.enabled == "boolean" && ge(!!n.watcher.enabled).catch(() => {}), on(), rr = !0;
|
|
}
|
|
return nr;
|
|
}
|
|
var vr = (e, t) => _r(e, t, { initRuntime: !0 }).settings, yr = (e, t) => {
|
|
let n = _r(e, t, { initRuntime: !1 });
|
|
Object.assign(n.settings, K());
|
|
let r = e || n.app, i = lr(n.settings, r, n.notifyApplied), a = lr(cr(G), r, () => {}, { wrapForComfy: !1 });
|
|
return i.unshift(sr(r, {
|
|
id: Jn,
|
|
category: [
|
|
Wn,
|
|
Kn.GENERAL,
|
|
"Reset"
|
|
],
|
|
name: "Reset all settings to defaults",
|
|
tooltip: "Reset every Majoor Assets Manager setting to its default value.",
|
|
type: "text",
|
|
defaultValue: ""
|
|
})), gr(r, i, a), i;
|
|
};
|
|
try {
|
|
let e = K();
|
|
e?.watcher && typeof e.watcher.enabled == "boolean" && w().then((e) => {
|
|
let t = !!e?.ok && !!e?.data?.enabled, n = K();
|
|
n.watcher = n.watcher || {}, typeof t == "boolean" && t !== !!n.watcher.enabled && (n.watcher.enabled = t, q(n), _t("mjr-settings-changed", { key: "watcher.enabled" }, { warnPrefix: "[Majoor]" }));
|
|
}).catch(() => {});
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
//#endregion
|
|
//#region ui/features/status/AssetStatusDotTheme.ts
|
|
function br(e) {
|
|
return String(e || "").trim().toLowerCase();
|
|
}
|
|
function xr({ dot: e = null, asset: t = null, scope: n = "" } = {}) {
|
|
let r = br(n);
|
|
if (r) return r === "custom";
|
|
let i = br(t?.type || t?.scope);
|
|
if (i) return i === "custom";
|
|
try {
|
|
let t = br(e?.closest?.(".mjr-grid")?.dataset?.mjrScope);
|
|
if (t) return t === "custom";
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
return !1;
|
|
}
|
|
function Sr(e, t = {}) {
|
|
let n = br(e);
|
|
return xr(t) ? n === "pending" || n === "info" ? "var(--mjr-browser-status-info, #4DB6AC)" : n === "success" ? "var(--mjr-browser-status-success, #2E7D32)" : n === "warning" ? "var(--mjr-browser-status-warning, #FFB74D)" : n === "error" ? "var(--mjr-browser-status-error, #EF5350)" : "var(--mjr-browser-status-neutral, #90A4AE)" : n === "pending" || n === "info" ? "var(--mjr-status-info, #64B5F6)" : n === "success" ? "var(--mjr-status-success, #4CAF50)" : n === "warning" ? "var(--mjr-status-warning, #FFA726)" : n === "error" ? "var(--mjr-status-error, #f44336)" : "var(--mjr-status-neutral, #666)";
|
|
}
|
|
//#endregion
|
|
//#region ui/stores/useRuntimeStore.ts
|
|
var Cr = ct("mjr-runtime", () => {
|
|
let e = j(null), t = j(null), n = j(!1), r = j(0), i = j(null), a = j(null), o = j(null), s = j(null), c = j(null), l = j([]), u = M(() => !!i.value), d = M(() => {
|
|
let e = s.value, t = c.value;
|
|
return !t || t <= 0 || e == null ? 0 : Math.round(e / t * 100);
|
|
});
|
|
function f(t) {
|
|
e.value = t;
|
|
}
|
|
function p(e) {
|
|
t.value = e;
|
|
}
|
|
function m(e, t) {
|
|
n.value = !!e, r.value = Math.max(0, Number(t || 0) || 0);
|
|
}
|
|
function h() {
|
|
return {
|
|
active: n.value,
|
|
queueLength: r.value
|
|
};
|
|
}
|
|
function g(e = {}) {
|
|
e.active_prompt_id !== void 0 && (i.value = e.active_prompt_id), e.queue_remaining !== void 0 && (a.value = e.queue_remaining), e.progress_node !== void 0 && (o.value = e.progress_node), e.progress_value !== void 0 && (s.value = e.progress_value), e.progress_max !== void 0 && (c.value = e.progress_max), e.cached_nodes !== void 0 && (l.value = e.cached_nodes ?? []);
|
|
}
|
|
function _() {
|
|
i.value = null, a.value = null, o.value = null, s.value = null, c.value = null, l.value = [];
|
|
}
|
|
return {
|
|
comfyApp: e,
|
|
comfyApi: t,
|
|
enrichmentActive: n,
|
|
enrichmentQueueLength: r,
|
|
activePromptId: i,
|
|
queueRemaining: a,
|
|
progressNode: o,
|
|
progressValue: s,
|
|
progressMax: c,
|
|
cachedNodes: l,
|
|
isExecuting: u,
|
|
progressPercent: d,
|
|
setComfyApp: f,
|
|
setComfyApi: p,
|
|
setEnrichmentState: m,
|
|
getEnrichmentState: h,
|
|
applyExecutionStatus: g,
|
|
resetExecution: _
|
|
};
|
|
});
|
|
//#endregion
|
|
//#region ui/stores/getOptionalRuntimeStore.ts
|
|
function wr() {
|
|
try {
|
|
return lt() ? Cr() : null;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
//#endregion
|
|
//#region ui/stores/runtimeEnrichmentState.ts
|
|
var Tr = Symbol.for("majoor.assets_manager.runtime_state");
|
|
function Er() {
|
|
return {
|
|
api: null,
|
|
assetsDeletedHandler: null,
|
|
enrichmentActive: !1,
|
|
enrichmentQueueLength: 0
|
|
};
|
|
}
|
|
function Dr() {
|
|
try {
|
|
let e = typeof globalThis < "u" ? globalThis : {};
|
|
return (!e[Tr] || typeof e[Tr] != "object") && (e[Tr] = Er()), e[Tr];
|
|
} catch {
|
|
return Er();
|
|
}
|
|
}
|
|
function Or(e, t) {
|
|
let n = wr();
|
|
if (n) {
|
|
n.setEnrichmentState(e, t);
|
|
return;
|
|
}
|
|
let r = Dr();
|
|
r.enrichmentActive = !!e, r.enrichmentQueueLength = Math.max(0, Number(t || 0) || 0);
|
|
}
|
|
function kr() {
|
|
let e = wr();
|
|
if (e) return e.getEnrichmentState();
|
|
let t = Dr();
|
|
return {
|
|
active: !!t.enrichmentActive,
|
|
queueLength: Math.max(0, Number(t.enrichmentQueueLength || 0) || 0)
|
|
};
|
|
}
|
|
//#endregion
|
|
//#region ui/features/grid/AssetCardRenderer.ts
|
|
function Ar(e) {
|
|
try {
|
|
return String(e || "").trim().toLowerCase();
|
|
} catch {
|
|
return "";
|
|
}
|
|
}
|
|
function jr(e) {
|
|
try {
|
|
return (String(e || "").split(".").pop() || "").toUpperCase();
|
|
} catch {
|
|
return "";
|
|
}
|
|
}
|
|
function Mr(e) {
|
|
try {
|
|
let t = String(e || ""), n = t.lastIndexOf("."), r = n > 0 ? t.slice(0, n) : t;
|
|
return String(r || "").trim().toLowerCase();
|
|
} catch {
|
|
return "";
|
|
}
|
|
}
|
|
function Nr(e) {
|
|
try {
|
|
if (String(e?.kind || "").toLowerCase() !== "video") return !1;
|
|
let t = String(e?.filename || "").toLowerCase();
|
|
return t.includes("-audio") || t.includes("_audio");
|
|
} catch {
|
|
return !1;
|
|
}
|
|
}
|
|
function Pr(e) {
|
|
try {
|
|
let t = String(e?.kind || "").toLowerCase(), n = 0;
|
|
Nr(e) ? n = 2 : t === "video" && (n = 1);
|
|
let r = +(Number(e?.has_generation_data || 0) > 0), i = Number(e?.size || 0), a = Number(e?.mtime || 0);
|
|
return [
|
|
n,
|
|
a,
|
|
r,
|
|
i
|
|
];
|
|
} catch {
|
|
return [
|
|
0,
|
|
0,
|
|
0,
|
|
0
|
|
];
|
|
}
|
|
}
|
|
function Fr(e, t) {
|
|
for (let n = 0; n < Math.max(e.length, t.length); n++) {
|
|
let r = (e[n] || 0) - (t[n] || 0);
|
|
if (r !== 0) return r;
|
|
}
|
|
return 0;
|
|
}
|
|
function Ir(e) {
|
|
if (!Array.isArray(e) || e.length === 0) return null;
|
|
if (e.length === 1) return e[0];
|
|
let t = e[0], n = Pr(t);
|
|
for (let r = 1; r < e.length; r++) {
|
|
let i = e[r], a = Pr(i);
|
|
Fr(a, n) > 0 && (t = i, n = a);
|
|
}
|
|
return t;
|
|
}
|
|
function Lr(e, t) {
|
|
if (!e || !Array.isArray(t) || t.length === 0 || (Number(e?.generation_time_ms ?? e?.metadata?.generation_time_ms ?? 0) || 0) > 0) return e;
|
|
let n = t.find((e) => (Number(e?.generation_time_ms ?? e?.metadata?.generation_time_ms ?? 0) || 0) > 0);
|
|
if (!n) return e;
|
|
let r = Number(n?.generation_time_ms ?? n?.metadata?.generation_time_ms ?? 0) || 0;
|
|
return r <= 0 ? e : (e.generation_time_ms = r, !e.has_generation_data && n?.has_generation_data && (e.has_generation_data = n.has_generation_data), e);
|
|
}
|
|
function Rr(e, t) {
|
|
let n = String(e?.kind || "").toLowerCase();
|
|
if (n) return n;
|
|
let r = new Set([
|
|
"PNG",
|
|
"JPG",
|
|
"JPEG",
|
|
"WEBP",
|
|
"GIF",
|
|
"BMP",
|
|
"TIF",
|
|
"TIFF"
|
|
]), i = new Set([
|
|
"MP4",
|
|
"WEBM",
|
|
"MOV",
|
|
"AVI",
|
|
"MKV"
|
|
]), a = new Set([
|
|
"MP3",
|
|
"WAV",
|
|
"OGG",
|
|
"FLAC"
|
|
]), o = new Set([
|
|
"OBJ",
|
|
"FBX",
|
|
"GLB",
|
|
"GLTF",
|
|
"STL",
|
|
"PLY",
|
|
"SPLAT",
|
|
"KSPLAT",
|
|
"SPZ"
|
|
]);
|
|
return r.has(t) ? "image" : i.has(t) ? "video" : a.has(t) ? "audio" : o.has(t) ? "model3d" : "unknown";
|
|
}
|
|
function zr(e) {
|
|
try {
|
|
return !!e()?.siblings?.hidePngSiblings;
|
|
} catch {
|
|
return !1;
|
|
}
|
|
}
|
|
function Br(e) {
|
|
return `${String(e?.source || e?.type || "").trim().toLowerCase()}|${String(e?.root_id || e?.custom_root_id || "").trim().toLowerCase()}|${String(e?.subfolder || "").trim().toLowerCase()}`;
|
|
}
|
|
function Vr(e) {
|
|
let t = Ar(e?.filename);
|
|
return t ? `${Br(e)}|${t}` : "";
|
|
}
|
|
function Hr(e, t = jr(e?.filename || "")) {
|
|
let n = Rr(e, t), r = String(e?.filename || "").trim();
|
|
if (!r) return "";
|
|
let i = Br(e);
|
|
if (n === "model3d") return `${i}|model3d|${r.toLowerCase()}`;
|
|
let a = Mr(r);
|
|
return a ? `${i}|media|${a}` : "";
|
|
}
|
|
function Ur(e) {
|
|
let t = e.nonImageSiblingKeys || /* @__PURE__ */ new Set();
|
|
e.nonImageSiblingKeys = t;
|
|
let n = e.stemMap || /* @__PURE__ */ new Map();
|
|
e.stemMap = n;
|
|
let r = e.assetIdSet || /* @__PURE__ */ new Set();
|
|
e.assetIdSet = r;
|
|
let i = e.seenKeys || /* @__PURE__ */ new Set();
|
|
return e.seenKeys = i, e.hiddenPngSiblings ??= 0, {
|
|
nonImageSiblingKeys: t,
|
|
stemMap: n,
|
|
assetIdSet: r,
|
|
seenKeys: i
|
|
};
|
|
}
|
|
function Wr(e, t, n) {
|
|
try {
|
|
t?.id != null && n.assetIdSet.delete(String(t.id));
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
try {
|
|
let r = e?.assetKeyFn?.(t);
|
|
r && n.seenKeys.delete(r);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
}
|
|
function Gr(e, t, n, r) {
|
|
let i = n.stemMap.get(t);
|
|
if (!i?.length) return [];
|
|
let a = [];
|
|
for (let e = i.length - 1; e >= 0; e--) r(i[e]) && (a.push(i[e]), i.splice(e, 1));
|
|
return i.length || n.stemMap.delete(t), a;
|
|
}
|
|
function Kr(e, t, n) {
|
|
if (!zr(n)) return {
|
|
hidden: !1,
|
|
hideEnabled: !1,
|
|
removed: []
|
|
};
|
|
let r = Ur(t), i = String(e?.filename || ""), a = jr(i), o = Rr(e, a), s = Hr(e, a);
|
|
if (!s) return {
|
|
hidden: !1,
|
|
hideEnabled: !0,
|
|
removed: []
|
|
};
|
|
if (o === "video" || o === "audio" || o === "model3d" || a === "WEBP") return r.nonImageSiblingKeys.add(s), {
|
|
hidden: !1,
|
|
hideEnabled: !0,
|
|
removed: Gr(t, s, r, (e) => jr(e?.filename || "") === "PNG")
|
|
};
|
|
if (a === "PNG") {
|
|
let t = `${Br(e)}|model3d|${Mr(i)}`;
|
|
if (r.nonImageSiblingKeys.has(s) || r.nonImageSiblingKeys.has(t)) return {
|
|
hidden: !0,
|
|
hideEnabled: !0,
|
|
removed: []
|
|
};
|
|
}
|
|
return {
|
|
hidden: !1,
|
|
hideEnabled: !0,
|
|
removed: []
|
|
};
|
|
}
|
|
function qr(e, t, n, r) {
|
|
let i = zr(r.loadMajoorSettings), a = n.filenameCounts || /* @__PURE__ */ new Map();
|
|
n.filenameCounts = a, r.clearGridMessage(e);
|
|
let o = r.ensureVirtualGrid(e, n);
|
|
if (!o) return 0;
|
|
i || (n.hiddenPngSiblings = 0), n.assetKeyFn = r.assetKey;
|
|
let s = Ur(n), c = /* @__PURE__ */ new Map();
|
|
for (let e of n.assets || []) {
|
|
let t = Vr(e);
|
|
if (!t) continue;
|
|
let n = c.get(t);
|
|
n || (n = [], c.set(t, n)), n.push(e);
|
|
}
|
|
let l = 0, u = !1, d = [], f = /* @__PURE__ */ new Set(), p = () => {
|
|
try {
|
|
let t = new Set((Array.isArray(n.assets) ? n.assets : []).map((e) => String(e?.id || "")).filter(Boolean));
|
|
for (let [i, o] of c.entries()) {
|
|
let s = (Array.isArray(o) ? o : []).filter((e) => {
|
|
let n = String(e?.id || "");
|
|
return n ? t.has(n) : !1;
|
|
}), c = s.length;
|
|
if (a.set(i, c), c < 2) {
|
|
for (let e of s) e._mjrNameCollision = !1, delete e._mjrNameCollisionCount, delete e._mjrNameCollisionPaths, e._mjrDupStack && (e._mjrDupStack = !1, e._mjrDupMembers = null, e._mjrDupCount = 0);
|
|
let t = n.renderedFilenameMap?.get(i);
|
|
if (t) for (let n of t) {
|
|
let t = n.querySelector?.(".mjr-file-badge");
|
|
r.setFileBadgeCollision(t, !1);
|
|
try {
|
|
r.ensureDupStackCard?.(e, n, n._mjrAsset);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
let l = Lr(Ir(s), s), u = s.filter((e) => e !== l);
|
|
for (let e of s) e._mjrNameCollision = !1, delete e._mjrNameCollisionCount, delete e._mjrNameCollisionPaths, e !== l && (e._mjrDupStack = !1, e._mjrDupMembers = null, e._mjrDupCount = 0);
|
|
let d = Array.isArray(l._mjrDupMembers) ? l._mjrDupMembers : [], f = new Set(d.map((e) => String(e?.id || ""))), p = [...d, ...s.filter((e) => !f.has(String(e?.id || "")))];
|
|
l._mjrDupStack = !0, l._mjrDupMembers = p, l._mjrDupCount = p.length, l._mjrNameCollision = !1;
|
|
let m = new Set(u.map((e) => String(e?.id || "")));
|
|
m.size > 0 && (n.assets = n.assets.filter((e) => !m.has(String(e?.id || ""))));
|
|
let h = n.renderedFilenameMap?.get(i);
|
|
if (h) for (let t of h) {
|
|
let n = t._mjrAsset, i = t.querySelector?.(".mjr-file-badge");
|
|
if (n === l || String(n?.id || "") === String(l?.id || "")) {
|
|
r.setFileBadgeCollision(i, !1);
|
|
try {
|
|
r.ensureDupStackCard?.(e, t, l);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
};
|
|
for (let e of t || []) {
|
|
try {
|
|
if (e?.id == null || String(e.id).trim() === "") {
|
|
let t = String(e?.kind || "").toLowerCase(), n = String(e?.filepath || "").trim(), r = String(e?.subfolder || "").trim(), i = String(e?.filename || "").trim();
|
|
e.id = `asset:${`${String(e?.type || "").trim().toLowerCase()}|${t}|${n}|${r}|${i}` || "unknown"}`;
|
|
}
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
let t = jr(String(e?.filename || "")), i = Kr(e, n, r.loadMajoorSettings);
|
|
for (let e of i.removed || []) f.add(e);
|
|
if (i.hidden) {
|
|
n.hiddenPngSiblings += 1;
|
|
continue;
|
|
}
|
|
let a = Vr(e);
|
|
if (a) {
|
|
let t = c.get(a);
|
|
t || (t = [], c.set(a, t)), t.push(e);
|
|
}
|
|
let o = r.assetKey(e);
|
|
if (!o || s.seenKeys.has(o) || e.id != null && s.assetIdSet.has(String(e.id))) continue;
|
|
s.seenKeys.add(o), e.id != null && s.assetIdSet.add(String(e.id)), d.push(e);
|
|
let u = Hr(e, t);
|
|
if (u) {
|
|
let t = s.stemMap.get(u);
|
|
t || (t = [], s.stemMap.set(u, t)), t.push(e);
|
|
}
|
|
l++;
|
|
}
|
|
if (f.size > 0) {
|
|
n.hiddenPngSiblings += f.size, n.assets = n.assets.filter((e) => !f.has(e));
|
|
for (let e = d.length - 1; e >= 0; e--) f.has(d[e]) && (d.splice(e, 1), l = Math.max(0, l - 1));
|
|
for (let e of f) Wr(n, e, s);
|
|
try {
|
|
for (let e of f) {
|
|
let t = Vr(e);
|
|
if (!t) continue;
|
|
let n = c.get(t);
|
|
if (!n) continue;
|
|
let r = n.indexOf(e);
|
|
r > -1 && n.splice(r, 1), n.length || c.delete(t);
|
|
}
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
u = !0;
|
|
}
|
|
d.length > 0 && (n.assets.push(...d), u = !0), u && (p(), o.setItems(n.assets), n.sentinel && e.appendChild(n.sentinel));
|
|
try {
|
|
e.dataset.mjrHidePngSiblingsEnabled = i ? "1" : "0", e.dataset.mjrHiddenPngSiblings = String(Number(n.hiddenPngSiblings || 0) || 0);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
return l;
|
|
}
|
|
//#endregion
|
|
//#region ui/components/Badges.ts
|
|
function Jr({ ext: e = "", filename: t = "", count: n = 0, paths: r = [] } = {}) {
|
|
let i = String(e || "").trim(), a = String(t || "").trim(), o = Math.max(0, Number(n) || 0), s = Array.isArray(r) ? r.map((e) => String(e || "").trim()).filter(Boolean) : [];
|
|
if (o < 2) return `${i} file`;
|
|
let c = [`${i}+ name collision in current view (${o})`];
|
|
if (a && c.push(`Name: ${a}`), s.length) {
|
|
c.push("Paths:");
|
|
for (let e of s.slice(0, 4)) c.push(`- ${e}`);
|
|
s.length > 4 && c.push(`- ... +${s.length - 4} more`);
|
|
}
|
|
return c.push("Click to select collisions in current view"), c.join("\n");
|
|
}
|
|
function Yr(e, t, n = !1, r = null) {
|
|
let i = document.createElement("div");
|
|
i.className = "mjr-file-badge";
|
|
let a = String(e || "").split(".").pop()?.toUpperCase?.() || "";
|
|
try {
|
|
i.dataset.mjrExt = a;
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
let o = {
|
|
image: "--mjr-badge-image",
|
|
video: "--mjr-badge-video",
|
|
audio: "--mjr-badge-audio",
|
|
model3d: "--mjr-badge-model3d"
|
|
}[Rr({ kind: t }, a)], s = o ? `var(${o}, #607D8B)` : "#607D8B", c = n ? "var(--mjr-badge-duplicate-alert, #ff1744)" : s;
|
|
i.textContent = a + (n ? "+" : ""), i.title = n ? Jr({
|
|
ext: a,
|
|
filename: e,
|
|
count: r?.count,
|
|
paths: r?.paths
|
|
}) : `${a} file`, i.style.cssText = `
|
|
position: absolute;
|
|
top: 6px;
|
|
left: 6px;
|
|
padding: 3px 8px;
|
|
border-radius: 4px;
|
|
font-size: 10px;
|
|
font-weight: 700;
|
|
background: ${c};
|
|
opacity: 0.85;
|
|
color: white;
|
|
text-transform: uppercase;
|
|
pointer-events: auto;
|
|
z-index: 10;
|
|
letter-spacing: 0.5px;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.3);
|
|
cursor: ${n ? "pointer" : "default"};
|
|
`;
|
|
try {
|
|
i.dataset.mjrBadgeBg = s;
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
return i;
|
|
}
|
|
function Xr(e, t, n = null) {
|
|
if (e) try {
|
|
let r = e.dataset?.mjrExt || "", i = e.dataset?.mjrBadgeBg || "var(--mjr-badge-image, #607D8B)";
|
|
e.textContent = String(r || "") + (t ? "+" : ""), e.title = t ? Jr({
|
|
ext: r,
|
|
filename: n?.filename || "",
|
|
count: n?.count,
|
|
paths: n?.paths
|
|
}) : `${r} file`, e.style.background = t ? "var(--mjr-badge-duplicate-alert, #ff1744)" : i, e.style.cursor = t ? "pointer" : "default";
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
}
|
|
function Zr(e) {
|
|
return e === !0 ? !0 : e === !1 ? !1 : e === 1 || e === "1" ? !0 : e === 0 || e === "0" ? !1 : null;
|
|
}
|
|
function Qr(e, t = []) {
|
|
if (!e || typeof e != "object") return null;
|
|
for (let n of t) if (e[n] != null) return e[n];
|
|
return null;
|
|
}
|
|
function $r(e) {
|
|
return typeof e == "string" && e.trim().length > 0;
|
|
}
|
|
function ei(e) {
|
|
if (Array.isArray(e)) return e.some((e) => String(e ?? "").trim().length > 0);
|
|
if (e && typeof e == "object") return Object.keys(e).length > 0;
|
|
if (typeof e != "string") return !1;
|
|
let t = e.trim();
|
|
if (!t || t === "[]" || t === "[ ]" || /^(null|none)$/i.test(t)) return !1;
|
|
if (t.startsWith("[") && t.endsWith("]") || t.startsWith("{") && t.endsWith("}")) try {
|
|
let e = JSON.parse(t);
|
|
return Array.isArray(e) ? e.some((e) => String(e ?? "").trim().length > 0) : e && typeof e == "object" ? Object.keys(e).length > 0 : !!e;
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
return !0;
|
|
}
|
|
function ti(e) {
|
|
let t = Qr(e, [
|
|
"auto_tags",
|
|
"autoTags",
|
|
"ai_auto_tags",
|
|
"aiAutoTags",
|
|
"suggested_tags",
|
|
"suggestedTags"
|
|
]), n = Qr(e, [
|
|
"enhanced_caption",
|
|
"enhancedCaption",
|
|
"enhanced_prompt",
|
|
"enhancedPrompt",
|
|
"ai_enhanced_prompt",
|
|
"aiEnhancedPrompt"
|
|
]), r = Zr(Qr(e, [
|
|
"has_ai_auto_tags",
|
|
"hasAiAutoTags",
|
|
"ai_has_auto_tags",
|
|
"aiHasAutoTags"
|
|
])), i = Zr(Qr(e, [
|
|
"has_ai_enhanced_caption",
|
|
"hasAiEnhancedCaption",
|
|
"ai_has_enhanced_caption",
|
|
"aiHasEnhancedCaption"
|
|
])), a = Zr(Qr(e, [
|
|
"has_ai_vector",
|
|
"hasAiVector",
|
|
"has_vector_embedding",
|
|
"hasVectorEmbedding",
|
|
"vector_indexed",
|
|
"vectorIndexed"
|
|
])), o = Zr(Qr(e, [
|
|
"has_ai_info",
|
|
"hasAiInfo",
|
|
"ai_indexed",
|
|
"aiIndexed"
|
|
])), s = r === !0 || r === null && ei(t), c = i === !0 || i === null && $r(n), l = a === !0 || o === !0;
|
|
return {
|
|
hasAiInfo: o === !0 || s || c || l,
|
|
hasAutoTags: s,
|
|
hasEnhancedPrompt: c,
|
|
hasVectorIndexed: l
|
|
};
|
|
}
|
|
function ni(e) {
|
|
let t = document.createElement("span");
|
|
t.className = "mjr-workflow-dot mjr-asset-status-dot";
|
|
let n = Zr(e?.has_workflow ?? e?.hasWorkflow), r = Zr(e?.has_generation_data ?? e?.hasGenerationData), i = kr(), a = i.queueLength, o = i.active || a > 0, s = "Pending: parsing metadata...", c = n === !0 || r === !0, l = n === !1 || r === !1, u = n === null || r === null;
|
|
n === !0 && r === !0 ? s = "Complete: workflow + generation data detected" : c ? s = n === !0 ? "Partial: workflow only (generation data missing)" : "Partial: generation data only (workflow missing)" : l && !c && !u ? s = "None: no workflow or generation data found" : u && (s = "Pending: metadata not parsed yet");
|
|
let d = u ? "pending" : n === !0 && r === !0 ? "success" : c ? "warning" : "error";
|
|
o && d !== "success" && (d = "pending", s = a > 0 ? `Pending: database metadata enrichment in progress (${a} queued)` : "Pending: database metadata enrichment in progress"), ri(t, d, s, { asset: e });
|
|
let f = ti(e);
|
|
if (f.hasAiInfo) {
|
|
let e = [];
|
|
f.hasVectorIndexed && e.push("vector indexed"), f.hasAutoTags && e.push("AI tag suggestions"), f.hasEnhancedPrompt && e.push("enhanced prompt"), t.textContent = "";
|
|
let n = document.createElement("i");
|
|
n.className = "pi pi-sparkles", n.setAttribute("aria-hidden", "true"), n.style.fontSize = "11px", n.style.lineHeight = "1", t.appendChild(n);
|
|
try {
|
|
t.dataset.mjrAi = "1";
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
t.title = `${s}\nAI: ${e.length ? e.join(", ") : "indexed"}\nClick to rescan this file`;
|
|
} else {
|
|
try {
|
|
t.dataset.mjrAi = "0";
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
t.textContent = "●", t.title = `${s}\nClick to rescan this file`;
|
|
}
|
|
return t;
|
|
}
|
|
function ri(e, t, n = "", r = {}) {
|
|
if (!e) return;
|
|
let i = String(t || "").toLowerCase(), a = Sr(i, {
|
|
dot: e,
|
|
...r || {}
|
|
});
|
|
try {
|
|
e.dataset.mjrStatus = i || "neutral";
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
if (e.style.cssText = `
|
|
color: ${a};
|
|
margin-left: 4px;
|
|
font-size: 12px;
|
|
line-height: 1;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
cursor: pointer;
|
|
transition: color 0.25s ease, opacity 0.25s ease;
|
|
`, n) try {
|
|
e.title = String(n);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
}
|
|
function ii(e) {
|
|
let t = Math.max(0, Math.min(5, Number(e) || 0));
|
|
if (t <= 0) return null;
|
|
let n = document.createElement("div");
|
|
n.className = "mjr-rating-badge", n.title = `Rating: ${t} star${t > 1 ? "s" : ""}`, n.style.cssText = "\n position: absolute;\n top: 6px;\n right: 6px;\n background: rgba(0, 0, 0, 0.55);\n border: 1px solid rgba(255, 255, 255, 0.12);\n padding: 2px 6px;\n border-radius: 6px;\n font-size: 13px;\n letter-spacing: 1px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n z-index: 10;\n text-shadow: 0 2px 6px rgba(0,0,0,0.6);\n box-shadow: 0 6px 18px rgba(0,0,0,0.25);\n ";
|
|
for (let e = 1; e <= t; e++) {
|
|
let r = document.createElement("span");
|
|
r.textContent = "★", r.style.color = "var(--mjr-rating-color, var(--mjr-star-active, #FFD45A))", r.style.marginRight = e < t ? "2px" : "0", n.appendChild(r);
|
|
}
|
|
return n;
|
|
}
|
|
function ai(e) {
|
|
if (Array.isArray(e)) return e.map((e) => String(e ?? "").trim()).filter(Boolean);
|
|
if (typeof e == "string") {
|
|
let t = e.trim();
|
|
if (!t) return [];
|
|
try {
|
|
let e = JSON.parse(t);
|
|
if (Array.isArray(e)) return e.map((e) => String(e ?? "").trim()).filter(Boolean);
|
|
} catch {}
|
|
return t.split(",").map((e) => e.trim()).filter(Boolean);
|
|
}
|
|
return [];
|
|
}
|
|
function oi(e) {
|
|
let t = Number(e) / 1e3;
|
|
return t >= 60 ? "#FF9800" : t >= 30 ? "#FFC107" : t >= 10 ? "#8BC34A" : "#4CAF50";
|
|
}
|
|
function si(e) {
|
|
let t = e / 1e3;
|
|
if (t >= 60) {
|
|
let e = (t / 60).toFixed(1);
|
|
return {
|
|
text: `${e}m`,
|
|
title: `Generation time: ${e} minutes (${t.toFixed(1)}s)`
|
|
};
|
|
}
|
|
let n = t.toFixed(1);
|
|
return {
|
|
text: `${n}s`,
|
|
title: `Generation time: ${n} seconds`
|
|
};
|
|
}
|
|
function ci(e, { maxMs: t = 864e5 } = {}) {
|
|
let n;
|
|
if (e == null) return 0;
|
|
if (typeof e == "string") {
|
|
let t = e.trim().toLowerCase();
|
|
if (!t) return 0;
|
|
let r = t.match(/^(-?\d+(?:[.,]\d+)?)\s*(s|sec|secs|second|seconds)$/i);
|
|
if (r) n = Number(r[1].replace(",", ".")) * 1e3;
|
|
else {
|
|
let e = t.match(/^(-?\d+(?:[.,]\d+)?)\s*(ms|msec|millisecond|milliseconds)$/i);
|
|
n = Number(e ? e[1].replace(",", ".") : t.replace(",", "."));
|
|
}
|
|
} else n = Number(e);
|
|
return !Number.isFinite(n) || n <= 0 || n >= Number(t) ? 0 : n;
|
|
}
|
|
function li(e) {
|
|
let t = document.createElement("div");
|
|
t.className = "mjr-tags-badge";
|
|
let n = ai(e);
|
|
return n.length === 0 ? (t.style.display = "none", t) : (t.textContent = n.join(", "), t.title = `Tags: ${n.join(", ")}`, t.style.cssText = "\n position: absolute;\n bottom: 6px;\n left: 6px;\n padding: 3px 6px;\n border-radius: 4px;\n background: rgba(0,0,0,0.8);\n color: var(--mjr-tag-color, #90CAF9);\n font-size: 9px;\n max-width: 80%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n pointer-events: none;\n z-index: 10;\n box-shadow: 0 2px 4px rgba(0,0,0,0.3);\n ", t);
|
|
}
|
|
//#endregion
|
|
//#region ui/utils/safeCall.ts
|
|
var ui = () => {};
|
|
function di(e) {
|
|
try {
|
|
return !!O?.[e];
|
|
} catch {
|
|
return !1;
|
|
}
|
|
}
|
|
function fi(e, t) {
|
|
try {
|
|
console.warn(`[Majoor] ${e}`, t);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
}
|
|
function pi(e, t = "safeCall") {
|
|
try {
|
|
return e?.();
|
|
} catch (e) {
|
|
di("DEBUG_SAFE_CALL") && fi(t, e);
|
|
return;
|
|
}
|
|
}
|
|
function mi(e, t, n, r, i = "safeAddListener") {
|
|
try {
|
|
return e?.addEventListener?.(t, n, r), () => {
|
|
try {
|
|
e?.removeEventListener?.(t, n, r);
|
|
} catch (e) {
|
|
di("DEBUG_SAFE_LISTENERS") && fi(`${i}:remove:${String(t || "")}`, e);
|
|
}
|
|
};
|
|
} catch (e) {
|
|
return di("DEBUG_SAFE_LISTENERS") && fi(`${i}:add:${String(t || "")}`, e), ui;
|
|
}
|
|
}
|
|
//#endregion
|
|
//#region ui/utils/mediaFps.ts
|
|
function hi(e) {
|
|
try {
|
|
let t = Number(e);
|
|
if (Number.isFinite(t) && t > 0) return t;
|
|
let n = String(e || "").trim();
|
|
if (!n) return null;
|
|
if (n.includes("/")) {
|
|
let [e, t] = n.split("/"), r = Number(e), i = Number(t);
|
|
if (Number.isFinite(r) && Number.isFinite(i) && i !== 0) {
|
|
let e = r / i;
|
|
return Number.isFinite(e) && e > 0 ? e : null;
|
|
}
|
|
}
|
|
let r = Number.parseFloat(n);
|
|
return Number.isFinite(r) && r > 0 ? r : null;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
function gi(e) {
|
|
try {
|
|
let t = e, n = t.metadata_raw || {}, r = (n.raw_ffprobe || {}).video_stream || {};
|
|
return hi(r.avg_frame_rate) ?? hi(r.r_frame_rate) ?? hi(n.fps_raw) ?? hi(n.fps) ?? hi(n.frame_rate) ?? hi(t.fps);
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
function _i(e, t) {
|
|
try {
|
|
let n = e, r = n.metadata_raw || {}, i = (r.raw_ffprobe || {}).video_stream || {}, a = Number(n.frame_count) || Number(r.frame_count) || Number(r.frames) || Number(i.nb_frames) || Number(i.nb_read_frames) || 0;
|
|
if (Number.isFinite(a) && a > 0) return Math.floor(a);
|
|
let o = Number(n.duration ?? r.duration ?? i.duration);
|
|
if (Number.isFinite(o) && o > 0 && t != null && Number.isFinite(t) && t > 0) return Math.max(1, Math.round(o * t));
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
return null;
|
|
}
|
|
function vi(e) {
|
|
let t = Number(e);
|
|
return !Number.isFinite(t) || t <= 0 ? "" : Math.abs(t - Math.round(t)) < .001 ? `${Math.round(t)} fps` : `${t.toFixed(3).replace(/\.?0+$/, "")} fps`;
|
|
}
|
|
function yi(e, t = 30) {
|
|
let n = hi(e);
|
|
if (n != null) return Math.max(1, Math.round(n * 1e3) / 1e3);
|
|
let r = hi(t);
|
|
return r == null ? 30 : Math.max(1, Math.round(r * 1e3) / 1e3);
|
|
}
|
|
//#endregion
|
|
//#region ui/features/workflows/workflowPickerState.ts
|
|
var Z = Le({
|
|
open: !1,
|
|
mode: "workflow",
|
|
title: "",
|
|
sourceAsset: null,
|
|
workflow: null,
|
|
items: [],
|
|
resolve: null
|
|
});
|
|
function bi({ title: e = "Select workflow", sourceAsset: t = null } = {}) {
|
|
return Si(null), Z.open = !0, Z.mode = "workflow", Z.title = String(e || "Select workflow"), Z.sourceAsset = t || null, Z.workflow = null, Z.items = [], new Promise((e) => {
|
|
Z.resolve = e;
|
|
});
|
|
}
|
|
function xi({ title: e = "Select asset", workflow: t = null, items: n = [] } = {}) {
|
|
return Si(null), Z.open = !0, Z.mode = "asset", Z.title = String(e || "Select asset"), Z.sourceAsset = null, Z.workflow = t || null, Z.items = Array.isArray(n) ? n.filter(Boolean) : [], new Promise((e) => {
|
|
Z.resolve = e;
|
|
});
|
|
}
|
|
function Si(e = null) {
|
|
let t = Z.resolve;
|
|
if (Z.open = !1, Z.mode = "workflow", Z.title = "", Z.sourceAsset = null, Z.workflow = null, Z.items = [], Z.resolve = null, typeof t == "function") try {
|
|
t(e || null);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
}
|
|
//#endregion
|
|
//#region ui/vue/majoorPrimeVue.ts
|
|
var Ci = {
|
|
Button: We,
|
|
Checkbox: at,
|
|
InputText: Xe,
|
|
Select: rt,
|
|
ToggleButton: $e,
|
|
Badge: Ge,
|
|
Tag: Ve,
|
|
Dialog: Je,
|
|
Menu: nt,
|
|
Listbox: Qe,
|
|
Tree: it,
|
|
VirtualScroller: Ue
|
|
};
|
|
function wi(e) {
|
|
return e.use(qe, {
|
|
ripple: !1,
|
|
unstyled: !0,
|
|
zIndex: { overlay: 10100 }
|
|
}), e.use(Ze), e.use(tt), Object.entries(Ci).forEach(([t, n]) => {
|
|
e.component(`M${t}`, n);
|
|
}), e;
|
|
}
|
|
//#endregion
|
|
//#region ui/vue/createVueApp.ts
|
|
function Ti(e, t = void 0) {
|
|
let n = ut(), r = Ke(e, t);
|
|
return r.use(n), wi(r), {
|
|
app: r,
|
|
pinia: n
|
|
};
|
|
}
|
|
var Ei = /* @__PURE__ */ new Map();
|
|
function Di(e, t, n) {
|
|
try {
|
|
window.dispatchEvent(new CustomEvent("mjr:keepalive-attached", { detail: {
|
|
mountKey: String(e || "_mjrVueApp"),
|
|
host: t || null,
|
|
container: n || null
|
|
} }));
|
|
} catch {}
|
|
}
|
|
function Oi(e) {
|
|
let t = document.createElement("div");
|
|
return t.dataset.mjrKeepAliveHost = String(e || "_mjrVueApp"), t.style.height = "100%", t.style.width = "100%", t.style.minHeight = "0", t.style.display = "flex", t.style.flexDirection = "column", t.style.overflow = "hidden", t;
|
|
}
|
|
function ki(e, t) {
|
|
!e || !t || (e.style.height = "100%", e.style.minHeight = "0", e.style.display = "flex", e.style.flexDirection = "column", e.style.overflow = "hidden", !(e.firstChild === t && e.childNodes.length === 1) && (e.replaceChildren(t), Di(t?.dataset?.mjrKeepAliveHost, t, e)));
|
|
}
|
|
function Ai(e, t, n = "_mjrVueApp") {
|
|
if (!e) return !1;
|
|
let r = Ei.get(n), i = !1;
|
|
if (!r) {
|
|
let e = Oi(n), { app: a } = Ti(t);
|
|
a.mount(e), r = {
|
|
app: a,
|
|
host: e,
|
|
container: null
|
|
}, Ei.set(n, r), i = !0;
|
|
}
|
|
return ki(e, r.host), r.container = e, i;
|
|
}
|
|
function ji(e, t = "_mjrVueApp") {
|
|
let n = Ei.get(t);
|
|
if (n?.app) {
|
|
try {
|
|
n.app.unmount();
|
|
} catch {}
|
|
try {
|
|
n.host?.remove?.();
|
|
} catch {}
|
|
Ei.delete(t);
|
|
}
|
|
}
|
|
//#endregion
|
|
//#region ui/utils/format.ts
|
|
function Mi(e) {
|
|
if (!e) return null;
|
|
let t = Number(e);
|
|
if (!isNaN(t)) return /* @__PURE__ */ new Date(t * 1e3);
|
|
let n = new Date(e);
|
|
return isNaN(n.getTime()) ? null : n;
|
|
}
|
|
function Ni(e) {
|
|
let t = Mi(e);
|
|
return t ? `${t.getDate().toString().padStart(2, "0")}/${(t.getMonth() + 1).toString().padStart(2, "0")}` : "";
|
|
}
|
|
function Pi(e) {
|
|
let t = Mi(e);
|
|
return t ? `${t.getHours().toString().padStart(2, "0")}:${t.getMinutes().toString().padStart(2, "0")}` : "";
|
|
}
|
|
function Fi(e) {
|
|
return e ? e < 60 ? `${Math.round(e)}s` : `${Math.floor(e / 60)}m ${Math.round(e % 60)}s` : "";
|
|
}
|
|
//#endregion
|
|
//#region ui/vue/components/panel/sidebar/SidebarFileInfoSection.vue
|
|
var Ii = {
|
|
key: 0,
|
|
class: "mjr-sidebar-section",
|
|
style: {
|
|
background: "rgba(255, 255, 255, 0.03)",
|
|
border: "1px solid var(--mjr-border, rgba(255, 255, 255, 0.12))",
|
|
"border-radius": "8px",
|
|
padding: "10px"
|
|
}
|
|
}, Li = { style: {
|
|
display: "flex",
|
|
"flex-direction": "column",
|
|
gap: "6px"
|
|
} }, Ri = ["title"], zi = ["title"], Bi = {
|
|
__name: "SidebarFileInfoSection",
|
|
props: { asset: {
|
|
type: Object,
|
|
required: !0
|
|
} },
|
|
setup(e) {
|
|
let t = e;
|
|
function n(e) {
|
|
if (!e || e <= 0) return "0 B";
|
|
let t = [
|
|
"B",
|
|
"KB",
|
|
"MB",
|
|
"GB"
|
|
], n = 0, r = e;
|
|
for (; r >= 1024 && n < t.length - 1;) r /= 1024, n += 1;
|
|
return `${r.toFixed(+(n > 0))} ${t[n]}`;
|
|
}
|
|
function r(e) {
|
|
try {
|
|
if (String(e?.kind || "").toLowerCase() === "video") return !0;
|
|
let t = String(e?.filename || e?.filepath || e?.path || "").toLowerCase();
|
|
return /\.(gif|webp|webm)$/.test(t);
|
|
} catch {
|
|
return !1;
|
|
}
|
|
}
|
|
function i(e, t) {
|
|
let n = e?.[t] ?? e?.file_info?.[t];
|
|
return n != null && n !== "" ? n : t === "workflow_id" ? e?.user_metadata?.workflow?.id ?? e?.metadata?.workflow_id ?? "" : "";
|
|
}
|
|
let a = M(() => {
|
|
let e = t.asset || {}, a = [];
|
|
if (e.width && e.height && a.push({
|
|
label: "Dimensions",
|
|
value: `${e.width} x ${e.height}`,
|
|
tooltip: "Image/video resolution in pixels"
|
|
}), e.duration && e.duration > 0 && a.push({
|
|
label: "Duration",
|
|
value: Fi(e.duration),
|
|
tooltip: "Video duration"
|
|
}), r(e)) {
|
|
let t = gi(e);
|
|
t != null && a.push({
|
|
label: "FPS",
|
|
value: vi(t),
|
|
tooltip: "Native frame rate"
|
|
});
|
|
let n = _i(e, t);
|
|
n != null && a.push({
|
|
label: "Length",
|
|
value: `${Math.max(0, Math.floor(n))} frames`,
|
|
tooltip: "Total frame count"
|
|
});
|
|
}
|
|
let o = ci(e.generation_time_ms ?? e.metadata?.generation_time_ms ?? 0);
|
|
o > 0 && a.push({
|
|
label: "Generation Time",
|
|
value: `${(Number(o) / 1e3).toFixed(1)}s`,
|
|
tooltip: "Time taken to generate this asset (workflow execution time)",
|
|
valueStyle: `color: ${oi(o)}; font-weight: 600;`
|
|
});
|
|
let s = e.generation_time || e.file_creation_time || e.mtime || e.created_at;
|
|
if (s) {
|
|
let e = Ni(s), t = Pi(s);
|
|
e && a.push({
|
|
label: "Date",
|
|
value: e,
|
|
tooltip: "File creation/generation date"
|
|
}), t && a.push({
|
|
label: "Time",
|
|
value: t,
|
|
tooltip: "File creation/generation time"
|
|
});
|
|
}
|
|
e.size && e.size > 0 && a.push({
|
|
label: "File Size",
|
|
value: n(e.size),
|
|
tooltip: "File size on disk"
|
|
}), e.id != null && a.push({
|
|
label: "Asset ID",
|
|
value: String(e.id),
|
|
tooltip: "Internal database asset identifier"
|
|
});
|
|
let c = String(i(e, "job_id") || "").trim();
|
|
c && a.push({
|
|
label: "Job ID",
|
|
value: c,
|
|
tooltip: "Workflow execution job identifier (prompt_id)"
|
|
});
|
|
let l = String(i(e, "source_node_id") || "").trim();
|
|
l && a.push({
|
|
label: "Source Node",
|
|
value: l,
|
|
tooltip: "ComfyUI node id that produced this file"
|
|
});
|
|
let u = String(i(e, "source_node_type") || "").trim();
|
|
u && a.push({
|
|
label: "Node Type",
|
|
value: u,
|
|
tooltip: "ComfyUI node class that produced this file"
|
|
});
|
|
let d = String(i(e, "workflow_id") || "").trim();
|
|
return d && a.push({
|
|
label: "Workflow ID",
|
|
value: d,
|
|
tooltip: "ComfyUI workflow identifier (from workflow.id in extra_data)"
|
|
}), a;
|
|
});
|
|
return (e, t) => a.value.length ? (F(), N("div", Ii, [t[0] ||= z("div", { style: {
|
|
"font-size": "12px",
|
|
"font-weight": "700",
|
|
color: "#607d8b",
|
|
"margin-bottom": "8px",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.4px"
|
|
} }, " File Info ", -1), z("div", Li, [(F(!0), N(B, null, V(a.value, (e) => (F(), N("div", {
|
|
key: e.label,
|
|
style: {
|
|
display: "flex",
|
|
gap: "10px",
|
|
"align-items": "flex-start",
|
|
"justify-content": "space-between"
|
|
}
|
|
}, [z("div", {
|
|
title: e.tooltip || "",
|
|
style: {
|
|
"font-size": "12px",
|
|
opacity: "0.68",
|
|
"min-width": "92px"
|
|
}
|
|
}, L(e.label), 9, Ri), z("div", {
|
|
style: R(e.valueStyle || "font-size: 12px; text-align: right; word-break: break-word"),
|
|
title: String(e.value || "")
|
|
}, L(e.value), 13, zi)]))), 128))])])) : P("", !0);
|
|
}
|
|
}, Vi = new Set([
|
|
"png",
|
|
"jpg",
|
|
"jpeg",
|
|
"webp",
|
|
"gif",
|
|
"bmp",
|
|
"tiff",
|
|
"tif",
|
|
"avif",
|
|
"heic",
|
|
"heif",
|
|
"apng",
|
|
"hdr",
|
|
"svg"
|
|
]);
|
|
function Hi(e) {
|
|
let t = String(e?.filename || e?.name || e?.filepath || e?.path || "").trim().toLowerCase();
|
|
return !t || !t.includes(".") ? "" : t.split(".").pop() || "";
|
|
}
|
|
function Ui(e) {
|
|
return String(e?.kind || "").trim().toLowerCase() === "image" || String(e?.mime || e?.mimetype || "").trim().toLowerCase().startsWith("image/") ? !0 : Vi.has(Hi(e));
|
|
}
|
|
function Wi(e) {
|
|
let t = Hi(e);
|
|
return t === "jpg" || t === "jpeg";
|
|
}
|
|
function Gi() {
|
|
try {
|
|
return !!(K()?.ai?.vectorSearchEnabled ?? !0);
|
|
} catch {
|
|
return !0;
|
|
}
|
|
}
|
|
function Ki(e) {
|
|
return e >= .75 ? "#4CAF50" : e >= .5 ? "#8BC34A" : e >= .3 ? "#FF9800" : "#F44336";
|
|
}
|
|
function qi(e) {
|
|
return e >= .85 ? "Excellent" : e >= .7 ? "Good" : e >= .5 ? "Fair" : e >= .3 ? "Low" : "Very Low";
|
|
}
|
|
function Ji(e) {
|
|
let t = String(e || "").trim();
|
|
if (!t) return "";
|
|
let n = [];
|
|
for (let e of t.replace(/\r\n/g, "\n").split("\n")) {
|
|
let t = String(e || "").trim();
|
|
t && (/^title\s*:/i.test(t) || (/^caption\s*:/i.test(t) && (t = t.replace(/^caption\s*:/i, "").trim()), t && n.push(t)));
|
|
}
|
|
return (n.length ? n.join(" ") : t).replace(/\s+/g, " ").replace(/:{2,}\s*$/, "").trim();
|
|
}
|
|
function Yi(e) {
|
|
let t = String(e?.filename || "").trim();
|
|
if (!t) return [];
|
|
let n = String(e?.subfolder || "").trim(), r = String(e?.folder_type || "input").trim().toLowerCase(), i = [], a = (e) => {
|
|
if (!e) return;
|
|
let r = we(t, n, e);
|
|
r && !i.includes(r) && i.push(r);
|
|
};
|
|
return (r === "input" || r === "output") && a(r), a("input"), a("output"), i;
|
|
}
|
|
function Xi(e) {
|
|
let t = String(e || "").trim();
|
|
if (!t) return !1;
|
|
if (t.startsWith("/")) return !0;
|
|
try {
|
|
let e = new URL(t);
|
|
return e.protocol === "http:" || e.protocol === "https:";
|
|
} catch {
|
|
return !1;
|
|
}
|
|
}
|
|
function Q(e) {
|
|
return e == null || e === "" ? "-" : String(e);
|
|
}
|
|
function Zi(e, t) {
|
|
let n = String(e?.pass_stage || e?.stage || e?.kind || "").trim().toLowerCase();
|
|
if (n === "txt2img" || n === "text_to_image" || n === "text-to-image") return A("sidebar.generation.stageTextToImage", "Text-to-Image");
|
|
if (n === "img2img" || n === "image_to_image" || n === "image-to-image") return A("sidebar.generation.stageImageToImage", "Image-to-Image");
|
|
if (n === "inpaint" || n === "inpainting") return A("sidebar.generation.stageInpaint", "Inpaint");
|
|
if (n === "upscale" || n === "upscaling") return A("sidebar.generation.stageUpscale", "Upscale");
|
|
if (n === "refine" || n === "refiner") return A("sidebar.generation.stageRefine", "Refine");
|
|
let r = String(e?.pass_name || "").trim();
|
|
if (r && r.toLowerCase() !== "base") return r;
|
|
let i = Number(e?.denoise);
|
|
return t === 0 || i === 1 ? A("sidebar.generation.stageBase", "Base") : Number.isFinite(i) && i < 1 ? A("sidebar.generation.stageRefineUpscale", "Refine / Upscale") : A("sidebar.generation.stagePassN", "Pass {n}", { n: t + 1 });
|
|
}
|
|
function Qi(e) {
|
|
return e?.geninfo && typeof e.geninfo == "object" ? { geninfo: e.geninfo } : e?.metadata && (typeof e.metadata == "object" || typeof e.metadata == "string") ? e.metadata : e?.prompt && (typeof e.prompt == "object" || typeof e.prompt == "string") ? e.prompt : e?.metadata_raw ? e.metadata_raw : e?.exif ? e.exif : null;
|
|
}
|
|
function $i(e) {
|
|
try {
|
|
if (!e || typeof e != "object") return !1;
|
|
if (e.is_override || typeof e.workflow_notes == "string" && e.workflow_notes.trim() || typeof e.notes == "string" && e.notes.trim() || Array.isArray(e.custom_info) && e.custom_info.length > 0 || e.engine && typeof e.engine == "object" && e.engine.type || mt(e.prompt) || typeof (e.negative_prompt || e.negativePrompt) == "string" && mt(e.negative_prompt || e.negativePrompt) || e.models || e.model || e.checkpoint || e.loras || e.sampler || e.sampler_name || e.steps || e.cfg || e.cfg_scale || e.cfg_high_noise || e.cfg_low_noise || e.scheduler || Array.isArray(e.chained_passes) && e.chained_passes.length > 0 || Array.isArray(e.all_samplers) && e.all_samplers.length > 0 || e.seed || e.denoise || e.denoising || e.clip_skip || e.voice || e.language || e.temperature || e.top_k || e.top_p || e.repetition_penalty || e.max_new_tokens || e.device || e.voice_preset || e.instruct || e.dtype || e.attn_implementation || e.enable_chunking !== void 0 || e.max_chars_per_chunk || e.chunk_combination_method || e.silence_between_chunks_ms || e.enable_audio_cache !== void 0 || e.batch_size !== void 0 || e.use_torch_compile !== void 0 || e.use_cuda_graphs !== void 0 || e.compile_mode || typeof e.lyrics == "string" && e.lyrics.trim()) return !0;
|
|
} catch {
|
|
return !1;
|
|
}
|
|
return !1;
|
|
}
|
|
function ea(e) {
|
|
return e ? typeof e == "string" ? ht(e) : typeof e == "object" ? ht(e.name || e.value || "") : "" : "";
|
|
}
|
|
function ta(e, t, n, r) {
|
|
let i = String(r || "").trim();
|
|
if (!i) return;
|
|
let a = `${n}::${i}`;
|
|
t.has(a) || (t.add(a), e.push({
|
|
label: n,
|
|
value: i
|
|
}));
|
|
}
|
|
function na(e) {
|
|
let t = `${String(e?.source || "").toLowerCase()} ${String(e?.name || e?.lora_name || "").toLowerCase()}`;
|
|
return t.includes("high_noise") || t.includes("high noise") ? "high_noise" : t.includes("low_noise") || t.includes("low noise") ? "low_noise" : "";
|
|
}
|
|
function ra(e) {
|
|
let t = [], n = Array.isArray(e.model_groups) ? e.model_groups : [];
|
|
if (n.length) return n.forEach((e) => {
|
|
if (!e || typeof e != "object") return;
|
|
let n = ea(e.model), r = Array.isArray(e.loras) ? e.loras.map((e) => pt(e)).filter(Boolean) : [];
|
|
!n && !r.length || t.push({
|
|
key: String(e.key || "").trim() || `group-${t.length + 1}`,
|
|
label: String(e.label || "").trim() || `Group ${t.length + 1}`,
|
|
model: n,
|
|
loras: r
|
|
});
|
|
}), t;
|
|
let r = e.models && typeof e.models == "object" ? e.models : null, i = Array.isArray(e.loras) ? e.loras : [];
|
|
return r && [{
|
|
key: "high_noise",
|
|
label: A("sidebar.generation.highNoise", "High Noise"),
|
|
model: ea(r.unet_high_noise)
|
|
}, {
|
|
key: "low_noise",
|
|
label: A("sidebar.generation.lowNoise", "Low Noise"),
|
|
model: ea(r.unet_low_noise)
|
|
}].forEach((e) => {
|
|
let n = i.filter((t) => na(t) === e.key).map((e) => pt(e)).filter(Boolean);
|
|
!e.model && !n.length || t.push({
|
|
...e,
|
|
loras: n
|
|
});
|
|
}), t;
|
|
}
|
|
function ia(e, t) {
|
|
return t == null ? null : {
|
|
label: e,
|
|
value: t ? A("state.on", "on") : A("state.off", "off")
|
|
};
|
|
}
|
|
function aa(e) {
|
|
return e != null && String(e).trim() !== "";
|
|
}
|
|
function oa(e) {
|
|
return new Set(Array.isArray(e.override_fields) ? e.override_fields.map((e) => String(e || "").trim()).filter(Boolean) : []);
|
|
}
|
|
function $(e, ...t) {
|
|
return t.some((t) => e.has(t));
|
|
}
|
|
function sa(e) {
|
|
return Array.isArray(e) ? e.filter((e) => e && typeof e == "object").map((e, t) => ({
|
|
title: String(e.title || A("sidebar.generation.customInfoN", "Custom Info {n}", { n: t + 1 })).trim(),
|
|
content: String(e.content ?? e.value ?? "").trim(),
|
|
color: /^#[0-9a-fA-F]{6}$/.test(String(e.color || "").trim()) ? String(e.color).trim() : "#2196F3"
|
|
})).filter((e) => e.content) : [];
|
|
}
|
|
function ca(e) {
|
|
let t = ft(Qi(e)), n = {
|
|
kind: "empty",
|
|
title: A("sidebar.generation.title", "Generation"),
|
|
workflowType: "",
|
|
workflowLabel: "",
|
|
workflowBadge: "",
|
|
isTruncated: !1,
|
|
positivePrompt: "",
|
|
negativePrompt: "",
|
|
positivePromptOverride: !1,
|
|
negativePromptOverride: !1,
|
|
promptTabs: [],
|
|
mediaOnlyMessage: "",
|
|
showAlignment: !1,
|
|
captionLabel: A("sidebar.generation.imageDescription", "Image Description"),
|
|
emptyCaptionText: A("sidebar.generation.noImageDescription", "No image description yet."),
|
|
isImageAsset: Ui(e),
|
|
lyrics: "",
|
|
modelFields: [],
|
|
modelGroups: [],
|
|
pipelineTabs: [],
|
|
samplingFields: [],
|
|
ttsFields: [],
|
|
ttsEngineFields: [],
|
|
ttsInstruction: "",
|
|
ttsRuntimeFields: [],
|
|
audioFields: [],
|
|
seed: null,
|
|
imageFields: [],
|
|
inputFiles: [],
|
|
isOverride: !1,
|
|
overrideLabel: "",
|
|
notesFields: [],
|
|
customInfoBlocks: []
|
|
};
|
|
if (!t || typeof t == "object" && Object.keys(t).length === 0 || !$i(t)) {
|
|
let t = e?.metadata_raw?.geninfo_status || e?.geninfo_status;
|
|
return t && typeof t == "object" && t.kind === "media_pipeline" ? {
|
|
...n,
|
|
kind: "media-only",
|
|
mediaOnlyMessage: A("sidebar.generation.mediaOnlyPipeline", "This file looks like a media-only pipeline (e.g. LoadVideo/VideoCombine) and does not contain generation parameters.")
|
|
} : Ui(e) || Wi(e) ? {
|
|
...n,
|
|
kind: "caption-only",
|
|
showAlignment: !1
|
|
} : n;
|
|
}
|
|
let r = t, i = oa(r), a = r.engine && typeof r.engine == "object" ? r.engine : null, o = !!(r.is_override || a?.mode === "override" || a?.parser_version === "geninfo-override-v1" || a?.source === "majoor_geninfo"), s = gt(r), c = dt(typeof r.prompt == "string" ? r.prompt : null, typeof (r.negative_prompt || r.negativePrompt) == "string" ? r.negative_prompt || r.negativePrompt : null), l = Array.isArray(r.all_positive_prompts) && r.all_positive_prompts.length > 1 ? r.all_positive_prompts.map((e, t) => {
|
|
let n = dt(typeof e == "string" ? e : "", typeof r.all_negative_prompts?.[t] == "string" ? r.all_negative_prompts[t] : "");
|
|
return {
|
|
label: A("sidebar.generation.promptN", "Prompt {n}", { n: t + 1 }),
|
|
positive: mt(n.positive),
|
|
negative: mt(n.negative)
|
|
};
|
|
}).filter((e) => e.positive) : [], u = [], d = /* @__PURE__ */ new Set(), f = r.models && typeof r.models == "object" ? r.models : null, p = ra(r), m = new Set(p.map((e) => String(e.model || "").trim()).filter(Boolean)), h = Array.isArray(r.all_checkpoints) && r.all_checkpoints.length > 1 ? r.all_checkpoints : null;
|
|
if (f) {
|
|
let e = new Set([
|
|
ea(f.unet_high_noise),
|
|
ea(f.unet_low_noise),
|
|
...m
|
|
].filter(Boolean));
|
|
if (h) h.forEach((e, t) => {
|
|
let n = ea(e);
|
|
ta(u, d, A("sidebar.generation.checkpointN", "Checkpoint {n}", { n: t + 1 }), n);
|
|
});
|
|
else {
|
|
let t = ea(f.checkpoint);
|
|
t && !e.has(t) && ta(u, d, A("sidebar.generation.checkpoint", "Checkpoint"), t);
|
|
}
|
|
[
|
|
["UNet", ea(f.unet)],
|
|
["Diffusion", ea(f.diffusion)],
|
|
[A("sidebar.generation.upscaler", "Upscaler"), ea(f.upscaler)],
|
|
["CLIP", ea(f.clip)],
|
|
["VAE", ea(f.vae)]
|
|
].forEach(([t, n]) => {
|
|
e.has(n) || ta(u, d, t, n);
|
|
});
|
|
} else (r.model || r.checkpoint) && ta(u, d, A("sidebar.generation.model", "Model"), ht(r.model || r.checkpoint));
|
|
if (Array.isArray(r.loras) && r.loras.length > 0) {
|
|
let e = r.loras.map((e) => pt(e)).filter(Boolean).join("\n");
|
|
e && ta(u, d, r.loras.length > 1 ? A("sidebar.generation.loras", "LoRAs") : "LoRA", e);
|
|
}
|
|
!f && r.clip && ta(u, d, "CLIP", ht(r.clip)), !f && r.vae && ta(u, d, "VAE", ht(r.vae)), !f && r.unet && ta(u, d, "UNet", ht(r.unet)), !f && r.diffusion && ta(u, d, "Diffusion", ht(r.diffusion)), f && r.clip && ta(u, d, "CLIP", ht(r.clip)), f && r.vae && ta(u, d, "VAE", ht(r.vae));
|
|
for (let e of u) {
|
|
let t = String(e.label || "").toLowerCase();
|
|
(t.includes("checkpoint") || t === "model") && (e.override = $(i, "checkpoint", "model")), t === "clip" && (e.override = $(i, "clip")), t === "vae" && (e.override = $(i, "vae")), t.includes("lora") && (e.override = $(i, "loras"));
|
|
}
|
|
let g = [];
|
|
aa(r.seed) && g.push({
|
|
label: A("sidebar.generation.seed", "Seed"),
|
|
value: r.seed,
|
|
override: $(i, "seed")
|
|
}), (r.sampler || r.sampler_name) && g.push({
|
|
label: A("sidebar.generation.sampler", "Sampler"),
|
|
value: r.sampler || r.sampler_name,
|
|
override: $(i, "sampler", "sampler_name")
|
|
}), aa(r.steps) && g.push({
|
|
label: A("sidebar.generation.steps", "Steps"),
|
|
value: r.steps,
|
|
override: $(i, "steps")
|
|
});
|
|
let _ = aa(r.cfg) ? r.cfg : r.cfg_scale;
|
|
aa(_) && g.push({
|
|
label: A("sidebar.generation.cfgScale", "CFG Scale"),
|
|
value: _,
|
|
override: $(i, "cfg", "cfg_scale")
|
|
}), r.cfg_high_noise !== void 0 && r.cfg_high_noise !== null && g.push({
|
|
label: A("sidebar.generation.cfgHighNoise", "CFG High Noise"),
|
|
value: r.cfg_high_noise
|
|
}), r.cfg_low_noise !== void 0 && r.cfg_low_noise !== null && g.push({
|
|
label: A("sidebar.generation.cfgLowNoise", "CFG Low Noise"),
|
|
value: r.cfg_low_noise
|
|
}), r.scheduler && g.push({
|
|
label: A("sidebar.generation.scheduler", "Scheduler"),
|
|
value: r.scheduler,
|
|
override: $(i, "scheduler")
|
|
});
|
|
let v = aa(r.denoise) ? r.denoise : r.denoising;
|
|
aa(v) && g.push({
|
|
label: A("sidebar.generation.denoise", "Denoise"),
|
|
value: v,
|
|
override: $(i, "denoise", "denoising")
|
|
});
|
|
let y = [];
|
|
Array.isArray(r.chained_passes) && r.chained_passes.length > 1 ? y = r.chained_passes.filter((e) => e && typeof e == "object").map((e, t) => ({
|
|
label: Zi(e, t),
|
|
fields: [
|
|
{
|
|
label: A("sidebar.generation.model", "Model"),
|
|
value: Q(e?.model)
|
|
},
|
|
{
|
|
label: A("sidebar.generation.sampler", "Sampler"),
|
|
value: Q(e?.sampler_name || e?.sampler)
|
|
},
|
|
{
|
|
label: A("sidebar.generation.scheduler", "Scheduler"),
|
|
value: Q(e?.scheduler)
|
|
},
|
|
{
|
|
label: A("sidebar.generation.steps", "Steps"),
|
|
value: Q(e?.steps)
|
|
},
|
|
{
|
|
label: "CFG",
|
|
value: Q(e?.cfg)
|
|
},
|
|
{
|
|
label: A("sidebar.generation.denoise", "Denoise"),
|
|
value: Q(e?.denoise)
|
|
},
|
|
{
|
|
label: A("sidebar.generation.seed", "Seed"),
|
|
value: Q(e?.seed_val || e?.seed)
|
|
}
|
|
]
|
|
})) : Array.isArray(r.all_samplers) && r.all_samplers.length > 1 && (y = r.all_samplers.filter((e) => e && typeof e == "object").map((e, t) => ({
|
|
label: Zi(e, t),
|
|
fields: [
|
|
{
|
|
label: A("sidebar.generation.model", "Model"),
|
|
value: Q(e?.model)
|
|
},
|
|
{
|
|
label: A("sidebar.generation.sampler", "Sampler"),
|
|
value: Q(e?.sampler_name || e?.sampler)
|
|
},
|
|
{
|
|
label: A("sidebar.generation.scheduler", "Scheduler"),
|
|
value: Q(e?.scheduler)
|
|
},
|
|
{
|
|
label: A("sidebar.generation.steps", "Steps"),
|
|
value: Q(e?.steps)
|
|
},
|
|
{
|
|
label: "CFG",
|
|
value: Q(e?.cfg)
|
|
},
|
|
{
|
|
label: A("sidebar.generation.denoise", "Denoise"),
|
|
value: Q(e?.denoise)
|
|
},
|
|
{
|
|
label: A("sidebar.generation.seed", "Seed"),
|
|
value: Q(e?.seed_val || e?.seed)
|
|
}
|
|
]
|
|
})));
|
|
let b = [];
|
|
r.voice && b.push({
|
|
label: A("sidebar.generation.narratorVoice", "Narrator Voice"),
|
|
value: r.voice
|
|
}), r.language && b.push({
|
|
label: A("sidebar.generation.language", "Language"),
|
|
value: r.language
|
|
}), r.top_k !== void 0 && r.top_k !== null && b.push({
|
|
label: "Top-k",
|
|
value: r.top_k
|
|
}), r.top_p !== void 0 && r.top_p !== null && b.push({
|
|
label: "Top-p",
|
|
value: r.top_p
|
|
}), r.temperature !== void 0 && r.temperature !== null && b.push({
|
|
label: A("sidebar.generation.temperature", "Temperature"),
|
|
value: r.temperature
|
|
}), r.repetition_penalty !== void 0 && r.repetition_penalty !== null && b.push({
|
|
label: A("sidebar.generation.repetitionPenalty", "Repetition Penalty"),
|
|
value: r.repetition_penalty
|
|
}), r.max_new_tokens !== void 0 && r.max_new_tokens !== null && b.push({
|
|
label: A("sidebar.generation.maxNewTokens", "Max New Tokens"),
|
|
value: r.max_new_tokens
|
|
});
|
|
let x = [];
|
|
r.device && x.push({
|
|
label: A("sidebar.generation.device", "Device"),
|
|
value: r.device
|
|
}), r.voice_preset && x.push({
|
|
label: A("sidebar.generation.voicePreset", "Voice Preset"),
|
|
value: r.voice_preset
|
|
}), r.dtype && x.push({
|
|
label: A("sidebar.generation.dtype", "Dtype"),
|
|
value: r.dtype
|
|
}), r.attn_implementation && x.push({
|
|
label: A("sidebar.generation.attention", "Attention"),
|
|
value: r.attn_implementation
|
|
}), r.compile_mode && x.push({
|
|
label: A("sidebar.generation.compileMode", "Compile Mode"),
|
|
value: r.compile_mode
|
|
}), [
|
|
ia(A("sidebar.generation.torchCompile", "Torch Compile"), r.use_torch_compile),
|
|
ia(A("sidebar.generation.cudaGraphs", "CUDA Graphs"), r.use_cuda_graphs),
|
|
ia(A("sidebar.generation.xVectorOnly", "X-Vector Only"), r.x_vector_only_mode)
|
|
].filter(Boolean).forEach((e) => x.push(e));
|
|
let S = [];
|
|
[
|
|
ia(A("sidebar.generation.chunking", "Chunking"), r.enable_chunking),
|
|
r.max_chars_per_chunk !== void 0 && r.max_chars_per_chunk !== null ? {
|
|
label: A("sidebar.generation.maxCharsChunk", "Max Chars/Chunk"),
|
|
value: r.max_chars_per_chunk
|
|
} : null,
|
|
r.chunk_combination_method ? {
|
|
label: A("sidebar.generation.chunkMethod", "Chunk Method"),
|
|
value: r.chunk_combination_method
|
|
} : null,
|
|
r.silence_between_chunks_ms !== void 0 && r.silence_between_chunks_ms !== null ? {
|
|
label: A("sidebar.generation.silenceBetweenChunks", "Silence Between Chunks (ms)"),
|
|
value: r.silence_between_chunks_ms
|
|
} : null,
|
|
ia(A("sidebar.generation.audioCache", "Audio Cache"), r.enable_audio_cache),
|
|
r.batch_size !== void 0 && r.batch_size !== null ? {
|
|
label: A("sidebar.generation.batchSize", "Batch Size"),
|
|
value: r.batch_size
|
|
} : null
|
|
].filter(Boolean).forEach((e) => S.push(e));
|
|
let ee = [];
|
|
r.lyrics_strength !== void 0 && r.lyrics_strength !== null && ee.push({
|
|
label: A("sidebar.generation.lyricsStrength", "Lyrics Strength"),
|
|
value: r.lyrics_strength
|
|
});
|
|
let C = [];
|
|
aa(v) && !g.some((e) => e.label === "Denoise") && C.push({
|
|
label: A("sidebar.generation.denoise", "Denoise"),
|
|
value: v
|
|
}), aa(r.clip_skip) && C.push({
|
|
label: A("sidebar.generation.clipSkip", "Clip Skip"),
|
|
value: r.clip_skip
|
|
});
|
|
let te = [], w = String(r.workflow_notes || r.notes || "").trim();
|
|
w && te.push({
|
|
label: A("sidebar.generation.workflowNotes", "Workflow Notes"),
|
|
value: w,
|
|
override: $(i, "workflow_notes", "notes")
|
|
});
|
|
let T = sa(r.custom_info), ne = Array.isArray(r.inputs) ? r.inputs.filter((e) => e && typeof e == "object" && e.filename).map((e, t) => ({
|
|
id: `${e.filename}-${t}`,
|
|
filename: String(e.filename || "").trim(),
|
|
filepath: String(e.filepath || e.filename || "").trim(),
|
|
role: String(e.role || "").trim(),
|
|
roleLabel: String(e.role || "").trim().replace(/_/g, " "),
|
|
isVideo: String(e.type || "").toLowerCase() === "video" || /\.(mp4|mov|webm)$/i.test(String(e.filename || "")),
|
|
previewCandidates: Yi(e)
|
|
})) : [];
|
|
return {
|
|
...n,
|
|
kind: "full",
|
|
metadata: r,
|
|
workflowType: s.workflowType,
|
|
workflowLabel: s.workflowLabel,
|
|
workflowBadge: s.workflowBadge,
|
|
isTruncated: !!(e?.geninfo?._truncated || e?.metadata?._truncated || e?.prompt?._truncated),
|
|
positivePrompt: l.length ? "" : String(c.positive || "").trim(),
|
|
negativePrompt: l.length ? "" : String(c.negative || "").trim(),
|
|
positivePromptOverride: $(i, "prompt", "positive", "positive_prompt"),
|
|
negativePromptOverride: $(i, "negative_prompt", "negative", "negativePrompt"),
|
|
promptTabs: l,
|
|
showAlignment: !!e?.id && (!!String(c.positive || "").trim() || l.length > 0),
|
|
isImageAsset: Ui(e),
|
|
lyrics: String(r.lyrics || "").trim(),
|
|
modelFields: u,
|
|
modelGroups: p,
|
|
pipelineTabs: y,
|
|
samplingFields: g,
|
|
ttsFields: b,
|
|
ttsEngineFields: x,
|
|
ttsInstruction: String(r.instruct || "").trim(),
|
|
ttsRuntimeFields: S,
|
|
audioFields: ee,
|
|
seed: r.seed ?? null,
|
|
imageFields: C,
|
|
inputFiles: ne,
|
|
isOverride: o,
|
|
overrideLabel: o ? "Gen Info Override" : "",
|
|
notesFields: te,
|
|
customInfoBlocks: T
|
|
};
|
|
}
|
|
//#endregion
|
|
//#region ui/vue/components/panel/sidebar/GenerationInputThumb.vue
|
|
var la = ["title"], ua = ["src"], da = ["src"], fa = {
|
|
key: 2,
|
|
style: {
|
|
position: "absolute",
|
|
bottom: "0",
|
|
left: "0",
|
|
right: "0",
|
|
background: "rgba(0,0,0,0.7)",
|
|
color: "white",
|
|
"font-size": "8px",
|
|
padding: "2px",
|
|
"text-align": "center",
|
|
"white-space": "nowrap",
|
|
overflow: "hidden",
|
|
"text-overflow": "ellipsis"
|
|
}
|
|
}, pa = {
|
|
key: 3,
|
|
title: "Video file",
|
|
style: {
|
|
position: "absolute",
|
|
color: "white",
|
|
opacity: "0.7",
|
|
"font-size": "16px",
|
|
"pointer-events": "none"
|
|
}
|
|
}, ma = {
|
|
__name: "GenerationInputThumb",
|
|
props: { inputFile: {
|
|
type: Object,
|
|
required: !0
|
|
} },
|
|
setup(e) {
|
|
let t = e, n = j(0), r = j(!1);
|
|
function i() {
|
|
return (Array.isArray(t.inputFile?.previewCandidates) ? t.inputFile.previewCandidates : [])[n.value] || "";
|
|
}
|
|
function a() {
|
|
let e = Array.isArray(t.inputFile?.previewCandidates) ? t.inputFile.previewCandidates : [];
|
|
n.value < e.length - 1 && (n.value += 1);
|
|
}
|
|
async function o(e) {
|
|
e?.stopPropagation?.();
|
|
let n = String(t.inputFile?.filepath || t.inputFile?.filename || "").trim();
|
|
if (n) try {
|
|
await navigator.clipboard.writeText(n), r.value = !0, setTimeout(() => {
|
|
r.value = !1;
|
|
}, 350);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
}
|
|
function s(e) {
|
|
e?.stopPropagation?.();
|
|
let t = i();
|
|
if (Xi(t)) try {
|
|
window.open(t, "_blank", "noopener,noreferrer");
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
}
|
|
function c(e) {
|
|
e.target?.play?.().catch?.(() => {});
|
|
}
|
|
function l(e) {
|
|
try {
|
|
e.target?.pause?.();
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
}
|
|
return (t, n) => (F(), N("div", {
|
|
title: `${e.inputFile.filename} (click to copy, double-click to open in new tab)`,
|
|
style: R({
|
|
width: "64px",
|
|
height: "64px",
|
|
background: "#222",
|
|
borderRadius: "4px",
|
|
overflow: "hidden",
|
|
position: "relative",
|
|
cursor: "pointer",
|
|
display: "flex",
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
outline: r.value ? "2px solid rgba(76, 175, 80, 0.9)" : "",
|
|
outlineOffset: r.value ? "1px" : ""
|
|
}),
|
|
onClick: o,
|
|
onDblclick: s
|
|
}, [e.inputFile.isVideo ? (F(), N("video", {
|
|
key: 0,
|
|
src: i(),
|
|
muted: "",
|
|
loop: "",
|
|
playsinline: "",
|
|
preload: "metadata",
|
|
style: {
|
|
width: "100%",
|
|
height: "100%",
|
|
"object-fit": "cover"
|
|
},
|
|
onError: a,
|
|
onMouseover: c,
|
|
onMouseout: l
|
|
}, null, 40, ua)) : (F(), N("img", {
|
|
key: 1,
|
|
src: i(),
|
|
style: {
|
|
width: "100%",
|
|
height: "100%",
|
|
"object-fit": "cover"
|
|
},
|
|
onError: a
|
|
}, null, 40, da)), e.inputFile.role && e.inputFile.role !== "secondary" ? (F(), N("div", fa, L(e.inputFile.roleLabel), 1)) : e.inputFile.isVideo ? (F(), N("div", pa, " Play ")) : P("", !0)], 44, la));
|
|
}
|
|
}, ha = {
|
|
key: 0,
|
|
style: {
|
|
display: "flex",
|
|
"flex-direction": "column",
|
|
gap: "12px"
|
|
}
|
|
}, ga = {
|
|
key: 0,
|
|
style: {
|
|
display: "flex",
|
|
alignItems: "center",
|
|
justifyContent: "space-between",
|
|
padding: "10px 12px",
|
|
background: "linear-gradient(135deg, rgba(33, 150, 243, 0.18) 0%, rgba(0, 188, 212, 0.10) 100%)",
|
|
borderLeft: "3px solid #2196F3",
|
|
border: "1px solid rgba(33, 150, 243, 0.45)",
|
|
boxShadow: "0 0 0 1px rgba(33, 150, 243, 0.15) inset",
|
|
borderRadius: "6px",
|
|
fontSize: "11px",
|
|
color: "var(--fg-color, #ccc)"
|
|
}
|
|
}, _a = { style: { opacity: "0.85" } }, va = { style: {
|
|
display: "flex",
|
|
"align-items": "center",
|
|
gap: "8px",
|
|
"flex-wrap": "wrap",
|
|
"justify-content": "flex-end"
|
|
} }, ya = ["title"], ba = ["title"], xa = { style: {
|
|
display: "flex",
|
|
"align-items": "center",
|
|
"justify-content": "space-between",
|
|
gap: "10px"
|
|
} }, Sa = { style: {
|
|
"font-size": "11px",
|
|
"font-weight": "700",
|
|
color: "#00BCD4",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.6px"
|
|
} }, Ca = { style: {
|
|
"font-size": "11px",
|
|
color: "var(--fg-color, rgba(255,255,255,0.9))",
|
|
"font-weight": "600"
|
|
} }, wa = { style: {
|
|
"font-size": "11px",
|
|
"font-weight": "600",
|
|
color: "#FF9800",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.5px",
|
|
"margin-bottom": "8px"
|
|
} }, Ta = { style: {
|
|
"font-size": "12px",
|
|
color: "var(--fg-color, rgba(255,255,255,0.9))",
|
|
"line-height": "1.5",
|
|
"white-space": "pre-wrap",
|
|
"word-break": "break-word"
|
|
} }, Ea = { style: {
|
|
"font-size": "11px",
|
|
"font-weight": "600",
|
|
color: "#9E9E9E",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.5px",
|
|
"margin-bottom": "8px"
|
|
} }, Da = { style: {
|
|
"font-size": "12px",
|
|
color: "var(--fg-color, rgba(255,255,255,0.9))",
|
|
"line-height": "1.5",
|
|
"white-space": "pre-wrap",
|
|
"word-break": "break-word"
|
|
} }, Oa = { style: {
|
|
"font-size": "11px",
|
|
"font-weight": "600",
|
|
color: "#4CAF50",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.5px",
|
|
"margin-bottom": "10px"
|
|
} }, ka = { style: {
|
|
display: "flex",
|
|
"flex-wrap": "wrap",
|
|
gap: "6px",
|
|
"margin-bottom": "10px"
|
|
} }, Aa = { style: {
|
|
"font-size": "10px",
|
|
"font-weight": "700",
|
|
color: "#4CAF50",
|
|
"letter-spacing": "0.4px"
|
|
} }, ja = ["onClick"], Ma = { style: {
|
|
"font-size": "10px",
|
|
"font-weight": "700",
|
|
color: "#F44336",
|
|
"letter-spacing": "0.4px",
|
|
"margin-top": "4px"
|
|
} }, Na = ["onClick"], Pa = { style: {
|
|
display: "flex",
|
|
"justify-content": "space-between",
|
|
"align-items": "center",
|
|
"font-size": "11px",
|
|
"font-weight": "600",
|
|
color: "#4CAF50",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.5px",
|
|
"margin-bottom": "8px"
|
|
} }, Fa = ["title"], Ia = ["title"], La = { style: {
|
|
display: "flex",
|
|
"justify-content": "space-between",
|
|
"align-items": "center",
|
|
"font-size": "11px",
|
|
"font-weight": "600",
|
|
color: "#F44336",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.5px",
|
|
"margin-bottom": "8px"
|
|
} }, Ra = ["title"], za = ["title"], Ba = { style: {
|
|
"font-size": "11px",
|
|
"font-weight": "600",
|
|
color: "#00BCD4",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.5px",
|
|
display: "flex",
|
|
"align-items": "center",
|
|
"justify-content": "space-between"
|
|
} }, Va = ["title"], Ha = { style: {
|
|
display: "flex",
|
|
"align-items": "center",
|
|
gap: "10px"
|
|
} }, Ua = { style: {
|
|
flex: "1",
|
|
height: "8px",
|
|
background: "rgba(255,255,255,0.1)",
|
|
"border-radius": "4px",
|
|
overflow: "hidden"
|
|
} }, Wa = {
|
|
key: 0,
|
|
style: {
|
|
"font-size": "10px",
|
|
color: "rgba(255,255,255,0.65)",
|
|
border: "1px dashed rgba(255,255,255,0.25)",
|
|
"border-radius": "4px",
|
|
padding: "6px 8px",
|
|
background: "rgba(255,255,255,0.04)"
|
|
}
|
|
}, Ga = { style: {
|
|
"font-size": "10px",
|
|
"font-weight": "600",
|
|
color: "rgba(0, 188, 212, 0.75)",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.5px",
|
|
"margin-top": "8px",
|
|
display: "flex",
|
|
"align-items": "center",
|
|
"justify-content": "space-between",
|
|
gap: "8px"
|
|
} }, Ka = ["title"], qa = { style: {
|
|
display: "flex",
|
|
"align-items": "center",
|
|
gap: "6px"
|
|
} }, Ja = ["title"], Ya = { style: {
|
|
display: "flex",
|
|
"justify-content": "space-between",
|
|
"align-items": "center",
|
|
"font-size": "11px",
|
|
"font-weight": "600",
|
|
color: "#00BCD4",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.5px",
|
|
"margin-bottom": "8px"
|
|
} }, Xa = { style: {
|
|
"font-size": "12px",
|
|
color: "var(--fg-color, rgba(255,255,255,0.9))",
|
|
"line-height": "1.5",
|
|
"white-space": "pre-wrap",
|
|
"word-break": "break-word"
|
|
} }, Za = { style: {
|
|
"font-size": "11px",
|
|
"font-weight": "600",
|
|
color: "#FF9800",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.5px",
|
|
"margin-bottom": "10px"
|
|
} }, Qa = { style: {
|
|
display: "flex",
|
|
"flex-wrap": "wrap",
|
|
gap: "6px",
|
|
"margin-bottom": "10px"
|
|
} }, $a = { style: {
|
|
"font-size": "10px",
|
|
"font-weight": "600",
|
|
color: "rgba(255,255,255,0.6)",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.4px"
|
|
} }, eo = ["onClick"], to = { style: {
|
|
"font-size": "11px",
|
|
"font-weight": "600",
|
|
color: "#9C27B0",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.5px",
|
|
"margin-bottom": "10px"
|
|
} }, no = { style: {
|
|
display: "grid",
|
|
"grid-template-columns": "repeat(auto-fit, minmax(220px, 1fr))",
|
|
gap: "10px"
|
|
} }, ro = { style: {
|
|
display: "flex",
|
|
"align-items": "center",
|
|
"justify-content": "space-between",
|
|
gap: "10px"
|
|
} }, io = { style: {
|
|
display: "flex",
|
|
"flex-direction": "column",
|
|
gap: "4px"
|
|
} }, ao = ["onClick"], oo = {
|
|
key: 0,
|
|
style: {
|
|
display: "flex",
|
|
"flex-direction": "column",
|
|
gap: "6px"
|
|
}
|
|
}, so = { style: {
|
|
"font-size": "10px",
|
|
"font-weight": "700",
|
|
color: "rgba(255,255,255,0.58)",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.4px"
|
|
} }, co = { style: {
|
|
display: "flex",
|
|
"flex-direction": "column",
|
|
gap: "5px"
|
|
} }, lo = ["onClick"], uo = { style: {
|
|
display: "grid",
|
|
"grid-template-columns": "auto 1fr",
|
|
gap: "8px 12px",
|
|
"align-items": "start"
|
|
} }, fo = ["title"], po = ["title"], mo = ["title", "onClick"], ho = { style: {
|
|
"font-size": "11px",
|
|
"font-weight": "600",
|
|
color: "#4CAF50",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.5px",
|
|
"margin-bottom": "10px"
|
|
} }, go = ["title", "onClick"], _o = ["title", "onClick"], vo = { style: {
|
|
display: "flex",
|
|
"justify-content": "space-between",
|
|
"align-items": "center",
|
|
"font-size": "11px",
|
|
"font-weight": "600",
|
|
color: "#26A69A",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.5px",
|
|
"margin-bottom": "8px"
|
|
} }, yo = ["title"], bo = { style: {
|
|
"font-size": "11px",
|
|
"font-weight": "700",
|
|
color: "#E91E63",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "1px"
|
|
} }, xo = ["title"], So = ["title"], Co = { style: {
|
|
display: "flex",
|
|
gap: "8px",
|
|
"flex-wrap": "wrap"
|
|
} }, wo = {
|
|
__name: "SidebarGenerationSection",
|
|
props: { asset: {
|
|
type: Object,
|
|
required: !0
|
|
} },
|
|
setup(e) {
|
|
let t = e, n = j(0), r = j(0), i = j(""), a = j(A("action.copy", "Copy")), o = j(A("action.generate", "Generate")), s = j(!1), c = j(u()), l = 0;
|
|
function u() {
|
|
return {
|
|
scoreText: "...",
|
|
scoreColor: "#888",
|
|
qualityText: A("status.loading", "Loading"),
|
|
qualityColor: "#888",
|
|
qualityBackground: "rgba(127,127,127,0.3)",
|
|
fillWidth: "0%",
|
|
fillColor: "#666",
|
|
aiStatusVisible: !1,
|
|
aiStatusText: A("sidebar.generation.aiDisabledEnv", "AI features are disabled (enable vector search env var).")
|
|
};
|
|
}
|
|
function d(e, t) {
|
|
let n = String(e || "").trim().replace(/^#/, "");
|
|
return /^[0-9a-fA-F]{6}$/.test(n) ? `rgba(${Number.parseInt(n.slice(0, 2), 16)}, ${Number.parseInt(n.slice(2, 4), 16)}, ${Number.parseInt(n.slice(4, 6), 16)}, ${t})` : `rgba(255,255,255,${t})`;
|
|
}
|
|
function f(e, { emphasis: t = !1, startAlpha: n = .16, endAlpha: r = .08 } = {}) {
|
|
return {
|
|
background: t ? `linear-gradient(135deg, ${d(e, n)} 0%, ${d(e, r)} 100%)` : "var(--comfy-menu-bg, rgba(0,0,0,0.3))",
|
|
borderLeft: `3px solid ${e}`,
|
|
border: t ? `1px solid ${d(e, .45)}` : "1px solid var(--border-color, rgba(255,255,255,0.12))",
|
|
boxShadow: t ? `0 0 0 1px ${d(e, .15)} inset` : "none",
|
|
borderRadius: "6px",
|
|
padding: "12px"
|
|
};
|
|
}
|
|
function p() {
|
|
return {
|
|
background: "linear-gradient(135deg, rgba(233, 30, 99, 0.15) 0%, rgba(156, 39, 176, 0.15) 100%)",
|
|
border: "2px solid #E91E63",
|
|
borderRadius: "8px",
|
|
padding: "12px 16px",
|
|
display: "flex",
|
|
alignItems: "center",
|
|
justifyContent: "space-between",
|
|
gap: "12px"
|
|
};
|
|
}
|
|
function h() {
|
|
return {
|
|
display: "inline-flex",
|
|
alignItems: "center",
|
|
borderRadius: "999px",
|
|
border: "1px solid rgba(0, 188, 212, 0.55)",
|
|
background: "rgba(0, 188, 212, 0.16)",
|
|
color: "#4DD0E1",
|
|
fontSize: "9px",
|
|
fontWeight: "700",
|
|
lineHeight: "1",
|
|
padding: "2px 6px",
|
|
letterSpacing: "0.2px",
|
|
textTransform: "uppercase",
|
|
whiteSpace: "nowrap"
|
|
};
|
|
}
|
|
let _ = M(() => ca(t.asset)), v = M(() => Gi()), y = M(() => _.value.kind === "full" || _.value.kind === "caption-only"), b = M(() => Ji(i.value) || _.value.emptyCaptionText), x = M(() => v.value && _.value.isImageAsset && !!t.asset?.id), S = M(() => v.value && !!Ji(b.value) && b.value !== _.value.emptyCaptionText), ee = M(() => {
|
|
let e = [];
|
|
return _.value.modelFields.length && e.push({
|
|
key: "model",
|
|
title: A("sidebar.generation.modelLora", "Model & LoRA"),
|
|
accent: "#9C27B0",
|
|
emphasis: !0,
|
|
fields: _.value.modelFields
|
|
}), !_.value.pipelineTabs.length && _.value.samplingFields.length && e.push({
|
|
key: "sampling",
|
|
title: A("sidebar.generation.sampling", "Sampling"),
|
|
accent: "#FF9800",
|
|
emphasis: !0,
|
|
fields: _.value.samplingFields
|
|
}), (_.value.ttsFields.length || _.value.workflowType.toLowerCase() === "tts") && e.push({
|
|
key: "tts",
|
|
title: "TTS",
|
|
accent: "#26A69A",
|
|
emphasis: !0,
|
|
fields: _.value.ttsFields
|
|
}), _.value.ttsEngineFields.length && e.push({
|
|
key: "tts-engine",
|
|
title: "TTS Engine",
|
|
accent: "#00897B",
|
|
emphasis: !1,
|
|
fields: _.value.ttsEngineFields
|
|
}), _.value.ttsRuntimeFields.length && e.push({
|
|
key: "tts-runtime",
|
|
title: "TTS Runtime",
|
|
accent: "#00796B",
|
|
emphasis: !1,
|
|
fields: _.value.ttsRuntimeFields
|
|
}), _.value.audioFields.length && e.push({
|
|
key: "audio",
|
|
title: A("sidebar.generation.audio", "Audio"),
|
|
accent: "#00BCD4",
|
|
emphasis: !1,
|
|
fields: _.value.audioFields
|
|
}), _.value.imageFields.length && e.push({
|
|
key: "image",
|
|
title: A("sidebar.generation.image", "Image"),
|
|
accent: "#2196F3",
|
|
emphasis: !1,
|
|
fields: _.value.imageFields
|
|
}), e;
|
|
});
|
|
function C(e, t, n = 450) {
|
|
if (!e) return;
|
|
let r = e.style.background;
|
|
e.style.background = t, setTimeout(() => {
|
|
e.style.background = r || "";
|
|
}, n);
|
|
}
|
|
function te(e, t = !0) {
|
|
return {
|
|
background: t ? `linear-gradient(135deg, ${d(e, .16)} 0%, ${d(e, .08)} 100%)` : "var(--comfy-menu-bg, rgba(0,0,0,0.3))",
|
|
border: `1px solid ${d(e, .42)}`,
|
|
boxShadow: `0 0 0 1px ${d(e, .14)} inset`,
|
|
borderRadius: "8px",
|
|
padding: "12px",
|
|
display: "flex",
|
|
flexDirection: "column",
|
|
gap: "10px"
|
|
};
|
|
}
|
|
function w(e) {
|
|
return e === "high_noise" ? "#FF7043" : e === "low_noise" ? "#29B6F6" : "#AB47BC";
|
|
}
|
|
async function T(e, t = null, n = "rgba(76, 175, 80, 0.35)") {
|
|
let r = String(e ?? "").trim();
|
|
if (!(!r || r === "-")) try {
|
|
await navigator.clipboard.writeText(r), C(t, n);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
}
|
|
function ne() {
|
|
c.value = {
|
|
scoreText: "AI OFF",
|
|
scoreColor: "#9E9E9E",
|
|
qualityText: A("status.disabled", "Disabled"),
|
|
qualityColor: "#BDBDBD",
|
|
qualityBackground: "rgba(158,158,158,0.25)",
|
|
fillWidth: "0%",
|
|
fillColor: "#777",
|
|
aiStatusVisible: !0,
|
|
aiStatusText: A("sidebar.generation.aiDisabledSettings", "AI features are disabled in settings.")
|
|
};
|
|
}
|
|
function re() {
|
|
c.value = u();
|
|
}
|
|
async function ie() {
|
|
l += 1;
|
|
let e = l;
|
|
if (!_.value.showAlignment || !t.asset?.id) {
|
|
re();
|
|
return;
|
|
}
|
|
if (!v.value) {
|
|
ne();
|
|
return;
|
|
}
|
|
re();
|
|
try {
|
|
let n = await g(t.asset.id);
|
|
if (e !== l) return;
|
|
if (!n?.ok && (String(n?.code || "").toUpperCase() === "SERVICE_UNAVAILABLE" || /vector search is not enabled/i.test(String(n?.error || "")))) {
|
|
ne();
|
|
return;
|
|
}
|
|
let r = n?.ok && n.data != null ? Number(n.data) : null;
|
|
if (!Number.isFinite(r)) {
|
|
c.value = {
|
|
scoreText: "N/A",
|
|
scoreColor: "#888",
|
|
qualityText: A("status.na", "N/A"),
|
|
qualityColor: "#888",
|
|
qualityBackground: "rgba(127,127,127,0.3)",
|
|
fillWidth: "0%",
|
|
fillColor: "#666",
|
|
aiStatusVisible: !1,
|
|
aiStatusText: ""
|
|
};
|
|
return;
|
|
}
|
|
let i = Math.round(r * 100), a = Ki(r);
|
|
c.value = {
|
|
scoreText: `${i}%`,
|
|
scoreColor: a,
|
|
qualityText: qi(r),
|
|
qualityColor: a,
|
|
qualityBackground: `${a}33`,
|
|
fillWidth: `${i}%`,
|
|
fillColor: a,
|
|
aiStatusVisible: !1,
|
|
aiStatusText: ""
|
|
};
|
|
} catch (t) {
|
|
if (console.debug?.(t), e !== l) return;
|
|
c.value = {
|
|
scoreText: "-",
|
|
scoreColor: "#888",
|
|
qualityText: A("status.unavailable", "Unavailable"),
|
|
qualityColor: "#888",
|
|
qualityBackground: "rgba(127,127,127,0.3)",
|
|
fillWidth: "0%",
|
|
fillColor: "#666",
|
|
aiStatusVisible: !1,
|
|
aiStatusText: ""
|
|
};
|
|
}
|
|
}
|
|
async function ae() {
|
|
if (!(!x.value || s.value)) {
|
|
s.value = !0, o.value = A("status.generating", "Generating...");
|
|
try {
|
|
let e = await m(t.asset.id);
|
|
e?.ok && (i.value = String(e?.data || "").trim());
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
} finally {
|
|
s.value = !1, o.value = A("action.generate", "Generate");
|
|
}
|
|
}
|
|
}
|
|
async function oe() {
|
|
if (S.value) try {
|
|
await navigator.clipboard.writeText(b.value), a.value = A("viewer.copySuccessShort", "Copied!"), setTimeout(() => {
|
|
a.value = A("action.copy", "Copy");
|
|
}, 900);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
}
|
|
return Pe(() => t.asset, () => {
|
|
n.value = 0, r.value = 0, i.value = String(t.asset?.enhanced_caption || "").trim(), a.value = A("action.copy", "Copy"), o.value = A("action.generate", "Generate");
|
|
}, { immediate: !0 }), Pe(() => [
|
|
t.asset?.id,
|
|
_.value.kind,
|
|
_.value.showAlignment,
|
|
v.value
|
|
], () => {
|
|
ie();
|
|
}, { immediate: !0 }), (e, t) => {
|
|
let i = ze("MButton");
|
|
return _.value.kind === "empty" ? P("", !0) : (F(), N("div", ha, [
|
|
_.value.workflowType ? (F(), N("div", ga, [z("span", _a, L(I(A)("viewer.workflow", "Workflow")), 1), z("div", va, [z("span", {
|
|
title: I(A)("sidebar.generation.workflowEngine", "Workflow engine: {value}", { value: _.value.workflowType }),
|
|
style: {
|
|
background: "#2196F3",
|
|
color: "white",
|
|
padding: "2px 8px",
|
|
"border-radius": "999px",
|
|
"font-weight": "bold",
|
|
"font-size": "10px",
|
|
"letter-spacing": "0.2px"
|
|
}
|
|
}, L(_.value.workflowLabel || _.value.workflowType), 9, ya), _.value.workflowBadge ? (F(), N("span", {
|
|
key: 0,
|
|
title: I(A)("sidebar.generation.apiProvider", "API provider: {value}", { value: _.value.workflowBadge }),
|
|
style: {
|
|
background: "rgba(255,255,255,0.08)",
|
|
color: "var(--fg-color, #eee)",
|
|
padding: "2px 8px",
|
|
"border-radius": "999px",
|
|
border: "1px solid rgba(255,255,255,0.14)",
|
|
"font-weight": "600",
|
|
"font-size": "10px",
|
|
"letter-spacing": "0.2px"
|
|
}
|
|
}, L(_.value.workflowBadge), 9, ba)) : P("", !0)])])) : P("", !0),
|
|
_.value.isOverride ? (F(), N("div", {
|
|
key: 1,
|
|
style: R(f("#00BCD4", {
|
|
emphasis: !0,
|
|
startAlpha: .14,
|
|
endAlpha: .08
|
|
}))
|
|
}, [z("div", xa, [z("span", Sa, L(I(A)("sidebar.generation.override", "Override")), 1), z("span", Ca, L(_.value.overrideLabel), 1)])], 4)) : P("", !0),
|
|
_.value.isTruncated ? (F(), N("div", {
|
|
key: 2,
|
|
style: R(f("#FF9800", {
|
|
emphasis: !0,
|
|
startAlpha: .12,
|
|
endAlpha: .08
|
|
}))
|
|
}, [z("div", wa, L(I(A)("sidebar.generation.metadataTruncated", "Metadata Truncated")), 1), z("div", Ta, L(I(A)("sidebar.generation.metadataTruncatedBody", "Generation data is incomplete because it exceeded the size limit.")), 1)], 4)) : P("", !0),
|
|
_.value.kind === "media-only" ? (F(), N("div", {
|
|
key: 3,
|
|
style: R(f("#9E9E9E", {
|
|
emphasis: !0,
|
|
startAlpha: .1,
|
|
endAlpha: .06
|
|
}))
|
|
}, [z("div", Ea, L(I(A)("sidebar.generation.generationData", "Generation Data")), 1), z("div", Da, L(_.value.mediaOnlyMessage), 1)], 4)) : P("", !0),
|
|
_.value.kind === "full" ? (F(), N(B, { key: 4 }, [_.value.promptTabs.length ? (F(), N("div", {
|
|
key: 0,
|
|
style: R(f("#4CAF50", {
|
|
emphasis: !0,
|
|
startAlpha: .16,
|
|
endAlpha: .1
|
|
}))
|
|
}, [
|
|
z("div", Oa, L(I(A)("sidebar.generation.promptPipeline", "Prompt Pipeline ({count} variants)", { count: _.value.promptTabs.length })), 1),
|
|
z("div", ka, [(F(!0), N(B, null, V(_.value.promptTabs, (e, t) => (F(), Re(i, {
|
|
key: e.label,
|
|
type: "button",
|
|
severity: "secondary",
|
|
text: "",
|
|
rounded: "",
|
|
style: R({
|
|
appearance: "none",
|
|
border: n.value === t ? "1px solid #4CAF50" : "1px solid var(--border-color, rgba(255,255,255,0.12))",
|
|
borderRadius: "999px",
|
|
background: n.value === t ? "#4CAF5033" : "rgba(127,127,127,0.12)",
|
|
color: n.value === t ? "#4CAF50" : "var(--fg-color, #ddd)",
|
|
fontSize: "11px",
|
|
padding: "4px 10px",
|
|
cursor: "pointer",
|
|
fontWeight: n.value === t ? "700" : "500",
|
|
boxShadow: n.value === t ? "0 0 0 1px #4CAF5055 inset" : "none"
|
|
}),
|
|
onClick: (e) => n.value = t
|
|
}, {
|
|
default: Be(() => [Fe(L(e.label), 1)]),
|
|
_: 2
|
|
}, 1032, ["style", "onClick"]))), 128))]),
|
|
(F(!0), N(B, null, V(_.value.promptTabs, (e, t) => Ne((F(), N("div", {
|
|
key: `${e.label}-panel`,
|
|
style: {
|
|
display: "flex",
|
|
"flex-direction": "column",
|
|
gap: "8px",
|
|
border: "1px solid rgba(76, 175, 80, 0.35)",
|
|
"border-radius": "6px",
|
|
background: "linear-gradient(135deg, rgba(76, 175, 80, 0.12) 0%, rgba(33, 150, 243, 0.08) 100%)",
|
|
"box-shadow": "0 0 0 1px rgba(76, 175, 80, 0.12) inset",
|
|
padding: "10px"
|
|
}
|
|
}, [
|
|
z("div", Aa, L(I(A)("sidebar.generation.positive", "POSITIVE")), 1),
|
|
z("div", {
|
|
style: {
|
|
"font-size": "12px",
|
|
color: "var(--fg-color, #ddd)",
|
|
"white-space": "pre-wrap",
|
|
"line-height": "1.35",
|
|
cursor: "pointer"
|
|
},
|
|
onClick: (t) => T(e.positive, t.currentTarget)
|
|
}, L(e.positive), 9, ja),
|
|
e.negative ? (F(), N(B, { key: 0 }, [z("div", Ma, L(I(A)("sidebar.generation.negative", "NEGATIVE")), 1), z("div", {
|
|
style: {
|
|
"font-size": "12px",
|
|
color: "var(--fg-color, #ddd)",
|
|
"white-space": "pre-wrap",
|
|
"line-height": "1.35",
|
|
cursor: "pointer"
|
|
},
|
|
onClick: (t) => T(e.negative, t.currentTarget)
|
|
}, L(e.negative), 9, Na)], 64)) : P("", !0)
|
|
])), [[st, n.value === t]])), 128))
|
|
], 4)) : _.value.positivePrompt ? (F(), N("div", {
|
|
key: 1,
|
|
style: R(f("#4CAF50", {
|
|
emphasis: !0,
|
|
startAlpha: .16,
|
|
endAlpha: .1
|
|
}))
|
|
}, [z("div", Pa, [z("span", null, L(I(A)("sidebar.generation.positivePrompt", "Positive Prompt")), 1), _.value.positivePromptOverride ? (F(), N("span", {
|
|
key: 0,
|
|
style: R(h()),
|
|
title: I(A)("sidebar.generation.overrideTooltip", "This field was forced by Majoor Gen Info Override")
|
|
}, L(I(A)("sidebar.generation.override", "override")), 13, Fa)) : P("", !0)]), z("div", {
|
|
title: I(A)("action.clickToCopy", "Click to copy"),
|
|
style: {
|
|
"font-size": "12px",
|
|
color: "var(--fg-color, rgba(255,255,255,0.9))",
|
|
"line-height": "1.5",
|
|
"white-space": "pre-wrap",
|
|
"word-break": "break-word",
|
|
cursor: "pointer"
|
|
},
|
|
onClick: t[0] ||= (e) => T(_.value.positivePrompt, e.currentTarget)
|
|
}, L(_.value.positivePrompt), 9, Ia)], 4)) : P("", !0), !_.value.promptTabs.length && _.value.negativePrompt ? (F(), N("div", {
|
|
key: 2,
|
|
style: R(f("#F44336", {
|
|
emphasis: !0,
|
|
startAlpha: .16,
|
|
endAlpha: .1
|
|
}))
|
|
}, [z("div", La, [z("span", null, L(I(A)("sidebar.generation.negativePrompt", "Negative Prompt")), 1), _.value.negativePromptOverride ? (F(), N("span", {
|
|
key: 0,
|
|
style: R(h()),
|
|
title: I(A)("sidebar.generation.overrideTooltip", "This field was forced by Majoor Gen Info Override")
|
|
}, L(I(A)("sidebar.generation.override", "override")), 13, Ra)) : P("", !0)]), z("div", {
|
|
title: I(A)("action.clickToCopy", "Click to copy"),
|
|
style: {
|
|
"font-size": "12px",
|
|
color: "var(--fg-color, rgba(255,255,255,0.9))",
|
|
"line-height": "1.5",
|
|
"white-space": "pre-wrap",
|
|
"word-break": "break-word",
|
|
cursor: "pointer"
|
|
},
|
|
onClick: t[1] ||= (e) => T(_.value.negativePrompt, e.currentTarget)
|
|
}, L(_.value.negativePrompt), 9, za)], 4)) : P("", !0)], 64)) : P("", !0),
|
|
y.value ? (F(), N("div", {
|
|
key: 5,
|
|
style: {
|
|
background: "linear-gradient(135deg, rgba(0, 188, 212, 0.14) 0%, rgba(33, 150, 243, 0.10) 100%)",
|
|
border: "1px solid rgba(0, 188, 212, 0.40)",
|
|
"border-radius": "6px",
|
|
padding: "12px",
|
|
display: "flex",
|
|
"flex-direction": "column",
|
|
gap: "10px"
|
|
},
|
|
class: et({ "mjr-ai-disabled-block": !v.value })
|
|
}, [
|
|
_.value.showAlignment ? (F(), N(B, { key: 0 }, [
|
|
z("div", Ba, [z("span", { title: I(A)("sidebar.generation.promptAlignmentTooltip", "How closely the generated image matches the prompt (SigLIP2 score)") }, L(I(A)("sidebar.generation.promptAlignment", "Prompt Alignment")), 9, Va)]),
|
|
z("div", Ha, [
|
|
z("div", Ua, [z("div", { style: R({
|
|
height: "100%",
|
|
width: c.value.fillWidth,
|
|
background: c.value.fillColor,
|
|
borderRadius: "4px",
|
|
transition: "width 0.6s ease, background 0.4s ease"
|
|
}) }, null, 4)]),
|
|
z("span", { style: R({
|
|
fontSize: "13px",
|
|
fontWeight: "700",
|
|
color: c.value.scoreColor,
|
|
minWidth: "60px",
|
|
textAlign: "right",
|
|
fontFamily: "'Consolas', 'Monaco', monospace"
|
|
}) }, L(c.value.scoreText), 5),
|
|
z("span", { style: R({
|
|
fontSize: "9px",
|
|
fontWeight: "700",
|
|
padding: "2px 6px",
|
|
borderRadius: "3px",
|
|
background: c.value.qualityBackground,
|
|
color: c.value.qualityColor,
|
|
textTransform: "uppercase",
|
|
letterSpacing: "0.5px"
|
|
}) }, L(c.value.qualityText), 5)
|
|
]),
|
|
c.value.aiStatusVisible ? (F(), N("div", Wa, L(c.value.aiStatusText), 1)) : P("", !0)
|
|
], 64)) : P("", !0),
|
|
z("div", Ga, [z("span", { title: I(A)("sidebar.generation.aiCaptionTooltip", "AI caption generated by Florence-2") }, L(_.value.captionLabel), 9, Ka), z("div", qa, [Ye(i, {
|
|
type: "button",
|
|
class: "mjr-ai-control",
|
|
severity: "secondary",
|
|
text: "",
|
|
disabled: !x.value || s.value,
|
|
style: R([{
|
|
border: "1px solid rgba(0,188,212,0.45)",
|
|
background: "rgba(0,188,212,0.12)",
|
|
color: "#00BCD4",
|
|
"border-radius": "4px",
|
|
"font-size": "10px",
|
|
"font-weight": "600",
|
|
padding: "2px 8px",
|
|
cursor: "pointer"
|
|
}, {
|
|
opacity: x.value ? "1" : "0.6",
|
|
cursor: x.value ? "pointer" : "default"
|
|
}]),
|
|
onClick: He(ae, ["stop"])
|
|
}, {
|
|
default: Be(() => [Fe(L(o.value), 1)]),
|
|
_: 1
|
|
}, 8, ["disabled", "style"]), Ye(i, {
|
|
type: "button",
|
|
class: "mjr-ai-control",
|
|
severity: "secondary",
|
|
text: "",
|
|
disabled: !S.value,
|
|
style: R([{
|
|
border: "1px solid rgba(0,188,212,0.45)",
|
|
background: "rgba(0,188,212,0.12)",
|
|
color: "#00BCD4",
|
|
"border-radius": "4px",
|
|
"font-size": "10px",
|
|
"font-weight": "600",
|
|
padding: "2px 8px",
|
|
cursor: "pointer"
|
|
}, {
|
|
opacity: S.value ? "1" : "0.6",
|
|
cursor: S.value ? "pointer" : "default"
|
|
}]),
|
|
onClick: He(oe, ["stop"])
|
|
}, {
|
|
default: Be(() => [Fe(L(a.value), 1)]),
|
|
_: 1
|
|
}, 8, ["disabled", "style"])])]),
|
|
z("div", {
|
|
title: v.value ? I(A)("sidebar.generation.copyCaptionTooltip", "Click to copy caption") : I(A)("sidebar.generation.aiCaptionDisabled", "AI caption controls are disabled"),
|
|
style: R({
|
|
marginTop: "4px",
|
|
padding: "8px",
|
|
borderRadius: "6px",
|
|
border: "1px solid rgba(0, 188, 212, 0.30)",
|
|
background: "rgba(0, 188, 212, 0.08)",
|
|
color: "rgba(230, 250, 255, 0.95)",
|
|
fontSize: "11px",
|
|
lineHeight: "1.45",
|
|
whiteSpace: "pre-wrap",
|
|
wordBreak: "break-word",
|
|
cursor: S.value ? "copy" : "default"
|
|
}),
|
|
onClick: oe
|
|
}, L(b.value), 13, Ja)
|
|
], 2)) : P("", !0),
|
|
_.value.lyrics ? (F(), N("div", {
|
|
key: 6,
|
|
style: R(f("#00BCD4", { emphasis: !1 }))
|
|
}, [z("div", Ya, [z("span", null, L(I(A)("sidebar.generation.lyrics", "Lyrics")), 1)]), z("div", Xa, L(_.value.lyrics), 1)], 4)) : P("", !0),
|
|
_.value.pipelineTabs.length ? (F(), N("div", {
|
|
key: 7,
|
|
style: R(f("#FF9800", {
|
|
emphasis: !0,
|
|
startAlpha: .16,
|
|
endAlpha: .1
|
|
}))
|
|
}, [
|
|
z("div", Za, L(I(A)("sidebar.generation.pipeline", "Generation Pipeline")), 1),
|
|
z("div", Qa, [(F(!0), N(B, null, V(_.value.pipelineTabs, (e, t) => (F(), Re(i, {
|
|
key: e.label,
|
|
type: "button",
|
|
severity: "secondary",
|
|
text: "",
|
|
rounded: "",
|
|
style: R({
|
|
appearance: "none",
|
|
border: r.value === t ? "1px solid #FF9800" : "1px solid var(--border-color, rgba(255,255,255,0.12))",
|
|
borderRadius: "999px",
|
|
background: r.value === t ? "#FF980033" : "rgba(127,127,127,0.12)",
|
|
color: r.value === t ? "#FF9800" : "var(--fg-color, #ddd)",
|
|
fontSize: "11px",
|
|
padding: "4px 10px",
|
|
cursor: "pointer",
|
|
fontWeight: r.value === t ? "700" : "500",
|
|
boxShadow: r.value === t ? "0 0 0 1px #FF980055 inset" : "none"
|
|
}),
|
|
onClick: (e) => r.value = t
|
|
}, {
|
|
default: Be(() => [Fe(L(e.label), 1)]),
|
|
_: 2
|
|
}, 1032, ["style", "onClick"]))), 128))]),
|
|
(F(!0), N(B, null, V(_.value.pipelineTabs, (e, t) => Ne((F(), N("div", {
|
|
key: `${e.label}-pipeline`,
|
|
style: {
|
|
display: "grid",
|
|
"grid-template-columns": "repeat(auto-fit, minmax(150px, 1fr))",
|
|
gap: "8px",
|
|
padding: "8px",
|
|
border: "1px solid rgba(255, 152, 0, 0.35)",
|
|
"border-radius": "6px",
|
|
background: "linear-gradient(135deg, rgba(255, 152, 0, 0.12) 0%, rgba(255, 193, 7, 0.08) 100%)",
|
|
"box-shadow": "0 0 0 1px rgba(255, 152, 0, 0.12) inset"
|
|
}
|
|
}, [(F(!0), N(B, null, V(e.fields, (t) => (F(), N("div", {
|
|
key: `${e.label}-${t.label}`,
|
|
style: {
|
|
display: "flex",
|
|
"flex-direction": "column",
|
|
gap: "2px",
|
|
"min-width": "0"
|
|
}
|
|
}, [z("span", $a, L(t.label), 1), z("span", {
|
|
style: {
|
|
"font-size": "12px",
|
|
color: "var(--fg-color, #ddd)",
|
|
"word-break": "break-word",
|
|
padding: "1px 3px",
|
|
"border-radius": "3px",
|
|
transition: "background 0.2s ease",
|
|
cursor: "copy"
|
|
},
|
|
onClick: (e) => T(t.value, e.currentTarget)
|
|
}, L(t.value), 9, eo)]))), 128))])), [[st, r.value === t]])), 128))
|
|
], 4)) : P("", !0),
|
|
_.value.modelGroups.length ? (F(), N("div", {
|
|
key: 8,
|
|
style: R(f("#9C27B0", {
|
|
emphasis: !0,
|
|
startAlpha: .18,
|
|
endAlpha: .1
|
|
}))
|
|
}, [z("div", to, L(I(A)("sidebar.generation.modelBranches", "Model Branches")), 1), z("div", no, [(F(!0), N(B, null, V(_.value.modelGroups, (e) => (F(), N("div", {
|
|
key: `model-group-${e.key}`,
|
|
style: R(te(w(e.key), !0))
|
|
}, [
|
|
z("div", ro, [z("div", { style: R({
|
|
fontSize: "10px",
|
|
fontWeight: "800",
|
|
color: w(e.key),
|
|
letterSpacing: "0.6px",
|
|
textTransform: "uppercase"
|
|
}) }, L(e.label), 5), z("span", { style: R({
|
|
fontSize: "9px",
|
|
fontWeight: "700",
|
|
color: "#fff",
|
|
background: d(w(e.key), .22),
|
|
border: `1px solid ${d(w(e.key), .48)}`,
|
|
borderRadius: "999px",
|
|
padding: "2px 8px",
|
|
letterSpacing: "0.4px",
|
|
textTransform: "uppercase"
|
|
}) }, L(e.loras?.length || 0) + " LoRA ", 5)]),
|
|
z("div", io, [t[4] ||= z("div", { style: {
|
|
"font-size": "10px",
|
|
"font-weight": "700",
|
|
color: "rgba(255,255,255,0.58)",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.4px"
|
|
} }, " UNet ", -1), z("div", {
|
|
style: {
|
|
"font-size": "12px",
|
|
color: "var(--fg-color, rgba(255,255,255,0.96))",
|
|
"line-height": "1.45",
|
|
"word-break": "break-word",
|
|
cursor: "pointer"
|
|
},
|
|
onClick: (t) => T(e.model, t.currentTarget)
|
|
}, L(e.model || "-"), 9, ao)]),
|
|
e.loras?.length ? (F(), N("div", oo, [z("div", so, L(I(A)("sidebar.generation.loraStack", "LoRA Stack")), 1), z("div", co, [(F(!0), N(B, null, V(e.loras, (t, n) => (F(), N("div", {
|
|
key: `${e.key}-lora-${n}`,
|
|
style: {
|
|
"font-size": "12px",
|
|
color: "var(--fg-color, rgba(255,255,255,0.92))",
|
|
"line-height": "1.4",
|
|
"word-break": "break-word",
|
|
padding: "6px 8px",
|
|
"border-radius": "6px",
|
|
background: "rgba(255,255,255,0.05)",
|
|
border: "1px solid rgba(255,255,255,0.08)",
|
|
cursor: "pointer"
|
|
},
|
|
onClick: (e) => T(t, e.currentTarget)
|
|
}, L(t), 9, lo))), 128))])])) : P("", !0)
|
|
], 4))), 128))])], 4)) : P("", !0),
|
|
(F(!0), N(B, null, V(ee.value, (e) => (F(), N("div", {
|
|
key: e.key,
|
|
style: R(f(e.accent, { emphasis: e.emphasis }))
|
|
}, [z("div", { style: R({
|
|
fontSize: "11px",
|
|
fontWeight: "600",
|
|
color: e.accent,
|
|
textTransform: "uppercase",
|
|
letterSpacing: "0.5px",
|
|
marginBottom: "10px"
|
|
}) }, L(e.title), 5), z("div", uo, [(F(!0), N(B, null, V(e.fields, (t) => (F(), N(B, { key: `${e.key}-${t.label}` }, [z("div", {
|
|
title: t.label,
|
|
style: {
|
|
"font-size": "11px",
|
|
color: "var(--mjr-muted, rgba(127,127,127,0.9))",
|
|
"font-weight": "500",
|
|
display: "flex",
|
|
"align-items": "center",
|
|
gap: "6px"
|
|
}
|
|
}, [z("span", null, L(t.label) + ":", 1), t.override ? (F(), N("span", {
|
|
key: 0,
|
|
style: R(h()),
|
|
title: I(A)("sidebar.generation.overrideTooltip", "This field was forced by Majoor Gen Info Override")
|
|
}, L(I(A)("sidebar.generation.override", "override")), 13, po)) : P("", !0)], 8, fo), z("div", {
|
|
title: `${t.label}: ${t.value}`,
|
|
style: {
|
|
"font-size": "12px",
|
|
color: "var(--fg-color, rgba(255,255,255,0.95))",
|
|
"word-break": "break-word",
|
|
"white-space": "pre-wrap",
|
|
cursor: "pointer"
|
|
},
|
|
onClick: (e) => T(t.value, e.currentTarget)
|
|
}, L(t.value), 9, mo)], 64))), 128))])], 4))), 128)),
|
|
_.value.notesFields.length ? (F(), N("div", {
|
|
key: 9,
|
|
style: R(f("#4CAF50", { emphasis: !1 }))
|
|
}, [z("div", ho, L(I(A)("sidebar.generation.notes", "Notes")), 1), (F(!0), N(B, null, V(_.value.notesFields, (e) => (F(), N("div", {
|
|
key: e.label,
|
|
title: `${e.label}: ${e.value}`,
|
|
style: {
|
|
"font-size": "12px",
|
|
color: "var(--fg-color, rgba(255,255,255,0.9))",
|
|
"line-height": "1.5",
|
|
"white-space": "pre-wrap",
|
|
"word-break": "break-word",
|
|
cursor: "pointer"
|
|
},
|
|
onClick: (t) => T(e.value, t.currentTarget)
|
|
}, L(e.value), 9, go))), 128))], 4)) : P("", !0),
|
|
(F(!0), N(B, null, V(_.value.customInfoBlocks, (e) => (F(), N("div", {
|
|
key: `${e.title}-${e.content}`,
|
|
style: R(f(e.color, { emphasis: !1 }))
|
|
}, [z("div", { style: R({
|
|
fontSize: "11px",
|
|
fontWeight: "600",
|
|
color: e.color,
|
|
textTransform: "uppercase",
|
|
letterSpacing: "0.5px",
|
|
marginBottom: "8px"
|
|
}) }, L(e.title), 5), z("div", {
|
|
title: `${e.title}: ${e.content}`,
|
|
style: {
|
|
"font-size": "12px",
|
|
color: "var(--fg-color, rgba(255,255,255,0.9))",
|
|
"line-height": "1.5",
|
|
"white-space": "pre-wrap",
|
|
"word-break": "break-word",
|
|
cursor: "pointer"
|
|
},
|
|
onClick: (t) => T(e.content, t.currentTarget)
|
|
}, L(e.content), 9, _o)], 4))), 128)),
|
|
_.value.ttsInstruction ? (F(), N("div", {
|
|
key: 10,
|
|
style: R(f("#26A69A", { emphasis: !1 }))
|
|
}, [z("div", vo, [z("span", null, L(I(A)("sidebar.generation.ttsInstruction", "TTS Instruction")), 1)]), z("div", {
|
|
title: I(A)("action.clickToCopy", "Click to copy"),
|
|
style: {
|
|
"font-size": "12px",
|
|
color: "var(--fg-color, rgba(255,255,255,0.9))",
|
|
"line-height": "1.5",
|
|
"white-space": "pre-wrap",
|
|
"word-break": "break-word",
|
|
cursor: "pointer"
|
|
},
|
|
onClick: t[2] ||= (e) => T(_.value.ttsInstruction, e.currentTarget)
|
|
}, L(_.value.ttsInstruction), 9, yo)], 4)) : P("", !0),
|
|
_.value.seed !== null && _.value.seed !== void 0 && _.value.seed !== "" ? (F(), N("div", {
|
|
key: 11,
|
|
style: R(p())
|
|
}, [z("div", bo, L(I(A)("sidebar.generation.seed", "SEED")), 1), z("div", {
|
|
title: I(A)("sidebar.generation.copySeedTooltip", "Click to copy seed: {seed}", { seed: _.value.seed }),
|
|
style: {
|
|
"font-size": "18px",
|
|
"font-weight": "700",
|
|
color: "#fff",
|
|
"font-family": "'Consolas', 'Monaco', monospace",
|
|
"letter-spacing": "1px",
|
|
cursor: "pointer",
|
|
padding: "4px 8px",
|
|
"border-radius": "4px",
|
|
transition: "background 0.2s"
|
|
},
|
|
onClick: t[3] ||= (e) => T(_.value.seed, e.currentTarget, "rgba(76, 175, 80, 0.4)")
|
|
}, L(_.value.seed), 9, xo)], 4)) : P("", !0),
|
|
_.value.inputFiles.length ? (F(), N("div", {
|
|
key: 12,
|
|
style: R(f("#4CAF50", {
|
|
emphasis: !0,
|
|
startAlpha: .16,
|
|
endAlpha: .1
|
|
}))
|
|
}, [z("div", {
|
|
title: I(A)("tooltip.generationInputs", "Input files used in generation"),
|
|
style: {
|
|
"font-size": "11px",
|
|
"font-weight": "600",
|
|
color: "#4CAF50",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.5px",
|
|
"margin-bottom": "8px"
|
|
}
|
|
}, L(I(A)("sidebar.generation.sourceFiles", "Source Files")), 9, So), z("div", Co, [(F(!0), N(B, null, V(_.value.inputFiles, (e) => (F(), Re(ma, {
|
|
key: e.id,
|
|
"input-file": e
|
|
}, null, 8, ["input-file"]))), 128))])], 4)) : P("", !0)
|
|
]));
|
|
};
|
|
}
|
|
}, To = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, Eo = /^[0-9a-f]{20,}$/i;
|
|
function Do(...e) {
|
|
for (let t of e) {
|
|
let e = String(t || "").trim();
|
|
if (e) return e;
|
|
}
|
|
return "";
|
|
}
|
|
function Oo(e) {
|
|
let t = String(e || "").trim();
|
|
return !!t && (To.test(t) || Eo.test(t));
|
|
}
|
|
function ko(e) {
|
|
return String(e?.type || e?.class_type || e?.comfyClass || e?.classType || "").trim();
|
|
}
|
|
function Ao(e) {
|
|
return Do(e?.properties?.subgraph_name, e?.title, e?.properties?.title, e?.properties?.name, e?.properties?.label, e?.name, e?.subgraph?.name, e?.subgraph_instance?.name);
|
|
}
|
|
function jo(e) {
|
|
let t = ko(e), n = Ao(e);
|
|
return n && (!t || Oo(t) || n !== t) ? n : t && !Oo(t) ? t : n || (t ? "Subgraph" : String(e?.id || "Node").trim() || "Node");
|
|
}
|
|
function Mo(e) {
|
|
let t = ko(e);
|
|
return t && !Oo(t) ? t : t ? "Subgraph" : "Node";
|
|
}
|
|
//#endregion
|
|
//#region ui/components/sidebar/utils/minimap.ts
|
|
var No = 6, Po = 1, Fo = 8, Io = 74, Lo = 42, Ro = [
|
|
["sampler", "#8e5cff"],
|
|
["ksampler", "#8e5cff"],
|
|
["loader", "#4f8cff"],
|
|
["load", "#4f8cff"],
|
|
["clip", "#d4a634"],
|
|
["vae", "#36a7c9"],
|
|
["latent", "#47a56d"],
|
|
["image", "#8fb04a"],
|
|
["video", "#c47b3d"],
|
|
["mask", "#999999"],
|
|
["conditioning", "#b56bd8"],
|
|
["controlnet", "#c44f76"],
|
|
["lora", "#d27a45"],
|
|
["save", "#4aa37c"],
|
|
["preview", "#4aa37c"],
|
|
["api", "#3aa6a6"]
|
|
], zo = (e, t, n) => {
|
|
let r = Number(e);
|
|
return Number.isFinite(r) ? Math.max(t, Math.min(n, r)) : t;
|
|
}, Bo = (e, t = !1) => {
|
|
let n = String(e || "").toUpperCase();
|
|
return n.includes("IMAGE") ? "rgba(145,198,99,0.9)" : n.includes("LATENT") ? "rgba(89,178,118,0.9)" : n.includes("MODEL") ? "rgba(112,155,255,0.9)" : n.includes("CONDITIONING") ? "rgba(191,123,226,0.9)" : n.includes("CLIP") ? "rgba(220,178,77,0.9)" : n.includes("VAE") ? "rgba(72,184,214,0.9)" : n.includes("MASK") ? "rgba(190,190,190,0.88)" : n.includes("STRING") || n.includes("TEXT") ? "rgba(230,230,230,0.86)" : n.includes("INT") || n.includes("FLOAT") || n.includes("NUMBER") ? "rgba(130,210,220,0.88)" : t ? "rgba(170,220,255,0.82)" : "rgba(255,255,255,0.72)";
|
|
}, Vo = (e, t, n) => {
|
|
let r = String(t || "").replace(/\s+/g, " ").trim(), i = Math.max(1, Number(n) || 1);
|
|
if (!r || e.measureText(r).width <= i) return r;
|
|
let a = r;
|
|
for (; a.length > 3 && e.measureText(`${a}...`).width > i;) a = a.slice(0, -1);
|
|
return a.length > 3 ? `${a}...` : r.slice(0, 3);
|
|
};
|
|
function Ho(e, t, n = null) {
|
|
if (!e) return;
|
|
let r = e.getContext?.("2d");
|
|
if (!r) return;
|
|
let i = {
|
|
nodeColors: !0,
|
|
showLinks: !0,
|
|
showGroups: !0,
|
|
renderBypassState: !0,
|
|
renderErrorState: !0,
|
|
showViewport: !0,
|
|
showNodeLabels: !1,
|
|
expandSubgraphs: !0,
|
|
...n && typeof n == "object" ? n : {}
|
|
}, a = i.expandSubgraphs === !1 ? t : Uo(t), o = Array.isArray(a?.nodes) ? a.nodes : [], s = Array.isArray(a?.groups) && a.groups || Array.isArray(a?.extra?.groups) && a.extra.groups || Array.isArray(a?.extra?.groupNodes) && a.extra.groupNodes || Array.isArray(a?.extra?.group_nodes) && a.extra.group_nodes || [], c = Array.isArray(a?.links) && a.links || Array.isArray(a?.extra?.links) && a.extra.links || [], l = Math.max(1, e.clientWidth || e.width || 1), u = Math.max(1, e.clientHeight || e.height || 1);
|
|
if ((!o || o.length === 0) && (!s || s.length === 0)) return r.clearRect(0, 0, l, u), null;
|
|
let d = (e, t) => {
|
|
if (!e || typeof e != "string") return `rgba(255,255,255,${t})`;
|
|
let n = e.trim();
|
|
if (!n) return `rgba(255,255,255,${t})`;
|
|
let r = n.match(/^rgba?\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)(?:\s*,\s*([0-9.]+))?\)\s*$/i);
|
|
if (r) {
|
|
let e = Number(r[1]), n = Number(r[2]), i = Number(r[3]);
|
|
if ([
|
|
e,
|
|
n,
|
|
i
|
|
].every((e) => Number.isFinite(e))) return `rgba(${e},${n},${i},${t})`;
|
|
}
|
|
let i = n.startsWith("#") ? n.slice(1) : "";
|
|
if (i.length === 3) {
|
|
let e = parseInt(i[0] + i[0], 16), n = parseInt(i[1] + i[1], 16), r = parseInt(i[2] + i[2], 16);
|
|
if ([
|
|
e,
|
|
n,
|
|
r
|
|
].every((e) => Number.isFinite(e))) return `rgba(${e},${n},${r},${t})`;
|
|
}
|
|
if (i.length === 6) {
|
|
let e = parseInt(i.slice(0, 2), 16), n = parseInt(i.slice(2, 4), 16), r = parseInt(i.slice(4, 6), 16);
|
|
if ([
|
|
e,
|
|
n,
|
|
r
|
|
].every((e) => Number.isFinite(e))) return `rgba(${e},${n},${r},${t})`;
|
|
}
|
|
return n;
|
|
}, f = (e) => {
|
|
let t = e?.bgcolor || e?.color || null;
|
|
if (t) return t;
|
|
let n = String(e?.category || e?.type || e?.comfyClass || e?.class_type || e?.title || "").toLowerCase();
|
|
for (let [e, t] of Ro) if (n.includes(e)) return t;
|
|
let r = 0;
|
|
for (let e = 0; e < n.length; e += 1) r = r * 31 + n.charCodeAt(e) | 0;
|
|
return `hsl(${Math.abs(r) % 360} 42% 42%)`;
|
|
}, p = (e) => {
|
|
let t = [], n = e?.inputs && typeof e.inputs == "object" && !Array.isArray(e.inputs) ? e.inputs : null;
|
|
if (n) {
|
|
for (let [e, r] of Object.entries(n)) if (!(Array.isArray(r) || r && typeof r == "object") && (t.push([e, r]), t.length >= 3)) return t;
|
|
}
|
|
let r = Array.isArray(e?.widgets_values) ? e.widgets_values : [], i = Array.isArray(e?.widgets) ? e.widgets : [], a = Array.isArray(e?.inputs) ? e.inputs : [], o = a.filter((e) => e?.widget === !0 || e?.widget && typeof e.widget == "object" || typeof e?.widget == "string" && e.widget.trim()), s = a.filter((e) => e?.link == null && Zo(e?.type)), c = (o.length ? o : s.length ? s : a).map((e) => String(e?.label || e?.localized_name || e?.name || e?.widget?.name || e?.widget?.label || "").trim());
|
|
return r.forEach((e, n) => {
|
|
let r = i[n]?.name || i[n]?.label || c[n] || `p${n + 1}`;
|
|
t.push([r, e]);
|
|
}), t.slice(0, 3);
|
|
}, m = [], h = /* @__PURE__ */ new Map(), g = (e) => {
|
|
if (Array.isArray(e) && e.length >= 2) return [Number(e[0]), Number(e[1])];
|
|
if (e && typeof e == "object") {
|
|
let t = e[0] ?? e[0] ?? e.x ?? e.left ?? null, n = e[1] ?? e[1] ?? e.y ?? e.top ?? null;
|
|
if (t !== null && n !== null) return [Number(t), Number(n)];
|
|
}
|
|
return null;
|
|
}, _ = (e) => {
|
|
if (Array.isArray(e) && e.length >= 2) return [Number(e[0]), Number(e[1])];
|
|
if (e && typeof e == "object") {
|
|
let t = e[0] ?? e[0] ?? e.w ?? e.width ?? null, n = e[1] ?? e[1] ?? e.h ?? e.height ?? null;
|
|
if (t !== null && n !== null) return [Number(t), Number(n)];
|
|
}
|
|
return null;
|
|
};
|
|
for (let e of o || []) {
|
|
let t = e?.id ?? e?.ID ?? e?.node_id ?? null, n = t == null ? null : String(t), r = g(e?.pos), o = _(e?.size);
|
|
if (!r || !o) continue;
|
|
let s = Number(r[0]), c = Number(r[1]), l = Math.max(1, Number(o[0])), u = Math.max(1, Number(o[1]));
|
|
if (!Number.isFinite(s) || !Number.isFinite(c) || !Number.isFinite(l) || !Number.isFinite(u)) continue;
|
|
let d = Number(e?.mode), v = d === 2 || d === 4, y = a?.extra?.errors || a?.extra?.node_errors || null, b = !!(y && typeof y == "object" && n && y[n] || e?.error || e?.errors || e?.flags?.error || e?.properties?.error), x = f(e), S = Array.isArray(e?.inputs) ? e.inputs : [], ee = Array.isArray(e?.outputs) ? e.outputs : [];
|
|
m.push({
|
|
kind: "node",
|
|
id: n,
|
|
x: s,
|
|
y: c,
|
|
w: l,
|
|
h: u,
|
|
fill: i.nodeColors ? x : null,
|
|
stroke: i.nodeColors ? e?.color || x : null,
|
|
bypassed: v,
|
|
errored: b,
|
|
type: String(e?.type || e?.comfyClass || e?.class_type || "").trim(),
|
|
rows: p(e),
|
|
inputs: S,
|
|
outputs: ee,
|
|
inputCount: S.length || (e?.inputs && typeof e.inputs == "object" ? Object.keys(e.inputs).length : 0),
|
|
outputCount: ee.length,
|
|
label: jo(e).replace(/\s+/g, " ").trim()
|
|
}), n && h.set(n, m[m.length - 1]);
|
|
}
|
|
if (i.showGroups) for (let e of s || []) {
|
|
let t = Array.isArray(e?.bounding) && e.bounding.length >= 4 ? e.bounding : null, n = t ? [Number(t[0]), Number(t[1])] : g(e?.pos), r = t ? [Number(t[2]), Number(t[3])] : _(e?.size);
|
|
if (!n || !r) continue;
|
|
let i = Number(n[0]), a = Number(n[1]), o = Math.max(1, Number(r[0])), s = Math.max(1, Number(r[1]));
|
|
!Number.isFinite(i) || !Number.isFinite(a) || !Number.isFinite(o) || !Number.isFinite(s) || m.push({
|
|
kind: "group",
|
|
x: i,
|
|
y: a,
|
|
w: o,
|
|
h: s,
|
|
fill: e?.color || e?.bgcolor || e?.borderColor || null,
|
|
stroke: e?.borderColor || e?.color || e?.bgcolor || null
|
|
});
|
|
}
|
|
if (!m.length) return r.clearRect(0, 0, l, u), null;
|
|
let v = m[0].x, y = m[0].y, b = m[0].x + m[0].w, x = m[0].y + m[0].h;
|
|
for (let e of m) v = Math.min(v, e.x), y = Math.min(y, e.y), b = Math.max(b, e.x + e.w), x = Math.max(x, e.y + e.h);
|
|
let S = Math.max(1, b - v), ee = Math.max(1, x - y), C = v + S / 2, te = y + ee / 2, w = i.view && typeof i.view == "object" ? i.view : Object.create(null), T = zo(w.zoom ?? 1, Po, Fo), ne = Math.max(1, S / T), re = Math.max(1, ee / T), ie = ne / 2, ae = re / 2, oe = ne >= S ? C : zo(w.centerX ?? C, v + ie, b - ie), E = re >= ee ? te : zo(w.centerY ?? te, y + ae, x - ae), se = oe - ie, ce = E - ae, D = No, le = Math.min((l - D * 2) / ne, (u - D * 2) / re), ue = w.hoveredNodeId !== null && w.hoveredNodeId !== void 0 ? String(w.hoveredNodeId) : null;
|
|
r.clearRect(0, 0, l, u), r.fillStyle = "rgba(0,0,0,0.22)", r.fillRect(0, 0, l, u);
|
|
let de = (e, t) => ({
|
|
x: D + (e - se) * le,
|
|
y: D + (t - ce) * le
|
|
}), fe = (e, t) => ({
|
|
x: zo(se + (Number(e) - D) / le, v, b),
|
|
y: zo(ce + (Number(t) - D) / le, y, x)
|
|
}), pe = (e) => ({
|
|
x: D + (e.x - se) * le,
|
|
y: D + (e.y - ce) * le,
|
|
w: Math.max(1, e.w * le),
|
|
h: Math.max(1, e.h * le)
|
|
}), me = (e) => Math.max(10, Math.min(24, Math.floor(Number(e) * .2))), he = (e, t, n) => {
|
|
let r = pe(e), i = me(r.h), a = n === "output" ? e.outputs : e.inputs, o = Math.max(1, Array.isArray(a) ? a.length : Number(e[`${n}Count`]) || 0), s = zo(t, 0, Math.max(0, o - 1));
|
|
return r.y + i + (r.h - i) * (s + 1) / (o + 1);
|
|
}, ge = (e) => Array.isArray(e) && e.length >= 5 ? {
|
|
originId: e[1],
|
|
originSlot: Number(e[2]) || 0,
|
|
targetId: e[3],
|
|
targetSlot: Number(e[4]) || 0,
|
|
type: e[5]
|
|
} : e && typeof e == "object" ? {
|
|
originId: e.origin_id ?? e.originId ?? e.from ?? null,
|
|
originSlot: Number(e.origin_slot ?? e.originSlot ?? e.fromSlot ?? 0) || 0,
|
|
targetId: e.target_id ?? e.targetId ?? e.to ?? null,
|
|
targetSlot: Number(e.target_slot ?? e.targetSlot ?? e.toSlot ?? 0) || 0,
|
|
type: e.type
|
|
} : null, _e = (e) => {
|
|
let t = String(e || "").toUpperCase();
|
|
return t.includes("IMAGE") ? "rgba(145,198,99,0.38)" : t.includes("LATENT") ? "rgba(89,178,118,0.38)" : t.includes("MODEL") ? "rgba(112,155,255,0.38)" : t.includes("CONDITIONING") ? "rgba(191,123,226,0.38)" : t.includes("CLIP") ? "rgba(220,178,77,0.38)" : t.includes("VAE") ? "rgba(72,184,214,0.38)" : t.includes("MASK") ? "rgba(190,190,190,0.36)" : "rgba(255,255,255,0.2)";
|
|
}, ve = () => {
|
|
if (i.showLinks && !(!c || c.length === 0)) {
|
|
r.save(), r.globalAlpha = 1, r.lineWidth = 1;
|
|
for (let e of c) {
|
|
let t = ge(e), n = t?.originId, i = t?.targetId;
|
|
if (n === null || i === null) continue;
|
|
let a = h.get(String(n)), o = h.get(String(i));
|
|
if (!a || !o) continue;
|
|
let s = pe(a), c = pe(o), l = {
|
|
x: s.x + s.w,
|
|
y: he(a, t?.originSlot ?? 0, "output")
|
|
}, u = {
|
|
x: c.x,
|
|
y: he(o, t?.targetSlot ?? 0, "input")
|
|
}, d = Math.max(12, Math.min(80, Math.abs(u.x - l.x) * .35));
|
|
r.strokeStyle = _e(t?.type), r.beginPath(), r.moveTo(l.x, l.y), r.bezierCurveTo(l.x + d, l.y, u.x - d, u.y, u.x, u.y), r.stroke();
|
|
}
|
|
r.restore();
|
|
}
|
|
}, ye = (e) => {
|
|
let { x: t, y: n, w: a, h: o } = pe(e), s = e.kind === "node", c = e.kind === "group", l = !!e.bypassed, u = !!e.errored, f = c ? .18 : l && i.renderBypassState ? .14 : .62, p = c ? .55 : l && i.renderBypassState ? .32 : .8, m = d(e.fill, f), h = d(e.stroke, p), g = s && i.showNodeLabels && a >= Io && o >= Lo, _ = Math.max(2, Math.min(g ? 7 : 8, Math.floor(Math.min(a, o) * .08))), v = s ? me(o) : 0;
|
|
if (r.save(), r.globalAlpha = 1, typeof m == "string" && (m.startsWith("#") || m.startsWith("rgb") || m.startsWith("hsl")) ? (r.fillStyle = m, r.globalAlpha = f) : (r.fillStyle = typeof m == "string" ? m : "rgba(82,88,96,0.72)", r.globalAlpha = f), typeof r.roundRect == "function" ? (r.beginPath(), r.roundRect(t, n, a, o, _), r.fill()) : r.fillRect(t, n, a, o), r.restore(), s && (r.save(), r.fillStyle = d(e.stroke || e.fill, l ? .34 : .9), typeof r.roundRect == "function" ? (r.beginPath(), r.roundRect(t, n, a, v, [
|
|
_,
|
|
_,
|
|
0,
|
|
0
|
|
]), r.fill()) : r.fillRect(t, n, a, v), r.restore()), r.globalAlpha = 1, r.strokeStyle = "rgba(255,255,255,0.22)", typeof h == "string" && (h.startsWith("#") || h.startsWith("rgb") || h.startsWith("hsl")) && (r.save(), r.globalAlpha = p, r.strokeStyle = h, r.restore()), s && l && i.renderBypassState) try {
|
|
r.setLineDash([3, 2]);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
else try {
|
|
r.setLineDash([]);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
if (r.lineWidth = 1, typeof r.roundRect == "function" ? (r.beginPath(), r.roundRect(t, n, a, o, _), r.stroke()) : r.strokeRect(t, n, a, o), s && a >= 24 && o >= 20) {
|
|
let n = Math.min(g ? 16 : 6, Number(e.inputCount) || 0), i = Math.min(g ? 16 : 6, Number(e.outputCount) || 0);
|
|
r.save(), r.strokeStyle = "rgba(0,0,0,0.48)", r.lineWidth = 1;
|
|
for (let i = 0; i < n; i += 1) {
|
|
let n = he(e, i, "input");
|
|
r.fillStyle = Bo(e.inputs?.[i]?.type, !1), r.beginPath(), r.arc(t, n, g ? 3 : 2.2, 0, Math.PI * 2), r.fill(), r.stroke();
|
|
}
|
|
for (let n = 0; n < i; n += 1) {
|
|
let i = he(e, n, "output");
|
|
r.fillStyle = Bo(e.outputs?.[n]?.type, !0), r.beginPath(), r.arc(t + a, i, g ? 3 : 2.2, 0, Math.PI * 2), r.fill(), r.stroke();
|
|
}
|
|
r.restore();
|
|
}
|
|
if (s && u && i.renderErrorState) {
|
|
try {
|
|
r.setLineDash([]);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
r.strokeStyle = "rgba(244,67,54,0.95)", r.lineWidth = 1.5, r.strokeRect(t - .5, n - .5, a + 1, o + 1);
|
|
}
|
|
if (s && ue && String(e.id || "") === ue) {
|
|
try {
|
|
r.setLineDash([]);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
r.strokeStyle = "rgba(255,224,130,0.96)", r.lineWidth = 2, r.strokeRect(t - 1, n - 1, a + 2, o + 2);
|
|
}
|
|
if (s && i.showNodeLabels && e.label && a >= 42 && o >= 12) {
|
|
let i = Math.max(8, Math.min(12, Math.floor(v * .58))), o = n + Math.max(8, Math.floor((v + i) / 2) - 1), s = Math.max(20, a - 6), c = e.label;
|
|
for (r.save(), r.beginPath(), r.rect(t + 2, n + 1, a - 4, v - 1), r.clip(), r.font = `600 ${i}px sans-serif`; c.length > 3 && r.measureText(`${c}...`).width > s;) c = c.slice(0, -1);
|
|
let l = c === e.label ? c : `${c}...`;
|
|
r.fillStyle = "rgba(255,255,255,0.92)", r.shadowColor = "rgba(0,0,0,0.5)", r.shadowBlur = 2, r.fillText(l, t + 3, o, s), r.restore();
|
|
}
|
|
if (s && i.showNodeLabels && Array.isArray(e.rows) && a >= 76 && o >= 46) {
|
|
let i = Math.max(7, Math.min(10, Math.floor(o * .12))), s = Math.max(9, i + 4), c = n + v + 4;
|
|
r.save(), r.font = `500 ${i}px sans-serif`, r.fillStyle = "rgba(255,255,255,0.62)";
|
|
for (let l = 0; l < e.rows.length; l += 1) {
|
|
let u = c + l * s;
|
|
if (u + s > n + o - 2) break;
|
|
let [d, f] = e.rows[l], p = `${String(d)}: ${String(f).replace(/\s+/g, " ").slice(0, 42)}`;
|
|
r.fillText(p, t + 5, u + i, Math.max(20, a - 10));
|
|
}
|
|
r.restore();
|
|
}
|
|
if (g && a >= 110) {
|
|
let n = Math.max(7, Math.min(9, Math.floor(o * .09)));
|
|
r.save(), r.font = `500 ${n}px sans-serif`, r.fillStyle = "rgba(255,255,255,0.5)";
|
|
let i = Math.max(24, a * .34);
|
|
for (let a = 0; a < Math.min(8, e.inputs?.length || 0); a += 1) {
|
|
let o = e.inputs[a], s = String(o?.label || o?.localized_name || o?.name || "").trim();
|
|
s && r.fillText(Vo(r, s, i), t + 7, he(e, a, "input") + n * .35, i);
|
|
}
|
|
for (let o = 0; o < Math.min(8, e.outputs?.length || 0); o += 1) {
|
|
let s = e.outputs[o], c = String(s?.label || s?.localized_name || s?.name || "").trim();
|
|
if (!c) continue;
|
|
let l = Vo(r, c, i);
|
|
r.fillText(l, t + a - 7 - Math.min(i, r.measureText(l).width), he(e, o, "output") + n * .35, i);
|
|
}
|
|
r.restore();
|
|
}
|
|
};
|
|
for (let e of m.filter((e) => e.kind === "group")) ye(e);
|
|
ve();
|
|
for (let e of m.filter((e) => e.kind === "node")) ye(e);
|
|
if (i.showViewport) try {
|
|
let e = je();
|
|
if (e) {
|
|
let t = de(e.x0, e.y0), n = de(e.x1, e.y1), i = Math.min(t.x, n.x), a = Math.min(t.y, n.y), o = Math.abs(n.x - t.x), s = Math.abs(n.y - t.y);
|
|
r.save(), r.globalAlpha = 1, r.strokeStyle = "rgba(255,255,255,0.9)", r.lineWidth = 1, r.strokeRect(i, a, o, s), r.restore();
|
|
}
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
return r.globalAlpha = 1, {
|
|
bounds: {
|
|
minX: v,
|
|
minY: y,
|
|
maxX: b,
|
|
maxY: x,
|
|
width: S,
|
|
height: ee
|
|
},
|
|
resolvedView: {
|
|
zoom: T,
|
|
centerX: oe,
|
|
centerY: E,
|
|
visibleW: ne,
|
|
visibleH: re,
|
|
viewMinX: se,
|
|
viewMinY: ce,
|
|
pad: D,
|
|
renderScale: le
|
|
},
|
|
canvasToWorld: fe,
|
|
worldToCanvas: de,
|
|
hitTestNode: (e, t) => {
|
|
let n = fe(e, t);
|
|
for (let e = m.length - 1; e >= 0; --e) {
|
|
let t = m[e];
|
|
if (t.kind === "node" && n.x >= t.x && n.x <= t.x + t.w && n.y >= t.y && n.y <= t.y + t.h) return t;
|
|
}
|
|
return null;
|
|
}
|
|
};
|
|
}
|
|
function Uo(e) {
|
|
if (!e || typeof e != "object") return e;
|
|
let t = Array.isArray(e.nodes) ? e.nodes.filter(Boolean) : [], n = Wo(e);
|
|
if (!t.length) return e;
|
|
let r = [], i = Array.isArray(e.links) ? [...e.links] : [], a = [...Array.isArray(e.groups) ? e.groups : [], ...Array.isArray(e.extra?.groups) ? e.extra.groups : []];
|
|
for (let e of t) {
|
|
r.push(e);
|
|
let t = Go(e, n);
|
|
if (!t || !Array.isArray(t.nodes) || !t.nodes.length) continue;
|
|
let o = qo(e, Uo(t));
|
|
r.push(...o.nodes), i.push(...o.links), o.group && a.push(o.group);
|
|
}
|
|
return {
|
|
...e,
|
|
nodes: r,
|
|
links: i,
|
|
groups: a,
|
|
extra: {
|
|
...e.extra || {},
|
|
groups: a
|
|
}
|
|
};
|
|
}
|
|
function Wo(e) {
|
|
let t = [
|
|
...Array.isArray(e?.definitions?.subgraphs) ? e.definitions.subgraphs : [],
|
|
...Array.isArray(e?.subgraphs) ? e.subgraphs : [],
|
|
...Array.isArray(e?.rootGraph?.subgraphs) ? e.rootGraph.subgraphs : []
|
|
], n = /* @__PURE__ */ new Map();
|
|
for (let e of t) for (let t of Ko(e)) t != null && n.set(String(t), e);
|
|
return n;
|
|
}
|
|
function Go(e, t) {
|
|
let n = [
|
|
e?.type,
|
|
e?.comfyClass,
|
|
e?.class_type,
|
|
e?.properties?.subgraph_id,
|
|
e?.properties?.subgraphId,
|
|
e?.subgraph?.id,
|
|
e?._subgraph?.id,
|
|
e?.subgraph_instance?.id
|
|
];
|
|
for (let e of n) {
|
|
if (e == null) continue;
|
|
let n = t.get(String(e));
|
|
if (n) return n;
|
|
}
|
|
return [
|
|
e?.subgraph,
|
|
e?._subgraph,
|
|
e?.subgraph?.graph,
|
|
e?.subgraph?.lgraph,
|
|
e?.properties?.subgraph,
|
|
e?.subgraph_instance,
|
|
e?.subgraph_instance?.graph,
|
|
e?.inner_graph,
|
|
e?.subgraph_graph
|
|
].find((e) => e && typeof e == "object" && Array.isArray(e.nodes)) || null;
|
|
}
|
|
function Ko(e) {
|
|
return [
|
|
e?.id,
|
|
e?.name,
|
|
e?.type,
|
|
e?.uuid,
|
|
e?.workflowId,
|
|
e?.workflow_id,
|
|
e?.properties?.subgraph_id,
|
|
e?.properties?.subgraphId
|
|
].filter((e) => e != null && String(e).trim());
|
|
}
|
|
function qo(e, t) {
|
|
let n = String(e?.id ?? e?.ID ?? ""), r = Yo(e?.pos) || [0, 0], i = Xo(e?.size) || [260, 180], a = t.nodes.filter(Boolean), o = Jo(a), s = Math.min(22, Math.max(8, i[0] * .08)), c = Math.min(34, Math.max(18, i[1] * .18)), l = Math.min(18, Math.max(8, i[1] * .08)), u = Math.max(40, i[0] - s * 2), d = Math.max(34, i[1] - c - l), f = Math.min(1, u / o.width, d / o.height), p = r[0] + s + (u - o.width * f) / 2, m = r[1] + c + (d - o.height * f) / 2, h = a.map((r) => {
|
|
let i = Yo(r?.pos) || [o.minX, o.minY], a = Xo(r?.size) || [140, 60];
|
|
return {
|
|
...r,
|
|
id: `${n}::${r?.id ?? r?.ID ?? ""}`,
|
|
pos: [p + (i[0] - o.minX) * f, m + (i[1] - o.minY) * f],
|
|
size: [Math.max(18, a[0] * f), Math.max(14, a[1] * f)],
|
|
_mjrSubgraphParentId: n,
|
|
_mjrSubgraphName: t?.name || e?.title || e?.type || "Subgraph"
|
|
};
|
|
}), g = (e) => `${n}::${e}`;
|
|
return {
|
|
nodes: h,
|
|
links: (Array.isArray(t.links) ? t.links : []).map((e) => {
|
|
if (Array.isArray(e) && e.length >= 4) {
|
|
let t = [...e];
|
|
return t[1] = g(t[1]), t[3] = g(t[3]), t;
|
|
}
|
|
return e && typeof e == "object" ? {
|
|
...e,
|
|
origin_id: e.origin_id == null ? e.origin_id : g(e.origin_id),
|
|
originId: e.originId == null ? e.originId : g(e.originId),
|
|
from: e.from == null ? e.from : g(e.from),
|
|
target_id: e.target_id == null ? e.target_id : g(e.target_id),
|
|
targetId: e.targetId == null ? e.targetId : g(e.targetId),
|
|
to: e.to == null ? e.to : g(e.to)
|
|
} : e;
|
|
}),
|
|
group: {
|
|
title: t?.name || e?.title || "Subgraph",
|
|
bounding: [
|
|
r[0] + 4,
|
|
r[1] + 18,
|
|
Math.max(1, i[0] - 8),
|
|
Math.max(1, i[1] - 22)
|
|
],
|
|
color: e?.color || e?.bgcolor || "#7f8ca3",
|
|
borderColor: "#9fb5d8"
|
|
}
|
|
};
|
|
}
|
|
function Jo(e) {
|
|
let t = Infinity, n = Infinity, r = -Infinity, i = -Infinity;
|
|
for (let a of e) {
|
|
let e = Yo(a?.pos);
|
|
if (!e) continue;
|
|
let o = Xo(a?.size) || [140, 60];
|
|
t = Math.min(t, e[0]), n = Math.min(n, e[1]), r = Math.max(r, e[0] + o[0]), i = Math.max(i, e[1] + o[1]);
|
|
}
|
|
return Number.isFinite(t) ? {
|
|
minX: t,
|
|
minY: n,
|
|
width: Math.max(1, r - t),
|
|
height: Math.max(1, i - n)
|
|
} : {
|
|
minX: 0,
|
|
minY: 0,
|
|
width: 1,
|
|
height: 1
|
|
};
|
|
}
|
|
function Yo(e) {
|
|
if (Array.isArray(e) && e.length >= 2) return [Number(e[0]), Number(e[1])];
|
|
if (e && typeof e == "object") {
|
|
let t = e[0] ?? e[0] ?? e.x ?? e.left ?? null, n = e[1] ?? e[1] ?? e.y ?? e.top ?? null;
|
|
if (t !== null && n !== null) return [Number(t), Number(n)];
|
|
}
|
|
return null;
|
|
}
|
|
function Xo(e) {
|
|
if (Array.isArray(e) && e.length >= 2) return [Number(e[0]), Number(e[1])];
|
|
if (e && typeof e == "object") {
|
|
let t = e[0] ?? e[0] ?? e.w ?? e.width ?? null, n = e[1] ?? e[1] ?? e.h ?? e.height ?? null;
|
|
if (t !== null && n !== null) return [Number(t), Number(n)];
|
|
}
|
|
return null;
|
|
}
|
|
function Zo(e) {
|
|
if (Array.isArray(e)) return !0;
|
|
let t = String(e || "").trim().toUpperCase();
|
|
return t === "INT" || t === "FLOAT" || t === "STRING" || t === "BOOLEAN" || t === "BOOL" || t === "COMBO" || t === "ENUM";
|
|
}
|
|
function Qo(e, t = null) {
|
|
if (!e || typeof e != "object") return null;
|
|
let n = {
|
|
maxNodes: 220,
|
|
...t && typeof t == "object" ? t : {}
|
|
}, r = Object.entries(e);
|
|
if (!r.length) return null;
|
|
let i = [], a = [], o = /* @__PURE__ */ new Map(), s = (e) => e == null ? null : String(e) || null, c = (e) => Array.isArray(e) && e.length === 2 && s(e[0]) != null && Number.isFinite(Number(e[1]));
|
|
for (let [e, t] of r.slice(0, n.maxNodes)) {
|
|
if (!t || typeof t != "object") continue;
|
|
let n = s(e);
|
|
if (!n) continue;
|
|
let r = String(t.class_type || t.type || t.classType || "").trim(), l = t.inputs && typeof t.inputs == "object" ? t.inputs : {}, u = {}, d = [];
|
|
for (let e of Object.values(l)) {
|
|
if (!c(e)) continue;
|
|
let t = s(e[0]);
|
|
t && (d.push(t), a.push([t, n]));
|
|
}
|
|
for (let [e, t] of Object.entries(l)) c(t) || (u[e] = t);
|
|
o.set(n, d);
|
|
let f = r.toLowerCase(), p = "#3a3a3a", m = "#6b6b6b";
|
|
f.includes("ksampler") || f.includes("sampler") ? (p = "#6a4b1f", m = "#b07a2c") : f.includes("cliptext") || f.includes("textencode") || f.includes("conditioning") ? (p = "#1f5f3a", m = "#2cb06c") : f.includes("checkpoint") || f.includes("loader") || f.includes("model") ? (p = "#243a6a", m = "#3f6fd6") : (f.includes("save") || f.includes("preview") || f.includes("video")) && (p = "#4a2a5f", m = "#8c4cd1"), i.push({
|
|
id: Number.isFinite(Number(n)) ? Number(n) : n,
|
|
type: r || "Node",
|
|
pos: [0, 0],
|
|
size: [180, 80],
|
|
bgcolor: p,
|
|
color: m,
|
|
title: String(t?._meta?.title || t?.title || "").trim() || void 0,
|
|
inputs: u,
|
|
outputs: []
|
|
});
|
|
}
|
|
if (!i.length) return null;
|
|
let l = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Set(), d = (e) => {
|
|
if (l.has(e)) return l.get(e);
|
|
if (u.has(e)) return 0;
|
|
u.add(e);
|
|
let t = 0, n = o.get(e) || [];
|
|
for (let e of n) t = Math.max(t, d(e) + 1);
|
|
return u.delete(e), l.set(e, t), t;
|
|
};
|
|
for (let e of i) d(String(e.id));
|
|
let f = /* @__PURE__ */ new Map();
|
|
for (let e of i) {
|
|
let t = l.get(String(e.id)) ?? 0;
|
|
f.has(t) || f.set(t, []), f.get(t).push(e);
|
|
}
|
|
let p = Array.from(f.keys()).sort((e, t) => e - t);
|
|
for (let e of p) {
|
|
let t = f.get(e) || [];
|
|
t.sort((e, t) => Number(e.id) - Number(t.id));
|
|
for (let n = 0; n < t.length; n++) t[n].pos = [e * 220, n * 110];
|
|
}
|
|
let m = 1;
|
|
return {
|
|
id: "synthetic",
|
|
nodes: i,
|
|
links: a.filter(([e, t]) => e !== t).slice(0, 4e3).map(([e, t]) => [
|
|
m++,
|
|
Number.isFinite(Number(e)) ? Number(e) : e,
|
|
0,
|
|
Number.isFinite(Number(t)) ? Number(t) : t,
|
|
0,
|
|
"LINK"
|
|
]),
|
|
extra: { synthetic: !0 }
|
|
};
|
|
}
|
|
//#endregion
|
|
//#region ui/vue/components/panel/sidebar/SidebarWorkflowSection.vue
|
|
var $o = {
|
|
key: 0,
|
|
class: "mjr-sidebar-section",
|
|
style: {
|
|
background: "var(--comfy-menu-bg, rgba(0,0,0,0.2))",
|
|
border: "1px solid var(--border-color, rgba(255,255,255,0.14))",
|
|
"border-radius": "8px",
|
|
padding: "12px",
|
|
"min-width": "300px"
|
|
}
|
|
}, es = { style: { "margin-bottom": "12px" } }, ts = { style: {
|
|
"font-size": "16px",
|
|
"font-weight": "800",
|
|
color: "rgba(255,255,255,0.94)",
|
|
"line-height": "1.25",
|
|
overflow: "hidden",
|
|
"text-overflow": "ellipsis"
|
|
} }, ns = ["title"], rs = { style: {
|
|
display: "flex",
|
|
"flex-wrap": "wrap",
|
|
gap: "8px",
|
|
"margin-bottom": "10px"
|
|
} }, is = { style: {
|
|
padding: "4px 9px",
|
|
"border-radius": "999px",
|
|
background: "rgba(33,150,243,0.14)",
|
|
border: "1px solid rgba(33,150,243,0.30)",
|
|
"font-size": "11px",
|
|
"font-weight": "700",
|
|
color: "#90CAF9",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.4px"
|
|
} }, as = {
|
|
key: 0,
|
|
style: {
|
|
padding: "4px 9px",
|
|
"border-radius": "999px",
|
|
background: "rgba(255,255,255,0.06)",
|
|
border: "1px solid rgba(255,255,255,0.12)",
|
|
"font-size": "11px",
|
|
"font-weight": "600",
|
|
color: "rgba(255,255,255,0.82)"
|
|
}
|
|
}, os = { style: {
|
|
display: "grid",
|
|
"grid-template-columns": "repeat(2, minmax(0, 1fr))",
|
|
gap: "8px",
|
|
"margin-bottom": "12px"
|
|
} }, ss = {
|
|
key: 0,
|
|
style: {
|
|
padding: "8px 10px",
|
|
"border-radius": "10px",
|
|
background: "rgba(255,255,255,0.04)",
|
|
border: "1px solid rgba(255,255,255,0.10)"
|
|
}
|
|
}, cs = { style: {
|
|
"font-size": "13px",
|
|
"font-weight": "750",
|
|
color: "rgba(255,255,255,0.92)",
|
|
"margin-top": "3px"
|
|
} }, ls = {
|
|
key: 1,
|
|
style: {
|
|
padding: "8px 10px",
|
|
"border-radius": "10px",
|
|
background: "rgba(255,255,255,0.04)",
|
|
border: "1px solid rgba(255,255,255,0.10)"
|
|
}
|
|
}, us = { style: {
|
|
"font-size": "13px",
|
|
"font-weight": "750",
|
|
color: "rgba(255,255,255,0.92)",
|
|
"margin-top": "3px"
|
|
} }, ds = {
|
|
key: 2,
|
|
style: {
|
|
padding: "8px 10px",
|
|
"border-radius": "10px",
|
|
background: "rgba(255,255,255,0.04)",
|
|
border: "1px solid rgba(255,255,255,0.10)"
|
|
}
|
|
}, fs = { style: {
|
|
"font-size": "13px",
|
|
"font-weight": "750",
|
|
color: "rgba(255,255,255,0.92)",
|
|
"margin-top": "3px"
|
|
} }, ps = {
|
|
key: 3,
|
|
style: {
|
|
padding: "8px 10px",
|
|
"border-radius": "10px",
|
|
background: "rgba(255,255,255,0.04)",
|
|
border: "1px solid rgba(255,255,255,0.10)"
|
|
}
|
|
}, ms = { style: {
|
|
"font-size": "12px",
|
|
"font-weight": "650",
|
|
color: "rgba(255,255,255,0.84)",
|
|
"margin-top": "3px"
|
|
} }, hs = {
|
|
key: 0,
|
|
style: {
|
|
"font-size": "11px",
|
|
color: "rgba(255,255,255,0.54)",
|
|
"margin-top": "2px"
|
|
}
|
|
}, gs = {
|
|
key: 0,
|
|
style: {
|
|
"margin-bottom": "12px",
|
|
padding: "10px",
|
|
"border-radius": "10px",
|
|
background: "rgba(244,67,54,0.08)",
|
|
border: "1px solid rgba(244,67,54,0.25)"
|
|
}
|
|
}, _s = {
|
|
key: 1,
|
|
style: {
|
|
display: "flex",
|
|
"flex-wrap": "wrap",
|
|
gap: "5px"
|
|
}
|
|
}, vs = {
|
|
key: 1,
|
|
style: {
|
|
"margin-bottom": "12px",
|
|
padding: "10px",
|
|
"border-radius": "10px",
|
|
background: "rgba(255,255,255,0.035)",
|
|
border: "1px solid rgba(255,255,255,0.10)"
|
|
}
|
|
}, ys = {
|
|
key: 0,
|
|
style: {
|
|
"font-size": "12px",
|
|
"line-height": "1.45",
|
|
color: "rgba(255,255,255,0.82)",
|
|
"white-space": "pre-wrap"
|
|
}
|
|
}, bs = { style: {
|
|
display: "grid",
|
|
"grid-template-columns": "repeat(2, minmax(0, 1fr))",
|
|
gap: "8px",
|
|
"margin-bottom": "12px"
|
|
} }, xs = { style: {
|
|
display: "grid",
|
|
"grid-template-columns": "repeat(3, minmax(0, 1fr))",
|
|
gap: "8px",
|
|
"margin-bottom": "12px"
|
|
} }, Ss = { style: {
|
|
padding: "8px 10px",
|
|
"border-radius": "10px",
|
|
background: "rgba(255,255,255,0.04)",
|
|
border: "1px solid rgba(255,255,255,0.10)"
|
|
} }, Cs = { style: {
|
|
"font-size": "18px",
|
|
"font-weight": "700",
|
|
color: "rgba(255,255,255,0.94)",
|
|
"margin-top": "2px"
|
|
} }, ws = { style: {
|
|
padding: "8px 10px",
|
|
"border-radius": "10px",
|
|
background: "rgba(255,255,255,0.04)",
|
|
border: "1px solid rgba(255,255,255,0.10)"
|
|
} }, Ts = { style: {
|
|
"font-size": "18px",
|
|
"font-weight": "700",
|
|
color: "rgba(255,255,255,0.94)",
|
|
"margin-top": "2px"
|
|
} }, Es = { style: {
|
|
padding: "8px 10px",
|
|
"border-radius": "10px",
|
|
background: "rgba(255,255,255,0.04)",
|
|
border: "1px solid rgba(255,255,255,0.10)"
|
|
} }, Ds = { style: {
|
|
"font-size": "18px",
|
|
"font-weight": "700",
|
|
color: "rgba(255,255,255,0.94)",
|
|
"margin-top": "2px"
|
|
} }, Os = { style: {
|
|
"margin-bottom": "12px",
|
|
padding: "10px",
|
|
"border-radius": "10px",
|
|
background: "rgba(255,255,255,0.03)",
|
|
border: "1px solid rgba(255,255,255,0.10)"
|
|
} }, ks = { style: {
|
|
display: "flex",
|
|
"align-items": "center",
|
|
"justify-content": "space-between",
|
|
gap: "10px",
|
|
"margin-bottom": "8px"
|
|
} }, As = { style: {
|
|
"font-size": "12px",
|
|
color: "rgba(255,255,255,0.8)",
|
|
"margin-top": "2px"
|
|
} }, js = {
|
|
key: 0,
|
|
style: {
|
|
display: "flex",
|
|
"flex-wrap": "wrap",
|
|
gap: "4px",
|
|
"justify-content": "flex-end"
|
|
}
|
|
}, Ms = { style: {
|
|
display: "flex",
|
|
gap: "8px",
|
|
"align-items": "center"
|
|
} }, Ns = ["placeholder"], Ps = {
|
|
key: 2,
|
|
class: "mjr-workflow-tree-wrap"
|
|
}, Fs = { class: "mjr-workflow-tree-node" }, Is = { class: "mjr-workflow-tree-node-name" }, Ls = {
|
|
key: 0,
|
|
class: "mjr-workflow-tree-node-type"
|
|
}, Rs = { class: "mjr-menu-item-hint" }, zs = {
|
|
key: 0,
|
|
class: "mjr-section-hint"
|
|
}, Bs = { style: {
|
|
display: "flex",
|
|
"align-items": "center",
|
|
"justify-content": "space-between",
|
|
gap: "10px",
|
|
"margin-top": "8px"
|
|
} }, Vs = { style: {
|
|
display: "flex",
|
|
"flex-wrap": "wrap",
|
|
gap: "6px",
|
|
"align-items": "center"
|
|
} }, Hs = {
|
|
key: 3,
|
|
style: {
|
|
display: "grid",
|
|
"grid-template-columns": "repeat(auto-fit, minmax(180px, 1fr))",
|
|
gap: "8px",
|
|
"align-items": "stretch",
|
|
"margin-top": "10px",
|
|
"margin-bottom": "10px"
|
|
}
|
|
}, Us = { style: {
|
|
display: "flex",
|
|
"flex-direction": "column",
|
|
gap: "2px",
|
|
"min-width": "0"
|
|
} }, Ws = { style: {
|
|
"font-size": "13px",
|
|
"font-weight": "600"
|
|
} }, Gs = { style: {
|
|
"font-size": "11px",
|
|
color: "rgba(255,255,255,0.58)"
|
|
} }, Ks = { style: {
|
|
display: "flex",
|
|
gap: "10px",
|
|
"align-items": "stretch",
|
|
"margin-top": "10px"
|
|
} }, qs = { style: {
|
|
display: "flex",
|
|
"justify-content": "space-between",
|
|
"align-items": "center",
|
|
gap: "10px",
|
|
"margin-top": "8px",
|
|
"font-size": "11px",
|
|
color: "rgba(255,255,255,0.58)"
|
|
} }, Js = ["open"], Ys = { style: {
|
|
background: "rgba(0,0,0,0.5)",
|
|
padding: "10px",
|
|
"border-radius": "6px",
|
|
"font-size": "11px",
|
|
overflow: "auto",
|
|
"max-height": "180px",
|
|
margin: "10px 0 0 0",
|
|
color: "#90CAF9",
|
|
"font-family": "'Consolas', 'Monaco', monospace"
|
|
} }, Xs = 1, Zs = 8, Qs = 250, $s = {
|
|
__name: "SidebarWorkflowSection",
|
|
props: { asset: {
|
|
type: Object,
|
|
required: !0
|
|
} },
|
|
setup(e) {
|
|
let t = e, n = Object.freeze({
|
|
nodeColors: !0,
|
|
showLinks: !0,
|
|
showGroups: !0,
|
|
renderBypassState: !0,
|
|
renderErrorState: !0,
|
|
showViewport: !0,
|
|
showNodeLabels: !1,
|
|
size: "comfortable"
|
|
}), r = Object.freeze({
|
|
zoom: 1,
|
|
centerX: null,
|
|
centerY: null,
|
|
hoveredNodeId: null
|
|
}), i = Object.freeze([
|
|
{
|
|
key: "compact",
|
|
label: "Compact",
|
|
height: 120
|
|
},
|
|
{
|
|
key: "comfortable",
|
|
label: "Comfort",
|
|
height: 160
|
|
},
|
|
{
|
|
key: "expanded",
|
|
label: "Expanded",
|
|
height: 220
|
|
}
|
|
]), a = j(null), o = j(""), s = j(!1), c = j(!1), l = j(null), d = j(!1), f = j(!1), p = j(ie()), m = j({ ...r }), h = j("crosshair"), g = j(""), _ = null, y = null, b = null;
|
|
function x(e, t, n) {
|
|
let r = Number(e);
|
|
return Number.isFinite(r) ? Math.max(t, Math.min(n, r)) : t;
|
|
}
|
|
function S(e) {
|
|
!e || typeof e != "object" || (m.value = {
|
|
...m.value,
|
|
zoom: x(e.zoom ?? m.value.zoom, Xs, Zs),
|
|
centerX: Number.isFinite(Number(e.centerX)) ? Number(e.centerX) : null,
|
|
centerY: Number.isFinite(Number(e.centerY)) ? Number(e.centerY) : null
|
|
});
|
|
}
|
|
function ee() {
|
|
m.value = { ...r }, g.value = "";
|
|
}
|
|
function C(e) {
|
|
let t = e?.metadata_raw ?? null;
|
|
if (!t) return null;
|
|
if (typeof t == "object") return t;
|
|
if (typeof t == "string") {
|
|
let e = t.trim();
|
|
if (!e) return null;
|
|
try {
|
|
let t = JSON.parse(e);
|
|
return t && typeof t == "object" ? t : null;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
function te(e) {
|
|
try {
|
|
let t = Object.entries(e || {});
|
|
if (!t.length) return !1;
|
|
let n = 0;
|
|
for (let [, e] of t.slice(0, 50)) if (!(!e || typeof e != "object") && (e.inputs && typeof e.inputs == "object" && (n += 1), n >= 2)) return !0;
|
|
} catch {
|
|
return !1;
|
|
}
|
|
return !1;
|
|
}
|
|
function w(e) {
|
|
let t = C(e), n = e?.workflow || e?.Workflow || e?.comfy_workflow || t?.workflow || t?.Workflow || t?.comfy_workflow || null;
|
|
if (!n) return null;
|
|
if (typeof n == "object") return n;
|
|
if (typeof n == "string") {
|
|
let e = n.trim();
|
|
if (!e) return null;
|
|
try {
|
|
return JSON.parse(e);
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
function ne(e) {
|
|
let t = C(e), n = e?.prompt || e?.Prompt || t?.prompt || t?.Prompt || null;
|
|
if (!n) return null;
|
|
if (typeof n == "object") return te(n) ? n : null;
|
|
if (typeof n == "string") {
|
|
let e = n.trim();
|
|
if (!e) return null;
|
|
try {
|
|
let t = JSON.parse(e);
|
|
return te(t) ? t : null;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
function ie() {
|
|
try {
|
|
let e = K?.()?.workflowMinimap;
|
|
if (e && typeof e == "object") return {
|
|
...n,
|
|
...e
|
|
};
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
try {
|
|
let e = localStorage?.getItem?.(T);
|
|
if (!e) return { ...n };
|
|
let t = JSON.parse(e);
|
|
if (!t || typeof t != "object") return { ...n };
|
|
let r = {
|
|
...n,
|
|
...t
|
|
};
|
|
try {
|
|
let e = K();
|
|
e.workflowMinimap = {
|
|
...e.workflowMinimap,
|
|
...r
|
|
}, q(e), localStorage?.removeItem?.(T);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
return r;
|
|
} catch {
|
|
return { ...n };
|
|
}
|
|
}
|
|
function oe(e) {
|
|
try {
|
|
let t = K();
|
|
t.workflowMinimap = {
|
|
...t.workflowMinimap,
|
|
...e
|
|
}, q(t);
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
}
|
|
let E = M(() => {
|
|
let e = w(t.asset) || w(l.value), n = ne(t.asset) || ne(l.value);
|
|
return !e && !n ? null : e || Qo(n);
|
|
}), se = M(() => String(t.asset?.filepath || t.asset?.path || t.asset?.file_info?.filepath || "").trim()), ce = M(() => String(t.asset?.display_name || t.asset?.name || t.asset?.filename || t.asset?.title || "Workflow").trim()), D = M(() => String(t.asset?.task || t.asset?.workflow_task || "").trim()), le = M(() => String(t.asset?.model_family || t.asset?.workflow_model_family || "").trim()), ue = M(() => String(t.asset?.provider || t.asset?.workflow_provider || "").trim()), fe = M(() => String(t.asset?.runs_on || t.asset?.runsOn || "").trim().toLowerCase()), pe = M(() => {
|
|
let e = fe.value, t = ue.value;
|
|
return e === "api" && t ? `API · ${t}` : e ? t && t.toLowerCase() !== e ? `${e} · ${t}` : e : t;
|
|
}), me = M(() => String(t.asset?.notes || "").trim()), ge = M(() => [
|
|
t.asset?.detected_task ? `detected: ${t.asset.detected_task}` : "",
|
|
t.asset?.detected_model_family ? t.asset.detected_model_family : "",
|
|
t.asset?.detected_provider ? t.asset.detected_provider : ""
|
|
].filter(Boolean).join(" · ")), _e = M(() => xe(t.asset?.missing_nodes || t.asset?.missingNodes)), ve = M(() => xe(t.asset?.missing_models || t.asset?.missingModels)), ye = M(() => {
|
|
let e = Number(t.asset?.usage_count || t.asset?.usageCount || 0);
|
|
return !Number.isFinite(e) || e <= 0 ? "" : `${Math.floor(e)} use${e === 1 ? "" : "s"}`;
|
|
}), be = M(() => O(t.asset?.mtime || t.asset?.modified_at || t.asset?.updated_at));
|
|
function xe(e) {
|
|
if (Array.isArray(e)) return e.map((e) => String(e || "").trim()).filter(Boolean);
|
|
if (typeof e == "string") {
|
|
let t = e.trim();
|
|
if (!t) return [];
|
|
try {
|
|
let e = JSON.parse(t);
|
|
if (Array.isArray(e)) return xe(e);
|
|
} catch {
|
|
return t.split(/[,\n]/).map((e) => e.trim()).filter(Boolean);
|
|
}
|
|
}
|
|
return [];
|
|
}
|
|
function O(e) {
|
|
let t = Number(e);
|
|
if (!Number.isFinite(t) || t <= 0) return "";
|
|
let n = t > 1e10 ? t : t * 1e3;
|
|
try {
|
|
return new Date(n).toLocaleString();
|
|
} catch {
|
|
return "";
|
|
}
|
|
}
|
|
async function Se() {
|
|
if (E.value) return;
|
|
let e = se.value;
|
|
if (e && !c.value) {
|
|
c.value = !0;
|
|
try {
|
|
let t = await ae(e, { timeoutMs: 25e3 });
|
|
if (!t?.ok) return;
|
|
let n = t?.data?.workflow || t?.workflow || null, r = t?.data?.prompt || t?.prompt || null;
|
|
if (!n && !r) return;
|
|
l.value = {
|
|
workflow: n,
|
|
prompt: r
|
|
};
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
} finally {
|
|
c.value = !1;
|
|
}
|
|
}
|
|
}
|
|
let Ce = M(() => t.asset?.has_generation_data ? "Complete" : "Partial"), we = M(() => E.value ? JSON.stringify(E.value, null, 2) : ""), Te = M(() => String(t.asset?.category || t.asset?.subfolder || t.asset?.folder || "").trim().replace(/^\/+|\/+$/g, "")), Ee = M(() => Te.value ? Te.value.split(/[\\/]+/).filter(Boolean) : []);
|
|
function De(e, t) {
|
|
let n = e?.id ?? e?.key ?? t + 1;
|
|
return String(e?.title || e?._meta?.title || e?.type || e?.class_type || e?.name || `Node ${n}`);
|
|
}
|
|
function k(e) {
|
|
return String(e?.type || e?.class_type || e?.name || "").trim();
|
|
}
|
|
function Oe() {
|
|
o.value = Te.value;
|
|
}
|
|
async function ke() {
|
|
let e = String(t.asset?.filepath || t.asset?.path || t.asset?.file_info?.filepath || "").trim();
|
|
if (!e) {
|
|
v(A("toast.workflowMissingPath", "Workflow file path is missing."), "error");
|
|
return;
|
|
}
|
|
let n = String(o.value || "").trim();
|
|
if (n !== Te.value) {
|
|
s.value = !0;
|
|
try {
|
|
let t = await u({
|
|
filepath: e,
|
|
category: n
|
|
}, { timeoutMs: 3e4 });
|
|
if (!t?.ok) {
|
|
v(t?.error || A("toast.workflowMoveFailed", "Failed to move workflow."), "error");
|
|
return;
|
|
}
|
|
o.value = String(t?.data?.workflow?.category || n || "").trim(), v(A("toast.workflowCategoryUpdated", "Workflow category updated"), "success", 1800);
|
|
} catch {
|
|
v(A("toast.workflowMoveFailed", "Failed to move workflow."), "error");
|
|
} finally {
|
|
s.value = !1;
|
|
}
|
|
}
|
|
}
|
|
async function je() {
|
|
let e = se.value;
|
|
if (!e) {
|
|
v(A("toast.workflowMissingPath", "Workflow file path is missing."), "error");
|
|
return;
|
|
}
|
|
let n = await re({
|
|
filepath: e,
|
|
limit: 12
|
|
}, { timeoutMs: 15e3 });
|
|
if (!n?.ok) {
|
|
v(n?.error || A("toast.workflowLoadFailed", "Failed to load workflow."), "error");
|
|
return;
|
|
}
|
|
let r = Array.isArray(n.data) ? n.data : [];
|
|
if (!r.length) {
|
|
v(A("toast.workflowThumbnailNoCandidates", "No linked outputs are available for this workflow yet."), "warning", 2600);
|
|
return;
|
|
}
|
|
let i = await xi({
|
|
title: A("ctx.setWorkflowThumbnail", "Set workflow thumbnail"),
|
|
workflow: t.asset,
|
|
items: r
|
|
});
|
|
if (!i?.filepath) return;
|
|
let a = await he({
|
|
filepath: e,
|
|
source_filepath: i.filepath
|
|
}, { timeoutMs: 3e4 });
|
|
if (!a?.ok) {
|
|
v(a?.error || A("toast.workflowSaveFailed", "Failed to save workflow."), "error");
|
|
return;
|
|
}
|
|
v(A("toast.workflowUpdated", "Workflow updated"), "success", 1800), window?.dispatchEvent?.(new CustomEvent("mjr:reload-grid", { detail: { reason: "workflow-thumbnail-sidebar" } }));
|
|
}
|
|
async function Le() {
|
|
if (await Se(), !E.value) {
|
|
v(A("toast.workflowLoadFailed", "Failed to load workflow."), "error");
|
|
return;
|
|
}
|
|
try {
|
|
await de.openAssets({
|
|
assets: [{
|
|
...t.asset,
|
|
workflow: E.value,
|
|
Workflow: E.value
|
|
}],
|
|
index: 0,
|
|
mode: "graph"
|
|
});
|
|
} catch (e) {
|
|
console.debug?.(e), v(A("toast.workflowLoadFailed", "Failed to load workflow."), "error");
|
|
}
|
|
}
|
|
let Ve = M(() => (Array.isArray(E.value?.nodes) ? E.value.nodes : []).slice(0, Qs).map((e, t) => {
|
|
let n = e?.id ?? e?.key ?? t + 1, r = k(e);
|
|
return {
|
|
key: String(n),
|
|
label: De(e, t),
|
|
icon: "pi pi-circle-fill",
|
|
data: {
|
|
id: n,
|
|
type: r
|
|
}
|
|
};
|
|
})), He = M(() => Math.max(0, Number(Ue.value.nodes || 0) - Ve.value.length)), Ue = M(() => {
|
|
let e = E.value;
|
|
return e ? {
|
|
nodes: Array.isArray(e?.nodes) ? e.nodes.length : 0,
|
|
links: Array.isArray(e?.links) && e.links.length || Array.isArray(e?.extra?.links) && e.extra.links.length || 0,
|
|
groups: Array.isArray(e?.groups) && e.groups.length || Array.isArray(e?.extra?.groups) && e.extra.groups.length || Array.isArray(e?.extra?.groupNodes) && e.extra.groupNodes.length || Array.isArray(e?.extra?.group_nodes) && e.extra.group_nodes.length || 0,
|
|
source: e?.extra?.synthetic ? "Synthetic" : "Embedded"
|
|
} : {
|
|
nodes: 0,
|
|
links: 0,
|
|
groups: 0,
|
|
source: ""
|
|
};
|
|
}), We = M(() => {
|
|
let e = String(p.value?.size || "comfortable");
|
|
return i.find((t) => t.key === e) || i[1];
|
|
}), Ge = M(() => `${We.value.height}px`), Ke = M(() => [
|
|
{
|
|
key: "showNodeLabels",
|
|
label: "Node Labels",
|
|
iconClass: "pi pi-tag"
|
|
},
|
|
{
|
|
key: "nodeColors",
|
|
label: "Node Colors",
|
|
iconClass: "pi pi-palette"
|
|
},
|
|
{
|
|
key: "showLinks",
|
|
label: "Show Links",
|
|
iconClass: "pi pi-share-alt"
|
|
},
|
|
{
|
|
key: "showGroups",
|
|
label: "Show Frames/Groups",
|
|
iconClass: "pi pi-th-large"
|
|
},
|
|
{
|
|
key: "renderBypassState",
|
|
label: "Render Bypass State",
|
|
iconClass: "pi pi-ban"
|
|
},
|
|
{
|
|
key: "renderErrorState",
|
|
label: "Render Error State",
|
|
iconClass: "pi pi-exclamation-triangle"
|
|
},
|
|
{
|
|
key: "showViewport",
|
|
label: "Show Viewport",
|
|
iconClass: "pi pi-window-maximize"
|
|
}
|
|
]);
|
|
function qe() {
|
|
let e = a.value, t = E.value;
|
|
if (!e || !t) return;
|
|
let n = Math.max(1, e.clientWidth || 320), r = Math.max(1, e.clientHeight || 120), i = Math.max(1, Math.min(2, window.devicePixelRatio || 1));
|
|
e.width = Math.floor(n * i), e.height = Math.floor(r * i);
|
|
let o = e.getContext("2d");
|
|
o && o.setTransform(i, 0, 0, i, 0, 0), y = Ho(e, t, {
|
|
...p.value,
|
|
view: m.value
|
|
}) || null, S(y?.resolvedView);
|
|
}
|
|
function Je(e) {
|
|
Ae(e);
|
|
}
|
|
function Xe(e) {
|
|
let t = a.value;
|
|
if (!t) return null;
|
|
let n = t.getBoundingClientRect?.();
|
|
return n ? {
|
|
x: Number(e?.clientX) - n.left,
|
|
y: Number(e?.clientY) - n.top
|
|
} : null;
|
|
}
|
|
function Ze(e) {
|
|
let t = Xe(e);
|
|
return !t || !y?.canvasToWorld ? null : {
|
|
local: t,
|
|
world: y.canvasToWorld(t.x, t.y)
|
|
};
|
|
}
|
|
function Qe(e) {
|
|
let t = Xe(e), n = t && y?.hitTestNode ? y.hitTestNode(t.x, t.y) : null, r = n?.id !== null && n?.id !== void 0 ? String(n.id) : null, i = m.value.hoveredNodeId !== null && m.value.hoveredNodeId !== void 0 ? String(m.value.hoveredNodeId) : null;
|
|
g.value = n?.label || "", r !== i && (m.value = {
|
|
...m.value,
|
|
hoveredNodeId: r
|
|
}, qe());
|
|
}
|
|
function $e(e) {
|
|
e && (Je(e), m.value = {
|
|
...m.value,
|
|
centerX: Number(e.x),
|
|
centerY: Number(e.y)
|
|
}, qe());
|
|
}
|
|
function tt(e) {
|
|
if (Number(e?.button ?? 0) !== 0) return;
|
|
let t = Ze(e);
|
|
t && (b = e.pointerId ?? 1, h.value = "grabbing", a.value?.setPointerCapture?.(b), $e(t.world), Qe(e), e.preventDefault?.(), e.stopPropagation?.());
|
|
}
|
|
function nt(e) {
|
|
if (b !== null && e.pointerId === b) {
|
|
let t = Ze(e);
|
|
t && $e(t.world), e.preventDefault?.(), e.stopPropagation?.();
|
|
return;
|
|
}
|
|
Qe(e);
|
|
}
|
|
function rt(e) {
|
|
b !== null && e?.pointerId === b && (a.value?.releasePointerCapture?.(b), b = null, h.value = "crosshair"), e?.type === "pointerleave" && (g.value = "", m.value.hoveredNodeId !== null && (m.value = {
|
|
...m.value,
|
|
hoveredNodeId: null
|
|
}, qe()));
|
|
}
|
|
function it(e) {
|
|
let t = Ze(e), n = y?.resolvedView;
|
|
if (!t || !n) return;
|
|
let r = x(Number(e?.deltaY) || 0, -240, 240), i = Math.exp(-r * .0025), a = x((Number(m.value.zoom) || 1) * i, Xs, Zs);
|
|
if (Math.abs(a - (Number(m.value.zoom) || 1)) < .001) {
|
|
e.preventDefault?.(), e.stopPropagation?.();
|
|
return;
|
|
}
|
|
let o = Math.max(1, Number(y?.bounds?.width || 1) / a), s = Math.max(1, Number(y?.bounds?.height || 1) / a), c = x((Number(t.world.x) - Number(n.viewMinX || 0)) / Math.max(1, Number(n.visibleW || 1)), 0, 1), l = x((Number(t.world.y) - Number(n.viewMinY || 0)) / Math.max(1, Number(n.visibleH || 1)), 0, 1);
|
|
m.value = {
|
|
...m.value,
|
|
zoom: a,
|
|
centerX: Number(t.world.x) + (.5 - c) * o,
|
|
centerY: Number(t.world.y) + (.5 - l) * s
|
|
}, qe(), Qe(e), e.preventDefault?.(), e.stopPropagation?.();
|
|
}
|
|
function at(e) {
|
|
let t = Ze(e);
|
|
ee(), t && Je(t.world), qe(), e.preventDefault?.(), e.stopPropagation?.();
|
|
}
|
|
function st(e) {
|
|
p.value = {
|
|
...p.value,
|
|
[e]: !p.value?.[e]
|
|
}, oe(p.value);
|
|
}
|
|
function ct(e) {
|
|
i.some((t) => t.key === e) && (p.value = {
|
|
...p.value,
|
|
size: e
|
|
}, oe(p.value));
|
|
}
|
|
return Me(() => {
|
|
a.value && typeof ResizeObserver == "function" && (_ = new ResizeObserver(() => qe()), _.observe(a.value)), Oe(), Se(), qe();
|
|
}), Pe(E, () => {
|
|
ee(), qe();
|
|
}, { flush: "post" }), Pe(se, () => {
|
|
l.value = null, Se();
|
|
}, { immediate: !0 }), Pe(Te, () => {
|
|
Oe();
|
|
}), Pe(p, () => {
|
|
qe();
|
|
}, {
|
|
deep: !0,
|
|
flush: "post"
|
|
}), Pe(d, () => {
|
|
qe();
|
|
}, { flush: "post" }), Ie(() => {
|
|
try {
|
|
_?.disconnect?.();
|
|
} catch (e) {
|
|
console.debug?.(e);
|
|
}
|
|
_ = null, b = null;
|
|
}), (e, t) => {
|
|
let n = ze("MButton"), r = ze("MTree");
|
|
return E.value ? (F(), N("div", $o, [
|
|
t[17] ||= z("div", { style: {
|
|
"font-size": "13px",
|
|
"font-weight": "600",
|
|
color: "var(--fg-color, #eaeaea)",
|
|
"margin-bottom": "12px",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.5px"
|
|
} }, " ComfyUI Workflow ", -1),
|
|
z("div", es, [z("div", ts, L(ce.value), 1), se.value ? (F(), N("div", {
|
|
key: 0,
|
|
style: {
|
|
"font-size": "11px",
|
|
color: "rgba(255,255,255,0.48)",
|
|
"margin-top": "4px",
|
|
overflow: "hidden",
|
|
"text-overflow": "ellipsis",
|
|
"white-space": "nowrap"
|
|
},
|
|
title: se.value
|
|
}, L(se.value), 9, ns)) : P("", !0)]),
|
|
z("div", rs, [z("div", is, L(Ce.value), 1), Ue.value.source ? (F(), N("div", as, L(Ue.value.source), 1)) : P("", !0)]),
|
|
z("div", os, [
|
|
D.value ? (F(), N("div", ss, [t[3] ||= z("div", { style: {
|
|
"font-size": "10px",
|
|
"font-weight": "700",
|
|
color: "rgba(255,255,255,0.55)",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.4px"
|
|
} }, "Task", -1), z("div", cs, L(D.value), 1)])) : P("", !0),
|
|
le.value ? (F(), N("div", ls, [t[4] ||= z("div", { style: {
|
|
"font-size": "10px",
|
|
"font-weight": "700",
|
|
color: "rgba(255,255,255,0.55)",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.4px"
|
|
} }, "Model", -1), z("div", us, L(le.value), 1)])) : P("", !0),
|
|
pe.value ? (F(), N("div", ds, [t[5] ||= z("div", { style: {
|
|
"font-size": "10px",
|
|
"font-weight": "700",
|
|
color: "rgba(255,255,255,0.55)",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.4px"
|
|
} }, "Runs on", -1), z("div", fs, L(pe.value), 1)])) : P("", !0),
|
|
ye.value || be.value ? (F(), N("div", ps, [
|
|
t[6] ||= z("div", { style: {
|
|
"font-size": "10px",
|
|
"font-weight": "700",
|
|
color: "rgba(255,255,255,0.55)",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.4px"
|
|
} }, "Library", -1),
|
|
z("div", ms, L(ye.value || be.value), 1),
|
|
ye.value && be.value ? (F(), N("div", hs, L(be.value), 1)) : P("", !0)
|
|
])) : P("", !0)
|
|
]),
|
|
_e.value.length || ve.value.length ? (F(), N("div", gs, [
|
|
t[7] ||= z("div", { style: {
|
|
"font-size": "10px",
|
|
"font-weight": "800",
|
|
color: "#ef9a9a",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.4px",
|
|
"margin-bottom": "6px"
|
|
} }, "Missing dependencies", -1),
|
|
_e.value.length ? (F(), N("div", {
|
|
key: 0,
|
|
style: R({
|
|
display: "flex",
|
|
flexWrap: "wrap",
|
|
gap: "5px",
|
|
marginBottom: ve.value.length ? "7px" : "0"
|
|
})
|
|
}, [(F(!0), N(B, null, V(_e.value, (e) => (F(), N("span", {
|
|
key: `node-${e}`,
|
|
style: {
|
|
padding: "3px 7px",
|
|
"border-radius": "999px",
|
|
background: "rgba(244,67,54,0.16)",
|
|
"font-size": "10px",
|
|
"font-weight": "700",
|
|
color: "#ffcdd2"
|
|
}
|
|
}, L(e), 1))), 128))], 4)) : P("", !0),
|
|
ve.value.length ? (F(), N("div", _s, [(F(!0), N(B, null, V(ve.value, (e) => (F(), N("span", {
|
|
key: `model-${e}`,
|
|
style: {
|
|
padding: "3px 7px",
|
|
"border-radius": "999px",
|
|
background: "rgba(255,152,0,0.16)",
|
|
"font-size": "10px",
|
|
"font-weight": "700",
|
|
color: "#ffe0b2"
|
|
}
|
|
}, L(e), 1))), 128))])) : P("", !0)
|
|
])) : P("", !0),
|
|
me.value || ge.value ? (F(), N("div", vs, [me.value ? (F(), N("div", ys, L(me.value), 1)) : P("", !0), ge.value ? (F(), N("div", {
|
|
key: 1,
|
|
style: R({
|
|
fontSize: "11px",
|
|
color: "rgba(255,255,255,0.48)",
|
|
marginTop: me.value ? "7px" : "0"
|
|
})
|
|
}, L(ge.value), 5)) : P("", !0)])) : P("", !0),
|
|
z("div", bs, [Ye(n, {
|
|
type: "button",
|
|
severity: "secondary",
|
|
text: "",
|
|
rounded: "",
|
|
style: {
|
|
height: "34px",
|
|
"border-radius": "9px",
|
|
border: "1px solid rgba(255,255,255,0.12)",
|
|
background: "rgba(33,150,243,0.14)",
|
|
color: "rgba(255,255,255,0.92)",
|
|
"font-size": "12px",
|
|
"font-weight": "750",
|
|
display: "inline-flex",
|
|
"align-items": "center",
|
|
"justify-content": "center",
|
|
gap: "7px"
|
|
},
|
|
onClick: je
|
|
}, {
|
|
default: Be(() => [t[8] ||= z("i", { class: "pi pi-image" }, null, -1), z("span", null, L(I(A)("ctx.setWorkflowThumbnail", "Set workflow thumbnail")), 1)]),
|
|
_: 1
|
|
}), Ye(n, {
|
|
type: "button",
|
|
severity: "secondary",
|
|
text: "",
|
|
rounded: "",
|
|
style: {
|
|
height: "34px",
|
|
"border-radius": "9px",
|
|
border: "1px solid rgba(255,255,255,0.12)",
|
|
background: "rgba(255,255,255,0.06)",
|
|
color: "rgba(255,255,255,0.92)",
|
|
"font-size": "12px",
|
|
"font-weight": "750",
|
|
display: "inline-flex",
|
|
"align-items": "center",
|
|
"justify-content": "center",
|
|
gap: "7px"
|
|
},
|
|
onClick: Le
|
|
}, {
|
|
default: Be(() => [t[9] ||= z("i", { class: "pi pi-search" }, null, -1), z("span", null, L(I(A)("ctx.inspect", "Inspect")), 1)]),
|
|
_: 1
|
|
})]),
|
|
z("div", xs, [
|
|
z("div", Ss, [t[10] ||= z("div", { style: {
|
|
"font-size": "10px",
|
|
"font-weight": "700",
|
|
color: "rgba(255,255,255,0.55)",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.4px"
|
|
} }, "Nodes", -1), z("div", Cs, L(Ue.value.nodes), 1)]),
|
|
z("div", ws, [t[11] ||= z("div", { style: {
|
|
"font-size": "10px",
|
|
"font-weight": "700",
|
|
color: "rgba(255,255,255,0.55)",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.4px"
|
|
} }, "Links", -1), z("div", Ts, L(Ue.value.links), 1)]),
|
|
z("div", Es, [t[12] ||= z("div", { style: {
|
|
"font-size": "10px",
|
|
"font-weight": "700",
|
|
color: "rgba(255,255,255,0.55)",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.4px"
|
|
} }, "Groups", -1), z("div", Ds, L(Ue.value.groups), 1)])
|
|
]),
|
|
z("div", Os, [z("div", ks, [z("div", null, [t[13] ||= z("div", { style: {
|
|
"font-size": "10px",
|
|
"font-weight": "700",
|
|
color: "rgba(255,255,255,0.55)",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.4px"
|
|
} }, "Category", -1), z("div", As, L(Te.value || "Root"), 1)]), Ee.value.length ? (F(), N("div", js, [(F(!0), N(B, null, V(Ee.value, (e) => (F(), N("span", {
|
|
key: e,
|
|
style: {
|
|
padding: "3px 7px",
|
|
"border-radius": "999px",
|
|
background: "rgba(33,150,243,0.12)",
|
|
border: "1px solid rgba(33,150,243,0.22)",
|
|
"font-size": "10px",
|
|
"font-weight": "700",
|
|
color: "#90CAF9",
|
|
"text-transform": "uppercase",
|
|
"letter-spacing": "0.3px"
|
|
}
|
|
}, L(e), 1))), 128))])) : P("", !0)]), z("div", Ms, [Ne(z("input", {
|
|
"onUpdate:modelValue": t[0] ||= (e) => o.value = e,
|
|
type: "text",
|
|
placeholder: I(A)("dialog.workflowCategory", "Workflow category"),
|
|
style: {
|
|
flex: "1",
|
|
"min-width": "0",
|
|
padding: "9px 10px",
|
|
"border-radius": "8px",
|
|
border: "1px solid rgba(255,255,255,0.12)",
|
|
background: "rgba(0,0,0,0.22)",
|
|
color: "rgba(255,255,255,0.92)",
|
|
"font-size": "12px"
|
|
}
|
|
}, null, 8, Ns), [[ot, o.value]]), Ye(n, {
|
|
type: "button",
|
|
severity: "secondary",
|
|
text: "",
|
|
rounded: "",
|
|
disabled: s.value,
|
|
style: R({
|
|
padding: "8px 12px",
|
|
borderRadius: "8px",
|
|
border: "1px solid rgba(255,255,255,0.12)",
|
|
background: s.value ? "rgba(255,255,255,0.06)" : "rgba(33,150,243,0.16)",
|
|
color: "rgba(255,255,255,0.92)",
|
|
cursor: s.value ? "wait" : "pointer",
|
|
fontSize: "12px",
|
|
fontWeight: "700",
|
|
whiteSpace: "nowrap"
|
|
}),
|
|
onClick: ke
|
|
}, {
|
|
default: Be(() => [Fe(L(s.value ? "Saving..." : "Move"), 1)]),
|
|
_: 1
|
|
}, 8, ["disabled", "style"])])]),
|
|
Ve.value.length ? (F(), N("div", Ps, [
|
|
t[14] ||= z("div", { class: "mjr-section-title" }, " Workflow Nodes ", -1),
|
|
Ye(r, {
|
|
value: Ve.value,
|
|
class: "mjr-workflow-tree",
|
|
"scroll-height": "180px",
|
|
pt: {
|
|
wrapper: { class: "mjr-workflow-tree-scroll" },
|
|
rootChildren: { class: "mjr-workflow-tree-list" },
|
|
nodeContent: { class: "mjr-workflow-tree-node-content" },
|
|
nodeToggleButton: { class: "mjr-workflow-tree-toggle" },
|
|
nodeIcon: { class: "mjr-workflow-tree-icon" },
|
|
nodeLabel: { class: "mjr-workflow-tree-label" }
|
|
}
|
|
}, {
|
|
default: Be(({ node: e }) => [z("span", Fs, [
|
|
z("span", Is, L(e.label), 1),
|
|
e.data?.type ? (F(), N("span", Ls, L(e.data.type), 1)) : P("", !0),
|
|
z("span", Rs, "#" + L(e.data?.id), 1)
|
|
])]),
|
|
_: 1
|
|
}, 8, ["value"]),
|
|
He.value ? (F(), N("div", zs, " +" + L(He.value) + " more nodes ", 1)) : P("", !0)
|
|
])) : P("", !0),
|
|
z("div", Bs, [z("div", Vs, [(F(!0), N(B, null, V(I(i), (e) => (F(), Re(n, {
|
|
key: e.key,
|
|
type: "button",
|
|
severity: "secondary",
|
|
text: "",
|
|
rounded: "",
|
|
title: `${e.label} minimap`,
|
|
style: R({
|
|
appearance: "none",
|
|
border: p.value.size === e.key ? "1px solid rgba(33,150,243,0.55)" : "1px solid rgba(255,255,255,0.12)",
|
|
borderRadius: "999px",
|
|
padding: "4px 10px",
|
|
background: p.value.size === e.key ? "rgba(33,150,243,0.18)" : "rgba(255,255,255,0.04)",
|
|
color: p.value.size === e.key ? "#90CAF9" : "rgba(255,255,255,0.78)",
|
|
fontSize: "11px",
|
|
fontWeight: p.value.size === e.key ? "700" : "600",
|
|
cursor: "pointer"
|
|
}),
|
|
onClick: (t) => ct(e.key)
|
|
}, {
|
|
default: Be(() => [Fe(L(e.label), 1)]),
|
|
_: 2
|
|
}, 1032, [
|
|
"title",
|
|
"style",
|
|
"onClick"
|
|
]))), 128))]), Ye(n, {
|
|
type: "button",
|
|
class: "mjr-btn mjr-icon-btn",
|
|
severity: "secondary",
|
|
text: "",
|
|
rounded: "",
|
|
title: I(A)("tooltip.minimapSettings", "Minimap settings"),
|
|
style: {
|
|
width: "28px",
|
|
height: "28px",
|
|
"border-radius": "8px",
|
|
display: "inline-flex",
|
|
"align-items": "center",
|
|
"justify-content": "center",
|
|
border: "1px solid var(--mjr-border, rgba(255,255,255,0.12))",
|
|
background: "rgba(255,255,255,0.06)",
|
|
color: "rgba(255,255,255,0.9)",
|
|
cursor: "pointer"
|
|
},
|
|
onClick: t[1] ||= (e) => d.value = !d.value
|
|
}, {
|
|
default: Be(() => [...t[15] ||= [z("i", { class: "pi pi-sliders-h" }, null, -1)]]),
|
|
_: 1
|
|
}, 8, ["title"])]),
|
|
d.value ? (F(), N("div", Hs, [(F(!0), N(B, null, V(Ke.value, (e) => (F(), Re(n, {
|
|
key: e.key,
|
|
type: "button",
|
|
severity: "secondary",
|
|
text: "",
|
|
style: R({
|
|
display: "flex",
|
|
alignItems: "center",
|
|
gap: "10px",
|
|
padding: "9px 10px",
|
|
borderRadius: "10px",
|
|
border: p.value?.[e.key] ? "1px solid rgba(76,175,80,0.40)" : "1px solid rgba(255,255,255,0.12)",
|
|
background: p.value?.[e.key] ? "rgba(76,175,80,0.10)" : "rgba(255,255,255,0.04)",
|
|
cursor: "pointer",
|
|
color: "rgba(255,255,255,0.92)",
|
|
textAlign: "left"
|
|
}),
|
|
onClick: (t) => st(e.key)
|
|
}, {
|
|
default: Be(() => [
|
|
z("span", { style: R({
|
|
width: "22px",
|
|
height: "22px",
|
|
borderRadius: "6px",
|
|
display: "inline-flex",
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
background: p.value?.[e.key] ? "rgba(76,175,80,0.95)" : "rgba(255,255,255,0.08)",
|
|
border: p.value?.[e.key] ? "1px solid rgba(76,175,80,0.35)" : "1px solid rgba(255,255,255,0.12)",
|
|
flex: "0 0 auto"
|
|
}) }, [z("i", {
|
|
class: "pi pi-check",
|
|
style: R({
|
|
fontSize: "12px",
|
|
opacity: p.value?.[e.key] ? "1" : "0"
|
|
})
|
|
}, null, 4)], 4),
|
|
z("i", {
|
|
class: et(e.iconClass),
|
|
style: {
|
|
"font-size": "18px",
|
|
opacity: "0.9",
|
|
width: "18px"
|
|
}
|
|
}, null, 2),
|
|
z("div", Us, [z("div", Ws, L(e.label), 1), z("div", Gs, L(p.value?.[e.key] ? "On" : "Off"), 1)])
|
|
]),
|
|
_: 2
|
|
}, 1032, ["style", "onClick"]))), 128))])) : P("", !0),
|
|
z("div", Ks, [z("canvas", {
|
|
ref_key: "canvasRef",
|
|
ref: a,
|
|
style: R({
|
|
width: "100%",
|
|
height: Ge.value,
|
|
cursor: h.value,
|
|
touchAction: "none",
|
|
borderRadius: "10px",
|
|
marginTop: "0",
|
|
background: "linear-gradient(180deg, rgba(7, 12, 18, 0.95) 0%, rgba(10, 16, 24, 0.92) 100%)",
|
|
border: "1px solid var(--mjr-border, rgba(255,255,255,0.12))",
|
|
boxShadow: "inset 0 0 0 1px rgba(255,255,255,0.03)"
|
|
}),
|
|
onPointerdown: tt,
|
|
onPointermove: nt,
|
|
onPointerup: rt,
|
|
onPointercancel: rt,
|
|
onPointerleave: rt,
|
|
onWheel: it,
|
|
onDblclick: at
|
|
}, null, 36)]),
|
|
z("div", qs, [z("span", null, L(g.value || "Click/drag to navigate | wheel to zoom"), 1), z("span", null, L(Math.round((m.value.zoom || 1) * 100)) + "% | " + L(We.value.label), 1)]),
|
|
z("details", {
|
|
open: f.value,
|
|
style: { "margin-top": "10px" },
|
|
onToggle: t[2] ||= (e) => f.value = e.target.open
|
|
}, [t[16] ||= z("summary", { style: {
|
|
cursor: "pointer",
|
|
color: "var(--mjr-muted, rgba(255,255,255,0.65))",
|
|
"font-size": "12px",
|
|
"user-select": "none"
|
|
} }, " Show raw JSON ", -1), z("pre", Ys, L(we.value), 1)], 40, Js)
|
|
])) : P("", !0);
|
|
};
|
|
}
|
|
};
|
|
//#endregion
|
|
export { li as A, Kr as B, _i as C, ri as D, pi as E, Xr as F, vr as G, kr as H, qr as I, K as J, cn as K, Ar as L, si as M, oi as N, Yr as O, ci as P, _t as Q, Lr as R, gi as S, mi as T, Or as U, Wr as V, yr as W, Ot as X, q as Y, kt as Z, xi as _, ko as a, yi as b, ca as c, Fi as d, Pi as f, Si as g, ji as h, jo as i, ni as j, ii as k, Bi as l, Ai as m, Ho as n, Mo as o, Ti as p, J as q, Qo as r, wo as s, $s as t, Ni as u, bi as v, ui as w, hi as x, Z as y, Ir as z };
|