diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx
index e138a812ab..c3d6fd9d7e 100644
--- a/src/renderer/src/App.tsx
+++ b/src/renderer/src/App.tsx
@@ -7,15 +7,13 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { Provider } from 'react-redux'
import { PersistGate } from 'redux-persist/integration/react'
-// TODO: 新路由系统入口,迁移完成后启用
-// import { AppShell } from './components/layout/AppShell'
+import { AppShell } from './components/layout/AppShell'
import TopViewContainer from './components/TopView'
import AntdProvider from './context/AntdProvider'
import { CodeStyleProvider } from './context/CodeStyleProvider'
import { NotificationProvider } from './context/NotificationProvider'
import StyleSheetManager from './context/StyleSheetManager'
import { ThemeProvider } from './context/ThemeProvider'
-import Router from './Router'
const logger = loggerService.withContext('App.tsx')
@@ -44,8 +42,7 @@ function App(): React.ReactElement {
- {/* TODO: 迁移完成后切换到 */}
-
+
diff --git a/src/renderer/src/Router.tsx b/src/renderer/src/Router.tsx
deleted file mode 100644
index fb555d8bc3..0000000000
--- a/src/renderer/src/Router.tsx
+++ /dev/null
@@ -1,67 +0,0 @@
-import '@renderer/databases'
-
-import type { FC } from 'react'
-import { useMemo } from 'react'
-import { HashRouter, Route, Routes } from 'react-router-dom'
-
-import Sidebar from './components/app/Sidebar'
-import { ErrorBoundary } from './components/ErrorBoundary'
-import TabsContainer from './components/Tab/TabContainer'
-import NavigationHandler from './handler/NavigationHandler'
-import { useNavbarPosition } from './hooks/useNavbar'
-import CodeToolsPage from './pages/code/CodeToolsPage'
-import FilesPage from './pages/files/FilesPage'
-import HomePage from './pages/home/HomePage'
-import KnowledgePage from './pages/knowledge/KnowledgePage'
-import LaunchpadPage from './pages/launchpad/LaunchpadPage'
-import MinAppPage from './pages/minapps/MinAppPage'
-import MinAppsPage from './pages/minapps/MinAppsPage'
-import NotesPage from './pages/notes/NotesPage'
-import PaintingsRoutePage from './pages/paintings/PaintingsRoutePage'
-import SettingsPage from './pages/settings/SettingsPage'
-import AssistantPresetsPage from './pages/store/assistants/presets/AssistantPresetsPage'
-import TranslatePage from './pages/translate/TranslatePage'
-
-const Router: FC = () => {
- const { navbarPosition } = useNavbarPosition()
-
- const routes = useMemo(() => {
- return (
-
-
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
-
-
- )
- }, [])
-
- if (navbarPosition === 'left') {
- return (
-
-
- {routes}
-
-
- )
- }
-
- return (
-
-
- {routes}
-
- )
-}
-
-export default Router
diff --git a/src/renderer/src/components/FreeTrialModelTag.tsx b/src/renderer/src/components/FreeTrialModelTag.tsx
index ad142ae0cf..649452f3de 100644
--- a/src/renderer/src/components/FreeTrialModelTag.tsx
+++ b/src/renderer/src/components/FreeTrialModelTag.tsx
@@ -30,13 +30,13 @@ export const FreeTrialModelTag: FC = ({ model, showLabel = true }) => {
}
const onSelectProvider = () => {
- NavigationService.navigate!(`/settings/provider?id=${providerId}`)
+ NavigationService.navigate!({ to: `/settings/provider`, search: { id: providerId } })
}
const onNavigateProvider = (e: MouseEvent) => {
e.stopPropagation()
SelectModelPopup.hide()
- NavigationService.navigate!(`/settings/provider?id=${providerId}`)
+ NavigationService.navigate?.({ to: '/settings/provider', search: { id: providerId } })
}
if (!showLabel) {
diff --git a/src/renderer/src/components/MinApp/MinApp.tsx b/src/renderer/src/components/MinApp/MinApp.tsx
index 801db2b082..3fb0e89715 100644
--- a/src/renderer/src/components/MinApp/MinApp.tsx
+++ b/src/renderer/src/components/MinApp/MinApp.tsx
@@ -6,11 +6,11 @@ import { useMinappPopup } from '@renderer/hooks/useMinappPopup'
import { useMinapps } from '@renderer/hooks/useMinapps'
import { useNavbarPosition } from '@renderer/hooks/useNavbar'
import type { MinAppType } from '@renderer/types'
+import { useNavigate } from '@tanstack/react-router'
import type { MenuProps } from 'antd'
import { Dropdown } from 'antd'
import type { FC } from 'react'
import { useTranslation } from 'react-i18next'
-import { useNavigate } from 'react-router-dom'
import styled from 'styled-components'
interface Props {
@@ -47,7 +47,7 @@ const MinApp: FC = ({ app, onClick, size = 60, isLast }) => {
const handleClick = () => {
if (isTopNavbar) {
// 顶部导航栏:导航到小程序页面
- navigate(`/apps/${app.id}`)
+ navigate({ to: `/apps/${app.id}` })
} else {
// 侧边导航栏:保持原有弹窗行为
openMinappKeepAlive(app)
diff --git a/src/renderer/src/components/MinApp/MinAppTabsPool.tsx b/src/renderer/src/components/MinApp/MinAppTabsPool.tsx
index 1bef9a532a..6bf54d4c7f 100644
--- a/src/renderer/src/components/MinApp/MinAppTabsPool.tsx
+++ b/src/renderer/src/components/MinApp/MinAppTabsPool.tsx
@@ -3,9 +3,9 @@ import WebviewContainer from '@renderer/components/MinApp/WebviewContainer'
import { useMinapps } from '@renderer/hooks/useMinapps'
import { useNavbarPosition } from '@renderer/hooks/useNavbar'
import { getWebviewLoaded, setWebviewLoaded } from '@renderer/utils/webviewStateManager'
+import { useLocation } from '@tanstack/react-router'
import type { WebviewTag } from 'electron'
import React, { useEffect, useRef } from 'react'
-import { useLocation } from 'react-router-dom'
import styled from 'styled-components'
/**
diff --git a/src/renderer/src/components/Popups/SelectModelPopup/popup.tsx b/src/renderer/src/components/Popups/SelectModelPopup/popup.tsx
index 1aa7859a99..908f471819 100644
--- a/src/renderer/src/components/Popups/SelectModelPopup/popup.tsx
+++ b/src/renderer/src/components/Popups/SelectModelPopup/popup.tsx
@@ -193,7 +193,7 @@ const PopupContainer: React.FC = ({ model, filter: baseFilter, showTagFil
e.stopPropagation()
setOpen(false)
resolve(undefined)
- window.navigate(`/settings/provider?id=${p.id}`)
+ window.navigate({ to: '/settings/provider', search: { id: p.id } })
}}
/>
diff --git a/src/renderer/src/components/Tab/TabContainer.tsx b/src/renderer/src/components/Tab/TabContainer.tsx
index 08f16bb9cc..986c6ec782 100644
--- a/src/renderer/src/components/Tab/TabContainer.tsx
+++ b/src/renderer/src/components/Tab/TabContainer.tsx
@@ -17,6 +17,7 @@ import { addTab, removeTab, setActiveTab, setTabs } from '@renderer/store/tabs'
import type { MinAppType } from '@renderer/types'
import { classNames } from '@renderer/utils'
import { ThemeMode } from '@shared/data/preference/preferenceTypes'
+import { useLocation, useNavigate } from '@tanstack/react-router'
import type { LRUCache } from 'lru-cache'
import {
FileSearch,
@@ -37,7 +38,6 @@ import {
} from 'lucide-react'
import { useCallback, useEffect, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
-import { useLocation, useNavigate } from 'react-router-dom'
import styled from 'styled-components'
import MinAppIcon from '../Icons/MinAppIcon'
@@ -203,17 +203,17 @@ const TabsContainer: React.FC = ({ children }) => {
const handleAddTab = () => {
hideMinappPopup()
- navigate('/launchpad')
+ navigate({ to: '/launchpad' })
}
const handleSettingsClick = () => {
hideMinappPopup()
- navigate(lastSettingsPath)
+ navigate({ to: lastSettingsPath })
}
const handleTabClick = (tab: Tab) => {
hideMinappPopup()
- navigate(tab.path)
+ navigate({ to: tab.path })
}
const visibleTabs = useMemo(() => tabs.filter((tab) => !specialTabs.includes(tab.id)), [tabs])
diff --git a/src/renderer/src/components/app/Sidebar.tsx b/src/renderer/src/components/app/Sidebar.tsx
index de30b1467b..d332a4a78f 100644
--- a/src/renderer/src/components/app/Sidebar.tsx
+++ b/src/renderer/src/components/app/Sidebar.tsx
@@ -30,9 +30,9 @@ import {
} from 'lucide-react'
import type { FC } from 'react'
import { useTranslation } from 'react-i18next'
-import { useLocation, useNavigate } from 'react-router-dom'
import styled from 'styled-components'
+import { useTabs } from '../../hooks/useTabs'
import UserPopup from '../Popups/UserPopup'
import { SidebarOpenedMinappTabs, SidebarPinnedApps } from './PinnedMinapps'
@@ -40,9 +40,11 @@ const Sidebar: FC = () => {
const { hideMinappPopup } = useMinappPopup()
const { pinned, minappShow } = useMinapps()
const [visibleSidebarIcons] = usePreference('ui.sidebar.icons.visible')
+ const { tabs, activeTabId, updateTab } = useTabs()
- const { pathname } = useLocation()
- const navigate = useNavigate()
+ // 获取当前 Tab 的 URL 作为 pathname
+ const activeTab = tabs.find((t) => t.id === activeTabId)
+ const pathname = activeTab?.url || '/'
const { theme, settedTheme, toggleTheme } = useTheme()
const avatar = useAvatar()
@@ -54,9 +56,12 @@ const Sidebar: FC = () => {
const showPinnedApps = pinned.length > 0 && visibleSidebarIcons.includes('minapp')
+ // 在当前 Tab 内跳转
const to = async (path: string) => {
await modelGenerating()
- navigate(path)
+ if (activeTabId) {
+ updateTab(activeTabId, { url: path })
+ }
}
const isFullscreen = useFullscreen()
@@ -121,14 +126,16 @@ const Sidebar: FC = () => {
const MainMenus: FC = () => {
const { hideMinappPopup } = useMinappPopup()
const { minappShow } = useMinapps()
+ const { tabs, activeTabId, updateTab } = useTabs()
+
+ // 获取当前 Tab 的 URL 作为 pathname
+ const activeTab = tabs.find((t) => t.id === activeTabId)
+ const pathname = activeTab?.url || '/'
- const { pathname } = useLocation()
const [visibleSidebarIcons] = usePreference('ui.sidebar.icons.visible')
const { defaultPaintingProvider } = useSettings()
- const navigate = useNavigate()
const { theme } = useTheme()
- const isRoute = (path: string): string => (pathname === path && !minappShow ? 'active' : '')
const isRoutes = (path: string): string => (pathname.startsWith(path) && !minappShow ? 'active' : '')
const iconMap = {
@@ -144,7 +151,7 @@ const MainMenus: FC = () => {
}
const pathMap = {
- assistants: '/',
+ assistants: '/chat',
store: '/store',
paintings: `/paintings/${defaultPaintingProvider}`,
translate: '/translate',
@@ -155,17 +162,24 @@ const MainMenus: FC = () => {
notes: '/notes'
}
+ // 在当前 Tab 内跳转
+ const to = async (path: string) => {
+ await modelGenerating()
+ if (activeTabId) {
+ updateTab(activeTabId, { url: path })
+ }
+ }
+
return visibleSidebarIcons.map((icon) => {
const path = pathMap[icon]
- const isActive = path === '/' ? isRoute(path) : isRoutes(path)
+ const isActive = isRoutes(path)
return (
{
hideMinappPopup()
- await modelGenerating()
- navigate(path)
+ await to(path)
}}>
{iconMap[icon]}
diff --git a/src/renderer/src/components/layout/AppShell.tsx b/src/renderer/src/components/layout/AppShell.tsx
index aece19abd7..75e9e5a824 100644
--- a/src/renderer/src/components/layout/AppShell.tsx
+++ b/src/renderer/src/components/layout/AppShell.tsx
@@ -1,3 +1,5 @@
+import '@renderer/databases'
+
import { cn, Tabs, TabsList, TabsTrigger } from '@cherrystudio/ui'
import { Plus, X } from 'lucide-react'
import { Activity } from 'react'
@@ -31,7 +33,7 @@ export const AppShell = () => {
id: uuid(),
type: 'route',
url: '/',
- title: 'New Tab',
+ title: 'New Tab'
})
}
diff --git a/src/renderer/src/env.d.ts b/src/renderer/src/env.d.ts
index f4452a5c31..8ff317bf1b 100644
--- a/src/renderer/src/env.d.ts
+++ b/src/renderer/src/env.d.ts
@@ -2,8 +2,8 @@
import type { PermissionUpdate } from '@anthropic-ai/claude-agent-sdk'
import type { ToastUtilities } from '@cherrystudio/ui'
+import type { UseNavigateResult } from '@tanstack/react-router'
import type { HookAPI } from 'antd/es/modal/useModal'
-import type { NavigateFunction } from 'react-router-dom'
interface ImportMetaEnv {
VITE_RENDERER_INTEGRATED_MODEL: string
@@ -18,7 +18,7 @@ declare global {
root: HTMLElement
modal: HookAPI
store: any
- navigate: NavigateFunction
+ navigate: UseNavigateResult
toast: ToastUtilities
agentTools: {
respondToPermission: (payload: {
diff --git a/src/renderer/src/handler/NavigationHandler.tsx b/src/renderer/src/handler/NavigationHandler.tsx
index 5e1ef56113..578f0daab7 100644
--- a/src/renderer/src/handler/NavigationHandler.tsx
+++ b/src/renderer/src/handler/NavigationHandler.tsx
@@ -1,8 +1,8 @@
import { useAppSelector } from '@renderer/store'
import { IpcChannel } from '@shared/IpcChannel'
+import { useLocation, useNavigate } from '@tanstack/react-router'
import { useEffect } from 'react'
import { useHotkeys } from 'react-hotkeys-hook'
-import { useLocation, useNavigate } from 'react-router-dom'
const NavigationHandler: React.FC = () => {
const location = useLocation()
@@ -17,7 +17,7 @@ const NavigationHandler: React.FC = () => {
if (location.pathname.startsWith('/settings')) {
return
}
- navigate('/settings/provider')
+ navigate({ to: '/settings/provider' })
},
{
splitKey: '!',
@@ -30,7 +30,7 @@ const NavigationHandler: React.FC = () => {
// Listen for navigate to About page event from macOS menu
useEffect(() => {
const handleNavigateToAbout = () => {
- navigate('/settings/about')
+ navigate({ to: '/settings/about' })
}
const removeListener = window.electron.ipcRenderer.on(IpcChannel.Windows_NavigateToAbout, handleNavigateToAbout)
diff --git a/src/renderer/src/hooks/useAppInit.ts b/src/renderer/src/hooks/useAppInit.ts
index 9c747033a9..e21b1ac95d 100644
--- a/src/renderer/src/hooks/useAppInit.ts
+++ b/src/renderer/src/hooks/useAppInit.ts
@@ -64,7 +64,7 @@ export function useAppInit() {
useEffect(() => {
window.api.getDataPathFromArgs().then((dataPath) => {
if (dataPath) {
- window.navigate('/settings/data', { replace: true })
+ window.navigate({ to: '/settings/data', replace: true })
}
})
}, [])
diff --git a/src/renderer/src/hooks/useMCPServers.ts b/src/renderer/src/hooks/useMCPServers.ts
index 26731e14fd..d9f59ca1a1 100644
--- a/src/renderer/src/hooks/useMCPServers.ts
+++ b/src/renderer/src/hooks/useMCPServers.ts
@@ -13,8 +13,8 @@ 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/${encodeURIComponent(server.id)}`)
+ NavigationService.navigate?.({ to: '/settings/mcp' })
+ NavigationService.navigate?.({ to: `/settings/mcp/settings/${encodeURIComponent(server.id)}` })
})
const selectMcpServers = (state: RootState) => state.mcp.servers
diff --git a/src/renderer/src/hooks/useMinappPopup.ts b/src/renderer/src/hooks/useMinappPopup.ts
index f08924bd0a..ccf06baba5 100644
--- a/src/renderer/src/hooks/useMinappPopup.ts
+++ b/src/renderer/src/hooks/useMinappPopup.ts
@@ -186,7 +186,7 @@ export const useMinappPopup = () => {
// Then navigate to the app tab using NavigationService
if (NavigationService.navigate) {
- NavigationService.navigate(`/apps/${config.id}`)
+ NavigationService.navigate({ to: `/apps/${config.id}` })
}
} else {
// For side navbar, use the traditional popup system
diff --git a/src/renderer/src/pages/code/CodeToolsPage.tsx b/src/renderer/src/pages/code/CodeToolsPage.tsx
index 1e90e8cf57..4944367874 100644
--- a/src/renderer/src/pages/code/CodeToolsPage.tsx
+++ b/src/renderer/src/pages/code/CodeToolsPage.tsx
@@ -19,12 +19,12 @@ import { getClaudeSupportedProviders } from '@renderer/utils/provider'
import type { TerminalConfig } from '@shared/config/constant'
import { codeTools, terminalApps } from '@shared/config/constant'
import { isSiliconAnthropicCompatibleModel } from '@shared/config/providers'
+import { Link } from '@tanstack/react-router'
import { Alert, Checkbox, Input, Popover, Select, Space } from 'antd'
import { ArrowUpRight, Download, FolderOpen, HelpCircle, Terminal, X } from 'lucide-react'
import type { FC } from 'react'
import { useCallback, useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { Link } from 'react-router-dom'
import styled from 'styled-components'
import {
diff --git a/src/renderer/src/pages/history/components/TopicMessages.tsx b/src/renderer/src/pages/history/components/TopicMessages.tsx
index 3d1400e7d4..48ab4ad6bd 100644
--- a/src/renderer/src/pages/history/components/TopicMessages.tsx
+++ b/src/renderer/src/pages/history/components/TopicMessages.tsx
@@ -11,9 +11,9 @@ import { getTopicById } from '@renderer/hooks/useTopic'
import { getAssistantById } from '@renderer/services/AssistantService'
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
import { locateToMessage } from '@renderer/services/MessagesService'
-import NavigationService from '@renderer/services/NavigationService'
import type { Topic } from '@renderer/types'
import { classNames, runAsyncFunction } from '@renderer/utils'
+import { useNavigate } from '@tanstack/react-router'
import { Divider, Empty } from 'antd'
import { t } from 'i18next'
import { Forward } from 'lucide-react'
@@ -27,7 +27,8 @@ interface Props extends React.HTMLAttributes {
}
const TopicMessages: FC = ({ topic: _topic, ...props }) => {
- const navigate = NavigationService.navigate!
+ const navigate = useNavigate()
+
const { handleScroll, containerRef } = useScrollPosition('TopicMessages')
const [messageStyle] = usePreference('chat.message.style')
const { setTimeoutTimer } = useTimer()
@@ -53,7 +54,7 @@ const TopicMessages: FC = ({ topic: _topic, ...props }) => {
await modelGenerating()
SearchPopup.hide()
const assistant = getAssistantById(topic.assistantId)
- navigate('/', { state: { assistant, topic } })
+ navigate({ to: '/chat', search: { assistantId: assistant?.id, topicId: topic.id } })
setTimeoutTimer('onContinueChat', () => EventEmitter.emit(EVENT_NAMES.SHOW_TOPIC_SIDEBAR), 100)
}
diff --git a/src/renderer/src/pages/home/HomePage.tsx b/src/renderer/src/pages/home/HomePage.tsx
index 4c216cf168..6c5d31e738 100644
--- a/src/renderer/src/pages/home/HomePage.tsx
+++ b/src/renderer/src/pages/home/HomePage.tsx
@@ -10,11 +10,11 @@ import { newMessagesActions } from '@renderer/store/newMessage'
import { setActiveAgentId, setActiveTopicOrSessionAction } from '@renderer/store/runtime'
import type { Assistant, Topic } from '@renderer/types'
import { MIN_WINDOW_HEIGHT, MIN_WINDOW_WIDTH, SECOND_MIN_WINDOW_WIDTH } from '@shared/config/constant'
+import { useNavigate, useSearch } from '@tanstack/react-router'
import { AnimatePresence, motion } from 'motion/react'
import type { FC } from 'react'
import { startTransition, useCallback, useEffect, useState } from 'react'
import { useDispatch } from 'react-redux'
-import { useLocation, useNavigate } from 'react-router-dom'
import styled from 'styled-components'
import Chat from './Chat'
@@ -31,13 +31,23 @@ const HomePage: FC = () => {
// Initialize agent session hook
useAgentSessionInitializer()
- const location = useLocation()
- const state = location.state
+ const search = useSearch({ strict: false }) as { assistantId?: string; topicId?: string }
+
+ // 根据 search params 中的 ID 查找对应的 assistant
+ const assistantFromSearch = search.assistantId
+ ? assistants.find((a) => a.id === search.assistantId)
+ : undefined
const [activeAssistant, _setActiveAssistant] = useState(
- state?.assistant || _activeAssistant || assistants[0]
+ assistantFromSearch || _activeAssistant || assistants[0]
)
- const { activeTopic, setActiveTopic: _setActiveTopic } = useActiveTopic(activeAssistant?.id ?? '', state?.topic)
+
+ // 根据 search params 中的 topicId 查找对应的 topic
+ const topicFromSearch = search.topicId
+ ? activeAssistant?.topics?.find((t) => t.id === search.topicId)
+ : undefined
+
+ const { activeTopic, setActiveTopic: _setActiveTopic } = useActiveTopic(activeAssistant?.id ?? '', topicFromSearch)
const [showAssistants] = usePreference('assistant.tab.show')
const [showTopics] = usePreference('topic.tab.show')
const [topicPosition] = usePreference('topic.position')
@@ -80,10 +90,10 @@ const HomePage: FC = () => {
}, [navigate])
useEffect(() => {
- state?.assistant && setActiveAssistant(state?.assistant)
- state?.topic && setActiveTopic(state?.topic)
+ assistantFromSearch && setActiveAssistant(assistantFromSearch)
+ topicFromSearch && setActiveTopic(topicFromSearch)
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [state])
+ }, [search.assistantId, search.topicId])
useEffect(() => {
const canMinimize = topicPosition == 'left' ? !showAssistants : !showAssistants && !showTopics
diff --git a/src/renderer/src/pages/home/Inputbar/tools/components/KnowledgeBaseButton.tsx b/src/renderer/src/pages/home/Inputbar/tools/components/KnowledgeBaseButton.tsx
index 9d43284022..e8d587db5d 100644
--- a/src/renderer/src/pages/home/Inputbar/tools/components/KnowledgeBaseButton.tsx
+++ b/src/renderer/src/pages/home/Inputbar/tools/components/KnowledgeBaseButton.tsx
@@ -5,11 +5,11 @@ import { QuickPanelReservedSymbol, useQuickPanel } from '@renderer/components/Qu
import type { ToolQuickPanelApi } from '@renderer/pages/home/Inputbar/types'
import { useAppSelector } from '@renderer/store'
import type { KnowledgeBase } from '@renderer/types'
+import { useNavigate } from '@tanstack/react-router'
import { CircleX, FileSearch, Plus } from 'lucide-react'
import type { FC } from 'react'
import { memo, useCallback, useEffect, useMemo, useRef } from 'react'
import { useTranslation } from 'react-i18next'
-import { useNavigate } from 'react-router'
interface Props {
quickPanel: ToolQuickPanelApi
@@ -54,7 +54,7 @@ const KnowledgeBaseButton: FC = ({ quickPanel, selectedBases, onSelect, d
items.push({
label: t('knowledge.add.title') + '...',
icon: ,
- action: () => navigate('/knowledge'),
+ action: () => navigate({ to: '/knowledge' }),
isSelected: false
})
diff --git a/src/renderer/src/pages/home/Inputbar/tools/components/MCPToolsButton.tsx b/src/renderer/src/pages/home/Inputbar/tools/components/MCPToolsButton.tsx
index 174a96936f..42eec3acd2 100644
--- a/src/renderer/src/pages/home/Inputbar/tools/components/MCPToolsButton.tsx
+++ b/src/renderer/src/pages/home/Inputbar/tools/components/MCPToolsButton.tsx
@@ -12,12 +12,12 @@ import { EventEmitter } from '@renderer/services/EventService'
import type { MCPPrompt, MCPResource, MCPServer } from '@renderer/types'
import { isToolUseModeFunction } from '@renderer/utils/assistant'
import { isGeminiWebSearchProvider, isSupportUrlContextProvider } from '@renderer/utils/provider'
+import { useNavigate } from '@tanstack/react-router'
import { Form, Input } from 'antd'
import { CircleX, Hammer, Plus } from 'lucide-react'
import type { FC } from 'react'
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { useNavigate } from 'react-router'
interface Props {
assistantId: string
@@ -205,7 +205,7 @@ const MCPToolsButton: FC = ({ quickPanel, setInputValue, resizeTextArea,
newList.push({
label: t('settings.mcp.addServer.label') + '...',
icon: ,
- action: () => navigate('/settings/mcp')
+ action: () => navigate({ to: '/settings/mcp' })
})
newList.unshift({
diff --git a/src/renderer/src/pages/home/Inputbar/tools/components/useMentionModelsPanel.tsx b/src/renderer/src/pages/home/Inputbar/tools/components/useMentionModelsPanel.tsx
index cda8816c6b..aa496e5265 100644
--- a/src/renderer/src/pages/home/Inputbar/tools/components/useMentionModelsPanel.tsx
+++ b/src/renderer/src/pages/home/Inputbar/tools/components/useMentionModelsPanel.tsx
@@ -9,6 +9,7 @@ import { getModelUniqId } from '@renderer/services/ModelService'
import type { FileType, Model } from '@renderer/types'
import { FileTypes } from '@renderer/types'
import { getFancyProviderName } from '@renderer/utils'
+import { useNavigate } from '@tanstack/react-router'
import { Avatar } from 'antd'
import { useLiveQuery } from 'dexie-react-hooks'
import { first, sortBy } from 'lodash'
@@ -16,7 +17,6 @@ import { AtSign, CircleX, Plus } from 'lucide-react'
import type React from 'react'
import { useCallback, useEffect, useMemo, useRef } from 'react'
import { useTranslation } from 'react-i18next'
-import { useNavigate } from 'react-router'
import styled from 'styled-components'
export type MentionTriggerInfo = { type: 'input' | 'button'; position?: number; originalText?: string }
@@ -194,7 +194,7 @@ export const useMentionModelsPanel = (params: Params, role: 'button' | 'manager'
items.push({
label: t('settings.models.add.add_model') + '...',
icon: ,
- action: () => navigate('/settings/provider'),
+ action: () => navigate({ to: '/settings/provider' }),
isSelected: false
})
diff --git a/src/renderer/src/pages/home/Messages/Blocks/ErrorBlock.tsx b/src/renderer/src/pages/home/Messages/Blocks/ErrorBlock.tsx
index 1cb445f12d..7399dc226a 100644
--- a/src/renderer/src/pages/home/Messages/Blocks/ErrorBlock.tsx
+++ b/src/renderer/src/pages/home/Messages/Blocks/ErrorBlock.tsx
@@ -3,7 +3,6 @@ import CodeViewer from '@renderer/components/CodeViewer'
import { useCodeStyle } from '@renderer/context/CodeStyleProvider'
import { useTimer } from '@renderer/hooks/useTimer'
import { getHttpMessageLabel, getProviderLabel } from '@renderer/i18n/label'
-import { getProviderById } from '@renderer/services/ProviderService'
import { useAppDispatch } from '@renderer/store'
import { removeBlocksThunk } from '@renderer/store/thunk/messageThunk'
import type { SerializedAiSdkError, SerializedAiSdkErrorUnion, SerializedError } from '@renderer/types/error'
@@ -33,10 +32,10 @@ import {
} from '@renderer/types/error'
import type { ErrorMessageBlock, Message } from '@renderer/types/newMessage'
import { formatAiSdkError, formatError, safeToString } from '@renderer/utils/error'
+import { Link } from '@tanstack/react-router'
import { Alert as AntdAlert, Modal } from 'antd'
import React, { useEffect, useState } from 'react'
import { Trans, useTranslation } from 'react-i18next'
-import { Link } from 'react-router-dom'
import styled from 'styled-components'
const HTTP_ERROR_CODES = [400, 401, 403, 404, 429, 500, 502, 503, 504]
@@ -71,8 +70,8 @@ const ErrorMessage: React.FC<{ block: ErrorMessageBlock }> = ({ block }) => {
provider: (
)
}}
diff --git a/src/renderer/src/pages/home/Navbar.tsx b/src/renderer/src/pages/home/Navbar.tsx
index fc3e1a76a1..20479478a6 100644
--- a/src/renderer/src/pages/home/Navbar.tsx
+++ b/src/renderer/src/pages/home/Navbar.tsx
@@ -16,6 +16,7 @@ import styled from 'styled-components'
import AssistantsDrawer from './components/AssistantsDrawer'
import UpdateAppButton from './components/UpdateAppButton'
+
interface Props {
activeAssistant: Assistant
activeTopic: Topic
diff --git a/src/renderer/src/pages/launchpad/LaunchpadPage.tsx b/src/renderer/src/pages/launchpad/LaunchpadPage.tsx
index f9c80f6aec..e17597975b 100644
--- a/src/renderer/src/pages/launchpad/LaunchpadPage.tsx
+++ b/src/renderer/src/pages/launchpad/LaunchpadPage.tsx
@@ -1,11 +1,11 @@
import App from '@renderer/components/MinApp/MinApp'
import { useMinapps } from '@renderer/hooks/useMinapps'
import { useSettings } from '@renderer/hooks/useSettings'
+import { useNavigate } from '@tanstack/react-router'
import { Code, FileSearch, Folder, Languages, LayoutGrid, NotepadText, Palette, Sparkle } from 'lucide-react'
import type { FC } from 'react'
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
-import { useNavigate } from 'react-router-dom'
import styled from 'styled-components'
const LaunchpadPage: FC = () => {
@@ -87,7 +87,7 @@ const LaunchpadPage: FC = () => {
{t('launchpad.apps')}
{appMenuItems.map((item) => (
- navigate(item.path)}>
+ navigate({ to: item.path })}>
{item.icon}
diff --git a/src/renderer/src/pages/minapps/MinAppPage.tsx b/src/renderer/src/pages/minapps/MinAppPage.tsx
index 4ee4549303..003d374880 100644
--- a/src/renderer/src/pages/minapps/MinAppPage.tsx
+++ b/src/renderer/src/pages/minapps/MinAppPage.tsx
@@ -6,10 +6,10 @@ import { useMinapps } from '@renderer/hooks/useMinapps'
import { useNavbarPosition } from '@renderer/hooks/useNavbar'
import TabsService from '@renderer/services/TabsService'
import { getWebviewLoaded, onWebviewStateChange, setWebviewLoaded } from '@renderer/utils/webviewStateManager'
+import { useNavigate, useParams } from '@tanstack/react-router'
import type { WebviewTag } from 'electron'
import type { FC } from 'react'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
-import { useNavigate, useParams } from 'react-router-dom'
import BeatLoader from 'react-spinners/BeatLoader'
import styled from 'styled-components'
@@ -20,7 +20,7 @@ import WebviewSearch from './components/WebviewSearch'
const logger = loggerService.withContext('MinAppPage')
const MinAppPage: FC = () => {
- const { appId } = useParams<{ appId: string }>()
+ const { appId } = useParams({ strict: false }) as { appId: string }
const { isTopNavbar } = useNavbarPosition()
const { openMinappKeepAlive, minAppsCache } = useMinappPopup()
const { minapps } = useMinapps()
@@ -64,7 +64,7 @@ const MinAppPage: FC = () => {
useEffect(() => {
// If app not found, redirect to apps list
if (!app) {
- navigate('/apps')
+ navigate({ to: '/apps' })
return
}
@@ -72,7 +72,7 @@ const MinAppPage: FC = () => {
// Only check once and only if we haven't already redirected
if (!initialIsTopNavbar.current && !hasRedirected.current) {
hasRedirected.current = true
- navigate('/apps')
+ navigate({ to: '/apps' })
// Open popup after navigation
setTimeout(() => {
openMinappKeepAlive(app)
diff --git a/src/renderer/src/pages/minapps/components/MinimalToolbar.tsx b/src/renderer/src/pages/minapps/components/MinimalToolbar.tsx
index 0d2d555e52..f94f594a2f 100644
--- a/src/renderer/src/pages/minapps/components/MinimalToolbar.tsx
+++ b/src/renderer/src/pages/minapps/components/MinimalToolbar.tsx
@@ -15,11 +15,11 @@ import { isDev } from '@renderer/config/constant'
import { DEFAULT_MIN_APPS } from '@renderer/config/minapps'
import { useMinapps } from '@renderer/hooks/useMinapps'
import type { MinAppType } from '@renderer/types'
+import { useNavigate } from '@tanstack/react-router'
import type { WebviewTag } from 'electron'
import type { FC } from 'react'
import { useCallback, useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { useNavigate } from 'react-router-dom'
import styled from 'styled-components'
const logger = loggerService.withContext('MinimalToolbar')
@@ -213,7 +213,7 @@ const MinimalToolbar: FC = ({ app, webviewRef, currentUrl, onReload, onOp
}, [app.id, webviewRef, scheduleNavigationUpdate])
const handleMinimize = useCallback(() => {
- navigate('/apps')
+ navigate({ to: '/apps' })
}, [navigate])
const handleTogglePin = useCallback(() => {
diff --git a/src/renderer/src/pages/paintings/AihubmixPage.tsx b/src/renderer/src/pages/paintings/AihubmixPage.tsx
index 294bed47f2..e3b494084d 100644
--- a/src/renderer/src/pages/paintings/AihubmixPage.tsx
+++ b/src/renderer/src/pages/paintings/AihubmixPage.tsx
@@ -19,12 +19,12 @@ import { translateText } from '@renderer/services/TranslateService'
import type { FileMetadata } from '@renderer/types'
import type { PaintingAction, PaintingsState } from '@renderer/types'
import { getErrorMessage, uuid } from '@renderer/utils'
+import { useLocation, useNavigate } from '@tanstack/react-router'
import { Input, InputNumber, Radio, Segmented, Select, Slider, Upload } from 'antd'
import TextArea from 'antd/es/input/TextArea'
import type { FC } from 'react'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { useLocation, useNavigate } from 'react-router-dom'
import styled from 'styled-components'
import SendMessageButton from '../home/Inputbar/SendMessageButton'
@@ -667,7 +667,7 @@ const AihubmixPage: FC<{ Options: string[] }> = ({ Options }) => {
const handleProviderChange = (providerId: string) => {
const routeName = location.pathname.split('/').pop()
if (providerId !== routeName) {
- navigate('../' + providerId, { replace: true })
+ navigate({ to: '../' + providerId, replace: true })
}
}
diff --git a/src/renderer/src/pages/paintings/DmxapiPage.tsx b/src/renderer/src/pages/paintings/DmxapiPage.tsx
index 7f83183d28..286bbfa210 100644
--- a/src/renderer/src/pages/paintings/DmxapiPage.tsx
+++ b/src/renderer/src/pages/paintings/DmxapiPage.tsx
@@ -11,13 +11,13 @@ import { useAllProviders } from '@renderer/hooks/useProvider'
import FileManager from '@renderer/services/FileManager'
import type { FileMetadata } from '@renderer/types'
import { convertToBase64, uuid } from '@renderer/utils'
+import { useLocation, useNavigate } from '@tanstack/react-router'
import type { DmxapiPainting } from '@types'
import { Input, InputNumber, Segmented, Select } from 'antd'
import TextArea from 'antd/es/input/TextArea'
import type { FC } from 'react'
import React, { useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { useLocation, useNavigate } from 'react-router-dom'
import styled from 'styled-components'
import { generationModeType } from '../../types'
@@ -640,7 +640,7 @@ const DmxapiPage: FC<{ Options: string[] }> = ({ Options }) => {
const handleProviderChange = (providerId: string) => {
const routeName = location.pathname.split('/').pop()
if (providerId !== routeName) {
- navigate('../' + providerId, { replace: true })
+ navigate({ to: '../' + providerId, replace: true })
}
}
diff --git a/src/renderer/src/pages/paintings/NewApiPage.tsx b/src/renderer/src/pages/paintings/NewApiPage.tsx
index ae2e423535..6275cba420 100644
--- a/src/renderer/src/pages/paintings/NewApiPage.tsx
+++ b/src/renderer/src/pages/paintings/NewApiPage.tsx
@@ -29,13 +29,13 @@ import type { PaintingAction, PaintingsState } from '@renderer/types'
import type { FileMetadata } from '@renderer/types'
import { getErrorMessage, uuid } from '@renderer/utils'
import { isNewApiProvider } from '@renderer/utils/provider'
+import { useLocation, useNavigate } from '@tanstack/react-router'
import { Empty, InputNumber, Segmented, Select, Upload } from 'antd'
import TextArea from 'antd/es/input/TextArea'
import type { FC } from 'react'
import React from 'react'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { useLocation, useNavigate } from 'react-router-dom'
import styled from 'styled-components'
import SendMessageButton from '../home/Inputbar/SendMessageButton'
@@ -436,7 +436,7 @@ const NewApiPage: FC<{ Options: string[] }> = ({ Options }) => {
const handleProviderChange = (providerId: string) => {
const routeName = location.pathname.split('/').pop()
if (providerId !== routeName) {
- navigate('../' + providerId, { replace: true })
+ navigate({ to: '../' + providerId, replace: true })
}
}
@@ -463,7 +463,7 @@ const NewApiPage: FC<{ Options: string[] }> = ({ Options }) => {
// 当 modelOptions 为空时,引导用户跳转到 Provider 设置页面,新增 image-generation 端点模型
const handleShowAddModelPopup = () => {
- navigate(`/settings/provider?id=${newApiProvider.id}`)
+ navigate({ to: `/settings/provider?id=${newApiProvider.id}` })
}
useEffect(() => {
diff --git a/src/renderer/src/pages/paintings/OvmsPage.tsx b/src/renderer/src/pages/paintings/OvmsPage.tsx
index 5e23c89984..38e207841c 100644
--- a/src/renderer/src/pages/paintings/OvmsPage.tsx
+++ b/src/renderer/src/pages/paintings/OvmsPage.tsx
@@ -15,13 +15,13 @@ import FileManager from '@renderer/services/FileManager'
import { translateText } from '@renderer/services/TranslateService'
import type { FileMetadata, OvmsPainting } from '@renderer/types'
import { getErrorMessage, uuid } from '@renderer/utils'
+import { useLocation, useNavigate } from '@tanstack/react-router'
import { Avatar, Input, InputNumber, Select, Slider } from 'antd'
import TextArea from 'antd/es/input/TextArea'
import { Info } from 'lucide-react'
import type { FC } from 'react'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { useLocation, useNavigate } from 'react-router-dom'
import styled from 'styled-components'
import SendMessageButton from '../home/Inputbar/SendMessageButton'
@@ -330,7 +330,7 @@ const OvmsPage: FC<{ Options: string[] }> = ({ Options }) => {
const handleProviderChange = (providerId: string) => {
const routeName = location.pathname.split('/').pop()
if (providerId !== routeName) {
- navigate('../' + providerId, { replace: true })
+ navigate({ to: '../' + providerId, replace: true })
}
}
diff --git a/src/renderer/src/pages/paintings/PaintingsRoutePage.tsx b/src/renderer/src/pages/paintings/PaintingsRoutePage.tsx
index 6629946879..7f2ce4c781 100644
--- a/src/renderer/src/pages/paintings/PaintingsRoutePage.tsx
+++ b/src/renderer/src/pages/paintings/PaintingsRoutePage.tsx
@@ -5,9 +5,9 @@ import { setDefaultPaintingProvider } from '@renderer/store/settings'
import { updateTab } from '@renderer/store/tabs'
import type { PaintingProvider, SystemProviderId } from '@renderer/types'
import { isNewApiProvider } from '@renderer/utils/provider'
+import { useParams } from '@tanstack/react-router'
import type { FC } from 'react'
import { useEffect, useMemo, useState } from 'react'
-import { Route, Routes, useParams } from 'react-router-dom'
import AihubmixPage from './AihubmixPage'
import DmxapiPage from './DmxapiPage'
@@ -22,8 +22,8 @@ const logger = loggerService.withContext('PaintingsRoutePage')
const BASE_OPTIONS: SystemProviderId[] = ['zhipu', 'aihubmix', 'silicon', 'dmxapi', 'tokenflux', 'ovms']
const PaintingsRoutePage: FC = () => {
- const params = useParams()
- const provider = params['*']
+ const params = useParams({ strict: false }) as { _splat?: string }
+ const provider = params._splat
const dispatch = useAppDispatch()
const providers = useAllProviders()
const [ovmsStatus, setOvmsStatus] = useState<'not-installed' | 'not-running' | 'running'>('not-running')
@@ -49,22 +49,34 @@ const PaintingsRoutePage: FC = () => {
}
}, [provider, dispatch, validOptions])
- return (
-
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- {/* new-api family providers are mounted dynamically below */}
- {newApiProviders.map((p) => (
- } />
- ))}
-
- )
+ // 根据 provider 渲染对应的页面
+ const renderPage = () => {
+ switch (provider) {
+ case 'zhipu':
+ return
+ case 'aihubmix':
+ return
+ case 'silicon':
+ return
+ case 'dmxapi':
+ return
+ case 'tokenflux':
+ return
+ case 'ovms':
+ return
+ case 'new-api':
+ return
+ default:
+ // 检查是否是 new-api 家族的 provider
+ if (provider && newApiProviders.some((p) => p.id === provider)) {
+ return
+ }
+ // 默认页面
+ return
+ }
+ }
+
+ return renderPage()
}
export default PaintingsRoutePage
diff --git a/src/renderer/src/pages/paintings/SiliconPage.tsx b/src/renderer/src/pages/paintings/SiliconPage.tsx
index 16ff35363a..4bd2b85b5d 100644
--- a/src/renderer/src/pages/paintings/SiliconPage.tsx
+++ b/src/renderer/src/pages/paintings/SiliconPage.tsx
@@ -23,12 +23,12 @@ import FileManager from '@renderer/services/FileManager'
import { translateText } from '@renderer/services/TranslateService'
import type { FileMetadata, Painting } from '@renderer/types'
import { getErrorMessage, uuid } from '@renderer/utils'
+import { useLocation, useNavigate } from '@tanstack/react-router'
import { Input, InputNumber, Radio, Select, Slider } from 'antd'
import TextArea from 'antd/es/input/TextArea'
import type { FC } from 'react'
import { useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { useLocation, useNavigate } from 'react-router-dom'
import styled from 'styled-components'
import SendMessageButton from '../home/Inputbar/SendMessageButton'
@@ -333,7 +333,7 @@ const SiliconPage: FC<{ Options: string[] }> = ({ Options }) => {
const handleProviderChange = (providerId: string) => {
const routeName = location.pathname.split('/').pop()
if (providerId !== routeName) {
- navigate('../' + providerId, { replace: true })
+ navigate({ to: '../' + providerId, replace: true })
}
}
diff --git a/src/renderer/src/pages/paintings/TokenFluxPage.tsx b/src/renderer/src/pages/paintings/TokenFluxPage.tsx
index 5ecba7a9b5..9c3f3c4b5b 100644
--- a/src/renderer/src/pages/paintings/TokenFluxPage.tsx
+++ b/src/renderer/src/pages/paintings/TokenFluxPage.tsx
@@ -15,12 +15,12 @@ import FileManager from '@renderer/services/FileManager'
import { translateText } from '@renderer/services/TranslateService'
import type { TokenFluxPainting } from '@renderer/types'
import { getErrorMessage, uuid } from '@renderer/utils'
+import { useLocation, useNavigate } from '@tanstack/react-router'
import { Select } from 'antd'
import TextArea from 'antd/es/input/TextArea'
import type { FC } from 'react'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { useLocation, useNavigate } from 'react-router-dom'
import styled from 'styled-components'
import SendMessageButton from '../home/Inputbar/SendMessageButton'
@@ -268,7 +268,7 @@ const TokenFluxPage: FC<{ Options: string[] }> = ({ Options }) => {
const handleProviderChange = (providerId: string) => {
const routeName = location.pathname.split('/').pop()
if (providerId !== routeName) {
- navigate('../' + providerId, { replace: true })
+ navigate({ to: '../' + providerId, replace: true })
}
}
diff --git a/src/renderer/src/pages/paintings/ZhipuPage.tsx b/src/renderer/src/pages/paintings/ZhipuPage.tsx
index 846e0e4e39..7c8e9c5e4c 100644
--- a/src/renderer/src/pages/paintings/ZhipuPage.tsx
+++ b/src/renderer/src/pages/paintings/ZhipuPage.tsx
@@ -12,12 +12,12 @@ import { usePaintings } from '@renderer/hooks/usePaintings'
import { useAllProviders } from '@renderer/hooks/useProvider'
import FileManager from '@renderer/services/FileManager'
import { getErrorMessage, uuid } from '@renderer/utils'
+import { useLocation, useNavigate } from '@tanstack/react-router'
import { InputNumber, Radio, Select } from 'antd'
import TextArea from 'antd/es/input/TextArea'
import type { FC } from 'react'
import { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { useLocation, useNavigate } from 'react-router-dom'
import styled from 'styled-components'
import SendMessageButton from '../home/Inputbar/SendMessageButton'
@@ -260,7 +260,7 @@ const ZhipuPage: FC<{ Options: string[] }> = ({ Options }) => {
const handleProviderChange = (providerId: string) => {
const routeName = location.pathname.split('/').pop()
if (providerId !== routeName) {
- navigate('../' + providerId, { replace: true })
+ navigate({ to: '../' + providerId, replace: true })
}
}
diff --git a/src/renderer/src/pages/paintings/utils/index.ts b/src/renderer/src/pages/paintings/utils/index.ts
index 8df6108c1e..d7f7359def 100644
--- a/src/renderer/src/pages/paintings/utils/index.ts
+++ b/src/renderer/src/pages/paintings/utils/index.ts
@@ -15,7 +15,7 @@ export function checkProviderEnabled(provider: Provider, t: TFunction): Promise<
closable: true,
okText: t('common.go_to_settings'),
onOk: () => {
- window.navigate?.(`/settings/provider?id=${provider.id}`)
+ window.navigate?.({ to: `/settings/provider`, search: { id: provider.id } })
reject('Provider disabled')
},
onCancel: () => reject('Provider disabled')
diff --git a/src/renderer/src/pages/settings/AboutSettings.tsx b/src/renderer/src/pages/settings/AboutSettings.tsx
index 571914ac4e..4a6b3cbe60 100644
--- a/src/renderer/src/pages/settings/AboutSettings.tsx
+++ b/src/renderer/src/pages/settings/AboutSettings.tsx
@@ -13,6 +13,7 @@ import i18n from '@renderer/i18n'
// import { setUpdateState as setAppUpdateState } from '@renderer/store/runtime'
import { runAsyncFunction } from '@renderer/utils'
import { ThemeMode, UpgradeChannel } from '@shared/data/preference/preferenceTypes'
+import { Link } from '@tanstack/react-router'
import { Avatar, Progress, Radio, Row, Tag } from 'antd'
import { debounce } from 'lodash'
import { Bug, Building2, Github, Globe, Mail, Rss } from 'lucide-react'
@@ -21,7 +22,6 @@ import type { FC } from 'react'
import { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import Markdown from 'react-markdown'
-import { Link } from 'react-router-dom'
import styled from 'styled-components'
import { SettingContainer, SettingDivider, SettingGroup, SettingRow, SettingTitle } from '.'
diff --git a/src/renderer/src/pages/settings/MCPSettings/InstallNpxUv.tsx b/src/renderer/src/pages/settings/MCPSettings/InstallNpxUv.tsx
index 20d6864582..6bd9acd5d7 100644
--- a/src/renderer/src/pages/settings/MCPSettings/InstallNpxUv.tsx
+++ b/src/renderer/src/pages/settings/MCPSettings/InstallNpxUv.tsx
@@ -3,11 +3,11 @@ import { Center, ColFlex } from '@cherrystudio/ui'
import { Button } from '@cherrystudio/ui'
import { useAppDispatch, useAppSelector } from '@renderer/store'
import { setIsBunInstalled, setIsUvInstalled } from '@renderer/store/mcp'
+import { useNavigate } from '@tanstack/react-router'
import { Alert } from 'antd'
import type { FC } from 'react'
import { useCallback, useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { useNavigate } from 'react-router'
import styled from 'styled-components'
import { SettingDescription, SettingRow, SettingSubtitle } from '..'
@@ -87,7 +87,7 @@ const InstallNpxUv: FC = ({ mini = false }) => {
diff --git a/src/renderer/src/pages/settings/MCPSettings/McpServersList.tsx b/src/renderer/src/pages/settings/MCPSettings/McpServersList.tsx
index 436f051faa..2fe6bd3185 100644
--- a/src/renderer/src/pages/settings/MCPSettings/McpServersList.tsx
+++ b/src/renderer/src/pages/settings/MCPSettings/McpServersList.tsx
@@ -9,12 +9,12 @@ import { useMCPServerTrust } from '@renderer/hooks/useMCPServerTrust'
import type { MCPServer } from '@renderer/types'
import { formatMcpError } from '@renderer/utils/error'
import { matchKeywordsInString } from '@renderer/utils/match'
+import { useNavigate } from '@tanstack/react-router'
import { Button, Dropdown, Empty } from 'antd'
import { Plus } from 'lucide-react'
import type { FC } from 'react'
import { startTransition, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { useNavigate } from 'react-router'
import styled from 'styled-components'
import { SettingTitle } from '..'
@@ -115,7 +115,7 @@ const McpServersList: FC = () => {
isActive: false
}
addMCPServer(newServer)
- navigate(`/settings/mcp/settings/${encodeURIComponent(newServer.id)}`)
+ navigate({ to: `/settings/mcp/settings/${encodeURIComponent(newServer.id)}` })
window.toast.success(t('settings.mcp.addSuccess'))
}, [addMCPServer, navigate, t])
@@ -260,7 +260,7 @@ const McpServersList: FC = () => {
isLoading={loadingServerIds.has(server.id)}
onToggle={async (active) => await handleToggleActive(server, active)}
onDelete={() => onDeleteMcpServer(server)}
- onEdit={() => navigate(`/settings/mcp/settings/${encodeURIComponent(server.id)}`)}
+ onEdit={() => navigate({ to: `/settings/mcp/settings/${encodeURIComponent(server.id)}` })}
onOpenUrl={(url) => window.open(url, '_blank')}
/>
)}
diff --git a/src/renderer/src/pages/settings/MCPSettings/McpSettings.tsx b/src/renderer/src/pages/settings/MCPSettings/McpSettings.tsx
index 2ff233ef7c..a9f7ad21e5 100644
--- a/src/renderer/src/pages/settings/MCPSettings/McpSettings.tsx
+++ b/src/renderer/src/pages/settings/MCPSettings/McpSettings.tsx
@@ -11,13 +11,13 @@ import MCPDescription from '@renderer/pages/settings/MCPSettings/McpDescription'
import type { MCPPrompt, MCPResource, MCPServer, MCPTool } from '@renderer/types'
import { parseKeyValueString } from '@renderer/utils/env'
import { formatMcpError } from '@renderer/utils/error'
+import { useNavigate, useParams } from '@tanstack/react-router'
import type { TabsProps } from 'antd'
import { Badge, Form, Input, Radio, Select, Tabs } from 'antd'
import TextArea from 'antd/es/input/TextArea'
import { ChevronDown, SaveIcon } from 'lucide-react'
import React, { useCallback, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { useNavigate, useParams } from 'react-router'
import styled from 'styled-components'
import { SettingContainer, SettingDivider, SettingGroup, SettingTitle } from '..'
@@ -68,7 +68,8 @@ type TabKey = 'settings' | 'description' | 'tools' | 'prompts' | 'resources'
const McpSettings: React.FC = () => {
const { t } = useTranslation()
- const { serverId } = useParams<{ serverId: string }>()
+ const params = useParams({ strict: false }) as { serverId?: string }
+ const serverId = params.serverId
const decodedServerId = serverId ? decodeURIComponent(serverId) : ''
const server = useMCPServer(decodedServerId).server as MCPServer
const { deleteMCPServer, updateMCPServer } = useMCPServers()
@@ -376,7 +377,7 @@ const McpSettings: React.FC = () => {
await window.api.mcp.removeServer(server)
deleteMCPServer(server.id)
window.toast.success(t('settings.mcp.deleteSuccess'))
- navigate('/settings/mcp')
+ navigate({ to: '/settings/mcp' })
}
})
} catch (error: any) {
diff --git a/src/renderer/src/pages/settings/MCPSettings/index.tsx b/src/renderer/src/pages/settings/MCPSettings/index.tsx
index 4637cf2e89..4dd878112b 100644
--- a/src/renderer/src/pages/settings/MCPSettings/index.tsx
+++ b/src/renderer/src/pages/settings/MCPSettings/index.tsx
@@ -8,30 +8,17 @@ import TokenFluxProviderLogo from '@renderer/assets/images/providers/tokenflux.p
import DividerWithText from '@renderer/components/DividerWithText'
import ListItem from '@renderer/components/ListItem'
import Scrollbar from '@renderer/components/Scrollbar'
-import { useTheme } from '@renderer/context/ThemeProvider'
-import { useMCPServers } from '@renderer/hooks/useMCPServers'
+import { Link, Outlet, useLocation, useNavigate } from '@tanstack/react-router'
import { Button, Flex } from 'antd'
import { FolderCog, Package, ShoppingBag } from 'lucide-react'
import type { FC } from 'react'
import { useTranslation } from 'react-i18next'
-import { Navigate, Route, Routes, useLocation, useNavigate } from 'react-router'
-import { Link } from 'react-router-dom'
import styled from 'styled-components'
-import { SettingContainer } from '..'
-import BuiltinMCPServerList from './BuiltinMCPServerList'
-import InstallNpxUv from './InstallNpxUv'
-import McpMarketList from './McpMarketList'
-import ProviderDetail from './McpProviderSettings'
-import McpServersList from './McpServersList'
-import McpSettings from './McpSettings'
-import NpxSearch from './NpxSearch'
import { providers } from './providers/config'
const MCPSettings: FC = () => {
- const { theme } = useTheme()
const { t } = useTranslation()
- const { mcpServers } = useMCPServers()
const navigate = useNavigate()
const location = useLocation()
@@ -84,7 +71,7 @@ const MCPSettings: FC = () => {
navigate('/settings/mcp/servers')}
+ onClick={() => navigate({ to: '/settings/mcp/servers' })}
icon={}
titleStyle={{ fontWeight: 500 }}
/>
@@ -92,14 +79,14 @@ const MCPSettings: FC = () => {
navigate('/settings/mcp/builtin')}
+ onClick={() => navigate({ to: '/settings/mcp/builtin' })}
icon={}
titleStyle={{ fontWeight: 500 }}
/>
navigate('/settings/mcp/marketplaces')}
+ onClick={() => navigate({ to: '/settings/mcp/marketplaces' })}
icon={}
titleStyle={{ fontWeight: 500 }}
/>
@@ -109,7 +96,7 @@ const MCPSettings: FC = () => {
key={provider.key}
title={provider.name}
active={activeView === provider.key}
- onClick={() => navigate(`/settings/mcp/${provider.key}`)}
+ onClick={() => navigate({ to: `/settings/mcp/${provider.key}` })}
icon={providerIcons[provider.key] || }
titleStyle={{ fontWeight: 500 }}
/>
@@ -125,50 +112,7 @@ const MCPSettings: FC = () => {
)}
-
- } />
- } />
- } />
-
-
-
- }
- />
-
-
-
- }
- />
-
-
-
- }
- />
-
-
-
- }
- />
- {providers.map((provider) => (
- }
- />
- ))}
-
+
@@ -212,12 +156,6 @@ const ProviderIcon = styled.img`
background-color: var(--color-background-soft);
`
-const ContentWrapper = styled.div`
- padding: 20px;
- overflow-y: auto;
- height: 100%;
-`
-
const BackButtonContainer = styled.div`
display: flex;
align-items: center;
diff --git a/src/renderer/src/pages/settings/ProviderSettings/ProviderList.tsx b/src/renderer/src/pages/settings/ProviderSettings/ProviderList.tsx
index 2d13804171..6bb0a9f93d 100644
--- a/src/renderer/src/pages/settings/ProviderSettings/ProviderList.tsx
+++ b/src/renderer/src/pages/settings/ProviderSettings/ProviderList.tsx
@@ -14,13 +14,13 @@ import ImageStorage from '@renderer/services/ImageStorage'
import type { Provider, ProviderType } from '@renderer/types'
import { isSystemProvider } from '@renderer/types'
import { getFancyProviderName, matchKeywordsInModel, matchKeywordsInProvider, uuid } from '@renderer/utils'
+import { useLocation, useNavigate, useSearch } from '@tanstack/react-router'
import type { MenuProps } from 'antd'
import { Dropdown, Input, Tag } from 'antd'
import { GripVertical, PlusIcon, Search, UserPen } from 'lucide-react'
import type { FC } from 'react'
import { startTransition, useCallback, useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { useSearchParams } from 'react-router-dom'
import styled from 'styled-components'
import AddProviderPopup from './AddProviderPopup'
@@ -35,7 +35,9 @@ const systemType = await window.api.system.getDeviceType()
const cpuName = await window.api.system.getCpuName()
const ProviderList: FC = () => {
- const [searchParams, setSearchParams] = useSearchParams()
+ const search = useSearch({ strict: false }) as Record
+ const navigate = useNavigate()
+ const location = useLocation()
const providers = useAllProviders()
const { updateProviders, addProvider, removeProvider, updateProvider } = useProviders()
const { setTimeoutTimer } = useTimer()
@@ -72,8 +74,8 @@ const ProviderList: FC = () => {
}, [providers])
useEffect(() => {
- if (searchParams.get('id')) {
- const providerId = searchParams.get('id')
+ if (search.id) {
+ const providerId = search.id
const provider = providers.find((p) => p.id === providerId)
if (provider) {
setSelectedProvider(provider)
@@ -89,10 +91,17 @@ const ProviderList: FC = () => {
} else {
setSelectedProvider(providers[0])
}
- searchParams.delete('id')
- setSearchParams(searchParams)
+ // 清除 id 参数
+ navigate({
+ to: location.pathname,
+ search: (prev) => {
+ const { id: _, ...rest } = prev as Record
+ return rest
+ },
+ replace: true
+ })
}
- }, [providers, searchParams, setSearchParams, setSelectedProvider, setTimeoutTimer])
+ }, [providers, search.id, navigate, location.pathname, setSelectedProvider, setTimeoutTimer])
// Handle provider add key from URL schema
useEffect(() => {
@@ -106,7 +115,7 @@ const ProviderList: FC = () => {
const { id } = data
const { updatedProvider, isNew, displayName } = await UrlSchemaInfoPopup.show(data)
- window.navigate(`/settings/provider?id=${id}`)
+ navigate({ to: '/settings/provider', search: { id } })
if (!updatedProvider) {
return
@@ -123,7 +132,7 @@ const ProviderList: FC = () => {
}
// 检查 URL 参数
- const addProviderData = searchParams.get('addProviderData')
+ const addProviderData = search.addProviderData
if (!addProviderData) {
return
}
@@ -132,17 +141,17 @@ const ProviderList: FC = () => {
const { id, apiKey: newApiKey, baseUrl, type, name } = JSON.parse(addProviderData)
if (!id || !newApiKey || !baseUrl) {
window.toast.error(t('settings.models.provider_key_add_failed_by_invalid_data'))
- window.navigate('/settings/provider')
+ navigate({ to: '/settings/provider' })
return
}
handleProviderAddKey({ id, apiKey: newApiKey, baseUrl, type, name })
} catch (error) {
window.toast.error(t('settings.models.provider_key_add_failed_by_invalid_data'))
- window.navigate('/settings/provider')
+ navigate({ to: '/settings/provider' })
}
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [searchParams])
+ }, [search.addProviderData])
const onAddProvider = async () => {
const { name: providerName, type, logo } = await AddProviderPopup.show()
diff --git a/src/renderer/src/pages/settings/SelectionAssistantSettings/SelectionAssistantSettings.tsx b/src/renderer/src/pages/settings/SelectionAssistantSettings/SelectionAssistantSettings.tsx
index 55bdb2ed0e..57aa40b97e 100644
--- a/src/renderer/src/pages/settings/SelectionAssistantSettings/SelectionAssistantSettings.tsx
+++ b/src/renderer/src/pages/settings/SelectionAssistantSettings/SelectionAssistantSettings.tsx
@@ -6,12 +6,12 @@ import { useTheme } from '@renderer/context/ThemeProvider'
import { getSelectionDescriptionLabel } from '@renderer/i18n/label'
import SelectionToolbar from '@renderer/windows/selection/toolbar/SelectionToolbar'
import type { SelectionFilterMode, SelectionTriggerMode } from '@shared/data/preference/preferenceTypes'
+import { Link } from '@tanstack/react-router'
import { Row, Slider } from 'antd'
import { CircleHelp, Edit2 } from 'lucide-react'
import type { FC } from 'react'
import { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { Link } from 'react-router-dom'
import styled from 'styled-components'
import {
diff --git a/src/renderer/src/pages/settings/SettingsPage.tsx b/src/renderer/src/pages/settings/SettingsPage.tsx
index a14e10973d..57bbcd6d2e 100644
--- a/src/renderer/src/pages/settings/SettingsPage.tsx
+++ b/src/renderer/src/pages/settings/SettingsPage.tsx
@@ -1,7 +1,7 @@
import { GlobalOutlined } from '@ant-design/icons'
import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar'
import Scrollbar from '@renderer/components/Scrollbar'
-import ModelSettings from '@renderer/pages/settings/ModelSettings/ModelSettings'
+import { Link, Outlet, useLocation } from '@tanstack/react-router'
import { Divider as AntDivider } from 'antd'
import {
Brain,
@@ -22,27 +22,11 @@ import {
} from 'lucide-react'
import type { FC } from 'react'
import { useTranslation } from 'react-i18next'
-import { Link, Route, Routes, useLocation } from 'react-router-dom'
import styled from 'styled-components'
-import AboutSettings from './AboutSettings'
-import DataSettings from './DataSettings/DataSettings'
-import DisplaySettings from './DisplaySettings/DisplaySettings'
-import DocProcessSettings from './DocProcessSettings'
-import GeneralSettings from './GeneralSettings'
-import MCPSettings from './MCPSettings'
-import MemorySettings from './MemorySettings'
-import NotesSettings from './NotesSettings'
-import { ProviderList } from './ProviderSettings'
-import QuickAssistantSettings from './QuickAssistantSettings'
-import QuickPhraseSettings from './QuickPhraseSettings'
-import SelectionAssistantSettings from './SelectionAssistantSettings/SelectionAssistantSettings'
-import ShortcutSettings from './ShortcutSettings'
-import { ApiServerSettings } from './ToolSettings/ApiServerSettings'
-import WebSearchSettings from './WebSearchSettings'
-
const SettingsPage: FC = () => {
- const { pathname } = useLocation()
+ const location = useLocation()
+ const { pathname } = location
const { t } = useTranslation()
const isRoute = (path: string): string => (pathname.startsWith(path) ? 'active' : '')
@@ -156,24 +140,7 @@ const SettingsPage: FC = () => {
-
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
-
+
diff --git a/src/renderer/src/routeTree.gen.ts b/src/renderer/src/routeTree.gen.ts
index f9781b3f31..b5357bda95 100644
--- a/src/renderer/src/routeTree.gen.ts
+++ b/src/renderer/src/routeTree.gen.ts
@@ -9,48 +9,510 @@
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
import { Route as rootRouteImport } from './routes/__root'
+import { Route as TranslateRouteImport } from './routes/translate'
+import { Route as StoreRouteImport } from './routes/store'
import { Route as SettingsRouteImport } from './routes/settings'
+import { Route as NotesRouteImport } from './routes/notes'
+import { Route as KnowledgeRouteImport } from './routes/knowledge'
+import { Route as FilesRouteImport } from './routes/files'
+import { Route as CodeRouteImport } from './routes/code'
+import { Route as ChatRouteImport } from './routes/chat'
import { Route as IndexRouteImport } from './routes/index'
+import { Route as SettingsIndexRouteImport } from './routes/settings/index'
+import { Route as PaintingsIndexRouteImport } from './routes/paintings/index'
+import { Route as AppsIndexRouteImport } from './routes/apps/index'
+import { Route as SettingsWebsearchRouteImport } from './routes/settings/websearch'
+import { Route as SettingsShortcutRouteImport } from './routes/settings/shortcut'
+import { Route as SettingsSelectionAssistantRouteImport } from './routes/settings/selectionAssistant'
+import { Route as SettingsQuickphraseRouteImport } from './routes/settings/quickphrase'
+import { Route as SettingsQuickAssistantRouteImport } from './routes/settings/quickAssistant'
+import { Route as SettingsProviderRouteImport } from './routes/settings/provider'
+import { Route as SettingsNotesRouteImport } from './routes/settings/notes'
+import { Route as SettingsModelRouteImport } from './routes/settings/model'
+import { Route as SettingsMemoryRouteImport } from './routes/settings/memory'
+import { Route as SettingsMcpRouteImport } from './routes/settings/mcp'
+import { Route as SettingsGeneralRouteImport } from './routes/settings/general'
+import { Route as SettingsDocprocessRouteImport } from './routes/settings/docprocess'
+import { Route as SettingsDisplayRouteImport } from './routes/settings/display'
+import { Route as SettingsDataRouteImport } from './routes/settings/data'
+import { Route as SettingsApiServerRouteImport } from './routes/settings/api-server'
+import { Route as SettingsAboutRouteImport } from './routes/settings/about'
+import { Route as PaintingsSplatRouteImport } from './routes/paintings/$'
+import { Route as AppsAppIdRouteImport } from './routes/apps/$appId'
+import { Route as SettingsMcpIndexRouteImport } from './routes/settings/mcp/index'
+import { Route as SettingsMcpServersRouteImport } from './routes/settings/mcp/servers'
+import { Route as SettingsMcpNpxSearchRouteImport } from './routes/settings/mcp/npx-search'
+import { Route as SettingsMcpMcpInstallRouteImport } from './routes/settings/mcp/mcp-install'
+import { Route as SettingsMcpMarketplacesRouteImport } from './routes/settings/mcp/marketplaces'
+import { Route as SettingsMcpBuiltinRouteImport } from './routes/settings/mcp/builtin'
+import { Route as SettingsMcpSplatRouteImport } from './routes/settings/mcp/$'
+import { Route as SettingsMcpSettingsServerIdRouteImport } from './routes/settings/mcp/settings.$serverId'
+const TranslateRoute = TranslateRouteImport.update({
+ id: '/translate',
+ path: '/translate',
+ getParentRoute: () => rootRouteImport,
+} as any)
+const StoreRoute = StoreRouteImport.update({
+ id: '/store',
+ path: '/store',
+ getParentRoute: () => rootRouteImport,
+} as any)
const SettingsRoute = SettingsRouteImport.update({
id: '/settings',
path: '/settings',
getParentRoute: () => rootRouteImport,
} as any)
+const NotesRoute = NotesRouteImport.update({
+ id: '/notes',
+ path: '/notes',
+ getParentRoute: () => rootRouteImport,
+} as any)
+const KnowledgeRoute = KnowledgeRouteImport.update({
+ id: '/knowledge',
+ path: '/knowledge',
+ getParentRoute: () => rootRouteImport,
+} as any)
+const FilesRoute = FilesRouteImport.update({
+ id: '/files',
+ path: '/files',
+ getParentRoute: () => rootRouteImport,
+} as any)
+const CodeRoute = CodeRouteImport.update({
+ id: '/code',
+ path: '/code',
+ getParentRoute: () => rootRouteImport,
+} as any)
+const ChatRoute = ChatRouteImport.update({
+ id: '/chat',
+ path: '/chat',
+ getParentRoute: () => rootRouteImport,
+} as any)
const IndexRoute = IndexRouteImport.update({
id: '/',
path: '/',
getParentRoute: () => rootRouteImport,
} as any)
+const SettingsIndexRoute = SettingsIndexRouteImport.update({
+ id: '/',
+ path: '/',
+ getParentRoute: () => SettingsRoute,
+} as any)
+const PaintingsIndexRoute = PaintingsIndexRouteImport.update({
+ id: '/paintings/',
+ path: '/paintings/',
+ getParentRoute: () => rootRouteImport,
+} as any)
+const AppsIndexRoute = AppsIndexRouteImport.update({
+ id: '/apps/',
+ path: '/apps/',
+ getParentRoute: () => rootRouteImport,
+} as any)
+const SettingsWebsearchRoute = SettingsWebsearchRouteImport.update({
+ id: '/websearch',
+ path: '/websearch',
+ getParentRoute: () => SettingsRoute,
+} as any)
+const SettingsShortcutRoute = SettingsShortcutRouteImport.update({
+ id: '/shortcut',
+ path: '/shortcut',
+ getParentRoute: () => SettingsRoute,
+} as any)
+const SettingsSelectionAssistantRoute =
+ SettingsSelectionAssistantRouteImport.update({
+ id: '/selectionAssistant',
+ path: '/selectionAssistant',
+ getParentRoute: () => SettingsRoute,
+ } as any)
+const SettingsQuickphraseRoute = SettingsQuickphraseRouteImport.update({
+ id: '/quickphrase',
+ path: '/quickphrase',
+ getParentRoute: () => SettingsRoute,
+} as any)
+const SettingsQuickAssistantRoute = SettingsQuickAssistantRouteImport.update({
+ id: '/quickAssistant',
+ path: '/quickAssistant',
+ getParentRoute: () => SettingsRoute,
+} as any)
+const SettingsProviderRoute = SettingsProviderRouteImport.update({
+ id: '/provider',
+ path: '/provider',
+ getParentRoute: () => SettingsRoute,
+} as any)
+const SettingsNotesRoute = SettingsNotesRouteImport.update({
+ id: '/notes',
+ path: '/notes',
+ getParentRoute: () => SettingsRoute,
+} as any)
+const SettingsModelRoute = SettingsModelRouteImport.update({
+ id: '/model',
+ path: '/model',
+ getParentRoute: () => SettingsRoute,
+} as any)
+const SettingsMemoryRoute = SettingsMemoryRouteImport.update({
+ id: '/memory',
+ path: '/memory',
+ getParentRoute: () => SettingsRoute,
+} as any)
+const SettingsMcpRoute = SettingsMcpRouteImport.update({
+ id: '/mcp',
+ path: '/mcp',
+ getParentRoute: () => SettingsRoute,
+} as any)
+const SettingsGeneralRoute = SettingsGeneralRouteImport.update({
+ id: '/general',
+ path: '/general',
+ getParentRoute: () => SettingsRoute,
+} as any)
+const SettingsDocprocessRoute = SettingsDocprocessRouteImport.update({
+ id: '/docprocess',
+ path: '/docprocess',
+ getParentRoute: () => SettingsRoute,
+} as any)
+const SettingsDisplayRoute = SettingsDisplayRouteImport.update({
+ id: '/display',
+ path: '/display',
+ getParentRoute: () => SettingsRoute,
+} as any)
+const SettingsDataRoute = SettingsDataRouteImport.update({
+ id: '/data',
+ path: '/data',
+ getParentRoute: () => SettingsRoute,
+} as any)
+const SettingsApiServerRoute = SettingsApiServerRouteImport.update({
+ id: '/api-server',
+ path: '/api-server',
+ getParentRoute: () => SettingsRoute,
+} as any)
+const SettingsAboutRoute = SettingsAboutRouteImport.update({
+ id: '/about',
+ path: '/about',
+ getParentRoute: () => SettingsRoute,
+} as any)
+const PaintingsSplatRoute = PaintingsSplatRouteImport.update({
+ id: '/paintings/$',
+ path: '/paintings/$',
+ getParentRoute: () => rootRouteImport,
+} as any)
+const AppsAppIdRoute = AppsAppIdRouteImport.update({
+ id: '/apps/$appId',
+ path: '/apps/$appId',
+ getParentRoute: () => rootRouteImport,
+} as any)
+const SettingsMcpIndexRoute = SettingsMcpIndexRouteImport.update({
+ id: '/',
+ path: '/',
+ getParentRoute: () => SettingsMcpRoute,
+} as any)
+const SettingsMcpServersRoute = SettingsMcpServersRouteImport.update({
+ id: '/servers',
+ path: '/servers',
+ getParentRoute: () => SettingsMcpRoute,
+} as any)
+const SettingsMcpNpxSearchRoute = SettingsMcpNpxSearchRouteImport.update({
+ id: '/npx-search',
+ path: '/npx-search',
+ getParentRoute: () => SettingsMcpRoute,
+} as any)
+const SettingsMcpMcpInstallRoute = SettingsMcpMcpInstallRouteImport.update({
+ id: '/mcp-install',
+ path: '/mcp-install',
+ getParentRoute: () => SettingsMcpRoute,
+} as any)
+const SettingsMcpMarketplacesRoute = SettingsMcpMarketplacesRouteImport.update({
+ id: '/marketplaces',
+ path: '/marketplaces',
+ getParentRoute: () => SettingsMcpRoute,
+} as any)
+const SettingsMcpBuiltinRoute = SettingsMcpBuiltinRouteImport.update({
+ id: '/builtin',
+ path: '/builtin',
+ getParentRoute: () => SettingsMcpRoute,
+} as any)
+const SettingsMcpSplatRoute = SettingsMcpSplatRouteImport.update({
+ id: '/$',
+ path: '/$',
+ getParentRoute: () => SettingsMcpRoute,
+} as any)
+const SettingsMcpSettingsServerIdRoute =
+ SettingsMcpSettingsServerIdRouteImport.update({
+ id: '/settings/$serverId',
+ path: '/settings/$serverId',
+ getParentRoute: () => SettingsMcpRoute,
+ } as any)
export interface FileRoutesByFullPath {
'/': typeof IndexRoute
- '/settings': typeof SettingsRoute
+ '/chat': typeof ChatRoute
+ '/code': typeof CodeRoute
+ '/files': typeof FilesRoute
+ '/knowledge': typeof KnowledgeRoute
+ '/notes': typeof NotesRoute
+ '/settings': typeof SettingsRouteWithChildren
+ '/store': typeof StoreRoute
+ '/translate': typeof TranslateRoute
+ '/apps/$appId': typeof AppsAppIdRoute
+ '/paintings/$': typeof PaintingsSplatRoute
+ '/settings/about': typeof SettingsAboutRoute
+ '/settings/api-server': typeof SettingsApiServerRoute
+ '/settings/data': typeof SettingsDataRoute
+ '/settings/display': typeof SettingsDisplayRoute
+ '/settings/docprocess': typeof SettingsDocprocessRoute
+ '/settings/general': typeof SettingsGeneralRoute
+ '/settings/mcp': typeof SettingsMcpRouteWithChildren
+ '/settings/memory': typeof SettingsMemoryRoute
+ '/settings/model': typeof SettingsModelRoute
+ '/settings/notes': typeof SettingsNotesRoute
+ '/settings/provider': typeof SettingsProviderRoute
+ '/settings/quickAssistant': typeof SettingsQuickAssistantRoute
+ '/settings/quickphrase': typeof SettingsQuickphraseRoute
+ '/settings/selectionAssistant': typeof SettingsSelectionAssistantRoute
+ '/settings/shortcut': typeof SettingsShortcutRoute
+ '/settings/websearch': typeof SettingsWebsearchRoute
+ '/apps': typeof AppsIndexRoute
+ '/paintings': typeof PaintingsIndexRoute
+ '/settings/': typeof SettingsIndexRoute
+ '/settings/mcp/$': typeof SettingsMcpSplatRoute
+ '/settings/mcp/builtin': typeof SettingsMcpBuiltinRoute
+ '/settings/mcp/marketplaces': typeof SettingsMcpMarketplacesRoute
+ '/settings/mcp/mcp-install': typeof SettingsMcpMcpInstallRoute
+ '/settings/mcp/npx-search': typeof SettingsMcpNpxSearchRoute
+ '/settings/mcp/servers': typeof SettingsMcpServersRoute
+ '/settings/mcp/': typeof SettingsMcpIndexRoute
+ '/settings/mcp/settings/$serverId': typeof SettingsMcpSettingsServerIdRoute
}
export interface FileRoutesByTo {
'/': typeof IndexRoute
- '/settings': typeof SettingsRoute
+ '/chat': typeof ChatRoute
+ '/code': typeof CodeRoute
+ '/files': typeof FilesRoute
+ '/knowledge': typeof KnowledgeRoute
+ '/notes': typeof NotesRoute
+ '/store': typeof StoreRoute
+ '/translate': typeof TranslateRoute
+ '/apps/$appId': typeof AppsAppIdRoute
+ '/paintings/$': typeof PaintingsSplatRoute
+ '/settings/about': typeof SettingsAboutRoute
+ '/settings/api-server': typeof SettingsApiServerRoute
+ '/settings/data': typeof SettingsDataRoute
+ '/settings/display': typeof SettingsDisplayRoute
+ '/settings/docprocess': typeof SettingsDocprocessRoute
+ '/settings/general': typeof SettingsGeneralRoute
+ '/settings/memory': typeof SettingsMemoryRoute
+ '/settings/model': typeof SettingsModelRoute
+ '/settings/notes': typeof SettingsNotesRoute
+ '/settings/provider': typeof SettingsProviderRoute
+ '/settings/quickAssistant': typeof SettingsQuickAssistantRoute
+ '/settings/quickphrase': typeof SettingsQuickphraseRoute
+ '/settings/selectionAssistant': typeof SettingsSelectionAssistantRoute
+ '/settings/shortcut': typeof SettingsShortcutRoute
+ '/settings/websearch': typeof SettingsWebsearchRoute
+ '/apps': typeof AppsIndexRoute
+ '/paintings': typeof PaintingsIndexRoute
+ '/settings': typeof SettingsIndexRoute
+ '/settings/mcp/$': typeof SettingsMcpSplatRoute
+ '/settings/mcp/builtin': typeof SettingsMcpBuiltinRoute
+ '/settings/mcp/marketplaces': typeof SettingsMcpMarketplacesRoute
+ '/settings/mcp/mcp-install': typeof SettingsMcpMcpInstallRoute
+ '/settings/mcp/npx-search': typeof SettingsMcpNpxSearchRoute
+ '/settings/mcp/servers': typeof SettingsMcpServersRoute
+ '/settings/mcp': typeof SettingsMcpIndexRoute
+ '/settings/mcp/settings/$serverId': typeof SettingsMcpSettingsServerIdRoute
}
export interface FileRoutesById {
__root__: typeof rootRouteImport
'/': typeof IndexRoute
- '/settings': typeof SettingsRoute
+ '/chat': typeof ChatRoute
+ '/code': typeof CodeRoute
+ '/files': typeof FilesRoute
+ '/knowledge': typeof KnowledgeRoute
+ '/notes': typeof NotesRoute
+ '/settings': typeof SettingsRouteWithChildren
+ '/store': typeof StoreRoute
+ '/translate': typeof TranslateRoute
+ '/apps/$appId': typeof AppsAppIdRoute
+ '/paintings/$': typeof PaintingsSplatRoute
+ '/settings/about': typeof SettingsAboutRoute
+ '/settings/api-server': typeof SettingsApiServerRoute
+ '/settings/data': typeof SettingsDataRoute
+ '/settings/display': typeof SettingsDisplayRoute
+ '/settings/docprocess': typeof SettingsDocprocessRoute
+ '/settings/general': typeof SettingsGeneralRoute
+ '/settings/mcp': typeof SettingsMcpRouteWithChildren
+ '/settings/memory': typeof SettingsMemoryRoute
+ '/settings/model': typeof SettingsModelRoute
+ '/settings/notes': typeof SettingsNotesRoute
+ '/settings/provider': typeof SettingsProviderRoute
+ '/settings/quickAssistant': typeof SettingsQuickAssistantRoute
+ '/settings/quickphrase': typeof SettingsQuickphraseRoute
+ '/settings/selectionAssistant': typeof SettingsSelectionAssistantRoute
+ '/settings/shortcut': typeof SettingsShortcutRoute
+ '/settings/websearch': typeof SettingsWebsearchRoute
+ '/apps/': typeof AppsIndexRoute
+ '/paintings/': typeof PaintingsIndexRoute
+ '/settings/': typeof SettingsIndexRoute
+ '/settings/mcp/$': typeof SettingsMcpSplatRoute
+ '/settings/mcp/builtin': typeof SettingsMcpBuiltinRoute
+ '/settings/mcp/marketplaces': typeof SettingsMcpMarketplacesRoute
+ '/settings/mcp/mcp-install': typeof SettingsMcpMcpInstallRoute
+ '/settings/mcp/npx-search': typeof SettingsMcpNpxSearchRoute
+ '/settings/mcp/servers': typeof SettingsMcpServersRoute
+ '/settings/mcp/': typeof SettingsMcpIndexRoute
+ '/settings/mcp/settings/$serverId': typeof SettingsMcpSettingsServerIdRoute
}
export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath
- fullPaths: '/' | '/settings'
+ fullPaths:
+ | '/'
+ | '/chat'
+ | '/code'
+ | '/files'
+ | '/knowledge'
+ | '/notes'
+ | '/settings'
+ | '/store'
+ | '/translate'
+ | '/apps/$appId'
+ | '/paintings/$'
+ | '/settings/about'
+ | '/settings/api-server'
+ | '/settings/data'
+ | '/settings/display'
+ | '/settings/docprocess'
+ | '/settings/general'
+ | '/settings/mcp'
+ | '/settings/memory'
+ | '/settings/model'
+ | '/settings/notes'
+ | '/settings/provider'
+ | '/settings/quickAssistant'
+ | '/settings/quickphrase'
+ | '/settings/selectionAssistant'
+ | '/settings/shortcut'
+ | '/settings/websearch'
+ | '/apps'
+ | '/paintings'
+ | '/settings/'
+ | '/settings/mcp/$'
+ | '/settings/mcp/builtin'
+ | '/settings/mcp/marketplaces'
+ | '/settings/mcp/mcp-install'
+ | '/settings/mcp/npx-search'
+ | '/settings/mcp/servers'
+ | '/settings/mcp/'
+ | '/settings/mcp/settings/$serverId'
fileRoutesByTo: FileRoutesByTo
- to: '/' | '/settings'
- id: '__root__' | '/' | '/settings'
+ to:
+ | '/'
+ | '/chat'
+ | '/code'
+ | '/files'
+ | '/knowledge'
+ | '/notes'
+ | '/store'
+ | '/translate'
+ | '/apps/$appId'
+ | '/paintings/$'
+ | '/settings/about'
+ | '/settings/api-server'
+ | '/settings/data'
+ | '/settings/display'
+ | '/settings/docprocess'
+ | '/settings/general'
+ | '/settings/memory'
+ | '/settings/model'
+ | '/settings/notes'
+ | '/settings/provider'
+ | '/settings/quickAssistant'
+ | '/settings/quickphrase'
+ | '/settings/selectionAssistant'
+ | '/settings/shortcut'
+ | '/settings/websearch'
+ | '/apps'
+ | '/paintings'
+ | '/settings'
+ | '/settings/mcp/$'
+ | '/settings/mcp/builtin'
+ | '/settings/mcp/marketplaces'
+ | '/settings/mcp/mcp-install'
+ | '/settings/mcp/npx-search'
+ | '/settings/mcp/servers'
+ | '/settings/mcp'
+ | '/settings/mcp/settings/$serverId'
+ id:
+ | '__root__'
+ | '/'
+ | '/chat'
+ | '/code'
+ | '/files'
+ | '/knowledge'
+ | '/notes'
+ | '/settings'
+ | '/store'
+ | '/translate'
+ | '/apps/$appId'
+ | '/paintings/$'
+ | '/settings/about'
+ | '/settings/api-server'
+ | '/settings/data'
+ | '/settings/display'
+ | '/settings/docprocess'
+ | '/settings/general'
+ | '/settings/mcp'
+ | '/settings/memory'
+ | '/settings/model'
+ | '/settings/notes'
+ | '/settings/provider'
+ | '/settings/quickAssistant'
+ | '/settings/quickphrase'
+ | '/settings/selectionAssistant'
+ | '/settings/shortcut'
+ | '/settings/websearch'
+ | '/apps/'
+ | '/paintings/'
+ | '/settings/'
+ | '/settings/mcp/$'
+ | '/settings/mcp/builtin'
+ | '/settings/mcp/marketplaces'
+ | '/settings/mcp/mcp-install'
+ | '/settings/mcp/npx-search'
+ | '/settings/mcp/servers'
+ | '/settings/mcp/'
+ | '/settings/mcp/settings/$serverId'
fileRoutesById: FileRoutesById
}
export interface RootRouteChildren {
IndexRoute: typeof IndexRoute
- SettingsRoute: typeof SettingsRoute
+ ChatRoute: typeof ChatRoute
+ CodeRoute: typeof CodeRoute
+ FilesRoute: typeof FilesRoute
+ KnowledgeRoute: typeof KnowledgeRoute
+ NotesRoute: typeof NotesRoute
+ SettingsRoute: typeof SettingsRouteWithChildren
+ StoreRoute: typeof StoreRoute
+ TranslateRoute: typeof TranslateRoute
+ AppsAppIdRoute: typeof AppsAppIdRoute
+ PaintingsSplatRoute: typeof PaintingsSplatRoute
+ AppsIndexRoute: typeof AppsIndexRoute
+ PaintingsIndexRoute: typeof PaintingsIndexRoute
}
declare module '@tanstack/react-router' {
interface FileRoutesByPath {
+ '/translate': {
+ id: '/translate'
+ path: '/translate'
+ fullPath: '/translate'
+ preLoaderRoute: typeof TranslateRouteImport
+ parentRoute: typeof rootRouteImport
+ }
+ '/store': {
+ id: '/store'
+ path: '/store'
+ fullPath: '/store'
+ preLoaderRoute: typeof StoreRouteImport
+ parentRoute: typeof rootRouteImport
+ }
'/settings': {
id: '/settings'
path: '/settings'
@@ -58,6 +520,41 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof SettingsRouteImport
parentRoute: typeof rootRouteImport
}
+ '/notes': {
+ id: '/notes'
+ path: '/notes'
+ fullPath: '/notes'
+ preLoaderRoute: typeof NotesRouteImport
+ parentRoute: typeof rootRouteImport
+ }
+ '/knowledge': {
+ id: '/knowledge'
+ path: '/knowledge'
+ fullPath: '/knowledge'
+ preLoaderRoute: typeof KnowledgeRouteImport
+ parentRoute: typeof rootRouteImport
+ }
+ '/files': {
+ id: '/files'
+ path: '/files'
+ fullPath: '/files'
+ preLoaderRoute: typeof FilesRouteImport
+ parentRoute: typeof rootRouteImport
+ }
+ '/code': {
+ id: '/code'
+ path: '/code'
+ fullPath: '/code'
+ preLoaderRoute: typeof CodeRouteImport
+ parentRoute: typeof rootRouteImport
+ }
+ '/chat': {
+ id: '/chat'
+ path: '/chat'
+ fullPath: '/chat'
+ preLoaderRoute: typeof ChatRouteImport
+ parentRoute: typeof rootRouteImport
+ }
'/': {
id: '/'
path: '/'
@@ -65,12 +562,296 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof IndexRouteImport
parentRoute: typeof rootRouteImport
}
+ '/settings/': {
+ id: '/settings/'
+ path: '/'
+ fullPath: '/settings/'
+ preLoaderRoute: typeof SettingsIndexRouteImport
+ parentRoute: typeof SettingsRoute
+ }
+ '/paintings/': {
+ id: '/paintings/'
+ path: '/paintings'
+ fullPath: '/paintings'
+ preLoaderRoute: typeof PaintingsIndexRouteImport
+ parentRoute: typeof rootRouteImport
+ }
+ '/apps/': {
+ id: '/apps/'
+ path: '/apps'
+ fullPath: '/apps'
+ preLoaderRoute: typeof AppsIndexRouteImport
+ parentRoute: typeof rootRouteImport
+ }
+ '/settings/websearch': {
+ id: '/settings/websearch'
+ path: '/websearch'
+ fullPath: '/settings/websearch'
+ preLoaderRoute: typeof SettingsWebsearchRouteImport
+ parentRoute: typeof SettingsRoute
+ }
+ '/settings/shortcut': {
+ id: '/settings/shortcut'
+ path: '/shortcut'
+ fullPath: '/settings/shortcut'
+ preLoaderRoute: typeof SettingsShortcutRouteImport
+ parentRoute: typeof SettingsRoute
+ }
+ '/settings/selectionAssistant': {
+ id: '/settings/selectionAssistant'
+ path: '/selectionAssistant'
+ fullPath: '/settings/selectionAssistant'
+ preLoaderRoute: typeof SettingsSelectionAssistantRouteImport
+ parentRoute: typeof SettingsRoute
+ }
+ '/settings/quickphrase': {
+ id: '/settings/quickphrase'
+ path: '/quickphrase'
+ fullPath: '/settings/quickphrase'
+ preLoaderRoute: typeof SettingsQuickphraseRouteImport
+ parentRoute: typeof SettingsRoute
+ }
+ '/settings/quickAssistant': {
+ id: '/settings/quickAssistant'
+ path: '/quickAssistant'
+ fullPath: '/settings/quickAssistant'
+ preLoaderRoute: typeof SettingsQuickAssistantRouteImport
+ parentRoute: typeof SettingsRoute
+ }
+ '/settings/provider': {
+ id: '/settings/provider'
+ path: '/provider'
+ fullPath: '/settings/provider'
+ preLoaderRoute: typeof SettingsProviderRouteImport
+ parentRoute: typeof SettingsRoute
+ }
+ '/settings/notes': {
+ id: '/settings/notes'
+ path: '/notes'
+ fullPath: '/settings/notes'
+ preLoaderRoute: typeof SettingsNotesRouteImport
+ parentRoute: typeof SettingsRoute
+ }
+ '/settings/model': {
+ id: '/settings/model'
+ path: '/model'
+ fullPath: '/settings/model'
+ preLoaderRoute: typeof SettingsModelRouteImport
+ parentRoute: typeof SettingsRoute
+ }
+ '/settings/memory': {
+ id: '/settings/memory'
+ path: '/memory'
+ fullPath: '/settings/memory'
+ preLoaderRoute: typeof SettingsMemoryRouteImport
+ parentRoute: typeof SettingsRoute
+ }
+ '/settings/mcp': {
+ id: '/settings/mcp'
+ path: '/mcp'
+ fullPath: '/settings/mcp'
+ preLoaderRoute: typeof SettingsMcpRouteImport
+ parentRoute: typeof SettingsRoute
+ }
+ '/settings/general': {
+ id: '/settings/general'
+ path: '/general'
+ fullPath: '/settings/general'
+ preLoaderRoute: typeof SettingsGeneralRouteImport
+ parentRoute: typeof SettingsRoute
+ }
+ '/settings/docprocess': {
+ id: '/settings/docprocess'
+ path: '/docprocess'
+ fullPath: '/settings/docprocess'
+ preLoaderRoute: typeof SettingsDocprocessRouteImport
+ parentRoute: typeof SettingsRoute
+ }
+ '/settings/display': {
+ id: '/settings/display'
+ path: '/display'
+ fullPath: '/settings/display'
+ preLoaderRoute: typeof SettingsDisplayRouteImport
+ parentRoute: typeof SettingsRoute
+ }
+ '/settings/data': {
+ id: '/settings/data'
+ path: '/data'
+ fullPath: '/settings/data'
+ preLoaderRoute: typeof SettingsDataRouteImport
+ parentRoute: typeof SettingsRoute
+ }
+ '/settings/api-server': {
+ id: '/settings/api-server'
+ path: '/api-server'
+ fullPath: '/settings/api-server'
+ preLoaderRoute: typeof SettingsApiServerRouteImport
+ parentRoute: typeof SettingsRoute
+ }
+ '/settings/about': {
+ id: '/settings/about'
+ path: '/about'
+ fullPath: '/settings/about'
+ preLoaderRoute: typeof SettingsAboutRouteImport
+ parentRoute: typeof SettingsRoute
+ }
+ '/paintings/$': {
+ id: '/paintings/$'
+ path: '/paintings/$'
+ fullPath: '/paintings/$'
+ preLoaderRoute: typeof PaintingsSplatRouteImport
+ parentRoute: typeof rootRouteImport
+ }
+ '/apps/$appId': {
+ id: '/apps/$appId'
+ path: '/apps/$appId'
+ fullPath: '/apps/$appId'
+ preLoaderRoute: typeof AppsAppIdRouteImport
+ parentRoute: typeof rootRouteImport
+ }
+ '/settings/mcp/': {
+ id: '/settings/mcp/'
+ path: '/'
+ fullPath: '/settings/mcp/'
+ preLoaderRoute: typeof SettingsMcpIndexRouteImport
+ parentRoute: typeof SettingsMcpRoute
+ }
+ '/settings/mcp/servers': {
+ id: '/settings/mcp/servers'
+ path: '/servers'
+ fullPath: '/settings/mcp/servers'
+ preLoaderRoute: typeof SettingsMcpServersRouteImport
+ parentRoute: typeof SettingsMcpRoute
+ }
+ '/settings/mcp/npx-search': {
+ id: '/settings/mcp/npx-search'
+ path: '/npx-search'
+ fullPath: '/settings/mcp/npx-search'
+ preLoaderRoute: typeof SettingsMcpNpxSearchRouteImport
+ parentRoute: typeof SettingsMcpRoute
+ }
+ '/settings/mcp/mcp-install': {
+ id: '/settings/mcp/mcp-install'
+ path: '/mcp-install'
+ fullPath: '/settings/mcp/mcp-install'
+ preLoaderRoute: typeof SettingsMcpMcpInstallRouteImport
+ parentRoute: typeof SettingsMcpRoute
+ }
+ '/settings/mcp/marketplaces': {
+ id: '/settings/mcp/marketplaces'
+ path: '/marketplaces'
+ fullPath: '/settings/mcp/marketplaces'
+ preLoaderRoute: typeof SettingsMcpMarketplacesRouteImport
+ parentRoute: typeof SettingsMcpRoute
+ }
+ '/settings/mcp/builtin': {
+ id: '/settings/mcp/builtin'
+ path: '/builtin'
+ fullPath: '/settings/mcp/builtin'
+ preLoaderRoute: typeof SettingsMcpBuiltinRouteImport
+ parentRoute: typeof SettingsMcpRoute
+ }
+ '/settings/mcp/$': {
+ id: '/settings/mcp/$'
+ path: '/$'
+ fullPath: '/settings/mcp/$'
+ preLoaderRoute: typeof SettingsMcpSplatRouteImport
+ parentRoute: typeof SettingsMcpRoute
+ }
+ '/settings/mcp/settings/$serverId': {
+ id: '/settings/mcp/settings/$serverId'
+ path: '/settings/$serverId'
+ fullPath: '/settings/mcp/settings/$serverId'
+ preLoaderRoute: typeof SettingsMcpSettingsServerIdRouteImport
+ parentRoute: typeof SettingsMcpRoute
+ }
}
}
+interface SettingsMcpRouteChildren {
+ SettingsMcpSplatRoute: typeof SettingsMcpSplatRoute
+ SettingsMcpBuiltinRoute: typeof SettingsMcpBuiltinRoute
+ SettingsMcpMarketplacesRoute: typeof SettingsMcpMarketplacesRoute
+ SettingsMcpMcpInstallRoute: typeof SettingsMcpMcpInstallRoute
+ SettingsMcpNpxSearchRoute: typeof SettingsMcpNpxSearchRoute
+ SettingsMcpServersRoute: typeof SettingsMcpServersRoute
+ SettingsMcpIndexRoute: typeof SettingsMcpIndexRoute
+ SettingsMcpSettingsServerIdRoute: typeof SettingsMcpSettingsServerIdRoute
+}
+
+const SettingsMcpRouteChildren: SettingsMcpRouteChildren = {
+ SettingsMcpSplatRoute: SettingsMcpSplatRoute,
+ SettingsMcpBuiltinRoute: SettingsMcpBuiltinRoute,
+ SettingsMcpMarketplacesRoute: SettingsMcpMarketplacesRoute,
+ SettingsMcpMcpInstallRoute: SettingsMcpMcpInstallRoute,
+ SettingsMcpNpxSearchRoute: SettingsMcpNpxSearchRoute,
+ SettingsMcpServersRoute: SettingsMcpServersRoute,
+ SettingsMcpIndexRoute: SettingsMcpIndexRoute,
+ SettingsMcpSettingsServerIdRoute: SettingsMcpSettingsServerIdRoute,
+}
+
+const SettingsMcpRouteWithChildren = SettingsMcpRoute._addFileChildren(
+ SettingsMcpRouteChildren,
+)
+
+interface SettingsRouteChildren {
+ SettingsAboutRoute: typeof SettingsAboutRoute
+ SettingsApiServerRoute: typeof SettingsApiServerRoute
+ SettingsDataRoute: typeof SettingsDataRoute
+ SettingsDisplayRoute: typeof SettingsDisplayRoute
+ SettingsDocprocessRoute: typeof SettingsDocprocessRoute
+ SettingsGeneralRoute: typeof SettingsGeneralRoute
+ SettingsMcpRoute: typeof SettingsMcpRouteWithChildren
+ SettingsMemoryRoute: typeof SettingsMemoryRoute
+ SettingsModelRoute: typeof SettingsModelRoute
+ SettingsNotesRoute: typeof SettingsNotesRoute
+ SettingsProviderRoute: typeof SettingsProviderRoute
+ SettingsQuickAssistantRoute: typeof SettingsQuickAssistantRoute
+ SettingsQuickphraseRoute: typeof SettingsQuickphraseRoute
+ SettingsSelectionAssistantRoute: typeof SettingsSelectionAssistantRoute
+ SettingsShortcutRoute: typeof SettingsShortcutRoute
+ SettingsWebsearchRoute: typeof SettingsWebsearchRoute
+ SettingsIndexRoute: typeof SettingsIndexRoute
+}
+
+const SettingsRouteChildren: SettingsRouteChildren = {
+ SettingsAboutRoute: SettingsAboutRoute,
+ SettingsApiServerRoute: SettingsApiServerRoute,
+ SettingsDataRoute: SettingsDataRoute,
+ SettingsDisplayRoute: SettingsDisplayRoute,
+ SettingsDocprocessRoute: SettingsDocprocessRoute,
+ SettingsGeneralRoute: SettingsGeneralRoute,
+ SettingsMcpRoute: SettingsMcpRouteWithChildren,
+ SettingsMemoryRoute: SettingsMemoryRoute,
+ SettingsModelRoute: SettingsModelRoute,
+ SettingsNotesRoute: SettingsNotesRoute,
+ SettingsProviderRoute: SettingsProviderRoute,
+ SettingsQuickAssistantRoute: SettingsQuickAssistantRoute,
+ SettingsQuickphraseRoute: SettingsQuickphraseRoute,
+ SettingsSelectionAssistantRoute: SettingsSelectionAssistantRoute,
+ SettingsShortcutRoute: SettingsShortcutRoute,
+ SettingsWebsearchRoute: SettingsWebsearchRoute,
+ SettingsIndexRoute: SettingsIndexRoute,
+}
+
+const SettingsRouteWithChildren = SettingsRoute._addFileChildren(
+ SettingsRouteChildren,
+)
+
const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute,
- SettingsRoute: SettingsRoute,
+ ChatRoute: ChatRoute,
+ CodeRoute: CodeRoute,
+ FilesRoute: FilesRoute,
+ KnowledgeRoute: KnowledgeRoute,
+ NotesRoute: NotesRoute,
+ SettingsRoute: SettingsRouteWithChildren,
+ StoreRoute: StoreRoute,
+ TranslateRoute: TranslateRoute,
+ AppsAppIdRoute: AppsAppIdRoute,
+ PaintingsSplatRoute: PaintingsSplatRoute,
+ AppsIndexRoute: AppsIndexRoute,
+ PaintingsIndexRoute: PaintingsIndexRoute,
}
export const routeTree = rootRouteImport
._addFileChildren(rootRouteChildren)
diff --git a/src/renderer/src/services/MessagesService.ts b/src/renderer/src/services/MessagesService.ts
index 58fa6fbea1..2773a56cec 100644
--- a/src/renderer/src/services/MessagesService.ts
+++ b/src/renderer/src/services/MessagesService.ts
@@ -23,9 +23,9 @@ import {
} from '@renderer/utils/messageUtils/create'
import { filterContextMessages } from '@renderer/utils/messageUtils/filters'
import { getMainTextContent } from '@renderer/utils/messageUtils/find'
+import type { UseNavigateResult } from '@tanstack/react-router'
import dayjs from 'dayjs'
import { t } from 'i18next'
-import type { NavigateFunction } from 'react-router'
import { getAssistantById, getAssistantProvider, getDefaultModel } from './AssistantService'
import { EVENT_NAMES, EventEmitter } from './EventService'
@@ -68,14 +68,14 @@ export function deleteMessageFiles(message: Message) {
})
}
-export async function locateToMessage(navigate: NavigateFunction, message: Message) {
+export async function locateToMessage(navigate: UseNavigateResult, message: Message) {
await modelGenerating()
SearchPopup.hide()
const assistant = getAssistantById(message.assistantId)
const topic = await getTopicById(message.topicId)
- navigate('/', { state: { assistant, topic } })
+ navigate({ to: '/chat', search: { assistantId: assistant?.id, topicId: topic?.id } })
setTimeout(() => EventEmitter.emit(EVENT_NAMES.SHOW_TOPIC_SIDEBAR), 0)
setTimeout(() => EventEmitter.emit(EVENT_NAMES.LOCATE_MESSAGE + ':' + message.id), 300)
diff --git a/src/renderer/src/services/NavigationService.ts b/src/renderer/src/services/NavigationService.ts
index 3c4ae54abe..ac4747b160 100644
--- a/src/renderer/src/services/NavigationService.ts
+++ b/src/renderer/src/services/NavigationService.ts
@@ -1,14 +1,15 @@
-import type { NavigateFunction } from 'react-router-dom'
+import type { UseNavigateResult } from '@tanstack/react-router'
+// Tab 导航服务 - 用于在非 React 组件中进行路由导航
interface INavigationService {
- navigate: NavigateFunction | null
- setNavigate: (navigateFunc: NavigateFunction) => void
+ navigate: UseNavigateResult | null
+ setNavigate: (navigateFunc: UseNavigateResult) => void
}
const NavigationService: INavigationService = {
navigate: null,
- setNavigate: (navigateFunc: NavigateFunction): void => {
+ setNavigate: (navigateFunc: UseNavigateResult): void => {
NavigationService.navigate = navigateFunc
window.navigate = NavigationService.navigate
}
diff --git a/src/renderer/src/services/TabsService.ts b/src/renderer/src/services/TabsService.ts
index a0c22c488b..e94faea192 100644
--- a/src/renderer/src/services/TabsService.ts
+++ b/src/renderer/src/services/TabsService.ts
@@ -55,12 +55,12 @@ class TabsService {
// 使用 NavigationService 导航到新的标签页
if (NavigationService.navigate) {
- NavigationService.navigate(lastTab.path)
+ NavigationService.navigate({ to: lastTab.path })
} else {
logger.warn('Navigation service not ready, will navigate on next render')
setTimeout(() => {
if (NavigationService.navigate) {
- NavigationService.navigate(lastTab.path)
+ NavigationService.navigate({ to: lastTab.path })
}
}, 100)
}
@@ -133,7 +133,7 @@ class TabsService {
// 导航到对应页面
if (NavigationService.navigate) {
- NavigationService.navigate(tab.path)
+ NavigationService.navigate({ to: tab.path })
}
return true