From 3f82a692a2dc4a1f2cc33392fd9a8d3b85b10852 Mon Sep 17 00:00:00 2001 From: one Date: Sat, 8 Mar 2025 17:17:47 +0800 Subject: [PATCH] feat: improve SelectModelPopup, fix model id concatenation (#2903) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: correctly concatenate model id * perf: delay model sorting * feat: sticky provider name during model selection * fix: model selector group title animation * fix: add back opacity --------- Co-authored-by: 亢奋猫 --- .../components/Popups/SelectModelPopup.tsx | 46 +++++++++++++------ 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/src/renderer/src/components/Popups/SelectModelPopup.tsx b/src/renderer/src/components/Popups/SelectModelPopup.tsx index 8dbf0f1f..aa8c2e10 100644 --- a/src/renderer/src/components/Popups/SelectModelPopup.tsx +++ b/src/renderer/src/components/Popups/SelectModelPopup.tsx @@ -66,22 +66,21 @@ const PopupContainer: React.FC = ({ model, resolve }) => { // 根据输入的文本筛选模型 const getFilteredModels = useCallback( (provider) => { - const nonEmbeddingModels = provider.models.filter((m) => !isEmbeddingModel(m)) + let models = provider.models.filter((m) => !isEmbeddingModel(m)) - if (!searchText.trim()) { - return sortBy(nonEmbeddingModels, ['group', 'name']) + if (searchText.trim()) { + const keywords = searchText.toLowerCase().split(/\s+/).filter(Boolean) + models = models.filter((m) => { + const fullName = provider.isSystem + ? `${m.name} ${provider.name} ${t('provider.' + provider.id)}` + : `${m.name} ${provider.name}` + + const lowerFullName = fullName.toLowerCase() + return keywords.every((keyword) => lowerFullName.includes(keyword)) + }) } - const keywords = searchText.toLowerCase().split(/\s+/).filter(Boolean) - - return sortBy(nonEmbeddingModels, ['group', 'name']).filter((m) => { - const fullName = provider.isSystem - ? `${m.name}${m.provider}${t('provider.' + provider.id)}` - : `${m.name}${m.provider}` - - const lowerFullName = fullName.toLowerCase() - return keywords.every((keyword) => lowerFullName.includes(keyword)) - }) + return sortBy(models, ['group', 'name']) }, [searchText, t] ) @@ -347,8 +346,27 @@ const StyledMenu = styled(Menu)` max-height: calc(60vh - 50px); .ant-menu-item-group-title { - padding: 5px 10px 0; + position: sticky; + top: 0; + z-index: 1; + margin: 0 -5px; + padding: 5px 10px; + padding-left: 18px; font-size: 12px; + font-weight: 500; + + /* Scroll-driven animation for sticky header */ + animation: background-change linear both; + animation-timeline: scroll(); + animation-range: entry 0% entry 1%; + } + + /* Simple animation that changes background color when sticky */ + @keyframes background-change { + to { + background-color: var(--color-background-soft); + opacity: 0.95; + } } .ant-menu-item {