import { useEffect, useMemo, useState } from "react"; import { useAppStore } from "./store/useAppStore"; import { TitleBar } from "./components/TitleBar"; import { UpdateButton } from "./components/UpdateButton"; import { ConnectionPanel } from "./features/connection/ConnectionPanel"; import { SubscriptionsPanel } from "./features/subscriptions/SubscriptionsPanel"; import { RoutingPanel } from "./features/routing/RoutingPanel"; import { SettingsPanel } from "./features/settings/SettingsPanel"; import { AndroidApp } from "./mobile/AndroidApp"; import { isAndroid } from "./lib/platform"; import type { Theme } from "./lib/types"; import { displayError, useI18n } from "./lib/i18n"; import "./App.css"; import "./mobile/android.css"; type TabId = "connection" | "subscriptions" | "routing" | "settings"; const NAV: { id: TabId; icon: string }[] = [ { id: "connection", icon: "⚡" }, // Вкладка «Подписки» скрыта (hidden) — панель остаётся в коде, но не в навигации. // { id: "subscriptions", label: "Подписки", icon: "🔗" }, { id: "routing", icon: "🧭" }, { id: "settings", icon: "⚙️" }, ]; function applyTheme(theme: Theme) { const resolved = theme === "system" ? window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : theme; document.documentElement.dataset.theme = resolved; } function App() { const { language, t } = useI18n(); const coreVersion = useAppStore((s) => s.coreVersion); const coreError = useAppStore((s) => s.coreError); const theme = useAppStore((s) => s.settings?.theme ?? "system"); const connection = useAppStore((s) => s.connection); const init = useAppStore((s) => s.init); const [tab, setTab] = useState("connection"); useEffect(() => { init(); }, [init]); useEffect(() => { document.documentElement.lang = language; }, [language]); useEffect(() => { applyTheme(theme); if (theme !== "system") return; const mq = window.matchMedia("(prefers-color-scheme: dark)"); const handler = () => applyTheme("system"); mq.addEventListener("change", handler); return () => mq.removeEventListener("change", handler); }, [theme]); const statusDot = useMemo(() => { switch (connection.state) { case "connected": return "dot ok"; case "connecting": case "disconnecting": return "dot busy"; case "error": return "dot err"; default: return "dot"; } }, [connection.state]); if (isAndroid) { return ; } return (
{tab === "connection" && } {tab === "subscriptions" && } {tab === "routing" && } {tab === "settings" && }
); } export default App;