refactor(MCPSettings): update navigation and enhance scroll position handling

- Updated navigation logic in `useMCPServers` and `McpServersList` to use server IDs in the URL for better routing.
- Implemented scroll position memory in `McpServersList` to enhance user experience when navigating back to the server list.
- Adjusted route parameters in `MCPSettings` to retrieve server IDs from the URL, improving data handling and clarity.
This commit is contained in:
kangfenmao 2025-07-25 10:15:13 +08:00
parent e3f061a54d
commit baad783d64
5 changed files with 37 additions and 14 deletions

View File

@ -83,7 +83,7 @@ export function useAssistant(id: string) {
),
updateAssistant: (assistant: Assistant) => dispatch(updateAssistant(assistant)),
updateAssistantSettings: (settings: Partial<AssistantSettings>) => {
dispatch(updateAssistantSettings({ assistantId: assistant.id, settings }))
assistant?.id && dispatch(updateAssistantSettings({ assistantId: assistant.id, settings }))
}
}
}

View File

@ -13,7 +13,7 @@ window.electron.ipcRenderer.on(IpcChannel.Mcp_ServersChanged, (_event, servers)
window.electron.ipcRenderer.on(IpcChannel.Mcp_AddServer, (_event, server: MCPServer) => {
store.dispatch(addMCPServer(server))
NavigationService.navigate?.('/settings/mcp')
NavigationService.navigate?.('/settings/mcp/settings', { state: { server } })
NavigationService.navigate?.(`/settings/mcp/settings/${encodeURIComponent(server.id)}`)
})
const selectMcpServers = (state) => state.mcp.servers

View File

@ -7,7 +7,7 @@ import { MCPServer } from '@renderer/types'
import { formatMcpError } from '@renderer/utils/error'
import { Badge, Button, Dropdown, Empty, Switch, Tag } from 'antd'
import { MonitorCheck, Plus, RefreshCw, Settings2, SquareArrowOutUpRight } from 'lucide-react'
import { FC, useCallback, useEffect, useState } from 'react'
import { FC, useCallback, useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useNavigate } from 'react-router'
import styled from 'styled-components'
@ -29,6 +29,28 @@ const McpServersList: FC = () => {
const [loadingServerIds, setLoadingServerIds] = useState<Set<string>>(new Set())
const [serverVersions, setServerVersions] = useState<Record<string, string | null>>({})
const scrollRef = useRef<HTMLDivElement>(null)
// 简单的滚动位置记忆
useEffect(() => {
// 恢复滚动位置
const savedScroll = sessionStorage.getItem('mcp-list-scroll')
if (savedScroll && scrollRef.current) {
scrollRef.current.scrollTop = Number(savedScroll)
}
// 保存滚动位置
const handleScroll = () => {
if (scrollRef.current) {
sessionStorage.setItem('mcp-list-scroll', String(scrollRef.current.scrollTop))
}
}
const container = scrollRef.current
container?.addEventListener('scroll', handleScroll)
return () => container?.removeEventListener('scroll', handleScroll)
}, [])
const fetchServerVersion = useCallback(async (server: MCPServer) => {
if (!server.isActive) return
@ -61,7 +83,7 @@ const McpServersList: FC = () => {
isActive: false
}
addMCPServer(newServer)
navigate(`/settings/mcp/settings`, { state: { server: newServer } })
navigate(`/settings/mcp/settings/${encodeURIComponent(newServer.id)}`)
window.message.success({ content: t('settings.mcp.addSuccess'), key: 'mcp-list' })
}, [addMCPServer, navigate, t])
@ -75,7 +97,7 @@ const McpServersList: FC = () => {
setIsAddModalVisible(false)
window.message.success({ content: t('settings.mcp.addSuccess'), key: 'mcp-quick-add' })
// Optionally navigate to the new server's settings page
// navigate(`/settings/mcp/settings`, { state: { server } })
// navigate(`/settings/mcp/settings/${encodeURIComponent(server.id)}`)
},
[addMCPServer, t]
)
@ -112,7 +134,7 @@ const McpServersList: FC = () => {
}
return (
<Container>
<Container ref={scrollRef}>
<ListHeader>
<SettingTitle style={{ gap: 3 }}>
<span>{t('settings.mcp.newServer')}</span>
@ -160,7 +182,9 @@ const McpServersList: FC = () => {
</ListHeader>
<DraggableList style={{ width: '100%' }} list={mcpServers} onUpdate={updateMcpServers}>
{(server: MCPServer) => (
<ServerCard key={server.id} onClick={() => navigate(`/settings/mcp/settings`, { state: { server } })}>
<ServerCard
key={server.id}
onClick={() => navigate(`/settings/mcp/settings/${encodeURIComponent(server.id)}`)}>
<ServerHeader>
<ServerName>
{server.logoUrl && <ServerLogo src={server.logoUrl} alt={`${server.name} logo`} />}
@ -190,7 +214,7 @@ const McpServersList: FC = () => {
<Button
icon={<Settings2 size={16} />}
type="text"
onClick={() => navigate(`/settings/mcp/settings`, { state: { server } })}
onClick={() => navigate(`/settings/mcp/settings/${encodeURIComponent(server.id)}`)}
/>
</StatusIndicator>
</ServerHeader>

View File

@ -10,7 +10,7 @@ import TextArea from 'antd/es/input/TextArea'
import { ChevronDown } from 'lucide-react'
import React, { useCallback, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useLocation, useNavigate } from 'react-router'
import { useNavigate, useParams } from 'react-router'
import styled from 'styled-components'
import { SettingContainer, SettingDivider, SettingGroup, SettingTitle } from '..'
@ -75,10 +75,9 @@ const parseKeyValueString = (str: string): Record<string, string> => {
const McpSettings: React.FC = () => {
const { t } = useTranslation()
const {
server: { id: serverId }
} = useLocation().state as { server: MCPServer }
const server = useMCPServer(serverId).server as MCPServer
const { serverId } = useParams<{ serverId: string }>()
const decodedServerId = serverId ? decodeURIComponent(serverId) : ''
const server = useMCPServer(decodedServerId).server as MCPServer
const { deleteMCPServer, updateMCPServer } = useMCPServers()
const [serverType, setServerType] = useState<MCPServer['type']>('stdio')
const [form] = Form.useForm<MCPFormValues>()

View File

@ -32,7 +32,7 @@ const MCPSettings: FC = () => {
<MainContainer>
<Routes>
<Route path="/" element={<McpServersList />} />
<Route path="settings" element={<McpSettings />} />
<Route path="settings/:serverId" element={<McpSettings />} />
<Route
path="npx-search"
element={