77 lines
2.7 KiB
TypeScript
77 lines
2.7 KiB
TypeScript
import { useMemo, useState } from "react";
|
||
import { Sidebar, type PageKey, PAGE_META } from "./components/Sidebar";
|
||
import { Header } from "./components/Header";
|
||
import { OverviewPage } from "./pages/Overview";
|
||
import { CatalogPage } from "./pages/Catalog";
|
||
import { MyCliPage } from "./pages/MyCli";
|
||
import { ConfigCenterPage } from "./pages/ConfigCenter";
|
||
import { BackupPage } from "./pages/Backup";
|
||
import { SettingsPage } from "./pages/Settings";
|
||
import { CliDetailPage } from "./pages/CliDetail";
|
||
import { useEnv } from "./hooks/useEnv";
|
||
import type { PlatformEnv, RuntimeInfo } from "./ipc/types";
|
||
|
||
/** 平台相关运行时集合(Windows 不看 apt,Linux 不看 winget) */
|
||
const WIN_RUNTIMES = ["node", "npm", "python", "uv", "git", "winget"] as const;
|
||
const LINUX_RUNTIMES = ["node", "npm", "python", "uv", "git", "apt"] as const;
|
||
|
||
function envWarningCount(env: PlatformEnv | null): number {
|
||
if (!env) return 0;
|
||
const keys = env.os === "windows" ? WIN_RUNTIMES : LINUX_RUNTIMES;
|
||
let n = 0;
|
||
for (const k of keys) {
|
||
const info = env.runtimes[k] as RuntimeInfo | null | undefined;
|
||
if (info && info.status !== "installed") n++;
|
||
}
|
||
return n;
|
||
}
|
||
|
||
export default function App() {
|
||
const [page, setPage] = useState<PageKey>("overview");
|
||
const [detailCliId, setDetailCliId] = useState<string | null>(null);
|
||
const { env } = useEnv();
|
||
const warningCount = envWarningCount(env);
|
||
|
||
function navigate(next: PageKey) {
|
||
setDetailCliId(null);
|
||
setPage(next);
|
||
}
|
||
|
||
const content = useMemo(() => {
|
||
if (detailCliId) {
|
||
return <CliDetailPage id={detailCliId} onBack={() => setDetailCliId(null)} />;
|
||
}
|
||
switch (page) {
|
||
case "overview":
|
||
return <OverviewPage onNavigate={navigate} onOpenDetail={setDetailCliId} />;
|
||
case "catalog":
|
||
return <CatalogPage onOpenDetail={setDetailCliId} />;
|
||
case "my-cli":
|
||
return <MyCliPage onNavigate={navigate} onOpenDetail={setDetailCliId} />;
|
||
case "config":
|
||
return <ConfigCenterPage onNavigate={navigate} />;
|
||
case "backup":
|
||
return <BackupPage />;
|
||
case "settings":
|
||
return <SettingsPage />;
|
||
}
|
||
}, [page, detailCliId, env]);
|
||
|
||
const title = detailCliId ? "CLI 详情" : PAGE_META[page].title;
|
||
|
||
return (
|
||
<div className="app-shell">
|
||
<Sidebar current={page} onNavigate={navigate} />
|
||
<div className="app-main">
|
||
<Header title={title} warningCount={warningCount} />
|
||
<main className="app-content">
|
||
{/* key 触发 §4.2 页面切换动效:translateY(8px)+淡入 */}
|
||
<div key={detailCliId ?? page} className="page-enter">
|
||
{content}
|
||
</div>
|
||
</main>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|