From e361f0ba0e398f41451a96c7db3fcfb8c5f6ce4e Mon Sep 17 00:00:00 2001 From: Josue Zamudio Date: Sun, 30 Aug 2026 19:19:56 +0000 Subject: [PATCH] Autoplay: playsinline + non-fatal tap-to-play fallback videoEl() lacked playsinline: on iOS Safari (and some Android browsers) v.play() then rejects with NotAllowedError even on the first, gesture-backed attempt. A tap on the 'Tap to play' overlay that is STILL rejected (e.g. the user has autoplay disallowed for the site) no longer goes to the fatal 'Playback failed: playback blocked by the browser' screen whose Retry just re-ran play() into the same wall. It stays on the tappable overlay with a hint to allow autoplay in the site settings. --- static/app.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/static/app.js b/static/app.js index 443e462..18ce665 100644 --- a/static/app.js +++ b/static/app.js @@ -609,7 +609,7 @@ function stepEp(d) { function videoEl() { const v = document.createElement("video"); - v.controls = true; v.autoplay = true; + v.controls = true; v.autoplay = true; v.playsinline = true; return v; } @@ -727,9 +727,15 @@ async function play(ep_id, ep_no) { // hls.js fatal-error path — leave its overlay alone. v.play().catch(err => { if (!err || err.name !== "NotAllowedError") return; - playerOverlay("Tap to play", () => { - v.play().catch(() => playerFail("playback blocked by the browser")); - }, "Play"); + // Not fatal: a tap (a real gesture) usually starts playback. If the + // browser rejects even that (autoplay disallowed for the site, …), + // stay on the tappable overlay and say what to change — retrying + // play() would just hit the same wall + const tap = () => v.play().catch(() => blocked()); + const blocked = () => playerOverlay( + "Browser blocked playback. Tap Play, or allow autoplay for this " + + "site in the browser's site settings", tap, "Play"); + blocked(); }); watchPos(v); postHistory({...meta(v), title: detail.name, slug_id: detail.slug_id, season_id: seasonId,