import { useEffect, useState, type ReactNode } from "react"; import { GameAPIProvider } from "@/shared/api/GameAPIContext"; import { AnalyticsProvider } from "@/shared/analytics"; export default function Wrapper({ children }: { children: ReactNode }) { const [gameAPI, setGameAPI] = useState(null); const [analytics, setAnalytics] = useState(null); // Dynamically import the appropriate platform implementation // Use build-time constant for tree-shaking useEffect(() => { if (__DESKTOP__) { Promise.all([import("@/desktop/api/tauriAPI"), import("@/desktop/analytics/tauriAnalytics")]).then( ([{ tauriAPI }, { tauriAnalytics }]) => { setGameAPI(tauriAPI); setAnalytics(tauriAnalytics); }, ); } else { Promise.all([import("@/browser/api/wasmBridge"), import("@/browser/analytics")]).then(([{ wasmBridge }, { wasmAnalytics }]) => { setGameAPI(wasmBridge); setAnalytics(wasmAnalytics); }); } }, []); // Browser-specific setup (must be before early return to satisfy Rules of Hooks) useEffect(() => { if (!__DESKTOP__) { // Disable context menu to prevent interference with right-click controls const handleContextMenu = (e: MouseEvent) => { e.preventDefault(); return false; }; document.addEventListener("contextmenu", handleContextMenu); // Handle user ID storage from worker const userIdChannel = new BroadcastChannel("user_id_storage"); userIdChannel.onmessage = (event) => { try { const msg = JSON.parse(event.data as string); if (msg.action === "save") { localStorage.setItem("app_session_id", msg.id); } else if (msg.action === "load") { const id = localStorage.getItem("app_session_id"); if (id) { userIdChannel.postMessage(JSON.stringify({ action: "load_response", id })); } } } catch {} }; return () => { document.removeEventListener("contextmenu", handleContextMenu); userIdChannel.close(); }; } }, []); // Wait for platform-specific modules to load if (!gameAPI || !analytics) { return null; } return ( {children} ); }