{#if loading}
Loading...
{:else}
{#if recognition.running}
Recognizing models... {recognition.done}/{recognition.total}
{/if}
0} bind:this={listEl} onscroll={onListScroll}> {#each filteredGroups as group (group.name)} {@const model = group.versions[0]} {@const displayName = group.name} {@const meta = [group.architecture, group.family].filter(Boolean).join(" · ")} {@const precs = groupPrecisions(group)}
{ e.stopPropagation(); handleGroupClick(group); }} onpointerenter={(e) => onItemEnter(e, { thumbnail: modelSettings[model.hash]?.thumbnail, name: displayName })} onpointerleave={onItemLeave}>
{displayName} {#if group.versions.length > 1 && !precs.length} {group.versions.length} {/if} {#if meta} {meta} {/if} {#if precs.length}
{#each precs as p} { e.stopPropagation(); p.installed ? handleInstalledPrecisionClick(p) : handleMissingPrecisionClick(group, p); }}> {p.precision.toUpperCase()}{p.installed ? "" : " ↓"} {/each}
{/if}
▸
{/each} {#each catalogInstalled as entry} {@const precisions = extractPrecisions(entry.files || [])} {@const status = catalogPrecisionStatus[entry.hash] || {}}
status[p] === "partial")} onclick={(e) => { e.stopPropagation(); const prec = precisions.find(p => status[p] === "installed") || precisions.find(p => status[p] === "partial"); if (prec) handleCatalogPrecisionClick(entry, prec, status[prec]); }}>
{entry.display_name || entry.model_name}
{#each precisions as prec} {@const st = status[prec] || "missing"} { e.stopPropagation(); handleCatalogPrecisionClick(entry, prec, st); }}> {prec.toUpperCase()}{st === "installed" ? "" : st === "partial" ? " ↻" : " ↓"} {/each}
›
{/each} {#if catalogGroups.length}
AVAILABLE FOR DOWNLOAD
{#each catalogGroups as group (group.name)} {@const meta = [group.architecture, group.family].filter(Boolean).join(" · ")}
{ e.stopPropagation(); handleCatalogGroupClick(group); }}>
{group.name} {#if group.versions.length > 1} {group.versions.length} {/if} {#if meta || group.partial} {meta}{#if group.partial}{meta ? " · " : ""}resume ↻{/if} {/if}
{group.versions.length > 1 ? "▸" : (group.partial ? "↻" : "↓")}
{/each} {/if} {#if searchQuery.trim() && (civitaiResults.length || civitaiLoading || civitaiHasSearched)}
CIVITAI
{#each civitaiResults as result}
onShowDownload(result)} onpointerenter={(e) => onItemEnter(e, { thumbnail: result.thumbnail, name: result.model_name, version: result.version, base_model: result.base_model, thumbs_up: result.thumbs_up, downloads: result.downloads, tags: result.tags, })} onpointerleave={onItemLeave}>
{result.model_name} {[result.architecture, result.family, result.file?.size_gb ? `${result.file.size_gb} GB` : "", result.downloads ? `${(result.downloads / 1000).toFixed(0)}k ↓` : ""].filter(Boolean).join(" · ")}
↓
{/each} {#if civitaiLoading && !civitaiResults.length}
Searching CivitAI…
{:else if civitaiLoading}
Loading more…
{:else if civitaiHasSearched && !civitaiResults.length}
No results on CivitAI
{/if}
{/if} {#if !filteredGroups.length && !catalogInstalled.length && !catalogUninstalled.length && !civitaiResults.length && !civitaiLoading && !civitaiHasSearched && !loading}
No matches
{/if}
{/if}
{#if activeSubmenu?.type === "version"} {@const group = activeSubmenu.group}
SELECT VERSION
{#each group.versions as model} {@const label = buildVersionLabel(model)}
handleVersionClick(model, label)}> {label} ▶
{/each}
{/if} {#if activeSubmenu?.type === "catalogVersion"} {@const group = activeSubmenu.group}
SELECT VERSION
{#each group.versions as entry}
handleCatalogVersionClick(entry)}> {buildCatalogVersionLabel(entry)} ↓
{/each}
{/if} {#if activeSubmenu?.type === "template" || activeNestedSubmenu} {@const model = activeNestedSubmenu?.model || activeSubmenu?.model} {@const tpls = model ? templatesForModel(model) : []} {@const displayName = activeNestedSubmenu?.versionLabel || activeSubmenu?.displayName || ""}
{displayName}
{#if canSwapInPlace(model)}
{ onSwapInPlace(model.filename, model.hash); onClose?.(); }}> (Current Workflow)
{#if tpls.length}
TEMPLATES
{/if} {/if} {#if tpls.length} {@const cats = [...new Set(tpls.map(t => t.category || "General"))]} {@const sortedCats = sortCategories(cats)} {#each sortedCats as cat} {@const catTpls = tpls.filter(t => (t.category || "General") === cat)} {#if catTpls.length} {#if sortedCats.length > 1}
{cat.toUpperCase()}
{/if} {#each catTpls as tpl}
handleTemplateClick(tpl, model)}> {tpl.name}
{/each} {/if} {/each} {:else}
No templates available
{/if}
{/if}