From 2ce1e11c05fe94558d9e99b88030050ac0e9668d Mon Sep 17 00:00:00 2001 From: duanfuxiang Date: Thu, 24 Apr 2025 17:57:31 +0800 Subject: [PATCH] add collected models --- .../chat-view/chat-input/ModelSelect.tsx | 352 +++++++++++++++--- src/contexts/LLMContext.tsx | 7 - src/database/json/migrateToJsonDatabase.ts | 1 + src/types/settings.ts | 6 + 4 files changed, 301 insertions(+), 65 deletions(-) diff --git a/src/components/chat-view/chat-input/ModelSelect.tsx b/src/components/chat-view/chat-input/ModelSelect.tsx index f006796..c0dc2c3 100644 --- a/src/components/chat-view/chat-input/ModelSelect.tsx +++ b/src/components/chat-view/chat-input/ModelSelect.tsx @@ -1,6 +1,6 @@ import * as DropdownMenu from '@radix-ui/react-dropdown-menu' import Fuse, { FuseResult } from 'fuse.js' -import { ChevronDown, ChevronUp } from 'lucide-react' +import { ChevronDown, ChevronUp, Star, StarOff } from 'lucide-react' import { useEffect, useMemo, useRef, useState } from 'react' import { useSettings } from '../../../contexts/SettingsContext' @@ -15,11 +15,15 @@ type TextSegment = { type SearchableItem = { id: string; html: string | TextSegment[]; + provider?: string; + isCollected?: boolean; }; type HighlightedItem = { id: string; html: TextSegment[]; + provider?: string; + isCollected?: boolean; }; // Reuse highlight function from ProviderModelsPicker @@ -166,11 +170,18 @@ export function ModelSelect() { }, [settings.chatModelProvider, settings.chatModelId]) const searchableItems = useMemo(() => { + // 检查是否在收藏列表中 + const isInCollected = (id: string) => { + return settings.collectedChatModels?.some(item => item.provider === modelProvider && item.modelId === id) || false; + }; + return modelIds.map((id) => ({ id, html: id, + provider: modelProvider, + isCollected: isInCollected(id), })) - }, [modelIds]) + }, [modelIds, modelProvider, settings.collectedChatModels]) const fuse = useMemo(() => { return new Fuse(searchableItems, { @@ -185,15 +196,49 @@ export function ModelSelect() { }, [searchableItems]) const filteredOptions = useMemo(() => { + // 首先获取搜索结果 const results: HighlightedItem[] = searchTerm ? highlight(fuse.search(searchTerm)) : searchableItems.map(item => ({ ...item, html: typeof item.html === 'string' ? [{ text: item.html, isHighlighted: false }] : item.html })) + + // 如果没有搜索关键词,按收藏状态排序(收藏的在前面) + if (!searchTerm) { + return [...results.filter(item => item.isCollected), ...results.filter(item => !item.isCollected)] + } + return results }, [searchableItems, searchTerm, fuse]) + // 添加或删除收藏 + const toggleCollected = (id: string, e: React.MouseEvent) => { + e.stopPropagation(); + e.preventDefault(); + + const isCurrentlyCollected = settings.collectedChatModels?.some( + item => item.provider === modelProvider && item.modelId === id + ); + + let newCollectedModels = settings.collectedChatModels || []; + + if (isCurrentlyCollected) { + // 移除收藏 + newCollectedModels = newCollectedModels.filter( + item => !(item.provider === modelProvider && item.modelId === id) + ); + } else { + // 添加收藏 + newCollectedModels = [...newCollectedModels, { provider: modelProvider, modelId: id }]; + } + + setSettings({ + ...settings, + collectedChatModels: newCollectedModels, + }); + }; + return ( <> @@ -208,6 +253,65 @@ export function ModelSelect() { + {/* 收藏的模型区域 - 所有providers的收藏模型 */} + {settings.collectedChatModels?.length > 0 && ( +
+
+ collected models +
+
    + {settings.collectedChatModels.map((collectedModel, index) => ( + { + setSettings({ + ...settings, + chatModelProvider: collectedModel.provider, + chatModelId: collectedModel.modelId, + }) + setChatModelId(collectedModel.modelId) + setSearchTerm("") + setIsOpen(false) + }} + className={`infio-llm-setting-combobox-option ${index === selectedIndex ? 'is-selected' : ''}`} + onMouseEnter={() => setSelectedIndex(index)} + asChild + > +
  • +
    + {collectedModel.provider} + {collectedModel.modelId} +
    +
    + { + e.stopPropagation(); + e.preventDefault(); + + // 从收藏中删除 + const newCollectedModels = settings.collectedChatModels.filter( + item => !(item.provider === collectedModel.provider && item.modelId === collectedModel.modelId) + ); + + setSettings({ + ...settings, + collectedChatModels: newCollectedModels, + }); + }} /> +
    +
  • +
    + ))} +
+
+
+ )} +