import React, { useEffect, useState } from 'react' import { setDragDropEnabled } from './components/GlobalDragDropOverlay' import { setNotebookDragDropEnabled } from './components/NotebookGlobalDragDropOverlay' import LoginPage from './components/LoginPage' import { SidebarRail, ViewType } from './components/layouts/SidebarRail' import { ChatView } from './components/views/ChatView' import { KnowledgeBaseView } from './components/views/KnowledgeBaseView' import { NotebooksView } from './components/views/NotebooksView' import { SettingsView } from './components/views/SettingsView' import { LanguageProvider } from './contexts/LanguageContext' import { ToastProvider } from './contexts/ToastContext' import { ConfirmProvider } from './contexts/ConfirmContext' import { modelConfigService } from './services/modelConfigService' import { authService } from './services/authService' import { ModelConfig, DEFAULT_MODELS } from './types' const AppContent: React.FC = () => { const [authToken, setAuthToken] = useState(null) const [currentUser, setCurrentUser] = useState(null); // Add current user state const [currentView, setCurrentView] = useState('chat') const [isVerifying, setIsVerifying] = useState(true) // Chat Context State const [chatContext, setChatContext] = useState<{ selectedGroups?: string[], selectedFiles?: string[] } | null>(null) // Model State const [modelConfigs, setModelConfigs] = useState(DEFAULT_MODELS) // Disable drag drop when view changes useEffect(() => { // ビュー切り替え時にドラッグアンドドロップ機能を一時的に無効にして、ナビゲーション時の点滅を防ぐ setDragDropEnabled(false); setNotebookDragDropEnabled(false); // 次のイベントループで有効にして、ビュー切り替えが完了することを確認 const timer = setTimeout(() => { setDragDropEnabled(true); setNotebookDragDropEnabled(true); }, 0); return () => { clearTimeout(timer); }; }, [currentView]); // Load token from localStorage on initial render useEffect(() => { const verifyToken = async () => { const storedToken = localStorage.getItem('authToken') if (storedToken) { try { const userProfile = await authService.getProfile(storedToken) // Get full profile setAuthToken(storedToken) setCurrentUser(userProfile) // Store user profile } catch (error) { console.error('Invalid token, logging out:', error) localStorage.removeItem('authToken') setAuthToken(null) setCurrentUser(null) } } setIsVerifying(false) } verifyToken() }, []) const handleLoginSuccess = async (token: string) => { setAuthToken(token) localStorage.setItem('authToken', token) try { const userProfile = await authService.getProfile(token) setCurrentUser(userProfile) } catch (error) { console.error('Failed to fetch user profile:', error) } } const handleLogout = () => { setAuthToken(null) setCurrentUser(null) localStorage.removeItem('authToken') } // Fetch Models const fetchAndSetModels = React.useCallback(async () => { if (!authToken) return try { const backendModels = await modelConfigService.getAll(authToken) const mergedModelsMap = new Map() DEFAULT_MODELS.forEach(m => mergedModelsMap.set(m.id, m)) backendModels.forEach(bm => { mergedModelsMap.set(bm.id, { ...bm }) }) const mergedModels = Array.from(mergedModelsMap.values()) setModelConfigs(mergedModels) } catch (error) { console.error('Failed to fetch model configs:', error) setModelConfigs(DEFAULT_MODELS) } }, [authToken]) useEffect(() => { if (authToken) { fetchAndSetModels() } }, [authToken, fetchAndSetModels]) const handleUpdateModels = React.useCallback(async (action: 'create' | 'update' | 'delete', model: ModelConfig) => { if (!authToken) return try { if (action === 'create') { await modelConfigService.create(authToken, model) } else if (action === 'update') { await modelConfigService.update(authToken, model.id, model) } else if (action === 'delete') { await modelConfigService.remove(authToken, model.id) } await fetchAndSetModels() } catch (error) { console.error(`Failed to perform ${action} on model config:`, error) throw error } }, [authToken, fetchAndSetModels]) const handleChatWithContext = (context: { selectedGroups?: string[], selectedFiles?: string[] }) => { setChatContext(context) setCurrentView('chat') } // Login Flow if (isVerifying) { return (

Verifying session...

) } if (!authToken) { return } // Main Layout (Rail + View) return (
{currentView === 'chat' && ( setCurrentView(view)} initialChatContext={chatContext} onClearContext={() => setChatContext(null)} isAdmin={!!currentUser?.isAdmin} /> )} {currentView === 'knowledge' && ( setCurrentView(view)} isAdmin={!!currentUser?.isAdmin} /> )} {currentView === 'notebooks' && ( )} {currentView === 'settings' && ( )}
) } const App: React.FC = () => { return ( ) } export default App