Files
smart-rgb/frontend/pages/+Wrapper.client.tsx
2025-10-11 14:52:54 -05:00

71 lines
2.3 KiB
TypeScript

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<any>(null);
const [analytics, setAnalytics] = useState<any>(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 (
<AnalyticsProvider api={analytics}>
<GameAPIProvider api={gameAPI}>{children}</GameAPIProvider>
</AnalyticsProvider>
);
}