import { RgthreeDialog } from "../../rgthree/common/dialog.js"; import { createElement as $el, empty, appendChildren, getClosestOrSelf, queryOne, query, setAttributes, } from "../../rgthree/common/utils_dom.js"; import { logoCivitai, link, pencilColored, diskColored, dotdotdot, } from "../../rgthree/common/media/svgs.js"; import { LORA_INFO_SERVICE } from "../../rgthree/common/model_info_service.js"; import { rgthree } from "./rgthree.js"; import { MenuButton } from "../../rgthree/common/menu.js"; import { generateId, injectCss } from "../../rgthree/common/shared_utils.js"; class RgthreeInfoDialog extends RgthreeDialog { constructor(file, type = "lora") { const dialogOptions = { class: "rgthree-info-dialog", title: `

Loading...

`, content: "
Loading..
", onBeforeClose: () => { return true; }, }; super(dialogOptions); this.modifiedModelData = false; this.modelInfo = null; this.init(file); } async init(file) { var _a, _b; const cssPromise = injectCss("rgthree/common/css/dialog_model_info.css"); this.modelInfo = await this.getModelInfo(file); await cssPromise; this.setContent(this.getInfoContent()); this.setTitle(((_a = this.modelInfo) === null || _a === void 0 ? void 0 : _a["name"]) || ((_b = this.modelInfo) === null || _b === void 0 ? void 0 : _b["file"]) || "Unknown"); this.attachEvents(); } getCloseEventDetail() { const detail = { dirty: this.modifiedModelData, }; return { detail }; } attachEvents() { this.contentElement.addEventListener("click", async (e) => { const target = getClosestOrSelf(e.target, "[data-action]"); const action = target === null || target === void 0 ? void 0 : target.getAttribute("data-action"); if (!target || !action) { return; } await this.handleEventAction(action, target, e); }); } async handleEventAction(action, target, e) { var _a, _b; const info = this.modelInfo; if (!(info === null || info === void 0 ? void 0 : info.file)) { return; } if (action === "fetch-civitai") { this.modelInfo = await this.refreshModelInfo(info.file); this.setContent(this.getInfoContent()); this.setTitle(((_a = this.modelInfo) === null || _a === void 0 ? void 0 : _a["name"]) || ((_b = this.modelInfo) === null || _b === void 0 ? void 0 : _b["file"]) || "Unknown"); } else if (action === "copy-trained-words") { const selected = query(".-rgthree-is-selected", target.closest("tr")); const text = selected.map((el) => el.getAttribute("data-word")).join(", "); await navigator.clipboard.writeText(text); rgthree.showMessage({ id: "copy-trained-words-" + generateId(4), type: "success", message: `Successfully copied ${selected.length} key word${selected.length === 1 ? "" : "s"}.`, timeout: 4000, }); } else if (action === "toggle-trained-word") { target === null || target === void 0 ? void 0 : target.classList.toggle("-rgthree-is-selected"); const tr = target.closest("tr"); if (tr) { const span = queryOne("td:first-child > *", tr); let small = queryOne("small", span); if (!small) { small = $el("small", { parent: span }); } const num = query(".-rgthree-is-selected", tr).length; small.innerHTML = num ? `${num} selected | Copy` : ""; } } else if (action === "edit-row") { const tr = target.closest("tr"); const td = queryOne("td:nth-child(2)", tr); const input = td.querySelector("input,textarea"); if (!input) { const fieldName = tr.dataset["fieldName"]; tr.classList.add("-rgthree-editing"); const isTextarea = fieldName === "userNote"; const input = $el(`${isTextarea ? "textarea" : 'input[type="text"]'}`, { value: td.textContent, }); input.addEventListener("keydown", (e) => { if (!isTextarea && e.key === "Enter") { const modified = saveEditableRow(info, tr, true); this.modifiedModelData = this.modifiedModelData || modified; e.stopPropagation(); e.preventDefault(); } else if (e.key === "Escape") { const modified = saveEditableRow(info, tr, false); this.modifiedModelData = this.modifiedModelData || modified; e.stopPropagation(); e.preventDefault(); } }); appendChildren(empty(td), [input]); input.focus(); } else if (target.nodeName.toLowerCase() === "button") { const modified = saveEditableRow(info, tr, true); this.modifiedModelData = this.modifiedModelData || modified; } e === null || e === void 0 ? void 0 : e.preventDefault(); e === null || e === void 0 ? void 0 : e.stopPropagation(); } } getInfoContent() { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y; const info = this.modelInfo || {}; const civitaiLink = (_a = info.links) === null || _a === void 0 ? void 0 : _a.find((i) => i.includes("civitai.com/models")); const html = ` ${infoTableRow("File", info.file || "")} ${infoTableRow("Hash (sha256)", info.sha256 || "")} ${civitaiLink ? infoTableRow("Civitai", `${logoCivitai}View on Civitai`) : ((_c = (_b = info.raw) === null || _b === void 0 ? void 0 : _b.civitai) === null || _c === void 0 ? void 0 : _c.error) === "Model not found" ? infoTableRow("Civitai", 'Model not found') : ((_e = (_d = info.raw) === null || _d === void 0 ? void 0 : _d.civitai) === null || _e === void 0 ? void 0 : _e.error) ? infoTableRow("Civitai", (_g = (_f = info.raw) === null || _f === void 0 ? void 0 : _f.civitai) === null || _g === void 0 ? void 0 : _g.error) : !((_h = info.raw) === null || _h === void 0 ? void 0 : _h.civitai) ? infoTableRow("Civitai", ``) : ""} ${infoTableRow("Name", info.name || ((_k = (_j = info.raw) === null || _j === void 0 ? void 0 : _j.metadata) === null || _k === void 0 ? void 0 : _k.ss_output_name) || "", "The name for display.", "name")} ${!info.baseModelFile && !info.baseModelFile ? "" : infoTableRow("Base Model", (info.baseModel || "") + (info.baseModelFile ? ` (${info.baseModelFile})` : ""))} ${!((_l = info.trainedWords) === null || _l === void 0 ? void 0 : _l.length) ? "" : infoTableRow("Trained Words", (_m = getTrainedWordsMarkup(info.trainedWords)) !== null && _m !== void 0 ? _m : "", "Trained words from the metadata and/or civitai. Click to select for copy.")} ${!((_p = (_o = info.raw) === null || _o === void 0 ? void 0 : _o.metadata) === null || _p === void 0 ? void 0 : _p.ss_clip_skip) || ((_r = (_q = info.raw) === null || _q === void 0 ? void 0 : _q.metadata) === null || _r === void 0 ? void 0 : _r.ss_clip_skip) == "None" ? "" : infoTableRow("Clip Skip", (_t = (_s = info.raw) === null || _s === void 0 ? void 0 : _s.metadata) === null || _t === void 0 ? void 0 : _t.ss_clip_skip)} ${infoTableRow("Strength Min", (_u = info.strengthMin) !== null && _u !== void 0 ? _u : "", "The recommended minimum strength, In the Power Lora Loader node, strength will signal when it is below this threshold.", "strengthMin")} ${infoTableRow("Strength Max", (_v = info.strengthMax) !== null && _v !== void 0 ? _v : "", "The recommended maximum strength. In the Power Lora Loader node, strength will signal when it is above this threshold.", "strengthMax")} ${""} ${infoTableRow("Additional Notes", (_w = info.userNote) !== null && _w !== void 0 ? _w : "", "Additional notes you'd like to keep and reference in the info dialog.", "userNote")}
`; const div = $el("div", { html }); if (rgthree.isDevMode()) { setAttributes(queryOne('[stub="menu"]', div), { children: [ new MenuButton({ icon: dotdotdot, options: [ { label: "More Actions", type: "title" }, { label: "Open API JSON", callback: async (e) => { var _a; if ((_a = this.modelInfo) === null || _a === void 0 ? void 0 : _a.file) { window.open(`rgthree/api/loras/info?file=${encodeURIComponent(this.modelInfo.file)}`); } }, }, { label: "Clear all local info", callback: async (e) => { var _a, _b, _c; if ((_a = this.modelInfo) === null || _a === void 0 ? void 0 : _a.file) { this.modelInfo = await LORA_INFO_SERVICE.clearFetchedInfo(this.modelInfo.file); this.setContent(this.getInfoContent()); this.setTitle(((_b = this.modelInfo) === null || _b === void 0 ? void 0 : _b["name"]) || ((_c = this.modelInfo) === null || _c === void 0 ? void 0 : _c["file"]) || "Unknown"); } }, }, ], }), ], }); } return div; } } export class RgthreeLoraInfoDialog extends RgthreeInfoDialog { async getModelInfo(file) { return LORA_INFO_SERVICE.getInfo(file, false, false); } async refreshModelInfo(file) { return LORA_INFO_SERVICE.refreshInfo(file); } async clearModelInfo(file) { return LORA_INFO_SERVICE.clearFetchedInfo(file); } } function infoTableRow(name, value, help = "", editableFieldName = "") { return ` ${name} ${help ? `` : ""} ${String(value).startsWith("<") ? value : `${value}`} ${editableFieldName ? `` : ""} `; } function getTrainedWordsMarkup(words) { let markup = `
    `; for (const wordData of words || []) { markup += `
  • ${wordData.word} ${wordData.civitai ? logoCivitai : ""} ${wordData.count != null ? `${wordData.count}` : ""}
  • `; } markup += `
`; return markup; } function saveEditableRow(info, tr, saving = true) { var _a; const fieldName = tr.dataset["fieldName"]; const input = queryOne("input,textarea", tr); let newValue = (_a = info[fieldName]) !== null && _a !== void 0 ? _a : ""; let modified = false; if (saving) { newValue = input.value; if (fieldName.startsWith("strength")) { if (Number.isNaN(Number(newValue))) { alert(`You must enter a number into the ${fieldName} field.`); return false; } newValue = (Math.round(Number(newValue) * 100) / 100).toFixed(2); } LORA_INFO_SERVICE.savePartialInfo(info.file, { [fieldName]: newValue }); modified = true; } tr.classList.remove("-rgthree-editing"); const td = queryOne("td:nth-child(2)", tr); appendChildren(empty(td), [$el("span", { text: newValue })]); return modified; } function imgInfoField(label, value) { return value != null ? `${label ? `` : ""}${value}` : ""; }