manus-clone-cn / src /App.tsx
Trae Assistant
Initial commit
69a3dd3
import { useState, useEffect } from 'react'
import Sidebar from './components/Sidebar'
import MainContent from './components/MainContent'
import DetailContent from './components/DetailContent'
import OriginalDetailContent from './components/OriginalDetailContent'
import { chatService } from './services/chatService'
import type { ChatSession } from './services/chatService'
function App() {
const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(false)
// Responsive Sidebar Logic
useEffect(() => {
const handleResize = () => {
if (window.innerWidth < 1024) {
setIsSidebarCollapsed(true)
} else {
setIsSidebarCollapsed(false)
}
}
// Initial check
handleResize()
window.addEventListener('resize', handleResize)
return () => window.removeEventListener('resize', handleResize)
}, [])
const [activeView, setActiveView] = useState<'home' | 'detail' | 'original'>(() => {
if (typeof window !== 'undefined') {
const saved = localStorage.getItem('activeView')
return (saved as 'home' | 'detail' | 'original') || 'home'
}
return 'home'
})
const [isDarkMode, setIsDarkMode] = useState(() => {
if (typeof window !== 'undefined') {
const saved = localStorage.getItem('theme')
if (saved) return saved === 'dark'
return window.matchMedia('(prefers-color-scheme: dark)').matches
}
return false
})
// Chat State
const [sessions, setSessions] = useState<ChatSession[]>(() => chatService.getHistory())
const [currentSessionId, setCurrentSessionId] = useState<string | null>(() => {
if (typeof window !== 'undefined') {
return localStorage.getItem('currentSessionId')
}
return null
})
useEffect(() => {
if (isDarkMode) {
document.documentElement.classList.add('dark')
localStorage.setItem('theme', 'dark')
} else {
document.documentElement.classList.remove('dark')
localStorage.setItem('theme', 'light')
}
}, [isDarkMode])
// Persist navigation state
useEffect(() => {
localStorage.setItem('activeView', activeView)
}, [activeView])
useEffect(() => {
if (currentSessionId) {
localStorage.setItem('currentSessionId', currentSessionId)
} else {
localStorage.removeItem('currentSessionId')
}
}, [currentSessionId])
const toggleTheme = () => setIsDarkMode(!isDarkMode)
const resetToDefault = () => {
setActiveView('home')
setCurrentSessionId(null)
}
const handleNewChat = (message: string) => {
const newSession = chatService.createSession(message)
setSessions(prevSessions => {
const updatedSessions = [newSession, ...prevSessions]
chatService.saveHistory(updatedSessions)
return updatedSessions
})
setCurrentSessionId(newSession.id)
setActiveView('detail')
}
const handleSelectSession = (sessionId: string) => {
setCurrentSessionId(sessionId)
setActiveView('detail')
// Auto-close sidebar on mobile after selection
if (window.innerWidth < 1024) {
setIsSidebarCollapsed(true)
}
}
const handleUpdateSession = (updatedSession: ChatSession) => {
setSessions(prevSessions => {
const updatedSessions = prevSessions.map(s => s.id === updatedSession.id ? updatedSession : s)
chatService.saveHistory(updatedSessions)
return updatedSessions
})
}
const handleRenameSession = (sessionId: string, newTitle: string) => {
setSessions(prevSessions => {
const updatedSessions = prevSessions.map(s =>
s.id === sessionId ? { ...s, title: newTitle } : s
);
chatService.saveHistory(updatedSessions);
return updatedSessions;
});
};
const handleDeleteSession = (sessionId: string) => {
setSessions(prevSessions => {
const updatedSessions = prevSessions.filter(s => s.id !== sessionId);
chatService.saveHistory(updatedSessions);
return updatedSessions;
});
if (currentSessionId === sessionId) {
setCurrentSessionId(null);
setActiveView('home');
}
};
const currentSession = sessions.find(s => s.id === currentSessionId)
return (
<div className="flex w-full h-screen bg-white dark:bg-gray-900 overflow-hidden font-sans text-gray-900 dark:text-gray-100 transition-colors duration-300">
<Sidebar
isCollapsed={isSidebarCollapsed}
toggleSidebar={() => setIsSidebarCollapsed(!isSidebarCollapsed)}
activeView={activeView}
onNavigate={setActiveView}
onReset={resetToDefault}
sessions={sessions}
currentSessionId={currentSessionId}
onSelectSession={handleSelectSession}
onRenameSession={handleRenameSession}
onDeleteSession={handleDeleteSession}
/>
{activeView === 'home' ? (
<MainContent
isDarkMode={isDarkMode}
toggleTheme={toggleTheme}
onNewChat={handleNewChat}
onToggleSidebar={() => setIsSidebarCollapsed(!isSidebarCollapsed)}
/>
) : activeView === 'detail' ? (
<DetailContent
key={currentSession?.id}
isDarkMode={isDarkMode}
toggleTheme={toggleTheme}
session={currentSession}
onUpdateSession={handleUpdateSession}
onToggleSidebar={() => setIsSidebarCollapsed(!isSidebarCollapsed)}
/>
) : (
<OriginalDetailContent
isDarkMode={isDarkMode}
toggleTheme={toggleTheme}
/>
)}
</div>
)
}
export default App