diff --git a/apps/desktop/src/renderer/src/App.tsx b/apps/desktop/src/renderer/src/App.tsx index 73213be93..dc5cf23c4 100644 --- a/apps/desktop/src/renderer/src/App.tsx +++ b/apps/desktop/src/renderer/src/App.tsx @@ -5,7 +5,6 @@ import { TooltipProvider } from '@multica/ui/components/ui/tooltip' import { Toaster } from './components/toaster' import Layout from './pages/layout' import HomePage from './pages/home' -import ChatPage from './pages/chat' import ProfilePage from './pages/agent/profile' import SkillsPage from './pages/agent/skills' import ToolsPage from './pages/agent/tools' @@ -73,7 +72,7 @@ const router = createHashRouter([ ), }, - { path: 'chat', element: }, + { path: 'chat', element: null }, { path: 'agent/profile', element: }, { path: 'agent/skills', element: }, { path: 'agent/tools', element: }, diff --git a/apps/desktop/src/renderer/src/components/local-chat.tsx b/apps/desktop/src/renderer/src/components/local-chat.tsx index 39c6c0b38..0f842a059 100644 --- a/apps/desktop/src/renderer/src/components/local-chat.tsx +++ b/apps/desktop/src/renderer/src/components/local-chat.tsx @@ -73,12 +73,13 @@ export function LocalChat({ initialPrompt }: LocalChatProps) { const currentMeta = current ? providers.find((p) => p.id === current.provider) : null // Auto-send initial prompt after a short delay - const hasSentInitialPrompt = useRef(false) + const lastPromptRef = useRef(undefined) useEffect(() => { - if (!agentId || !initialPrompt || hasSentInitialPrompt.current) return + if (!agentId || !initialPrompt) return + if (initialPrompt === lastPromptRef.current) return const timer = setTimeout(() => { - hasSentInitialPrompt.current = true + lastPromptRef.current = initialPrompt sendMessage(initialPrompt) // Remove prompt from URL to prevent re-sending on back navigation navigate('/chat', { replace: true }) diff --git a/apps/desktop/src/renderer/src/pages/layout.tsx b/apps/desktop/src/renderer/src/pages/layout.tsx index 1651e447a..476f61c73 100644 --- a/apps/desktop/src/renderer/src/pages/layout.tsx +++ b/apps/desktop/src/renderer/src/pages/layout.tsx @@ -1,3 +1,4 @@ +import { useState, useEffect } from 'react' import { Outlet, NavLink, useLocation, useNavigate } from 'react-router-dom' import { Button } from '@multica/ui/components/ui/button' import { MulticaIcon } from '@multica/ui/components/multica-icon' @@ -43,6 +44,7 @@ import { } from '@multica/ui/components/ui/sidebar' import { cn } from '@multica/ui/lib/utils' import { ModeToggle } from '../components/mode-toggle' +import { LocalChat } from '../components/local-chat' import { DeviceConfirmDialog } from '../components/device-confirm-dialog' import { UpdateNotification } from '../components/update-notification' import { useAuthStore } from '../stores/auth' @@ -151,8 +153,20 @@ export default function Layout() { const location = useLocation() const navigate = useNavigate() const isAgentActive = location.pathname.startsWith('/agent') + const isOnChat = location.pathname === '/chat' const { user, clearAuth } = useAuthStore() + // Lazy mount: only mount Chat on first visit, then keep it mounted forever + const [chatMounted, setChatMounted] = useState(false) + useEffect(() => { + if (isOnChat && !chatMounted) setChatMounted(true) + }, [isOnChat, chatMounted]) + + // Extract initialPrompt from URL search params when navigating to /chat?prompt=... + const initialPrompt = isOnChat + ? new URLSearchParams(location.search).get('prompt') ?? undefined + : undefined + const handleLogout = async () => { await clearAuth() navigate('/login') @@ -285,7 +299,14 @@ export default function Layout() {
- +
+ +
+ {chatMounted && ( +
+ +
+ )}