Files
smart-rgb/frontend/pages/+Wrapper.client.tsx
2025-10-10 20:00:55 -05:00

86 lines
2.7 KiB
TypeScript

import { useEffect, useMemo, useState, type ReactNode } from 'react'
import { GameAPIProvider } from '@/shared/api/GameAPIContext'
import { AnalyticsProvider } from '@/shared/analytics'
export default function Wrapper({ children }: { children: ReactNode }) {
// Determine platform based on build-time define
const isDesktop = typeof __DESKTOP__ !== 'undefined' ? __DESKTOP__ : false
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 {}
}
// Create canvas element for the game renderer
const canvas = document.createElement('canvas')
canvas.id = 'game-canvas'
document.body.appendChild(canvas)
return () => {
document.removeEventListener('contextmenu', handleContextMenu)
userIdChannel.close()
if (canvas.parentElement) {
canvas.remove()
}
}
}
}, [])
// Wait for platform-specific modules to load
if (!gameAPI || !analytics) {
return null
}
return (
<AnalyticsProvider api={analytics}>
<GameAPIProvider api={gameAPI}>{children}</GameAPIProvider>
</AnalyticsProvider>
)
}