mirror of
https://github.com/screentinker/screentinker.git
synced 2026-06-17 03:32:32 -06:00
Each playlist item can carry schedule blocks (active days, start/end time-of-day, optional start/end dates). An item plays when the screen's local "now" matches at least one block; an item with no blocks always plays. #74 covers time-of-day/day-of-week windows including overnight wrap; #75 covers inclusive date ranges (auto-expiry). Evaluation is on-device, so dayparting and expiry work offline. - Shared evaluator contract: shared/schedule-vectors.json (39 vectors — DST US+AU, overnight-wrap anchoring, timezone correctness, date boundaries). Canonical JS evaluator in server/lib/schedule-eval.js; Kotlin and Tizen ports kept in lockstep by drift guards (Tizen byte-diff test, Kotlin JUnit reads the shared JSON, new android-test CI job). - All three players (web, Android, Tizen) filter by schedule against their own clock, idle with a "Nothing scheduled" message + 30s re-check when everything is filtered, and fail open on any evaluator error. - Editor: per-item schedule modal + row badge in the playlist editor; client validation mirrors the server; editing marks the playlist draft. - Part B (behaviour change): device/group schedule overrides now evaluate in each device's effective timezone instead of server-local time. - Device detail shows the reported timezone + a clock-skew warning. - i18n for en/es/fr/de/pt across all new strings (namespaced itemsched.* to avoid colliding with the device-schedule calendar's schedule.*). - CHANGELOG documents the feature, the Part B change, the fail-open guarantee, and the scheduled-single-video re-render tradeoff. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
47 lines
1.7 KiB
HTML
47 lines
1.7 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
|
<title>ScreenTinker</title>
|
|
<link rel="stylesheet" href="css/style.css">
|
|
</head>
|
|
<body>
|
|
<!-- Setup: enter server URL -->
|
|
<div id="setup" class="screen">
|
|
<div class="card">
|
|
<h1>ScreenTinker</h1>
|
|
<p class="sub">Digital Signage Player</p>
|
|
<label for="serverUrl">Server URL</label>
|
|
<input id="serverUrl" type="url" value="https://screentinker.com" autocomplete="off"
|
|
autocorrect="off" autocapitalize="off" spellcheck="false">
|
|
<button id="connectBtn">Connect</button>
|
|
<p id="setupStatus" class="status"></p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Pairing: show the code -->
|
|
<div id="pairing" class="screen hidden">
|
|
<div class="card">
|
|
<h1>ScreenTinker</h1>
|
|
<p class="sub">Pair this display</p>
|
|
<div id="pairCode" class="code">------</div>
|
|
<p class="hint">Enter this code in your ScreenTinker dashboard<br>(Devices → Pair a display)</p>
|
|
<p id="pairStatus" class="status">Waiting to be paired…</p>
|
|
<button id="resetBtn" class="ghost">Change server</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Playback stage -->
|
|
<div id="stage" class="screen stage hidden"></div>
|
|
|
|
<!-- Tiny on-screen status (offline / errors), auto-hides -->
|
|
<div id="toast" class="toast hidden"></div>
|
|
|
|
<script src="js/socket.io.min.js"></script>
|
|
<script src="js/schedule-eval.js"></script>
|
|
<script src="js/player.js"></script>
|
|
<script src="js/app.js"></script>
|
|
</body>
|
|
</html>
|