mirror of
https://github.com/Xevion/smart-rgb.git
synced 2025-12-06 15:16:36 -06:00
72 lines
2.1 KiB
TypeScript
72 lines
2.1 KiB
TypeScript
import { useState, useEffect, lazy, Suspense } from "react";
|
|
import "./+Page.css";
|
|
import { MenuScreen } from "@/shared/components/MenuScreen";
|
|
import { useAnalytics } from "@/shared/analytics";
|
|
|
|
// Lazy load components that aren't needed immediately
|
|
const GameContainer = lazy(() => import("./GameContainer.client").then(m => ({ default: m.GameContainer })));
|
|
const AlphaWarningModal = lazy(() => import("@/shared/components/AlphaWarningModal"));
|
|
|
|
function App() {
|
|
const [showMenu, setShowMenu] = useState(true);
|
|
const [isHydrated, setIsHydrated] = useState(false);
|
|
const analytics = useAnalytics();
|
|
|
|
// Mark as hydrated after first render to prevent hydration mismatch
|
|
useEffect(() => {
|
|
setIsHydrated(true);
|
|
}, []);
|
|
|
|
// Prefetch components after initial render
|
|
useEffect(() => {
|
|
const timer = setTimeout(() => {
|
|
// Trigger chunk downloads without rendering
|
|
import("./GameContainer.client");
|
|
import("@/shared/components/AlphaWarningModal");
|
|
}, 2000);
|
|
return () => clearTimeout(timer);
|
|
}, []);
|
|
|
|
// Track app started on mount
|
|
useEffect(() => {
|
|
if (!analytics) return;
|
|
analytics.track("app_started", {
|
|
platform: __DESKTOP__ ? "desktop" : "browser",
|
|
});
|
|
}, [analytics]);
|
|
|
|
const handleStartSingleplayer = () => {
|
|
setShowMenu(false);
|
|
};
|
|
|
|
const handleExit = async () => {
|
|
if (__DESKTOP__) {
|
|
const { invoke } = await import("@tauri-apps/api/core");
|
|
await invoke("request_exit").catch((err) => {
|
|
console.error("Failed to request exit:", err);
|
|
});
|
|
}
|
|
};
|
|
|
|
// Don't render game components until hydration is complete
|
|
if (!isHydrated) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<>
|
|
{/* Menu Screen - pre-renderable, covers everything when visible */}
|
|
{showMenu && <MenuScreen onStartSingleplayer={handleStartSingleplayer} onExit={handleExit} />}
|
|
|
|
{/* Game Container - client-only, lazy loaded when game starts */}
|
|
{!showMenu && (
|
|
<Suspense fallback={null}>
|
|
<GameContainer onReturnToMenu={() => setShowMenu(true)} />
|
|
</Suspense>
|
|
)}
|
|
</>
|
|
);
|
|
}
|
|
|
|
export default App;
|