spaxel/dashboard/ambient.html
jedarden 0141820981 Implement Component 31: Ambient Dashboard Mode
- Fix auto-dim timeout from 60 seconds to 30 minutes (30 * 60 * 1000ms)
- Add auth.js dependency to ambient.html for proper authentication
- Rewrite ambient.test.js to remove problematic require() statements
- Update ambient.js with proper time-of-day handling
- Enhance ambient.css with time-of-day palette themes

Ambient mode provides a simplified, always-on display for wall-mounted
tablets with Canvas 2D rendering, time-of-day awareness, auto-dim after
30min of no presence, alert mode with pulsing red border, and morning
briefing integration.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-06 03:59:12 -04:00

105 lines
4.3 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<title>Spaxel Ambient Display</title>
<link rel="stylesheet" href="css/tokens.css">
<link rel="stylesheet" href="css/layout.css">
<link rel="stylesheet" href="css/ambient.css">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="theme-color" content="#18191b">
</head>
<body class="ambient-mode">
<div class="app-shell app-shell--full">
<!-- Main content (full viewport ambient display) -->
<main class="app-main ambient-container" id="ambient-container">
<!-- Floor Plan Canvas -->
<div class="ambient-floorplan">
<canvas id="ambient-canvas" class="ambient-canvas"></canvas>
</div>
<!-- Status Bar -->
<div class="ambient-status">
<div class="ambient-status-item">
<div class="ambient-status-dot online" id="ambient-status-dot"></div>
<span id="ambient-status-text">Loading...</span>
</div>
<div class="ambient-status-item">
<span id="ambient-time"></span>
</div>
<div class="ambient-status-item">
<span id="ambient-nodes">0 nodes</span>
</div>
</div>
<!-- Alert Overlay -->
<div id="ambient-alert" class="ambient-alert hidden">
<div class="ambient-alert-icon">&#9888;</div>
<div class="ambient-alert-title" id="alert-title">Alert</div>
<div class="ambient-alert-message" id="alert-message"></div>
<div class="ambient-alert-actions">
<button class="ambient-alert-btn primary" id="alert-action-primary">I'm Fine</button>
<button class="ambient-alert-btn secondary" id="alert-action-secondary">Dismiss</button>
</div>
</div>
<!-- Morning Briefing Overlay -->
<div id="ambient-briefing" class="ambient-briefing hidden">
<div class="ambient-briefing-content">
<div class="ambient-briefing-greeting" id="briefing-greeting">Good morning!</div>
<div id="briefing-content"></div>
<button class="ambient-briefing-dismiss" id="briefing-dismiss">Got it</button>
</div>
</div>
<!-- "All Secure" Message -->
<div id="ambient-secure" class="ambient-secure" style="display: none;">
<div class="ambient-secure-icon">&#128274;</div>
<div class="ambient-secure-text">All secure</div>
</div>
</main>
</div><!-- /.app-shell -->
<!-- Ambient Mode -->
<script src="js/auth.js"></script>
<script src="js/ambient_renderer.js"></script>
<script src="js/ambient_briefing.js"></script>
<script src="js/ambient.js"></script>
<script>
// Override init to auto-enable ambient mode (no hash check needed)
(function() {
'use strict';
// Wait for DOM to be ready
document.addEventListener('DOMContentLoaded', function() {
// Check authentication first
if (window.SpaxelAuth) {
SpaxelAuth.checkStatus().then(function(isAuthenticated) {
if (isAuthenticated) {
// Auto-enable ambient mode
if (window.SpaxelAmbientMode) {
window.SpaxelAmbientMode.enable();
}
} else {
// Show PIN entry or redirect
window.location.href = '/';
}
}).catch(function() {
// On auth error, redirect to main dashboard
window.location.href = '/';
});
} else {
// Auth module not loaded, try to enable ambient mode anyway
// WebSocket will fail authentication if not logged in
if (window.SpaxelAmbientMode) {
window.SpaxelAmbientMode.enable();
}
}
});
})();
</script>
</body>
</html>