Add Setting to optionally download descriptions as Notes.
- Added more server print statements for saving/moving/deleting files. - Added slight gap between download inputs.
This commit is contained in:
10
__init__.py
10
__init__.py
@@ -185,6 +185,7 @@ def ui_rules():
|
|||||||
Rule("model-add-embedding-extension", False, bool),
|
Rule("model-add-embedding-extension", False, bool),
|
||||||
Rule("model-add-drag-strict-on-field", False, bool),
|
Rule("model-add-drag-strict-on-field", False, bool),
|
||||||
Rule("model-add-offset", 25, int),
|
Rule("model-add-offset", 25, int),
|
||||||
|
Rule("download-save-description-as-text-file", False, bool),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -232,6 +233,7 @@ async def save_ui_settings(request):
|
|||||||
rules = ui_rules()
|
rules = ui_rules()
|
||||||
validated_settings = config_loader.validated(rules, settings)
|
validated_settings = config_loader.validated(rules, settings)
|
||||||
success = config_loader.yaml_save(ui_settings_uri, rules, validated_settings)
|
success = config_loader.yaml_save(ui_settings_uri, rules, validated_settings)
|
||||||
|
print("Saved file: " + ui_settings_uri)
|
||||||
return web.json_response({
|
return web.json_response({
|
||||||
"success": success,
|
"success": success,
|
||||||
"settings": validated_settings if success else "",
|
"settings": validated_settings if success else "",
|
||||||
@@ -920,6 +922,7 @@ async def move_model(request):
|
|||||||
return web.json_response({ "success": False })
|
return web.json_response({ "success": False })
|
||||||
try:
|
try:
|
||||||
shutil.move(old_file, new_file)
|
shutil.move(old_file, new_file)
|
||||||
|
print("Moved file: " + new_file)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
print(e, file=sys.stderr, flush=True)
|
print(e, file=sys.stderr, flush=True)
|
||||||
return web.json_response({ "success": False })
|
return web.json_response({ "success": False })
|
||||||
@@ -928,8 +931,10 @@ async def move_model(request):
|
|||||||
for extension in preview_extensions + (model_info_extension,):
|
for extension in preview_extensions + (model_info_extension,):
|
||||||
old_file = old_file_without_extension + extension
|
old_file = old_file_without_extension + extension
|
||||||
if os.path.isfile(old_file):
|
if os.path.isfile(old_file):
|
||||||
|
new_file = new_file_without_extension + extension
|
||||||
try:
|
try:
|
||||||
shutil.move(old_file, new_file_without_extension + extension)
|
shutil.move(old_file, new_file)
|
||||||
|
print("Moved file: " + new_file)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
print(e, file=sys.stderr, flush=True)
|
print(e, file=sys.stderr, flush=True)
|
||||||
|
|
||||||
@@ -942,6 +947,7 @@ def delete_same_name_files(path_without_extension, extensions, keep_extension=No
|
|||||||
file = path_without_extension + extension
|
file = path_without_extension + extension
|
||||||
if os.path.isfile(file):
|
if os.path.isfile(file):
|
||||||
os.remove(file)
|
os.remove(file)
|
||||||
|
print("Deleted file: " + file)
|
||||||
|
|
||||||
|
|
||||||
@server.PromptServer.instance.routes.post("/model-manager/model/delete")
|
@server.PromptServer.instance.routes.post("/model-manager/model/delete")
|
||||||
@@ -965,6 +971,7 @@ async def delete_model(request):
|
|||||||
if os.path.isfile(model_path):
|
if os.path.isfile(model_path):
|
||||||
os.remove(model_path)
|
os.remove(model_path)
|
||||||
result["success"] = True
|
result["success"] = True
|
||||||
|
print("Deleted file: " + model_path)
|
||||||
|
|
||||||
delete_same_name_files(path_and_name, preview_extensions)
|
delete_same_name_files(path_and_name, preview_extensions)
|
||||||
delete_same_name_files(path_and_name, (model_info_extension,))
|
delete_same_name_files(path_and_name, (model_info_extension,))
|
||||||
@@ -994,6 +1001,7 @@ async def set_notes(request):
|
|||||||
try:
|
try:
|
||||||
with open(filename, "w", encoding="utf-8") as f:
|
with open(filename, "w", encoding="utf-8") as f:
|
||||||
f.write(text)
|
f.write(text)
|
||||||
|
print("Saved file: " + filename)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
print(e, file=sys.stderr, flush=True)
|
print(e, file=sys.stderr, flush=True)
|
||||||
web.json_response({ "success": False })
|
web.json_response({ "success": False })
|
||||||
|
|||||||
@@ -239,10 +239,16 @@
|
|||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
.model-manager [data-name="Download"] .download-settings {
|
.model-manager [data-name="Download"] .download-settings-wrapper {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.model-manager [data-name="Download"] .download-settings {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
row-gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.model-manager .download-model-infos {
|
.model-manager .download-model-infos {
|
||||||
padding: 16px 0;
|
padding: 16px 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -175,6 +175,31 @@ function buttonAlert(element, success, successText = "", failureText = "", reset
|
|||||||
}, 1000, element, name, resetText);
|
}, 1000, element, name, resetText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} modelPath
|
||||||
|
* @param {string} newValue
|
||||||
|
* @returns {Promise<boolean>}
|
||||||
|
*/
|
||||||
|
async function saveNotes(modelPath, newValue) {
|
||||||
|
return request(
|
||||||
|
"/model-manager/notes/save",
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify({
|
||||||
|
"path": modelPath,
|
||||||
|
"notes": newValue,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
).then((result) => {
|
||||||
|
return result["success"];
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.warn(err);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
class Tabs {
|
class Tabs {
|
||||||
/** @type {Record<string, HTMLDivElement>} */
|
/** @type {Record<string, HTMLDivElement>} */
|
||||||
#head = {};
|
#head = {};
|
||||||
@@ -1938,7 +1963,8 @@ class ModelInfoView {
|
|||||||
if (noteValue.trim() !== savedNotesValue.trim()) {
|
if (noteValue.trim() !== savedNotesValue.trim()) {
|
||||||
const saveChanges = window.confirm("Save notes?");
|
const saveChanges = window.confirm("Save notes?");
|
||||||
if (saveChanges) {
|
if (saveChanges) {
|
||||||
const saved = await this.#saveNotes(noteValue);
|
const path = this.elements.info.dataset.path;
|
||||||
|
const saved = await saveNotes(path, noteValue);
|
||||||
if (!saved) {
|
if (!saved) {
|
||||||
window.alert("Failed to save notes!");
|
window.alert("Failed to save notes!");
|
||||||
return;
|
return;
|
||||||
@@ -1957,32 +1983,6 @@ class ModelInfoView {
|
|||||||
this.element.style.display = "none";
|
this.element.style.display = "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} newValue
|
|
||||||
* @returns {Promise<boolean>}
|
|
||||||
*/
|
|
||||||
async #saveNotes(newValue) {
|
|
||||||
return request(
|
|
||||||
"/model-manager/notes/save",
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
body: JSON.stringify({
|
|
||||||
"path": this.elements.info.dataset.path,
|
|
||||||
"notes": newValue,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
).then((result) => {
|
|
||||||
const success = result["success"];
|
|
||||||
if (success) {
|
|
||||||
this.#savedNotesValue = newValue;
|
|
||||||
}
|
|
||||||
return success;
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} searchPath
|
* @param {string} searchPath
|
||||||
* @param {() => Promise<void>} updateModels
|
* @param {() => Promise<void>} updateModels
|
||||||
@@ -2140,7 +2140,12 @@ class ModelInfoView {
|
|||||||
elements.push($el("button", {
|
elements.push($el("button", {
|
||||||
textContent: "Save Notes",
|
textContent: "Save Notes",
|
||||||
onclick: async (e) => {
|
onclick: async (e) => {
|
||||||
const saved = await this.#saveNotes(notes.value);
|
const path = this.elements.info.dataset.path;
|
||||||
|
const newValue = notes.value;
|
||||||
|
const saved = await saveNotes(path, newValue);
|
||||||
|
if (saved) {
|
||||||
|
this.#savedNotesValue = newValue;
|
||||||
|
}
|
||||||
buttonAlert(e.target, saved);
|
buttonAlert(e.target, saved);
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
@@ -2240,6 +2245,7 @@ class Civitai {
|
|||||||
return image["url"];
|
return image["url"];
|
||||||
}),
|
}),
|
||||||
"name": modelVersionInfo["name"],
|
"name": modelVersionInfo["name"],
|
||||||
|
"description": modelVersionInfo["description"] ?? "",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2275,6 +2281,7 @@ class Civitai {
|
|||||||
return {
|
return {
|
||||||
"name": modelVersionInfo["model"]["name"],
|
"name": modelVersionInfo["model"]["name"],
|
||||||
"type": modelVersionInfo["model"]["type"],
|
"type": modelVersionInfo["model"]["type"],
|
||||||
|
"description": modelVersionInfo["description"] ?? "",
|
||||||
"versions": [filesInfo]
|
"versions": [filesInfo]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2306,7 +2313,8 @@ class Civitai {
|
|||||||
return {
|
return {
|
||||||
"name": modelInfo["name"],
|
"name": modelInfo["name"],
|
||||||
"type": modelInfo["type"],
|
"type": modelInfo["type"],
|
||||||
"versions": modelVersions
|
"description": modelInfo["description"] ?? "",
|
||||||
|
"versions": modelVersions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -2506,9 +2514,51 @@ class DownloadTab {
|
|||||||
/** @type {HTMLInputElement} */ overwrite: null,
|
/** @type {HTMLInputElement} */ overwrite: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** @type {DOMParser} */
|
||||||
|
#domParser = null;
|
||||||
|
|
||||||
/** @type {() => Promise<void>} */
|
/** @type {() => Promise<void>} */
|
||||||
#updateModels = () => {};
|
#updateModels = () => {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ModelData} modelData
|
||||||
|
* @param {any} settings
|
||||||
|
* @param {() => Promise<void>} updateModels
|
||||||
|
*/
|
||||||
|
constructor(modelData, settings, updateModels) {
|
||||||
|
this.#domParser = new DOMParser();
|
||||||
|
this.#updateModels = updateModels;
|
||||||
|
const search = async() => this.search(modelData, settings);
|
||||||
|
$el("div.tab-header", {
|
||||||
|
$: (el) => (this.element = el),
|
||||||
|
}, [
|
||||||
|
$el("div.row.tab-header-flex-block", [
|
||||||
|
$el("input.search-text-area", {
|
||||||
|
$: (el) => (this.elements.url = el),
|
||||||
|
type: "text",
|
||||||
|
name: "model download url",
|
||||||
|
autocomplete: "off",
|
||||||
|
placeholder: "example: https://civitai.com/models/207992/stable-video-diffusion-svd",
|
||||||
|
onkeydown: (e) => {
|
||||||
|
if (e.key === "Enter") {
|
||||||
|
e.stopPropagation();
|
||||||
|
search();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
$el("button.icon-button", {
|
||||||
|
onclick: () => search(),
|
||||||
|
textContent: "🔍︎",
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
$el("div.download-model-infos", {
|
||||||
|
$: (el) => (this.elements.infos = el),
|
||||||
|
}, [
|
||||||
|
$el("div", ["Input a URL to select a model to download."]),
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tries to return the related ComfyUI model directory if unambiguous.
|
* Tries to return the related ComfyUI model directory if unambiguous.
|
||||||
*
|
*
|
||||||
@@ -2554,9 +2604,10 @@ class DownloadTab {
|
|||||||
* @param {Object} info
|
* @param {Object} info
|
||||||
* @param {ModelData} modelData
|
* @param {ModelData} modelData
|
||||||
* @param {int} id
|
* @param {int} id
|
||||||
|
* @param {any} settings
|
||||||
* @returns {HTMLDivElement}
|
* @returns {HTMLDivElement}
|
||||||
*/
|
*/
|
||||||
#modelInfo(info, modelData, id) {
|
#modelInfo(info, modelData, id, settings) {
|
||||||
const downloadPreviewSelect = new ImageSelect(
|
const downloadPreviewSelect = new ImageSelect(
|
||||||
"model-download-info-preview-model" + "-" + id,
|
"model-download-info-preview-model" + "-" + id,
|
||||||
info["images"],
|
info["images"],
|
||||||
@@ -2604,17 +2655,13 @@ class DownloadTab {
|
|||||||
style: { display: "flex", "flex-wrap": "wrap", gap: "16px" },
|
style: { display: "flex", "flex-wrap": "wrap", gap: "16px" },
|
||||||
}, [
|
}, [
|
||||||
downloadPreviewSelect.elements.previews,
|
downloadPreviewSelect.elements.previews,
|
||||||
$el("div.download-settings", [
|
$el("div.download-settings-wrapper", [
|
||||||
$el("div", {
|
$el("div.download-settings", [
|
||||||
style: { "margin-top": "8px" }
|
|
||||||
}, [
|
|
||||||
$el("button.icon-button", {
|
$el("button.icon-button", {
|
||||||
textContent: "📥︎",
|
textContent: "📥︎",
|
||||||
onclick: async (e) => {
|
onclick: async (e) => {
|
||||||
const formData = new FormData();
|
const pathDirectory = el_saveDirectoryPath.value;
|
||||||
formData.append("download", info["downloadUrl"]);
|
const modelName = (() => {
|
||||||
formData.append("path", el_saveDirectoryPath.value);
|
|
||||||
formData.append("name", (() => {
|
|
||||||
const filename = info["fileName"];
|
const filename = info["fileName"];
|
||||||
const name = el_filename.value;
|
const name = el_filename.value;
|
||||||
if (name === "") {
|
if (name === "") {
|
||||||
@@ -2624,7 +2671,11 @@ class DownloadTab {
|
|||||||
return filename.endsWith(ext);
|
return filename.endsWith(ext);
|
||||||
}) ?? "";
|
}) ?? "";
|
||||||
return name + ext;
|
return name + ext;
|
||||||
})());
|
})();
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append("download", info["downloadUrl"]);
|
||||||
|
formData.append("path", pathDirectory);
|
||||||
|
formData.append("name", modelName);
|
||||||
const image = await downloadPreviewSelect.getImage();
|
const image = await downloadPreviewSelect.getImage();
|
||||||
formData.append("image", image === PREVIEW_NONE_URI ? "" : image);
|
formData.append("image", image === PREVIEW_NONE_URI ? "" : image);
|
||||||
formData.append("overwrite", this.elements.overwrite.checked);
|
formData.append("overwrite", this.elements.overwrite.checked);
|
||||||
@@ -2645,6 +2696,14 @@ class DownloadTab {
|
|||||||
return [false, "📥︎"];
|
return [false, "📥︎"];
|
||||||
});
|
});
|
||||||
if (success) {
|
if (success) {
|
||||||
|
const description = info["description"];
|
||||||
|
if (settings["download-save-description-as-text-file"].checked && description !== "") {
|
||||||
|
const modelPath = pathDirectory + searchSeparator + modelName;
|
||||||
|
const saved = await saveNotes(modelPath, description);
|
||||||
|
if (!saved) {
|
||||||
|
console.warn("Description was note saved as notes!");
|
||||||
|
}
|
||||||
|
}
|
||||||
this.#updateModels();
|
this.#updateModels();
|
||||||
}
|
}
|
||||||
buttonAlert(e.target, success, "✔", "✖", resultText);
|
buttonAlert(e.target, success, "✔", "✖", resultText);
|
||||||
@@ -2669,8 +2728,9 @@ class DownloadTab {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {ModelData} modelData
|
* @param {ModelData} modelData
|
||||||
|
* @param {any} settings
|
||||||
*/
|
*/
|
||||||
async search(modelData) {
|
async search(modelData, settings) {
|
||||||
const infosHtml = this.elements.infos;
|
const infosHtml = this.elements.infos;
|
||||||
infosHtml.innerHTML = "";
|
infosHtml.innerHTML = "";
|
||||||
|
|
||||||
@@ -2683,8 +2743,11 @@ class DownloadTab {
|
|||||||
}
|
}
|
||||||
const infos = [];
|
const infos = [];
|
||||||
const type = civitaiInfo["type"];
|
const type = civitaiInfo["type"];
|
||||||
|
const modelInfo = civitaiInfo["description"]?? "";
|
||||||
civitaiInfo["versions"].forEach((version) => {
|
civitaiInfo["versions"].forEach((version) => {
|
||||||
const images = version["images"];
|
const images = version["images"];
|
||||||
|
const versionDescription = version["description"]??"";
|
||||||
|
const description = (versionDescription + "\n\n" + modelInfo).trim().replace(/<[^>]+>/g, ""); // quick hack
|
||||||
version["files"].forEach((file) => {
|
version["files"].forEach((file) => {
|
||||||
infos.push({
|
infos.push({
|
||||||
"images": images,
|
"images": images,
|
||||||
@@ -2692,6 +2755,7 @@ class DownloadTab {
|
|||||||
"modelType": type,
|
"modelType": type,
|
||||||
"downloadUrl": file["downloadUrl"],
|
"downloadUrl": file["downloadUrl"],
|
||||||
"downloadFilePath": "",
|
"downloadFilePath": "",
|
||||||
|
"description": description,
|
||||||
"details": {
|
"details": {
|
||||||
"fileSizeKB": file["sizeKB"],
|
"fileSizeKB": file["sizeKB"],
|
||||||
"fileType": file["type"],
|
"fileType": file["type"],
|
||||||
@@ -2724,6 +2788,7 @@ class DownloadTab {
|
|||||||
"modelType": "",
|
"modelType": "",
|
||||||
"downloadUrl": baseDownloadUrl + "/" + file + "?download=true",
|
"downloadUrl": baseDownloadUrl + "/" + file + "?download=true",
|
||||||
"downloadFilePath": file.substring(0, indexSep + 1),
|
"downloadFilePath": file.substring(0, indexSep + 1),
|
||||||
|
"description": "",
|
||||||
"details": {
|
"details": {
|
||||||
"fileSizeKB": undefined, // TODO: too hard?
|
"fileSizeKB": undefined, // TODO: too hard?
|
||||||
},
|
},
|
||||||
@@ -2739,6 +2804,7 @@ class DownloadTab {
|
|||||||
"modelType": DownloadTab.modelTypeToComfyUiDirectory(file["type"], "") ?? "",
|
"modelType": DownloadTab.modelTypeToComfyUiDirectory(file["type"], "") ?? "",
|
||||||
"downloadUrl": file["download"],
|
"downloadUrl": file["download"],
|
||||||
"downloadFilePath": "",
|
"downloadFilePath": "",
|
||||||
|
"description": file["description"],
|
||||||
"details": {},
|
"details": {},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@@ -2756,6 +2822,7 @@ class DownloadTab {
|
|||||||
modelInfo,
|
modelInfo,
|
||||||
modelData,
|
modelData,
|
||||||
id,
|
id,
|
||||||
|
settings,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
if (modelInfosHtml.length === 0) {
|
if (modelInfosHtml.length === 0) {
|
||||||
@@ -2765,51 +2832,18 @@ class DownloadTab {
|
|||||||
if (modelInfosHtml.length === 1) {
|
if (modelInfosHtml.length === 1) {
|
||||||
modelInfosHtml[0].open = true;
|
modelInfosHtml[0].open = true;
|
||||||
}
|
}
|
||||||
const label = $checkbox({
|
|
||||||
$: (el) => { this.elements.overwrite = el; },
|
const downloadSettings = $el("div", [
|
||||||
textContent: "Overwrite Existing Files",
|
$checkbox({
|
||||||
});
|
$: (el) => { this.elements.overwrite = el; },
|
||||||
modelInfosHtml.unshift(label);
|
textContent: "Overwrite Existing Files.",
|
||||||
|
checked: false,
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
modelInfosHtml.unshift(downloadSettings);
|
||||||
}
|
}
|
||||||
infosHtml.append.apply(infosHtml, modelInfosHtml);
|
infosHtml.append.apply(infosHtml, modelInfosHtml);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {ModelData} modelData
|
|
||||||
* @param {() => Promise<void>} updateModels
|
|
||||||
*/
|
|
||||||
constructor(modelData, updateModels) {
|
|
||||||
this.#updateModels = updateModels;
|
|
||||||
const search = async() => this.search(modelData);
|
|
||||||
$el("div.tab-header", {
|
|
||||||
$: (el) => (this.element = el),
|
|
||||||
}, [
|
|
||||||
$el("div.row.tab-header-flex-block", [
|
|
||||||
$el("input.search-text-area", {
|
|
||||||
$: (el) => (this.elements.url = el),
|
|
||||||
type: "text",
|
|
||||||
name: "model download url",
|
|
||||||
autocomplete: "off",
|
|
||||||
placeholder: "example: https://civitai.com/models/207992/stable-video-diffusion-svd",
|
|
||||||
onkeydown: (e) => {
|
|
||||||
if (e.key === "Enter") {
|
|
||||||
e.stopPropagation();
|
|
||||||
search();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
$el("button.icon-button", {
|
|
||||||
onclick: () => search(),
|
|
||||||
textContent: "🔍︎",
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
$el("div.download-model-infos", {
|
|
||||||
$: (el) => (this.elements.infos = el),
|
|
||||||
}, [
|
|
||||||
$el("div", ["Input a URL to select a model to download."]),
|
|
||||||
]),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ModelTab {
|
class ModelTab {
|
||||||
@@ -2986,6 +3020,8 @@ class SettingsTab {
|
|||||||
/** @type {HTMLInputElement} */ "model-add-embedding-extension": null,
|
/** @type {HTMLInputElement} */ "model-add-embedding-extension": null,
|
||||||
/** @type {HTMLInputElement} */ "model-add-drag-strict-on-field": null,
|
/** @type {HTMLInputElement} */ "model-add-drag-strict-on-field": null,
|
||||||
/** @type {HTMLInputElement} */ "model-add-offset": null,
|
/** @type {HTMLInputElement} */ "model-add-offset": null,
|
||||||
|
|
||||||
|
/** @type {HTMLInputElement} */ "download-save-description-as-text-file": null,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -3164,6 +3200,11 @@ class SettingsTab {
|
|||||||
}),
|
}),
|
||||||
$el("p", ["Add model offset"]),
|
$el("p", ["Add model offset"]),
|
||||||
]),
|
]),
|
||||||
|
$el("h2", ["Download"]),
|
||||||
|
$checkbox({
|
||||||
|
$: (el) => (settings["download-save-description-as-text-file"] = el),
|
||||||
|
textContent: "Save descriptions as notes (in .txt file).",
|
||||||
|
}),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3284,6 +3325,7 @@ class ModelManager extends ComfyDialog {
|
|||||||
|
|
||||||
const downloadTab = new DownloadTab(
|
const downloadTab = new DownloadTab(
|
||||||
this.#modelData,
|
this.#modelData,
|
||||||
|
this.#settingsTab.elements.settings,
|
||||||
this.#refreshModels,
|
this.#refreshModels,
|
||||||
);
|
);
|
||||||
this.#downloadTab = DownloadTab;
|
this.#downloadTab = DownloadTab;
|
||||||
|
|||||||
Reference in New Issue
Block a user