1. 工具批量审批:解决并行工具审批弹框覆盖问题,新增批量 IPC 通道和列表 UI,支持同工具多次调用分组展示;2. 审批弹框健壮性:超时 toast 防风暴、agent 状态同步清空、ErrorBoundary 防白屏;3. run_command maxFrequency 从 3 调整为 10;4. 开发规范新增 Toast 通知铁律(必须使用 MeToast)
93 lines
4.0 KiB
TypeScript
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>
|
|
);
|
|
}
|