mirror of
https://github.com/ggml-org/llama.cpp.git
synced 2026-10-01 18:37:28 -05:00
ui : list a favorite once, in its own section
Assisted-by: pi:llama.cpp/DeepSeek-V4.1-Flash
This commit is contained in:
@@ -323,11 +323,7 @@
|
||||
<p class="px-4 py-3 text-sm text-muted-foreground">{ms.emptyMessage}</p>
|
||||
{/if}
|
||||
|
||||
{#snippet modelOption(
|
||||
item: ModelItem,
|
||||
hideOrgName: boolean,
|
||||
showFavIndicator: boolean
|
||||
)}
|
||||
{#snippet modelOption(item: ModelItem, hideOrgName: boolean)}
|
||||
{@const { option } = item}
|
||||
{@const isSelected = currentModel === option.model || ms.activeId === option.id}
|
||||
{@const isHighlighted = option.id === highlightedId}
|
||||
@@ -349,7 +345,6 @@
|
||||
onSelect={ms.handleSelect}
|
||||
{option}
|
||||
showBaseModelAvatar
|
||||
{showFavIndicator}
|
||||
/>
|
||||
{/snippet}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
sectionHeaderClass?: string;
|
||||
onSelect: (modelId: string) => void;
|
||||
onInfoClick: (modelName: string) => void;
|
||||
renderOption?: import('svelte').Snippet<[ModelItem, boolean, boolean]>;
|
||||
renderOption?: import('svelte').Snippet<[ModelItem, boolean]>;
|
||||
/** Favorite models of every backend, listed in their own section. */
|
||||
favorites?: ModelItem[];
|
||||
/** Show the organization name in every model id of the list. */
|
||||
@@ -63,7 +63,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
{#snippet defaultOption(item: ModelItem, hideOrgName: boolean, showFavIndicator: boolean)}
|
||||
{#snippet defaultOption(item: ModelItem, hideOrgName: boolean)}
|
||||
{@const { option } = item}
|
||||
{@const isSelected = currentModel === option.model || activeId === option.id}
|
||||
{@const isFav = modelsStore.favoriteModelIds.has(option.model)}
|
||||
@@ -79,11 +79,11 @@
|
||||
{onSelect}
|
||||
{option}
|
||||
showBaseModelAvatar
|
||||
{showFavIndicator}
|
||||
/>
|
||||
{/snippet}
|
||||
|
||||
{#if favorites.length > 0}
|
||||
<!-- Favorites come first; the sections below skip them -->
|
||||
<CollapsibleSection
|
||||
revealChevronOnHover
|
||||
triggerClass="{headerClass} flex w-full cursor-pointer items-center gap-1.5 text-left"
|
||||
@@ -96,7 +96,7 @@
|
||||
{/snippet}
|
||||
|
||||
{#each favorites as item (`fav-${item.option.id}`)}
|
||||
{@render render(item, !showOrgName, false)}
|
||||
{@render render(item, !showOrgName)}
|
||||
{/each}
|
||||
</CollapsibleSection>
|
||||
{/if}
|
||||
@@ -123,12 +123,12 @@
|
||||
{/snippet}
|
||||
|
||||
{#each groups.loaded as item (`loaded-${item.option.id}`)}
|
||||
{@render render(item, !showOrgName, true)}
|
||||
{@render render(item, !showOrgName)}
|
||||
{/each}
|
||||
|
||||
{#each groups.available as group (group.orgName)}
|
||||
{#each group.items as item (item.option.id)}
|
||||
{@render render(item, !showOrgName, true)}
|
||||
{@render render(item, !showOrgName)}
|
||||
{/each}
|
||||
{/each}
|
||||
</CollapsibleSection>
|
||||
@@ -168,7 +168,7 @@
|
||||
|
||||
{#if provider.items.length > 0}
|
||||
{#each provider.items as item (`${provider.backendId}-${item.option.id}`)}
|
||||
{@render render(item, !showOrgName, true)}
|
||||
{@render render(item, !showOrgName)}
|
||||
{/each}
|
||||
|
||||
{#if onProviderOpen && provider.matched > provider.items.length}
|
||||
|
||||
@@ -26,9 +26,6 @@
|
||||
isSelected: boolean;
|
||||
isHighlighted: boolean;
|
||||
isFav: boolean;
|
||||
/** Show the filled heart at rest. Off inside the favorites section, where
|
||||
* every row is a favorite. */
|
||||
showFavIndicator?: boolean;
|
||||
hideOrgName?: boolean;
|
||||
onSelect: (modelId: string) => void;
|
||||
onMouseEnter: () => void;
|
||||
@@ -48,8 +45,7 @@
|
||||
onMouseEnter,
|
||||
onSelect,
|
||||
option,
|
||||
showBaseModelAvatar = false,
|
||||
showFavIndicator = true
|
||||
showBaseModelAvatar = false
|
||||
}: Props = $props();
|
||||
|
||||
// row actions follow the backend that serves the row, not the selected one
|
||||
@@ -167,8 +163,7 @@
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||
<div
|
||||
class="pointer-events-none flex items-center justify-center gap-1 pl-2 group-hover:pointer-events-auto [@media(pointer:coarse)]:pointer-events-auto [@media(pointer:coarse)]:opacity-100 {isFav &&
|
||||
showFavIndicator
|
||||
class="pointer-events-none flex items-center justify-center gap-1 pl-2 group-hover:pointer-events-auto [@media(pointer:coarse)]:pointer-events-auto [@media(pointer:coarse)]:opacity-100 {isFav
|
||||
? ''
|
||||
: 'opacity-0 group-hover:opacity-100'}"
|
||||
onclick={(e) => e.stopPropagation()}
|
||||
|
||||
@@ -145,9 +145,13 @@ export function useModelsSelector(opts: UseModelsSelectorOptions): UseModelsSele
|
||||
};
|
||||
})
|
||||
);
|
||||
// favorites are listed once, at the top: the sections below skip them
|
||||
const sectionOptions = $derived(
|
||||
filteredOptions.filter((option) => !modelsStore.favoriteModelIds.has(option.model))
|
||||
);
|
||||
const providerSections = $derived(
|
||||
groupProviderOptions(
|
||||
filteredOptions,
|
||||
sectionOptions,
|
||||
remoteProviders,
|
||||
// a drill-in or a search reaches every model, the sections stay short
|
||||
providerViewId || searchTerm ? Infinity : REMOTE_PROVIDER_MODEL_LIMIT
|
||||
@@ -160,7 +164,7 @@ export function useModelsSelector(opts: UseModelsSelectorOptions): UseModelsSele
|
||||
return { ...EMPTY_GROUPS, providers: sections };
|
||||
}
|
||||
|
||||
const local = groupModelOptions(filteredOptions.filter(isLocalOption), (m) =>
|
||||
const local = groupModelOptions(sectionOptions.filter(isLocalOption), (m) =>
|
||||
modelsStore.isModelLoaded(m)
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user