disable screen lock

This commit is contained in:
cpu
2025-05-09 15:04:47 +02:00
parent 216f0043e5
commit dfc0cc331a
5 changed files with 113 additions and 14 deletions

View File

@@ -17,6 +17,7 @@ Game enthusiasts who play turn-based games (board games, tabletop RPGs, card gam
* **JavaScript:** For application logic, timer functionality, and event handling. * **JavaScript:** For application logic, timer functionality, and event handling.
* **Web Audio API:** For audio feedback (ticking sounds, alerts). * **Web Audio API:** For audio feedback (ticking sounds, alerts).
* **Browser API:** For capturing Players' photo. * **Browser API:** For capturing Players' photo.
* **Screen Wake Lock API:** For preventing of the screen lock in a PWA.
* **Local Storage/IndexedDB:** For persistent storage of player data, timer states, and settings. * **Local Storage/IndexedDB:** For persistent storage of player data, timer states, and settings.
* **Service Worker:** Essential for PWA functionality (offline access, push notifications - potential future feature). * **Service Worker:** Essential for PWA functionality (offline access, push notifications - potential future feature).
* **Manifest File:** Defines the PWA's metadata (name, icons, theme color). * **Manifest File:** Defines the PWA's metadata (name, icons, theme color).
@@ -125,7 +126,7 @@ For an enhanced tactile experience, Nexus Timer supports Smart Buttons based on
} }
``` ```
## Building for the production ## Building for the production
Navigate to your project directory on the server Navigate to the projects' directory on the server
```bash ```bash
cd /virt cd /virt
``` ```
@@ -154,7 +155,7 @@ Use the editor to create or overwrite the service:
```bash ```bash
sudo systemctl edit --force --full virt-nexus-timer.service sudo systemctl edit --force --full virt-nexus-timer.service
``` ```
Paste the contents from virt-nexus-timer.service, then save and exit. Paste the content from `systemd/virt-nexus-timer.service`, then save and exit.
Enable on system boot and start the service Enable on system boot and start the service
```bash ```bash

View File

@@ -41,14 +41,13 @@
"Pass Turn / My Pause" Hotkey: "Pass Turn / My Pause" Hotkey:
</label> </label>
<div class="flex items-center"> <div class="flex items-center">
<!-- Display field - not an input anymore, triggers overlay -->
<button <button
type="button" type="button"
id="playerHotkeyDisplay" id="playerHotkeyDisplay"
@click="startCapturePlayerHotkey" @click="startCapturePlayerHotkey"
class="input-base w-12 h-8 text-center font-mono text-lg p-0 cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-700" class="input-base w-12 h-8 font-mono text-lg p-0 cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-700 flex items-center justify-center"
> >
{{ editablePlayer.hotkey ? editablePlayer.hotkey.toUpperCase() : '-' }} <span>{{ editablePlayer.hotkey ? editablePlayer.hotkey.toUpperCase() : '-' }}</span>
</button> </button>
<button <button
type="button" type="button"

View File

@@ -0,0 +1,66 @@
// src/services/WakeLockService.js
let wakeLock = null;
let wakeLockActive = false;
const requestWakeLock = async () => {
if ('wakeLock' in navigator && !wakeLockActive) {
try {
wakeLock = await navigator.wakeLock.request('screen');
wakeLockActive = true;
console.log('Screen Wake Lock activated.');
wakeLock.addEventListener('release', () => {
console.log('Screen Wake Lock was released.');
wakeLockActive = false;
wakeLock = null; // Clear the reference
// Optionally, re-request if it was released unexpectedly and should be active
// For now, we'll let it be re-requested manually by the app logic
});
} catch (err) {
console.error(`Failed to acquire Screen Wake Lock: ${err.name}, ${err.message}`);
wakeLock = null;
wakeLockActive = false;
}
} else {
console.warn('Screen Wake Lock API not supported or already active.');
}
};
const releaseWakeLock = async () => {
if (wakeLock && wakeLockActive) {
try {
await wakeLock.release();
// The 'release' event listener on wakeLock itself will set wakeLockActive = false and wakeLock = null
} catch (err) {
console.error(`Failed to release Screen Wake Lock: ${err.name}, ${err.message}`);
// Even if release fails, mark as inactive to allow re-request
wakeLock = null;
wakeLockActive = false;
}
} else {
// console.log('No active Screen Wake Lock to release or already released.');
}
};
// Handle visibility changes to re-acquire lock if necessary
const handleVisibilityChange = () => {
if (wakeLock !== null && document.visibilityState === 'visible') {
// If we had a wake lock and the page became visible again,
// it might have been released by the browser. Try to re-acquire.
// This behavior is usually handled automatically by the browser with the 'release' event
// but can be a fallback. For now, we rely on manual re-request.
// console.log('Page visible, checking wake lock status.');
} else if (document.visibilityState === 'hidden' && wakeLockActive) {
// The browser usually releases the wake lock when tab is hidden.
// Our 'release' event listener should handle this.
}
};
document.addEventListener('visibilitychange', handleVisibilityChange);
// document.addEventListener('fullscreenchange', handleVisibilityChange); // Also useful for fullscreen
export const WakeLockService = {
request: requestWakeLock,
release: releaseWakeLock,
isActive: () => wakeLockActive,
};

View File

@@ -83,6 +83,7 @@ import { useRouter } from 'vue-router';
import PlayerDisplay from '../components/PlayerDisplay.vue'; import PlayerDisplay from '../components/PlayerDisplay.vue';
import PlayerListItem from '../components/PlayerListItem.vue'; import PlayerListItem from '../components/PlayerListItem.vue';
import { AudioService } from '../services/AudioService'; import { AudioService } from '../services/AudioService';
import { WakeLockService } from '../services/WakeLockService';
const store = useStore(); const store = useStore();
const router = useRouter(); const router = useRouter();
@@ -93,7 +94,7 @@ const currentPlayer = computed(() => store.getters.currentPlayer);
const nextPlayer = computed(() => store.getters.nextPlayer); const nextPlayer = computed(() => store.getters.nextPlayer);
const gameMode = computed(() => store.getters.gameMode); const gameMode = computed(() => store.getters.gameMode);
const isMuted = computed(() => store.getters.isMuted); const isMuted = computed(() => store.getters.isMuted);
// const gameRunning = computed(() => store.getters.gameRunning); const gameRunning = computed(() => store.getters.gameRunning);
let timerInterval = null; let timerInterval = null;
@@ -130,12 +131,42 @@ onMounted(() => {
timerInterval = setInterval(() => { timerInterval = setInterval(() => {
store.dispatch('tick'); store.dispatch('tick');
}, 1000); }, 1000);
// Attempt to acquire wake lock if game is already running (e.g., page refresh)
if (gameRunning.value) {
WakeLockService.request();
}
}); });
onUnmounted(() => { onUnmounted(async () => {
clearInterval(timerInterval); clearInterval(timerInterval);
AudioService.stopContinuousTick(); AudioService.stopContinuousTick();
AudioService.cancelPassTurnSound(); AudioService.cancelPassTurnSound();
await WakeLockService.release(); // Release wake lock when leaving the game view
});
// Watch gameRunning state to acquire/release wake lock
watch(gameRunning, async (isRunning) => {
if (isRunning) {
await WakeLockService.request();
} else {
// Don't release immediately on pause, only if all timers stop and stay stopped.
// For simplicity, we'll rely on onUnmounted for now or if explicitly navigating away.
// If you want to release on extended pause, you'd need more logic here.
// Perhaps only release if gameMode is normal and current player is paused,
// or if allTimers mode and ALL are paused.
// For now, aggressive release on any gameRunning=false might be too much.
// Let's only release it when navigating away or explicitly stopped.
// The browser will also release it if the tab is hidden.
// Let's make it simpler: release if game isn't running
if (!WakeLockService.isActive()) return; // Avoid releasing if not active
// A short delay before releasing to avoid flickering if quickly pausing/resuming
setTimeout(async () => {
if (!store.getters.gameRunning && WakeLockService.isActive()) { // Check again before releasing
await WakeLockService.release();
}
}, 3000); // e.g., release after 3 seconds of no activity
}
}); });
watch(gameMode, (newMode) => { watch(gameMode, (newMode) => {
@@ -180,7 +211,8 @@ watch(() => currentPlayer.value?.isTimerRunning, (isRunning, wasRunning) => {
}); });
const navigateToSetup = () => { const navigateToSetup = async () => {
await WakeLockService.release(); // Release before navigating
const isAnyTimerActive = store.getters.gameRunning; const isAnyTimerActive = store.getters.gameRunning;
if (isAnyTimerActive) { if (isAnyTimerActive) {
if (window.confirm('Game is active. Going to Setup will pause all timers. Continue?')) { if (window.confirm('Game is active. Going to Setup will pause all timers. Continue?')) {
@@ -192,9 +224,10 @@ const navigateToSetup = () => {
} }
}; };
const navigateToInfo = () => { const navigateToInfo = async () => {
await WakeLockService.release(); // Release before navigating
if (store.getters.gameRunning) { if (store.getters.gameRunning) {
store.commit('PAUSE_ALL_TIMERS'); store.commit('PAUSE_ALL_TIMERS'); // Good practice to pause if navigating away
} }
router.push({ name: 'Info' }); router.push({ name: 'Info' });
}; };

View File

@@ -72,9 +72,9 @@
type="button" type="button"
id="globalHotkeyStopPauseDisplay" id="globalHotkeyStopPauseDisplay"
@click="startCaptureGlobalHotkey('stopPause')" @click="startCaptureGlobalHotkey('stopPause')"
class="input-base w-12 h-8 text-center font-mono text-lg p-0 cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-700" class="input-base w-12 h-8 font-mono text-lg p-0 cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-700 flex items-center justify-center"
> >
{{ globalHotkeyStopPauseDisplay || '-' }} <span>{{ globalHotkeyStopPauseDisplay || '-' }}</span>
</button> </button>
<button type="button" @click="clearGlobalHotkey('stopPause')" class="text-xs text-blue-500 hover:underline ml-2 px-2 py-1 rounded hover:bg-gray-100 dark:hover:bg-gray-600"> <button type="button" @click="clearGlobalHotkey('stopPause')" class="text-xs text-blue-500 hover:underline ml-2 px-2 py-1 rounded hover:bg-gray-100 dark:hover:bg-gray-600">
Clear Clear
@@ -91,9 +91,9 @@
type="button" type="button"
id="globalHotkeyRunAllDisplay" id="globalHotkeyRunAllDisplay"
@click="startCaptureGlobalHotkey('runAll')" @click="startCaptureGlobalHotkey('runAll')"
class="input-base w-12 h-8 text-center font-mono text-lg p-0 cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-700" class="input-base w-12 h-8 font-mono text-lg p-0 cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-700 flex items-center justify-center"
> >
{{ globalHotkeyRunAllDisplay || '-' }} <span>{{ globalHotkeyRunAllDisplay || '-' }}</span>
</button> </button>
<button type="button" @click="clearGlobalHotkey('runAll')" class="text-xs text-blue-500 hover:underline ml-2 px-2 py-1 rounded hover:bg-gray-100 dark:hover:bg-gray-600"> <button type="button" @click="clearGlobalHotkey('runAll')" class="text-xs text-blue-500 hover:underline ml-2 px-2 py-1 rounded hover:bg-gray-100 dark:hover:bg-gray-600">
Clear Clear