331de4bc9e
- New settings page at /settings (localhost-only) accessible via tray icon - PIN manager with 6-digit codes, 5-min TTL, single-use - API token uses secrets.token_urlsafe(32) for 256-bit entropy - Config auto-creates config.yaml on first run with detected local IP - Default PIN and token generated randomly on first startup - Added pin_ttl setting (default 300s) - Updated build_exe.py for onefile exe with settings assets bundled - Added start.bat and start.sh for easy development startup
154 lines
5.4 KiB
HTML
154 lines
5.4 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta
|
|
name="viewport"
|
|
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
|
|
/>
|
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
<meta name="mobile-web-app-capable" content="yes" />
|
|
<title data-i18n="app_name">PaperDash</title>
|
|
<link rel="stylesheet" href="style.css" />
|
|
</head>
|
|
<body>
|
|
<div id="app">
|
|
<!-- PIN Login Screen -->
|
|
<div id="login-screen" class="screen active">
|
|
<h1 data-i18n="login_title">PaperDash</h1>
|
|
<p data-i18n="login_subtitle">Enter PIN to connect</p>
|
|
<input
|
|
type="password"
|
|
id="pin-input"
|
|
maxlength="4"
|
|
data-i18n-placeholder="login_placeholder"
|
|
placeholder="****"
|
|
autocomplete="off"
|
|
/>
|
|
<button id="connect-btn" data-i18n="login_button">Connect</button>
|
|
<p id="login-error" class="error"></p>
|
|
</div>
|
|
|
|
<!-- Main Dashboard -->
|
|
<div id="dashboard-screen" class="screen">
|
|
<!-- Settings Button -->
|
|
<button id="btn-settings" class="settings-btn">⚙</button>
|
|
|
|
<!-- Media Section -->
|
|
<section id="media-section" class="panel">
|
|
<h2 data-i18n="now_playing">Now Playing</h2>
|
|
<div id="artwork-container"></div>
|
|
<div id="track-info">
|
|
<div id="track-title" class="track-title" data-i18n="no_playback">
|
|
No playback
|
|
</div>
|
|
<div id="track-artist" class="track-artist"></div>
|
|
<div id="track-album" class="track-album"></div>
|
|
</div>
|
|
<div id="progress-container">
|
|
<div id="progress-bar">
|
|
<div id="progress-fill"></div>
|
|
</div>
|
|
<div id="progress-text">
|
|
<span id="progress-current">0:00</span>
|
|
<span id="progress-duration">0:00</span>
|
|
</div>
|
|
</div>
|
|
<div id="media-controls">
|
|
<button id="btn-prev" class="control-btn">⏮</button>
|
|
<button id="btn-playpause" class="control-btn">⏸</button>
|
|
<button id="btn-next" class="control-btn">⏭</button>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Audio Mixer Section -->
|
|
<section id="audio-section" class="panel">
|
|
<h2 data-i18n="audio_mixer">Audio Mixer</h2>
|
|
<div id="master-volume">
|
|
<span id="master-label" data-i18n="master_label">Master</span>
|
|
<div class="volume-controls">
|
|
<button id="btn-vol-down" class="volume-btn">-</button>
|
|
<span id="master-volume-value">50%</span>
|
|
<button id="btn-vol-up" class="volume-btn">+</button>
|
|
</div>
|
|
<button id="btn-mute" class="mute-btn" data-i18n="mute">
|
|
MUTE
|
|
</button>
|
|
</div>
|
|
<div id="channels-container"></div>
|
|
</section>
|
|
|
|
<!-- Telemetry Section -->
|
|
<section id="telemetry-section" class="panel">
|
|
<h2 data-i18n="system">System</h2>
|
|
<div id="telemetry-grid">
|
|
<div class="telemetry-item">
|
|
<span class="telemetry-label">CPU</span>
|
|
<span id="cpu-temp" class="telemetry-value">--</span>
|
|
</div>
|
|
<div class="telemetry-item">
|
|
<span class="telemetry-label">GPU</span>
|
|
<span id="gpu-temp" class="telemetry-value">--</span>
|
|
</div>
|
|
<div class="telemetry-item">
|
|
<span class="telemetry-label">RAM</span>
|
|
<span id="ram-usage" class="telemetry-value">--</span>
|
|
</div>
|
|
<div class="telemetry-item">
|
|
<span class="telemetry-label">VRAM</span>
|
|
<span id="vram-usage" class="telemetry-value">--</span>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Notifications Section -->
|
|
<section id="notifications-section" class="panel">
|
|
<h2 data-i18n="notifications">Notifications</h2>
|
|
<div id="notifications-container"></div>
|
|
</section>
|
|
</div>
|
|
|
|
<!-- Settings Screen -->
|
|
<div id="settings-screen" class="screen">
|
|
<h1 data-i18n="settings_title">Settings</h1>
|
|
<p data-i18n="settings_subtitle">Enter API token to access settings</p>
|
|
<input
|
|
type="password"
|
|
id="settings-token-input"
|
|
placeholder="API Token"
|
|
autocomplete="off"
|
|
/>
|
|
<button id="settings-access-btn" data-i18n="access">Access</button>
|
|
<p id="settings-error" class="error"></p>
|
|
|
|
<div id="settings-content" style="display: none">
|
|
<section class="panel">
|
|
<h2 data-i18n="dashboard_pin_label">Dashboard PIN</h2>
|
|
<input
|
|
type="text"
|
|
id="settings-pin"
|
|
maxlength="4"
|
|
placeholder="****"
|
|
/>
|
|
</section>
|
|
|
|
<section class="panel">
|
|
<h2 data-i18n="api_token_label">API Token</h2>
|
|
<input
|
|
type="password"
|
|
id="settings-token"
|
|
placeholder="API Token"
|
|
/>
|
|
</section>
|
|
|
|
<button id="settings-save-btn" data-i18n="save">Save</button>
|
|
<button id="settings-back-btn" data-i18n="back">Back</button>
|
|
<p id="settings-status" class="status"></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="app.js"></script>
|
|
</body>
|
|
</html>
|