// app.js - Main Application Orchestrator import * as config from './config.js'; import * as state from './core/state.js'; import * as ui from './ui/ui.js'; import * as timer from './core/timer.js'; import camera from './ui/camera.js'; // Default export import { initEnv } from './env-loader.js'; import * as pushSettingsUI from './ui/pushSettingsUI.js'; // Import the new push settings UI module // Import externalized modules import * as gameActions from './core/gameActions.js'; import * as playerManager from './core/playerManager.js'; import * as eventHandlers from './core/eventHandlers.js'; import * as serviceWorkerManager from './services/serviceWorkerManager.js'; import * as screenLockManager from './services/screenLockManager.js'; // Import the screen lock manager // --- Initialization --- async function initialize() { console.log("Initializing Game Timer App..."); // 0. Wait for environment variables to load try { await initEnv(); console.log("Environment variables loaded"); } catch (error) { console.warn("Failed to load environment variables, using defaults:", error); } // 1. Load saved state or defaults state.loadData(); // Setup Flic action handlers early in the initialization process // to ensure they're available when the service worker initializes const flicActionHandlers = { [config.FLIC_ACTIONS.SINGLE_CLICK]: playerManager.nextPlayer, [config.FLIC_ACTIONS.DOUBLE_CLICK]: playerManager.previousPlayer, [config.FLIC_ACTIONS.HOLD]: gameActions.togglePauseResume, }; // Log the registered handlers for debugging console.log("Registering Flic action handlers:", { "SingleClick": config.FLIC_ACTIONS.SINGLE_CLICK, "DoubleClick": config.FLIC_ACTIONS.DOUBLE_CLICK, "Hold": config.FLIC_ACTIONS.HOLD }); serviceWorkerManager.setFlicActionHandlers(flicActionHandlers); // 2. Initialize UI (pass carousel swipe handler) ui.initUI({ onCarouselSwipe: (direction) => { if (direction > 0) playerManager.nextPlayer(); else playerManager.previousPlayer(); } }); // 3. Initialize Timer (pass callbacks for UI updates/state changes) timer.initTimer({ onTimerTick: eventHandlers.handleTimerTick, onPlayerSwitch: eventHandlers.handlePlayerSwitchOnTimer, onGameOver: gameActions.handleGameOver }); // 4. Initialize Camera (pass elements and capture callback) camera.init( { // Pass relevant DOM elements cameraContainer: ui.elements.cameraContainer, cameraView: ui.elements.cameraView, cameraCanvas: ui.elements.cameraCanvas, cameraCaptureButton: ui.elements.cameraCaptureButton, cameraCancelButton: ui.elements.cameraCancelButton }, { // Pass options/callbacks onCapture: eventHandlers.handleCameraCapture } ); // 5. Set up UI Event Listeners that trigger actions ui.elements.gameButton.addEventListener('click', eventHandlers.handleGameButtonClick); ui.elements.setupButton.addEventListener('click', eventHandlers.handleSetupButtonClick); ui.elements.addPlayerButton.addEventListener('click', eventHandlers.handleAddPlayerButtonClick); ui.elements.resetButton.addEventListener('click', eventHandlers.handleResetButtonClick); ui.elements.playerForm.addEventListener('submit', playerManager.handlePlayerFormSubmit); ui.elements.cancelButton.addEventListener('click', eventHandlers.handlePlayerModalCancel); ui.elements.deletePlayerButton.addEventListener('click', playerManager.handleDeletePlayer); ui.elements.resetConfirmButton.addEventListener('click', eventHandlers.handleResetConfirm); ui.elements.resetCancelButton.addEventListener('click', eventHandlers.handleResetCancel); ui.elements.cameraButton.addEventListener('click', eventHandlers.handleCameraButtonClick); // 6. Initialize Push Notification Settings UI pushSettingsUI.initPushSettingsUI(); // 7. Setup Service Worker (which also initializes Flic) serviceWorkerManager.setupServiceWorker(serviceWorkerManager.flicMessageHandler); // 8. Initialize Screen Lock Manager (automatically acquires wake lock) const screenLockSupported = await screenLockManager.initScreenLockManager(); console.log(`Screen Wake Lock API ${screenLockSupported ? 'is' : 'is not'} supported`); // 9. Initial UI Update based on loaded state ui.renderPlayers(); ui.updateGameButton(); // 10. Reset running state to paused on load if (state.getGameState() === config.GAME_STATES.RUNNING) { console.log("Game was running on load, setting to paused."); state.setGameState(config.GAME_STATES.PAUSED); ui.updateGameButton(); ui.renderPlayers(); } console.log("App Initialized."); } // --- Start the application --- // We need to use an async IIFE to await the async initialize function (async () => { try { await initialize(); } catch (error) { console.error("Error initializing application:", error); } })();