feat(model-manager): base-model multi-select filter on CivitAI browse

Add a checkbox dropdown to filter the CivitAI catalog by one or more base
models (SD 1.5, SDXL, Pony, Illustrious, Flux, etc.), mapped to the API's
`baseModels` array param. Backend search accepts comma-separated
base_models; button shows the selected count with a Clear action.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-07 16:37:33 -04:00
parent 505f212c4d
commit 15e0dc3772
6 changed files with 86 additions and 4 deletions
+46
View File
@@ -404,11 +404,56 @@ $("#galleryMore").addEventListener("click", () => loadGallery(false));
const browseState = { loaded: false, page: null, cursor: null, busy: false };
// CivitAI base-model values (exact strings the API expects).
const BASE_MODELS = [
"SD 1.5", "SD 2.1", "SDXL 1.0", "SDXL Lightning", "SDXL Hyper", "SDXL Turbo",
"Pony", "Illustrious", "NoobAI", "Flux.1 S", "Flux.1 D", "Flux.1 Kontext",
"SD 3", "SD 3.5", "SD 3.5 Medium", "SD 3.5 Large", "Stable Cascade",
"Wan Video", "Hunyuan Video", "LTXV", "Qwen", "Chroma", "HiDream", "Other",
];
function initBaseModelDropdown() {
const panel = $("#bBasePanel");
for (const bm of BASE_MODELS) {
const lab = document.createElement("label");
lab.className = "multi-opt";
const cb = document.createElement("input");
cb.type = "checkbox";
cb.value = bm;
cb.className = "bm-check";
cb.addEventListener("change", updateBaseModelLabel);
lab.append(cb, document.createTextNode(" " + bm));
panel.appendChild(lab);
}
$("#bBaseBtn").addEventListener("click", (e) => {
e.stopPropagation();
panel.hidden = !panel.hidden;
});
$("#bBaseClear").addEventListener("click", () => {
$$(".bm-check").forEach((c) => { c.checked = false; });
updateBaseModelLabel();
});
document.addEventListener("click", (e) => {
if (!$("#bBaseDD").contains(e.target)) panel.hidden = true;
});
}
function selectedBaseModels() {
return $$(".bm-check").filter((c) => c.checked).map((c) => c.value);
}
function updateBaseModelLabel() {
const n = selectedBaseModels().length;
$("#bBaseBtn").textContent = n ? `Base model (${n}) ▾` : "Base model ▾";
}
function browseParams() {
const p = new URLSearchParams();
const q = $("#bSearch").value.trim();
if (q) p.set("query", q);
if ($("#bType").value) p.set("types", $("#bType").value);
const bms = selectedBaseModels();
if (bms.length) p.set("base_models", bms.join(","));
p.set("sort", $("#bSort").value);
p.set("period", $("#bPeriod").value);
p.set("nsfw", $("#bNsfw").checked ? "true" : "false");
@@ -622,6 +667,7 @@ $("#saveSettings").addEventListener("click", async () => {
(async function init() {
await loadModelTypes();
initBaseModelDropdown();
const wanted = new URLSearchParams(location.search).get("view");
const valid = ["installed", "gallery", "browse", "download", "settings"];
showView(valid.includes(wanted) ? wanted : "installed");