import { useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { toast } from "sonner"; import { Plus, Settings } from "lucide-react"; import type { Provider } from "@/types"; import { useProvidersQuery } from "@/lib/query"; import { providersApi, settingsApi, type AppType, type ProviderSwitchEvent } from "@/lib/api"; import { useProviderActions } from "@/hooks/useProviderActions"; import { extractErrorMessage } from "@/utils/errorUtils"; import { AppSwitcher } from "@/components/AppSwitcher"; import { ModeToggle } from "@/components/mode-toggle"; import { ProviderList } from "@/components/providers/ProviderList"; import { AddProviderDialog } from "@/components/providers/AddProviderDialog"; import { EditProviderDialog } from "@/components/providers/EditProviderDialog"; import { ConfirmDialog } from "@/components/ConfirmDialog"; import { SettingsDialog } from "@/components/settings/SettingsDialog"; import { UpdateBadge } from "@/components/UpdateBadge"; import UsageScriptModal from "@/components/UsageScriptModal"; import McpPanel from "@/components/mcp/McpPanel"; import { Button } from "@/components/ui/button"; function App() { const { t } = useTranslation(); const [activeApp, setActiveApp] = useState("claude"); const [isSettingsOpen, setIsSettingsOpen] = useState(false); const [isAddOpen, setIsAddOpen] = useState(false); const [isMcpOpen, setIsMcpOpen] = useState(false); const [editingProvider, setEditingProvider] = useState(null); const [usageProvider, setUsageProvider] = useState(null); const [confirmDelete, setConfirmDelete] = useState(null); const { data, isLoading, refetch } = useProvidersQuery(activeApp); const providers = useMemo(() => data?.providers ?? {}, [data]); const currentProviderId = data?.currentProviderId ?? ""; // 🎯 使用 useProviderActions Hook 统一管理所有 Provider 操作 const { addProvider, updateProvider, switchProvider, deleteProvider, saveUsageScript, } = useProviderActions(activeApp); // 监听来自托盘菜单的切换事件 useEffect(() => { let unsubscribe: (() => void) | undefined; const setupListener = async () => { try { unsubscribe = await providersApi.onSwitched( async (event: ProviderSwitchEvent) => { if (event.appType === activeApp) { await refetch(); } }, ); } catch (error) { console.error("[App] Failed to subscribe provider switch event", error); } }; setupListener(); return () => { unsubscribe?.(); }; }, [activeApp, refetch]); // 打开网站链接 const handleOpenWebsite = async (url: string) => { try { await settingsApi.openExternal(url); } catch (error) { const detail = extractErrorMessage(error) || t("notifications.openLinkFailed", { defaultValue: "链接打开失败", }); toast.error(detail); } }; // 编辑供应商 const handleEditProvider = async (provider: Provider) => { await updateProvider(provider); setEditingProvider(null); }; // 确认删除供应商 const handleConfirmDelete = async () => { if (!confirmDelete) return; await deleteProvider(confirmDelete.id); setConfirmDelete(null); }; // 导入配置成功后刷新 const handleImportSuccess = async () => { await refetch(); try { await providersApi.updateTrayMenu(); } catch (error) { console.error("[App] Failed to refresh tray menu", error); } }; return (
CC Switch setIsSettingsOpen(true)} />
setIsAddOpen(true)} />
{ if (!open) { setEditingProvider(null); } }} onSubmit={handleEditProvider} appType={activeApp} /> {usageProvider && ( setUsageProvider(null)} onSave={(script) => { void saveUsageScript(usageProvider, script); }} /> )} void handleConfirmDelete()} onCancel={() => setConfirmDelete(null)} />
); } export default App;