Files
iptvnator/apps/web
4grayandClaude Fable 5 dded17010d fix(playback): keep the display awake while built-in players play video (#1405)
* fix(playback): keep the display awake while built-in players play video

Closes #1095. The renderer tracks every playing <video> through
document-level capture listeners (element-level release listeners catch
the detached-element pause on component teardown) and, while any video
is playing and the document is visible, holds a display-sleep lock:
a main-process powerSaveBlocker over IPC in Electron — reliable on
Linux where Chromium's own video wake lock depends on DE D-Bus
inhibitors — and the Screen Wake Lock API in the PWA. The vote is
auto-cleared when the renderer reloads or dies. Radio's <audio>
deliberately never blocks display sleep; embedded MPV and external
MPV/VLC already manage their own inhibition.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(playback): withdraw the keep-awake vote when the renderer crashes

A crash emits render-process-gone while the WebContents object stays
alive, so the destroyed listener alone missed it: without a follow-up
reload the display stayed pinned awake. Review finding by Codex.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(playback): keep the display lock for picture-in-picture playback

Minimizing the window hides the document but leaves the PiP surface on
screen, so the visibility gate was releasing the lock mid-watch. A
tracked playing video that owns document.pictureInPictureElement now
counts as visible playback, and PiP enter/leave events resynchronize
the gate. Review finding by Codex.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(playback): re-evaluate the wake lock after a rejection masked a state change

In the PWA path a hidden-visible round-trip (or pause/resume) while
wakeLock.request() was pending got swallowed by the in-flight guard; if
that request then rejected, only the flag was cleared and a continuously
playing visible video sat without a wake lock until the next unrelated
event. State changes arriving mid-flight now queue one re-evaluation on
rejection; permanent denials still don't loop because nothing queues a
retry without a fresh interleaved change. Review finding by Codex.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(playback): mirror the display-sleep contract into AGENTS.md

AGENTS.md carries its own playback sections (radio, shared controls,
PiP), so the keep-awake contract belongs there too. Review finding by
Codex.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-12 00:23:03 +02:00
..
2025-10-07 18:02:13 +02:00