Files
metona-ai-desktop/src/App.tsx
T
thzxx 64af91bde9 feat: 升级至 v0.3.9 — 工具批量审批 + run_command 频率限制优化 + Toast 规范
1. 工具批量审批:解决并行工具审批弹框覆盖问题,新增批量 IPC 通道和列表 UI,支持同工具多次调用分组展示;2. 审批弹框健壮性:超时 toast 防风暴、agent 状态同步清空、ErrorBoundary 防白屏;3. run_command maxFrequency 从 3 调整为 10;4. 开发规范新增 Toast 通知铁律(必须使用 MeToast)
2026-07-21 11:43:41 +08:00

93 lines
4.0 KiB
TypeScript

/**
* MetonaAI Desktop — 根组件
*
* 三栏布局:Header + [Sidebar | Chat | DetailPanel] + StatusBar
* + ToastContainer + SettingsModal + OnboardingWizard
*
* 连接所有 Store,注册快捷键,初始化主题。
*/
import { ThemeProvider, CssBaseline } from '@mui/material';
import { useEffect } from 'react';
import { Header } from '@renderer/components/layout/Header';
import { Sidebar } from '@renderer/components/layout/Sidebar';
import { DetailPanel } from '@renderer/components/layout/DetailPanel';
import { StatusBar } from '@renderer/components/layout/StatusBar';
import { ChatPanel } from '@renderer/components/chat/ChatPanel';
import { SettingsModal } from '@renderer/components/settings/SettingsModal';
import { OnboardingWizard } from '@renderer/components/onboarding/OnboardingWizard';
import { CommandPalette } from '@renderer/components/CommandPalette';
import { ToastContainer } from '@renderer/components/ToastContainer';
import { ConfirmationDialog } from '@renderer/components/ConfirmationDialog';
import { ContextMenuDialogHost } from '@renderer/components/ContextMenu';
import { ErrorBoundary } from '@renderer/components/common/ErrorBoundary';
import { useTheme } from '@renderer/hooks/useTheme';
import { useKeyboardShortcuts } from '@renderer/hooks/useKeyboardShortcuts';
import { useAgentStream } from '@renderer/hooks/useAgentStream';
import { useUIStore } from '@renderer/stores/ui-store';
import { useAgentStore } from '@renderer/stores/agent-store';
import { metonaDarkTheme, metonaLightTheme } from '@renderer/lib/theme';
export default function App(): React.JSX.Element {
useTheme();
useKeyboardShortcuts();
useAgentStream();
const resolvedTheme = useUIStore((s) => s.resolvedTheme);
const muiTheme = resolvedTheme === 'dark' ? metonaDarkTheme : metonaLightTheme;
// v0.3.0: 面板可见性(支持快捷键和专注模式)
const sidebarVisible = useUIStore((s) => s.sidebarVisible);
const detailVisible = useUIStore((s) => s.detailVisible);
// 启动时从数据库恢复状态
useEffect(() => {
if (window.metona?.config?.get) {
window.metona.config.get('onboarding.completed').then((v) => {
if (v === true) useUIStore.getState().setOnboardingCompleted(true);
}).catch((err) => { console.error('[App]', err); });
// M-25 修复: 改用 Promise.allSettled,单个配置读取失败不影响另一个
Promise.allSettled([
window.metona.config.get('llm.provider'),
window.metona.config.get('llm.model'),
]).then(([providerResult, modelResult]) => {
const provider = providerResult.status === 'fulfilled' ? (providerResult.value as string) || '' : '';
const model = modelResult.status === 'fulfilled' ? (modelResult.value as string) || '' : '';
if (provider || model) useAgentStore.getState().setProvider(provider, model);
// P1-6 修复: 配置加载完成,启用发送按钮
useAgentStore.getState().setConfigLoaded(true);
});
} else {
// 无 IPC 可用时也标记为已加载(避免永久禁用)
useAgentStore.getState().setConfigLoaded(true);
}
}, []);
return (
<ThemeProvider theme={muiTheme}>
<CssBaseline />
<div
className="h-screen w-screen flex flex-col overflow-hidden select-none"
style={{ background: muiTheme.palette.background.default, color: muiTheme.palette.text.primary }}
>
{/* H-7 修复: 添加 Header Bar — 规范要求布局为 Header (全宽) + [Sidebar|ChatPanel|DetailPanel] + StatusBar */}
<Header />
<div className="flex-1 flex overflow-hidden min-h-0">
{sidebarVisible && <Sidebar />}
<ChatPanel />
{detailVisible && <DetailPanel />}
</div>
<StatusBar />
<SettingsModal />
<OnboardingWizard />
<CommandPalette />
<ToastContainer />
<ErrorBoundary fallbackTitle="工具确认弹框渲染失败">
<ConfirmationDialog />
</ErrorBoundary>
<ContextMenuDialogHost />
</div>
</ThemeProvider>
);
}