diff --git a/src/js/app.js b/src/js/app.js index e603bab..b0d7e91 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -31,6 +31,23 @@ async function initialize() { // 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) => { @@ -74,30 +91,14 @@ async function initialize() { // 6. Initialize Push Notification Settings UI pushSettingsUI.initPushSettingsUI(); - // 7. Setup Flic action handlers - 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); - - // 8. Setup Service Worker (which also initializes Flic) + // 7. Setup Service Worker (which also initializes Flic) serviceWorkerManager.setupServiceWorker(serviceWorkerManager.flicMessageHandler); - // 9. Initial UI Update based on loaded state + // 8. Initial UI Update based on loaded state ui.renderPlayers(); ui.updateGameButton(); - // 10. Reset running state to paused on load + // 9. 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); diff --git a/src/js/services/pushFlicIntegration.js b/src/js/services/pushFlicIntegration.js index 26012ff..459dd66 100644 --- a/src/js/services/pushFlicIntegration.js +++ b/src/js/services/pushFlicIntegration.js @@ -281,7 +281,13 @@ export function handleFlicAction(action, buttonId, timestamp, batteryLevel) { // --- Initialization --- export function initPushFlic(handlers) { - actionHandlers = handlers; // Store the handlers passed from app.js + // Store the handlers passed from app.js + if (handlers && Object.keys(handlers).length > 0) { + actionHandlers = handlers; + console.log('[PushFlic] Registered action handlers:', Object.keys(actionHandlers)); + } else { + console.warn('[PushFlic] No action handlers provided to initPushFlic, actions will not work!'); + } // Auto-subscribe when permission is granted if ('serviceWorker' in navigator) { diff --git a/src/js/services/serviceWorkerManager.js b/src/js/services/serviceWorkerManager.js index 4f98fd4..7b9b549 100644 --- a/src/js/services/serviceWorkerManager.js +++ b/src/js/services/serviceWorkerManager.js @@ -6,13 +6,29 @@ import * as pushFlic from './pushFlicIntegration.js'; let flicActionHandlers = {}; export function setFlicActionHandlers(handlers) { - flicActionHandlers = handlers; + if (handlers && Object.keys(handlers).length > 0) { + flicActionHandlers = handlers; + console.log('[ServiceWorkerManager] Stored action handlers:', Object.keys(flicActionHandlers)); + + // If pushFlic is already initialized, update its handlers directly + if (navigator.serviceWorker.controller) { + pushFlic.initPushFlic(flicActionHandlers); + } + } else { + console.warn('[ServiceWorkerManager] No action handlers provided to setFlicActionHandlers!'); + } } // --- Flic Integration Setup --- export function initFlic() { + // Make sure we have handlers before initializing + if (Object.keys(flicActionHandlers).length === 0) { + console.warn('[ServiceWorkerManager] No Flic handlers registered before initFlic! Actions may not work.'); + } + // This function is used by setupServiceWorker and relies on // flicActionHandlers being set before this is called + console.log('[ServiceWorkerManager] Initializing PushFlic with handlers:', Object.keys(flicActionHandlers)); pushFlic.initPushFlic(flicActionHandlers); } @@ -34,8 +50,13 @@ export function flicMessageHandler(event) { // Check if this is a Flic action message if (event.data && event.data.type === 'flic-action') { const { action, button, timestamp, batteryLevel } = event.data; - // Pass to push-flic service to handle - pushFlic.handleFlicAction(action, button, timestamp, batteryLevel); + + try { + // Pass to push-flic service to handle + pushFlic.handleFlicAction(action, button, timestamp, batteryLevel); + } catch (error) { + console.error('[App] Error handling flic action:', error); + } } } @@ -43,46 +64,60 @@ export function flicMessageHandler(event) { function handleServiceWorkerMessage(event) { // Check if the message might be from our service worker if (event.data && typeof event.data === 'object') { - console.log('[App] Potential SW message received:', event.data); - // Process the message with our flicMessageHandler - flicMessageHandler(event); + console.log('[App] Potential window message received:', event.data); + + // If it looks like a flic action message, handle it + if (event.data.type === 'flic-action') { + try { + // Process the message with our flicMessageHandler + flicMessageHandler(event); + } catch (error) { + console.error('[App] Error handling window message:', error); + } + } } } // --- Service Worker and PWA Setup --- export function setupServiceWorker(messageHandler) { if ('serviceWorker' in navigator) { + console.log('[ServiceWorkerManager] Setting up service worker...'); + // Set up global message event listener on window object window.addEventListener('message', handleServiceWorkerMessage); // Listen for messages FROM the Service Worker // This is the main way messages from the service worker are received - navigator.serviceWorker.addEventListener('message', messageHandler); + navigator.serviceWorker.addEventListener('message', event => { + console.log('[ServiceWorkerManager] Service worker message received:', event.data); + messageHandler(event); + }); window.addEventListener('load', () => { + console.log('[ServiceWorkerManager] Window loaded, registering service worker...'); navigator.serviceWorker.register('/sw.js') .then(registration => { - console.log('ServiceWorker registered successfully.'); + console.log('[ServiceWorkerManager] ServiceWorker registered successfully.'); // Add an event listener that will work with service worker controlled clients if (navigator.serviceWorker.controller) { - console.log('Service worker already controlling the page, setting up message listener'); + console.log('[ServiceWorkerManager] Service worker already controlling the page.'); } // Initialize Flic integration initFlic(); }) .catch(error => { - console.error('ServiceWorker registration failed:', error); + console.error('[ServiceWorkerManager] ServiceWorker registration failed:', error); }); }); // Listen for SW controller changes navigator.serviceWorker.addEventListener('controllerchange', () => { - console.log('Service Worker controller changed, potentially updated.'); + console.log('[ServiceWorkerManager] Service Worker controller changed, potentially updated.'); }); } else { - console.warn('ServiceWorker not supported.'); + console.warn('[ServiceWorkerManager] ServiceWorker not supported.'); } } \ No newline at end of file diff --git a/sw.js b/sw.js index 76740a4..c722146 100644 --- a/sw.js +++ b/sw.js @@ -91,7 +91,8 @@ self.addEventListener('push', event => { data: { action: 'Unknown', button: 'Unknown', - batteryLevel: undefined + batteryLevel: undefined, + timestamp: new Date().toISOString() } }; @@ -108,6 +109,12 @@ self.addEventListener('push', event => { data: parsedData.data || pushData.data // Expecting { action: 'SingleClick', button: 'game-button', batteryLevel: 75 } }; + // Ensure all required fields are present in data + pushData.data = pushData.data || {}; + if (!pushData.data.timestamp) { + pushData.data.timestamp = new Date().toISOString(); + } + } catch (e) { console.error('[ServiceWorker] Error parsing push data:', e); // Use default notification if parsing fails @@ -120,12 +127,14 @@ self.addEventListener('push', event => { // --- Send message to client(s) --- const messagePayload = { type: 'flic-action', // Custom message type - action: pushData.data.action, // e.g., 'SingleClick', 'DoubleClick', 'Hold' - button: pushData.data.button, // e.g., the button name - timestamp: pushData.data.timestamp, // e.g., the timestamp of the action + action: pushData.data.action || 'Unknown', // e.g., 'SingleClick', 'DoubleClick', 'Hold' + button: pushData.data.button || 'Unknown', // e.g., the button name + timestamp: pushData.data.timestamp || new Date().toISOString(), // e.g., the timestamp of the action batteryLevel: pushData.data.batteryLevel // e.g., the battery level percentage }; + console.log('[ServiceWorker] Preparing message payload:', messagePayload); + // Send message to all open PWA windows controlled by this SW event.waitUntil( self.clients.matchAll({