feat: pinned models

This commit is contained in:
Timothy Jaeryang Baek 2025-06-09 01:24:11 +04:00
parent 3448362e00
commit a64667ca8d
6 changed files with 33 additions and 17 deletions

View File

@ -25,6 +25,24 @@
toast.success($i18n.t('Default model updated')); toast.success($i18n.t('Default model updated'));
}; };
const pinModelHandler = async (modelId) => {
let pinnedModels = $settings?.pinnedModels ?? [];
if (pinnedModels.includes(modelId)) {
pinnedModels = pinnedModels.filter((id) => id !== modelId);
} else {
pinnedModels = [...new Set([...pinnedModels, modelId])];
}
if (pinnedModels.length > 5) {
toast.error($i18n.t('You can only pin up to 5 models.'));
return;
}
settings.set({ ...$settings, pinnedModels: pinnedModels });
await updateUserSettings(localStorage.token, { ui: $settings });
};
$: if (selectedModels.length > 0 && $models.length > 0) { $: if (selectedModels.length > 0 && $models.length > 0) {
selectedModels = selectedModels.map((model) => selectedModels = selectedModels.map((model) =>
$models.map((m) => m.id).includes(model) ? model : '' $models.map((m) => m.id).includes(model) ? model : ''
@ -49,6 +67,7 @@
? ($user?.permissions?.chat?.temporary ?? true) && ? ($user?.permissions?.chat?.temporary ?? true) &&
!($user?.permissions?.chat?.temporary_enforced ?? false) !($user?.permissions?.chat?.temporary_enforced ?? false)
: true} : true}
{pinModelHandler}
bind:value={selectedModel} bind:value={selectedModel}
/> />
</div> </div>

View File

@ -4,7 +4,7 @@
import { getContext, tick } from 'svelte'; import { getContext, tick } from 'svelte';
import dayjs from '$lib/dayjs'; import dayjs from '$lib/dayjs';
import { mobile, pinnedModels, user } from '$lib/stores'; import { mobile, settings, user } from '$lib/stores';
import Tooltip from '$lib/components/common/Tooltip.svelte'; import Tooltip from '$lib/components/common/Tooltip.svelte';
import { copyToClipboard, sanitizeResponseContent } from '$lib/utils'; import { copyToClipboard, sanitizeResponseContent } from '$lib/utils';
@ -22,6 +22,8 @@
export let value: string = ''; export let value: string = '';
export let unloadModelHandler: (modelValue: string) => void = () => {}; export let unloadModelHandler: (modelValue: string) => void = () => {};
export let pinModelHandler: (modelValue: string) => void = () => {};
export let onClick: () => void = () => {}; export let onClick: () => void = () => {};
const copyLinkHandler = async (model) => { const copyLinkHandler = async (model) => {
@ -236,13 +238,7 @@
<ModelItemMenu <ModelItemMenu
bind:show={showMenu} bind:show={showMenu}
model={item.model} model={item.model}
toggleSidebarHandler={() => { {pinModelHandler}
if ($pinnedModels.includes(item.model.id)) {
pinnedModels.set($pinnedModels.filter((id) => id !== item.model.id));
} else {
pinnedModels.set([...new Set([...$pinnedModels, item.model.id])]);
}
}}
copyLinkHandler={() => { copyLinkHandler={() => {
copyLinkHandler(item.model); copyLinkHandler(item.model);
}} }}

View File

@ -8,14 +8,14 @@
import Link from '$lib/components/icons/Link.svelte'; import Link from '$lib/components/icons/Link.svelte';
import Eye from '$lib/components/icons/Eye.svelte'; import Eye from '$lib/components/icons/Eye.svelte';
import EyeSlash from '$lib/components/icons/EyeSlash.svelte'; import EyeSlash from '$lib/components/icons/EyeSlash.svelte';
import { pinnedModels } from '$lib/stores'; import { settings } from '$lib/stores';
const i18n = getContext('i18n'); const i18n = getContext('i18n');
export let show = false; export let show = false;
export let model; export let model;
export let toggleSidebarHandler: Function = () => {}; export let pinModelHandler: (modelId: string) => void = () => {};
export let copyLinkHandler: Function = () => {}; export let copyLinkHandler: Function = () => {};
export let onClose: Function = () => {}; export let onClose: Function = () => {};
@ -52,18 +52,18 @@
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
toggleSidebarHandler(); pinModelHandler(model?.id);
show = false; show = false;
}} }}
> >
{#if ($pinnedModels ?? []).includes(model?.id)} {#if ($settings?.pinnedModels ?? []).includes(model?.id)}
<EyeSlash /> <EyeSlash />
{:else} {:else}
<Eye /> <Eye />
{/if} {/if}
<div class="flex items-center"> <div class="flex items-center">
{#if ($pinnedModels ?? []).includes(model?.id)} {#if ($settings?.pinnedModels ?? []).includes(model?.id)}
{$i18n.t('Hide from Sidebar')} {$i18n.t('Hide from Sidebar')}
{:else} {:else}
{$i18n.t('Keep in Sidebar')} {$i18n.t('Keep in Sidebar')}

View File

@ -57,6 +57,8 @@
export let className = 'w-[32rem]'; export let className = 'w-[32rem]';
export let triggerClassName = 'text-lg'; export let triggerClassName = 'text-lg';
export let pinModelHandler: (modelId: string) => void = () => {};
let tagsContainerElement; let tagsContainerElement;
let show = false; let show = false;
@ -500,6 +502,7 @@
{item} {item}
{index} {index}
{value} {value}
{pinModelHandler}
{unloadModelHandler} {unloadModelHandler}
onClick={() => { onClick={() => {
value = item.value; value = item.value;

View File

@ -22,7 +22,6 @@
socket, socket,
config, config,
isApp, isApp,
pinnedModels,
models models
} from '$lib/stores'; } from '$lib/stores';
import { onMount, getContext, tick, onDestroy } from 'svelte'; import { onMount, getContext, tick, onDestroy } from 'svelte';
@ -646,9 +645,9 @@
</div> </div>
{/if} {/if}
{#if ($pinnedModels ?? []).length > 0} {#if ($settings?.pinnedModels ?? []).length > 0}
<div class="pt-1.5"> <div class="pt-1.5">
{#each $pinnedModels as modelId (modelId)} {#each $settings.pinnedModels as modelId (modelId)}
{@const model = $models.find((model) => model.id === modelId)} {@const model = $models.find((model) => model.id === modelId)}
<div class="px-1.5 flex justify-center text-gray-800 dark:text-gray-200"> <div class="px-1.5 flex justify-center text-gray-800 dark:text-gray-200">
<a <a

View File

@ -52,7 +52,6 @@ export const pinnedChats = writable([]);
export const tags = writable([]); export const tags = writable([]);
export const models: Writable<Model[]> = writable([]); export const models: Writable<Model[]> = writable([]);
export const pinnedModels = writable([]);
export const prompts: Writable<null | Prompt[]> = writable(null); export const prompts: Writable<null | Prompt[]> = writable(null);
export const knowledge: Writable<null | Document[]> = writable(null); export const knowledge: Writable<null | Document[]> = writable(null);