mirror of
https://github.com/Xevion/smart-rgb.git
synced 2025-12-09 16:08:41 -06:00
Update source files
This commit is contained in:
71
frontend/pages/index/+Page.tsx
Normal file
71
frontend/pages/index/+Page.tsx
Normal file
@@ -0,0 +1,71 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user