From 7d609a255421898fddf92af2dc4b44d25af7bae7 Mon Sep 17 00:00:00 2001 From: cpu Date: Sun, 30 Mar 2025 23:46:13 +0200 Subject: [PATCH] Screen Wake Lock --- index.html | 7 +- js/app.js | 11 ++- js/core/gameActions.js | 45 ++++++++++- js/services/screenLockManager.js | 128 +++++++++++++++++++++++++++++++ test.html | 5 +- 5 files changed, 186 insertions(+), 10 deletions(-) create mode 100644 js/services/screenLockManager.js diff --git a/index.html b/index.html index f20efe9..f494ae9 100644 --- a/index.html +++ b/index.html @@ -214,9 +214,10 @@ let backendUrl; try { const configModule = await import('/js/config.js'); - backendUrl = configModule.BACKEND_URL || 'https://webpush.virtonline.eu'; + backendUrl = configModule.BACKEND_URL; } catch (error) { - backendUrl = 'https://webpush.virtonline.eu'; + output.textContent = 'Failed to load backend URL. Please check configuration.\n'; + return; } const webhookUrl = `${backendUrl}/webhook/${action}`; @@ -279,4 +280,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/js/app.js b/js/app.js index b0d7e91..f78e4fd 100644 --- a/js/app.js +++ b/js/app.js @@ -4,8 +4,6 @@ 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 audioManager from './ui/audio.js'; -import * as pushFlic from './services/pushFlicIntegration.js'; import { initEnv } from './env-loader.js'; import * as pushSettingsUI from './ui/pushSettingsUI.js'; // Import the new push settings UI module @@ -14,6 +12,7 @@ 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 --- @@ -93,12 +92,16 @@ async function initialize() { // 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`); - // 8. Initial UI Update based on loaded state + // 9. Initial UI Update based on loaded state ui.renderPlayers(); ui.updateGameButton(); - // 9. Reset running state to paused on load + // 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); diff --git a/js/core/gameActions.js b/js/core/gameActions.js index 2f71581..6bc3276 100644 --- a/js/core/gameActions.js +++ b/js/core/gameActions.js @@ -4,6 +4,7 @@ import * as state from './state.js'; import * as ui from '../ui/ui.js'; import * as timer from './timer.js'; import audioManager from '../ui/audio.js'; +import * as screenLockManager from '../services/screenLockManager.js'; // Import screen lock manager // --- Core Game Actions --- @@ -12,6 +13,14 @@ export function handleGameOver() { state.setGameState(config.GAME_STATES.OVER); audioManager.play('gameOver'); timer.stopTimer(); // Ensure timer is stopped + + // Release screen wake lock when game is over + screenLockManager.releaseWakeLock().then(success => { + if (success) { + console.log('Screen wake lock released on game over'); + } + }); + ui.updateGameButton(); ui.renderPlayers(); // Update to show final state } @@ -25,6 +34,16 @@ export function startGame() { state.setGameState(config.GAME_STATES.RUNNING); audioManager.play('gameStart'); timer.startTimer(); + + // Acquire screen wake lock when game starts + screenLockManager.acquireWakeLock().then(success => { + if (success) { + console.log('Screen wake lock acquired for game'); + } else { + console.warn('Failed to acquire screen wake lock'); + } + }); + ui.updateGameButton(); ui.renderPlayers(); // Ensure active timer styling is applied } @@ -35,6 +54,14 @@ export function pauseGame() { state.setGameState(config.GAME_STATES.PAUSED); audioManager.play('gamePause'); timer.stopTimer(); + + // Release screen wake lock when game is paused + screenLockManager.releaseWakeLock().then(success => { + if (success) { + console.log('Screen wake lock released on pause'); + } + }); + ui.updateGameButton(); ui.renderPlayers(); // Ensure active timer styling is removed } @@ -76,6 +103,14 @@ export function resetGame() { state.resetPlayersTime(); state.setGameState(config.GAME_STATES.SETUP); state.setCurrentPlayerIndex(0); // Go back to first player + + // Release screen wake lock when game is reset + screenLockManager.releaseWakeLock().then(success => { + if (success) { + console.log('Screen wake lock released on reset'); + } + }); + audioManager.play('buttonClick'); // Or a specific reset sound? ui.updateGameButton(); ui.renderPlayers(); @@ -84,8 +119,16 @@ export function resetGame() { export function fullResetApp() { timer.stopTimer(); state.resetToDefaults(); + + // Release screen wake lock on full reset + screenLockManager.releaseWakeLock().then(success => { + if (success) { + console.log('Screen wake lock released on full reset'); + } + }); + audioManager.play('gameOver'); // Use game over sound for full reset ui.hideResetModal(); ui.updateGameButton(); ui.renderPlayers(); -} \ No newline at end of file +} \ No newline at end of file diff --git a/js/services/screenLockManager.js b/js/services/screenLockManager.js new file mode 100644 index 0000000..c96ae4b --- /dev/null +++ b/js/services/screenLockManager.js @@ -0,0 +1,128 @@ +// screenLockManager.js - Manages screen wake lock to prevent screen from turning off +// Uses the Screen Wake Lock API: https://developer.mozilla.org/en-US/docs/Web/API/Screen_Wake_Lock_API + +let wakeLock = null; +let isLockEnabled = false; + +/** + * Requests a screen wake lock to prevent the screen from turning off + * @returns {Promise} - True if wake lock was acquired successfully + */ +export async function acquireWakeLock() { + if (!isScreenWakeLockSupported()) { + console.warn('[ScreenLockManager] Screen Wake Lock API not supported in this browser'); + return false; + } + + try { + // Release any existing wake lock first + await releaseWakeLock(); + + // Request a new wake lock + wakeLock = await navigator.wakeLock.request('screen'); + isLockEnabled = true; + + console.log('[ScreenLockManager] Screen Wake Lock acquired'); + + // Add event listeners to reacquire the lock when needed + setupWakeLockListeners(); + + return true; + } catch (error) { + console.error('[ScreenLockManager] Error acquiring wake lock:', error); + isLockEnabled = false; + return false; + } +} + +/** + * Releases the screen wake lock if one is active + * @returns {Promise} - True if wake lock was released successfully + */ +export async function releaseWakeLock() { + if (!wakeLock) { + return true; // No wake lock to release + } + + try { + await wakeLock.release(); + wakeLock = null; + isLockEnabled = false; + console.log('[ScreenLockManager] Screen Wake Lock released'); + return true; + } catch (error) { + console.error('[ScreenLockManager] Error releasing wake lock:', error); + return false; + } +} + +/** + * Checks if the Screen Wake Lock API is supported in this browser + * @returns {boolean} - True if supported + */ +export function isScreenWakeLockSupported() { + return 'wakeLock' in navigator && 'request' in navigator.wakeLock; +} + +/** + * Returns the current status of the wake lock + * @returns {boolean} - True if wake lock is currently active + */ +export function isWakeLockActive() { + return isLockEnabled && wakeLock !== null; +} + +/** + * Sets up event listeners to reacquire the wake lock when needed + * (e.g., when the page becomes visible again after being hidden) + */ +function setupWakeLockListeners() { + // When the page becomes visible again, reacquire the wake lock + document.addEventListener('visibilitychange', handleVisibilityChange); + + // When the screen orientation changes, reacquire the wake lock + if ('screen' in window && 'orientation' in window.screen) { + window.screen.orientation.addEventListener('change', handleOrientationChange); + } +} + +/** + * Handles visibility change events to reacquire wake lock when page becomes visible + */ +async function handleVisibilityChange() { + if (isLockEnabled && document.visibilityState === 'visible') { + // Only try to reacquire if we previously had a lock + await acquireWakeLock(); + } +} + +/** + * Handles orientation change events to reacquire wake lock + */ +async function handleOrientationChange() { + if (isLockEnabled) { + // Some devices may release the wake lock on orientation change + await acquireWakeLock(); + } +} + +/** + * Initializes the screen lock manager + * @param {Object} options - Configuration options + * @param {boolean} options.autoAcquire - Whether to automatically acquire wake lock on init + * @returns {Promise} - True if initialization was successful + */ +export async function initScreenLockManager(options = {}) { + const { autoAcquire = true } = options; // Default to true - automatically acquire on init + + // Check for support + const isSupported = isScreenWakeLockSupported(); + console.log(`[ScreenLockManager] Screen Wake Lock API ${isSupported ? 'is' : 'is not'} supported`); + + // Automatically acquire wake lock if supported (now default behavior) + if (autoAcquire && isSupported) { + return await acquireWakeLock(); + } + + return isSupported; +} diff --git a/test.html b/test.html index cf8bfc6..2c32e21 100644 --- a/test.html +++ b/test.html @@ -239,9 +239,10 @@ let backendUrl; try { const configModule = await import('./src/js/config.js'); - backendUrl = configModule.BACKEND_URL || 'https://webpush.virtonline.eu'; + backendUrl = configModule.BACKEND_URL; } catch (error) { - backendUrl = 'https://webpush.virtonline.eu'; + output.textContent += '\nFailed to load backend URL.'; + return; } const webhookUrl = `${backendUrl}/webhook/${action}`;