Add wake lock toggle to prevent screen sleep on player display

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-27 11:56:11 -04:00
parent 58cc588726
commit 7b52480329
+46 -8
View File
@@ -7,7 +7,7 @@ import {
UserCheck, UserX, HeartCrack, HeartPulse, Zap, EyeOff, ExternalLink, AlertTriangle, UserCheck, UserX, HeartCrack, HeartPulse, Zap, EyeOff, ExternalLink, AlertTriangle,
Play as PlayIcon, Pause as PauseIcon, SkipForward as SkipForwardIcon, Play as PlayIcon, Pause as PauseIcon, SkipForward as SkipForwardIcon,
StopCircle as StopCircleIcon, Users2, Dices, ChevronUp, ChevronDown, ScrollText, StopCircle as StopCircleIcon, Users2, Dices, ChevronUp, ChevronDown, ScrollText,
Maximize2, Minimize2 Maximize2, Minimize2, Moon, Coffee
} from 'lucide-react'; } from 'lucide-react';
// Custom CSS for death animation (player view only) // Custom CSS for death animation (player view only)
@@ -2311,6 +2311,8 @@ function DisplayView() {
const [campaignBackgroundUrl, setCampaignBackgroundUrl] = useState(''); const [campaignBackgroundUrl, setCampaignBackgroundUrl] = useState('');
const [isPlayerDisplayActive, setIsPlayerDisplayActive] = useState(false); const [isPlayerDisplayActive, setIsPlayerDisplayActive] = useState(false);
const [isFullscreen, setIsFullscreen] = useState(false); const [isFullscreen, setIsFullscreen] = useState(false);
const [wakeLockEnabled, setWakeLockEnabled] = useState(false);
const wakeLockRef = useRef(null);
const currentParticipantRef = useRef(null); const currentParticipantRef = useRef(null);
useEffect(() => { useEffect(() => {
@@ -2327,6 +2329,33 @@ function DisplayView() {
} }
}; };
useEffect(() => {
if (!wakeLockEnabled) {
wakeLockRef.current?.release();
wakeLockRef.current = null;
return;
}
const acquire = async () => {
try {
wakeLockRef.current = await navigator.wakeLock.request('screen');
} catch (e) {
console.error('Wake lock failed:', e);
}
};
acquire();
// Re-acquire after tab becomes visible again (browser auto-releases on hide)
const onVisChange = () => { if (document.visibilityState === 'visible') acquire(); };
document.addEventListener('visibilitychange', onVisChange);
return () => {
document.removeEventListener('visibilitychange', onVisChange);
wakeLockRef.current?.release();
wakeLockRef.current = null;
};
}, [wakeLockEnabled]);
useEffect(() => { useEffect(() => {
if (!db) { if (!db) {
setEncounterError("Firestore not available."); setEncounterError("Firestore not available.");
@@ -2450,13 +2479,22 @@ function DisplayView() {
className={`p-4 md:p-8 rounded-xl shadow-2xl ${!campaignBackgroundUrl ? 'bg-stone-950' : ''}`} className={`p-4 md:p-8 rounded-xl shadow-2xl ${!campaignBackgroundUrl ? 'bg-stone-950' : ''}`}
style={displayStyles} style={displayStyles}
> >
<button <div className="fixed top-3 right-3 z-50 flex gap-2">
onClick={toggleFullscreen} <button
title={isFullscreen ? 'Exit fullscreen' : 'Enter fullscreen'} onClick={() => setWakeLockEnabled(v => !v)}
className="fixed top-3 right-3 z-50 bg-stone-800 bg-opacity-80 hover:bg-opacity-100 text-stone-300 hover:text-white p-2 rounded-lg transition-all" title={wakeLockEnabled ? 'Allow sleep' : 'Prevent sleep'}
> className={`p-2 rounded-lg transition-all ${wakeLockEnabled ? 'bg-amber-600 hover:bg-amber-700 text-white' : 'bg-stone-800 bg-opacity-80 hover:bg-opacity-100 text-stone-300 hover:text-white'}`}
{isFullscreen ? <Minimize2 size={20} /> : <Maximize2 size={20} />} >
</button> {wakeLockEnabled ? <Coffee size={20} /> : <Moon size={20} />}
</button>
<button
onClick={toggleFullscreen}
title={isFullscreen ? 'Exit fullscreen' : 'Enter fullscreen'}
className="bg-stone-800 bg-opacity-80 hover:bg-opacity-100 text-stone-300 hover:text-white p-2 rounded-lg transition-all"
>
{isFullscreen ? <Minimize2 size={20} /> : <Maximize2 size={20} />}
</button>
</div>
<div className={campaignBackgroundUrl ? 'bg-stone-950 bg-opacity-75 p-4 md:p-6 rounded-lg' : ''}> <div className={campaignBackgroundUrl ? 'bg-stone-950 bg-opacity-75 p-4 md:p-6 rounded-lg' : ''}>
<h2 className="text-4xl md:text-5xl font-bold text-center text-amber-400 mb-2 font-cinzel tracking-wide">{name}</h2> <h2 className="text-4xl md:text-5xl font-bold text-center text-amber-400 mb-2 font-cinzel tracking-wide">{name}</h2>