mirror of
https://github.com/screentinker/screentinker.git
synced 2026-08-14 06:16:20 -06:00
PlaylistPlayer and ZoneRenderer share one #stage node, but every playlist-update unconditionally blanked the OTHER renderer (zoneRenderer.clear() in the single-zone branch, player.stop() in the layout branch) and then hit that renderer's unchanged- signature `return` — leaving the stage BLANK. Same class as the Android #162 wedge (a stale "still on screen" belief trusted while nothing is actually rendered): - fires on the routine ~60s heartbeat re-register (server re-pushes the same playlist), - permanent for a single looping item (no advance timer to self-heal), - also stranded the stage on suspend -> resume and cold-start cached-playlist restore. Fix: track which renderer owns the shared stage (stageOwner) and only blank the other one when actually switching modes, invalidating the incoming renderer's signature so it repaints on the switch; never blank on a same-mode unchanged update. Added ZoneRenderer.invalidate() to mirror PlaylistPlayer.invalidate(). Verified with a faithful state-machine simulation: old code blanks 8x across a realistic pair/heartbeat/switch/suspend sequence, fixed code 0x. The web player (server/player/index.html) was reviewed and is NOT vulnerable — its unchanged-guard already verifies real DOM surface health (needsReattach, the #146 fix) and its JS state resets on reload, so there is no analogous wedge. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| app.js | ||
| device-control.js | ||
| pip-overlay.js | ||
| player.js | ||
| schedule-eval.js | ||
| socket.io.min.js | ||