fix(554): mute the channel preview, and name blocked autoplay only when that is the cause #910
5
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
350509f8bb |
docs(554): the opt-in's unreachability is about started, not about mount order
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 22s
PR Gates / decisions lifecycle (pull_request) Successful in 26s
PR Gates / Fix proofs (Proves trailers) (pull_request) Successful in 14s
PR Gates / Docs update reminder (pull_request) Successful in 14s
Review verdict / Set review-verdict status (pull_request_target) Successful in 35s
review-verdict/h10 Review-verdict: MERGEABLE @ 350509f (base: main)
PR Gates / Script lint and tests (ruff + pytest) (pull_request) Successful in 16m49s
Build ErsatzTV Image / CI toolchain image resolves (pull_request) Successful in 33s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 9m20s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 6m1s
Build ErsatzTV Image / Delimiter ban (release path) (pull_request) Successful in 45s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 8s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 5s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 6m21s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Skipped
"its button renders only before the player has ever mounted" is loose: a channel switch to a forced channel re-renders the button after a player has mounted for the previous channel. The load-bearing fact is the one the code comment states — the button renders only while `started` is false, and the only thing that un-starts the panel is the channel reset that clears the flag in the same batch. Refs #554 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015QqCpYFsKgnAnx6jVwrKiV |
||
|
|
f119bfcb29 |
docs(554): the opt-in is a third path back to starting, and the invariant must say so
The hint's single-guard invariant was stated as "every path back to `starting` clears the flag itself", enumerating Retry and a channel change. `onOptIn` is a third such path and clears nothing, so the sentence was false as written — in the code comment, in the Retry test's comment, and in docs/spa-conventions.md §5b. Adding a clear to `onOptIn` would be dead code no test could distinguish, which is the exact shape this branch removed from `onPlaying`. The omission is correct for a reason none of the three places stated: the opt-in button renders only while `started` is false, `started` only goes false in the render-phase reset that clears the flag two lines later, and no player exists to set the flag while `started` is false. State that exception, and pin the reachability premise it rests on with a test that fails if the opt-in button outlives the mounted player. Refs #554 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015QqCpYFsKgnAnx6jVwrKiV |
||
|
|
b6b4fb6619 |
test(554): pin both clears the hint's single guard depends on
Dropping the onPlaying clear made the `state === 'starting'` render guard the hint's only guard, which moves the burden onto the two paths back to `starting`: each has to clear `autoplayBlocked` itself. Both were assertable but unasserted — either `setAutoplayBlocked(false)` could be deleted with the whole panel suite green, so the invariant the code comment and docs/spa-conventions.md §5b both state was unpinned in both of its named paths. Add one test per path (Retry; a channel switch), each asserting the hint is gone while the panel is back at `starting` — so the render guard cannot be what hid it. Each also asserts the player really re-mounted (loadSource count / last URL, plus a non-null <video>), so the hint cannot be absent merely because the `resolvedSrc` block is unrendered. Measured on this tree, each mutation caught by exactly one test: deleting the onRetry clear reds only 'clicking Retry clears the autoplay-blocked hint' (Tests 1 failed | 25 passed); deleting the render-phase reset clear reds only 'clears the autoplay-blocked hint when switching to a different channel' (1 failed | 25 passed); replacing `autoplayBlocked && state === 'starting' &&` with `autoplayBlocked &&` reds one test too. Unmutated: 26 passed. Refs #554 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015QqCpYFsKgnAnx6jVwrKiV |
||
|
|
4e042fb7de |
fix(554): the hint's cause must be measured, and muting is the consumer's call
Round one measured three defects in the first commit. onAutoplayBlocked fired on ANY rejected video.play(), so the panel could say "autoplay was blocked" when it was not. A play() interrupted by teardown rejects with AbortError — which is exactly what the panel's own Retry produces while the MANIFEST_PARSED play() is still pending — and because the element was muted, a genuine NotAllowedError is the rare case, so the realistic firings were the mislabelled ones. Report only a DOMException named NotAllowedError, on both the MSE and native paths. `muted` was applied to the shared player unconditionally, which silently muted the playback-troubleshooting screen — the tool whose job includes verifying the audio side of an FFmpeg profile, and which the legacy Blazor player never muted. Make it an opt-in `muted` prop defaulting to false; the channel preview passes it, troubleshooting does not, and a test on each side pins its own value. The two clauses hiding the hint once playback starts masked each other: removing either alone left the panel suite green. Every path back to 'starting' (Retry, a channel change) already clears the flag itself, so the clear in onPlaying could never be the load-bearing guard — drop it and let the `state === 'starting'` render guard be the single pinned one. Also cover the native-HLS (Safari) branch, which no test had ever executed: its play() kick, its playing/error wiring, and both autoplay rejection names. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015QqCpYFsKgnAnx6jVwrKiV |
||
|
|
02e1c583e9 |
fix(554): mute the preview player so autoplay is never blocked
Build ErsatzTV Image / CI toolchain image resolves (pull_request) Successful in 6s
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 9s
PR Gates / Docs update reminder (pull_request) Successful in 21s
Build ErsatzTV Image / Delimiter ban (release path) (pull_request) Successful in 24s
PR Gates / Fix proofs (Proves trailers) (pull_request) Successful in 13s
PR Gates / decisions lifecycle (pull_request) Successful in 27s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 9m10s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 6m24s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Skipped
PR Gates / Script lint and tests (ruff + pytest) (pull_request) Successful in 17m7s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 5m47s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 7s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 5s
review-verdict/h10 Awaiting review verdict for 02e1c58
Review verdict / Set review-verdict status (pull_request_target) Successful in 33s
HlsPlayer's manifest GET can block until segments exist (unbounded maxTimeToFirstByteMs), so MANIFEST_PARSED can arrive past the browser's transient user-activation window and video.play() gets rejected as blocked autoplay — the channel preview panel then sat at "starting" over a black frame with no hint the operator just needed to press play. Render the <video> element muted (browsers permit autoplay of muted media without user activation) so the common case starts on its own, and add an optional onAutoplayBlocked callback for the residual case (stricter policy/extension) that the channel preview panel wires to a "press play" hint shown only while still starting. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015QqCpYFsKgnAnx6jVwrKiV |