import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import Layout from './components/layout/Layout';
import Dashboard from './pages/Dashboard';
import Accounts from './pages/Accounts';
import Settings from './pages/Settings';
import ApiProxy from './pages/ApiProxy';
import Monitor from './pages/Monitor';
import TokenStats from './pages/TokenStats';
import Security from './pages/Security';
import ThemeManager from './components/common/ThemeManager';
import UserToken from './pages/UserToken';
import { UpdateNotification } from './components/UpdateNotification';
import DebugConsole from './components/debug/DebugConsole';
import { useEffect, useState } from 'react';
import { useConfigStore } from './stores/useConfigStore';
import { useAccountStore } from './stores/useAccountStore';
import { useTranslation } from 'react-i18next';
import { listen } from '@tauri-apps/api/event';
import { isTauri } from './utils/env';
import { request as invoke } from './utils/request';
import { AdminAuthGuard } from './components/common/AdminAuthGuard';
const router = createBrowserRouter([
{
path: '/',
element: ,
children: [
{
index: true,
element: ,
},
{
path: 'accounts',
element: ,
},
{
path: 'api-proxy',
element: ,
},
{
path: 'monitor',
element: ,
},
{
path: 'token-stats',
element: ,
},
{
path: 'user-token',
element: ,
},
{
path: 'security',
element: ,
},
{
path: 'settings',
element: ,
},
],
},
]);
function App() {
const { config, loadConfig } = useConfigStore();
const { fetchCurrentAccount, fetchAccounts } = useAccountStore();
const { i18n } = useTranslation();
useEffect(() => {
loadConfig();
}, [loadConfig]);
// Sync language from config
useEffect(() => {
if (config?.language) {
i18n.changeLanguage(config.language);
// Support RTL
if (config.language === 'ar') {
document.documentElement.dir = 'rtl';
} else {
document.documentElement.dir = 'ltr';
}
}
}, [config?.language, i18n]);
// Listen for tray events
useEffect(() => {
if (!isTauri()) return;
const unlistenPromises: Promise<() => void>[] = [];
// 监听托盘切换账号事件
unlistenPromises.push(
listen('tray://account-switched', () => {
console.log('[App] Tray account switched, refreshing...');
fetchCurrentAccount();
fetchAccounts();
})
);
// 监听托盘刷新事件
unlistenPromises.push(
listen('tray://refresh-current', () => {
console.log('[App] Tray refresh triggered, refreshing...');
fetchCurrentAccount();
fetchAccounts();
})
);
// 监听后端全量刷新事件 (Command / Scheduler)
unlistenPromises.push(
listen('accounts://refreshed', () => {
console.log('[App] Backend triggered quota refresh, syncing UI...');
fetchCurrentAccount();
fetchAccounts();
})
);
// Cleanup
return () => {
Promise.all(unlistenPromises).then(unlisteners => {
unlisteners.forEach(unlisten => unlisten());
});
};
}, [fetchCurrentAccount, fetchAccounts]);
// Update notification state
const [showUpdateNotification, setShowUpdateNotification] = useState(false);
// Check for updates on startup
useEffect(() => {
const checkUpdates = async () => {
try {
console.log('[App] Checking if we should check for updates...');
const shouldCheck = await invoke('should_check_updates');
console.log('[App] Should check updates:', shouldCheck);
if (shouldCheck) {
setShowUpdateNotification(true);
// 我们这里只负责显示通知组件,通知组件内部会去调用 check_for_updates
// 我们在显示组件后,标记已经检查过了(即便失败或无更新,组件内部也会处理)
await invoke('update_last_check_time');
console.log('[App] Update check cycle initiated and last check time updated.');
}
} catch (error) {
console.error('Failed to check update settings:', error);
}
};
// Delay check to avoid blocking initial render
const timer = setTimeout(checkUpdates, 2000);
return () => clearTimeout(timer);
}, []);
return (
{showUpdateNotification && (
setShowUpdateNotification(false)} />
)}
);
}
export default App;