From ddc5f46e9b1ea33481f25815f5b5e3d51e423c85 Mon Sep 17 00:00:00 2001 From: one Date: Wed, 27 Aug 2025 00:04:52 +0800 Subject: [PATCH] feat: goto provider settings from models popup (#9573) * feat: goto provider settings from models popup * refactor: improve paddings * refactor: update types * refactor: update types * doc: update comments * refactor: more comments * refactor: scroll to the selected provider on navigation * test: update mocks --- .../__tests__/DraggableVirtualList.test.tsx | 10 +++- .../src/components/DraggableList/index.tsx | 6 ++- .../components/DraggableList/virtual-list.tsx | 35 ++++++++++++-- .../Popups/SelectModelPopup/popup.tsx | 33 +++++++++++-- .../Popups/SelectModelPopup/types.ts | 46 +++++++++++++++---- src/renderer/src/i18n/locales/en-us.json | 3 ++ src/renderer/src/i18n/locales/ja-jp.json | 3 ++ src/renderer/src/i18n/locales/ru-ru.json | 3 ++ src/renderer/src/i18n/locales/zh-cn.json | 3 ++ src/renderer/src/i18n/locales/zh-tw.json | 3 ++ src/renderer/src/i18n/translate/el-gr.json | 3 ++ src/renderer/src/i18n/translate/es-es.json | 3 ++ src/renderer/src/i18n/translate/fr-fr.json | 3 ++ src/renderer/src/i18n/translate/pt-pt.json | 3 ++ .../pages/settings/ProviderSettings/index.tsx | 23 ++++++++-- 15 files changed, 154 insertions(+), 26 deletions(-) diff --git a/src/renderer/src/components/DraggableList/__tests__/DraggableVirtualList.test.tsx b/src/renderer/src/components/DraggableList/__tests__/DraggableVirtualList.test.tsx index 523ef89d26..d931d961b8 100644 --- a/src/renderer/src/components/DraggableList/__tests__/DraggableVirtualList.test.tsx +++ b/src/renderer/src/components/DraggableList/__tests__/DraggableVirtualList.test.tsx @@ -32,7 +32,7 @@ vi.mock('@hello-pangea/dnd', () => ({ })) vi.mock('@tanstack/react-virtual', () => ({ - useVirtualizer: ({ count }) => ({ + useVirtualizer: ({ count, getScrollElement }) => ({ getVirtualItems: () => Array.from({ length: count }, (_, index) => ({ index, @@ -41,7 +41,13 @@ vi.mock('@tanstack/react-virtual', () => ({ size: 50 })), getTotalSize: () => count * 50, - measureElement: vi.fn() + measureElement: vi.fn(), + scrollToIndex: vi.fn(), + scrollToOffset: vi.fn(), + scrollElement: getScrollElement(), + measure: vi.fn(), + resizeItem: vi.fn(), + getVirtualIndexes: () => Array.from({ length: count }, (_, i) => i) }) })) diff --git a/src/renderer/src/components/DraggableList/index.tsx b/src/renderer/src/components/DraggableList/index.tsx index 642b12bfd7..3a953115fa 100644 --- a/src/renderer/src/components/DraggableList/index.tsx +++ b/src/renderer/src/components/DraggableList/index.tsx @@ -1,3 +1,7 @@ export { default as DraggableList } from './list' export { useDraggableReorder } from './useDraggableReorder' -export { default as DraggableVirtualList } from './virtual-list' +export { + default as DraggableVirtualList, + type DraggableVirtualListProps, + type DraggableVirtualListRef +} from './virtual-list' diff --git a/src/renderer/src/components/DraggableList/virtual-list.tsx b/src/renderer/src/components/DraggableList/virtual-list.tsx index 69b0ced667..e915eec1fe 100644 --- a/src/renderer/src/components/DraggableList/virtual-list.tsx +++ b/src/renderer/src/components/DraggableList/virtual-list.tsx @@ -10,8 +10,19 @@ import { } from '@hello-pangea/dnd' import Scrollbar from '@renderer/components/Scrollbar' import { droppableReorder } from '@renderer/utils' -import { useVirtualizer } from '@tanstack/react-virtual' -import { type Key, memo, useCallback, useRef } from 'react' +import { type ScrollToOptions, useVirtualizer, type VirtualItem } from '@tanstack/react-virtual' +import { type Key, memo, useCallback, useImperativeHandle, useRef } from 'react' + +export interface DraggableVirtualListRef { + measure: () => void + scrollElement: () => HTMLDivElement | null + scrollToOffset: (offset: number, options?: ScrollToOptions) => void + scrollToIndex: (index: number, options?: ScrollToOptions) => void + resizeItem: (index: number, size: number) => void + getTotalSize: () => number + getVirtualItems: () => VirtualItem[] + getVirtualIndexes: () => number[] +} /** * 泛型 Props,用于配置 DraggableVirtualList。 @@ -31,8 +42,8 @@ import { type Key, memo, useCallback, useRef } from 'react' * @property {React.ReactNode} [header] 列表头部内容 * @property {(item: T, index: number) => React.ReactNode} children 列表项渲染函数 */ -interface DraggableVirtualListProps { - ref?: React.Ref +export interface DraggableVirtualListProps { + ref?: React.Ref className?: string style?: React.CSSProperties scrollerStyle?: React.CSSProperties @@ -100,9 +111,23 @@ function DraggableVirtualList({ overscan }) + useImperativeHandle( + ref, + () => ({ + measure: () => virtualizer.measure(), + scrollElement: () => virtualizer.scrollElement, + scrollToOffset: (offset, options) => virtualizer.scrollToOffset(offset, options), + scrollToIndex: (index, options) => virtualizer.scrollToIndex(index, options), + resizeItem: (index, size) => virtualizer.resizeItem(index, size), + getTotalSize: () => virtualizer.getTotalSize(), + getVirtualItems: () => virtualizer.getVirtualItems(), + getVirtualIndexes: () => virtualizer.getVirtualIndexes() + }), + [virtualizer] + ) + return (
diff --git a/src/renderer/src/components/Popups/SelectModelPopup/popup.tsx b/src/renderer/src/components/Popups/SelectModelPopup/popup.tsx index 3ea309f6a0..b45cb0a63c 100644 --- a/src/renderer/src/components/Popups/SelectModelPopup/popup.tsx +++ b/src/renderer/src/components/Popups/SelectModelPopup/popup.tsx @@ -8,8 +8,9 @@ import { useProviders } from '@renderer/hooks/useProvider' import { getModelUniqId } from '@renderer/services/ModelService' import { Model, Provider } from '@renderer/types' import { classNames, filterModelsByKeywords, getFancyProviderName } from '@renderer/utils' -import { Avatar, Divider, Empty, Modal } from 'antd' +import { Avatar, Button, Divider, Empty, Modal, Tooltip } from 'antd' import { first, sortBy } from 'lodash' +import { SettingsIcon } from 'lucide-react' import React, { startTransition, useCallback, @@ -150,6 +151,22 @@ const PopupContainer: React.FC = ({ model, resolve, modelFilter }) => { key: `provider-${p.id}`, type: 'group', name: getFancyProviderName(p), + actions: ( + +