ui : favorite every model of a family from its row

Assisted-by: pi:llama.cpp/DeepSeek-V4.1-Flash
This commit is contained in:
Aleksander Grygier
2026-09-28 12:10:12 +02:00
parent 8b0a10f7d2
commit bddd909f00
2 changed files with 61 additions and 16 deletions
@@ -19,6 +19,7 @@
Upload
} from '@lucide/svelte';
import {
ActionIcon,
DropdownMenuActions,
Logo,
ModelAvatar,
@@ -346,10 +347,12 @@
{#snippet familyRow(family: ModelFamilyGroup)}
{@const isExpanded = !collapsedFamilies.has(family.key)}
{@const countLabel = `${family.entries.length} model${family.entries.length === 1 ? '' : 's'}`}
{@const options = family.entries.flatMap((entry) => entry.quants)}
{@const favorite = options.some((option) => isFavorite(option))}
<div class="px-2">
<div
class="{rowGrid} cursor-pointer rounded-md px-2 py-2.5 transition hover:bg-muted/40"
class="{rowGrid} group cursor-pointer rounded-md px-2 py-2.5 transition hover:bg-muted/40"
onclick={() => toggleFamily(family.key)}
onkeydown={(event) => event.key === 'Enter' && toggleFamily(family.key)}
role="button"
@@ -366,6 +369,41 @@
<span class="truncate text-sm font-medium">{family.label}</span>
<span class="text-sm text-muted-foreground">{countLabel}</span>
<span
class="flex shrink-0"
onclick={(event) => event.stopPropagation()}
onkeydown={(event) => event.stopPropagation()}
role="presentation"
>
{#if favorite}
<ActionIcon
class="h-5 w-5 text-rose-500 hover:text-foreground"
icon={HeartOff}
iconSize="h-4 w-4"
onclick={() =>
modelsStore.setFavorites(
options.map((option) => option.model),
false
)}
tooltip="Remove family from favorites"
tooltipAsTitle
/>
{:else}
<ActionIcon
class="h-5 w-5 opacity-0 transition group-hover:opacity-100 [@media(pointer:coarse)]:opacity-100"
icon={Heart}
iconSize="h-4 w-4"
onclick={() =>
modelsStore.setFavorites(
options.map((option) => option.model),
true
)}
tooltip="Add family to favorites"
tooltipAsTitle
/>
{/if}
</span>
</span>
<span></span>
+22 -15
View File
@@ -518,6 +518,27 @@ class ModelsStore implements ModelPropsHost, ModelStatusHost {
}
}
/** Add or remove several models at once, e.g. every quant of a family. */
setFavorites(modelIds: string[], favorite: boolean): void {
const next = new SvelteSet(this.favoriteModelIds);
for (const modelId of modelIds) {
if (favorite) {
next.add(modelId);
} else {
next.delete(modelId);
}
}
this.favoriteModelIds = next;
try {
localStorage.setItem(FAVORITE_MODELS_LOCALSTORAGE_KEY, JSON.stringify([...next]));
} catch {
toast.error('Failed to save favorite models to local storage');
}
}
/**
* Activate a backend for the selector tabs. Everything comes from memory:
* the model list and router rows are prefetched at startup and the local
@@ -571,21 +592,7 @@ class ModelsStore implements ModelPropsHost, ModelStatusHost {
}
toggleFavorite(modelId: string): void {
const next = new SvelteSet(this.favoriteModelIds);
if (next.has(modelId)) {
next.delete(modelId);
} else {
next.add(modelId);
}
this.favoriteModelIds = next;
try {
localStorage.setItem(FAVORITE_MODELS_LOCALSTORAGE_KEY, JSON.stringify([...next]));
} catch {
toast.error('Failed to save favorite models to local storage');
}
this.setFavorites([modelId], !this.favoriteModelIds.has(modelId));
}
/** Models hidden from the selector stay in the manager, flagged and unhideable. */