Add fullscreen toggle and wake lock to prevent screen sleep
## Features - Fullscreen button (⛶) in header to toggle fullscreen mode - Wake Lock API integration to keep screen on while using the app - Sun icon (☀) indicator shows wake lock status (bright = active) ## Wake Lock behavior - Automatically requests wake lock when page loads - Re-acquires wake lock when returning to the page - Visual indicator pulses when active - Gracefully hidden if Wake Lock API not supported ## Fullscreen - Works on Android Chrome and desktop browsers - iOS Safari has limited support (no fullscreen API) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -550,3 +550,47 @@ body {
|
|||||||
color: white;
|
color: white;
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fullscreen Button */
|
||||||
|
.header-btn.icon-btn {
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wake Lock Status */
|
||||||
|
.wake-lock-status {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0.25rem 0.5rem;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 1rem;
|
||||||
|
opacity: 0.4;
|
||||||
|
transition: opacity 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wake-lock-status.active {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wake-lock-status .wake-icon {
|
||||||
|
color: #ffc107;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wake-lock-status.active .wake-icon {
|
||||||
|
animation: pulse-glow 2s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse-glow {
|
||||||
|
0%, 100% { opacity: 1; }
|
||||||
|
50% { opacity: 0.6; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fullscreen styles */
|
||||||
|
:fullscreen .header {
|
||||||
|
padding-top: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
:fullscreen .macro-grid {
|
||||||
|
padding-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|||||||
@@ -33,6 +33,10 @@
|
|||||||
<div class="status-dot"></div>
|
<div class="status-dot"></div>
|
||||||
<span>Disconnected</span>
|
<span>Disconnected</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="wake-lock-status" id="wake-lock-status" title="Screen wake lock">
|
||||||
|
<span class="wake-icon">☀</span>
|
||||||
|
</div>
|
||||||
|
<button class="header-btn icon-btn" id="fullscreen-btn" onclick="app.toggleFullscreen()" title="Toggle fullscreen">⛶</button>
|
||||||
<button class="header-btn secondary" onclick="app.refresh()">Refresh</button>
|
<button class="header-btn secondary" onclick="app.refresh()">Refresh</button>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ class MacroPadApp {
|
|||||||
this.tabs = [];
|
this.tabs = [];
|
||||||
this.currentTab = 'All';
|
this.currentTab = 'All';
|
||||||
this.ws = null;
|
this.ws = null;
|
||||||
|
this.wakeLock = null;
|
||||||
|
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
@@ -15,6 +16,7 @@ class MacroPadApp {
|
|||||||
await this.loadMacros();
|
await this.loadMacros();
|
||||||
this.setupWebSocket();
|
this.setupWebSocket();
|
||||||
this.setupEventListeners();
|
this.setupEventListeners();
|
||||||
|
this.setupWakeLock();
|
||||||
this.checkInstallPrompt();
|
this.checkInstallPrompt();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,6 +247,58 @@ class MacroPadApp {
|
|||||||
this.loadTabs();
|
this.loadTabs();
|
||||||
this.loadMacros();
|
this.loadMacros();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fullscreen
|
||||||
|
toggleFullscreen() {
|
||||||
|
if (!document.fullscreenElement) {
|
||||||
|
document.documentElement.requestFullscreen().catch(err => {
|
||||||
|
console.log('Fullscreen error:', err);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
document.exitFullscreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wake Lock - prevents screen from sleeping
|
||||||
|
async setupWakeLock() {
|
||||||
|
if (!('wakeLock' in navigator)) {
|
||||||
|
console.log('Wake Lock API not supported');
|
||||||
|
document.getElementById('wake-lock-status')?.remove();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request wake lock
|
||||||
|
await this.requestWakeLock();
|
||||||
|
|
||||||
|
// Re-acquire wake lock when page becomes visible again
|
||||||
|
document.addEventListener('visibilitychange', async () => {
|
||||||
|
if (document.visibilityState === 'visible') {
|
||||||
|
await this.requestWakeLock();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async requestWakeLock() {
|
||||||
|
try {
|
||||||
|
this.wakeLock = await navigator.wakeLock.request('screen');
|
||||||
|
this.updateWakeLockStatus(true);
|
||||||
|
|
||||||
|
this.wakeLock.addEventListener('release', () => {
|
||||||
|
this.updateWakeLockStatus(false);
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Wake Lock error:', err);
|
||||||
|
this.updateWakeLockStatus(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateWakeLockStatus(active) {
|
||||||
|
const status = document.getElementById('wake-lock-status');
|
||||||
|
if (status) {
|
||||||
|
status.classList.toggle('active', active);
|
||||||
|
status.title = active ? 'Screen will stay on' : 'Screen may sleep';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize app
|
// Initialize app
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// MacroPad PWA Service Worker
|
// MacroPad PWA Service Worker
|
||||||
const CACHE_NAME = 'macropad-v2';
|
const CACHE_NAME = 'macropad-v3';
|
||||||
const ASSETS_TO_CACHE = [
|
const ASSETS_TO_CACHE = [
|
||||||
'/',
|
'/',
|
||||||
'/static/css/styles.css',
|
'/static/css/styles.css',
|
||||||
|
|||||||
Reference in New Issue
Block a user