瀏覽代碼

feat: pinned models

Timothy Jaeryang Baek 4 月之前
父節點
當前提交
a64667ca8d

+ 19 - 0
src/lib/components/chat/ModelSelector.svelte

@@ -25,6 +25,24 @@
 		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) {
 		selectedModels = selectedModels.map((model) =>
 			$models.map((m) => m.id).includes(model) ? model : ''
@@ -49,6 +67,7 @@
 							? ($user?.permissions?.chat?.temporary ?? true) &&
 								!($user?.permissions?.chat?.temporary_enforced ?? false)
 							: true}
+						{pinModelHandler}
 						bind:value={selectedModel}
 					/>
 				</div>

+ 4 - 8
src/lib/components/chat/ModelSelector/ModelItem.svelte

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

+ 5 - 5
src/lib/components/chat/ModelSelector/ModelItemMenu.svelte

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

+ 3 - 0
src/lib/components/chat/ModelSelector/Selector.svelte

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

+ 2 - 3
src/lib/components/layout/Sidebar.svelte

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

+ 0 - 1
src/lib/stores/index.ts

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