diff --git a/static/app.js b/static/app.js index e1cd2e5..20e5b66 100644 --- a/static/app.js +++ b/static/app.js @@ -126,6 +126,14 @@ async function showAnime(slug_id, opts = {}) { if (opts.ep) { const cur = [...eps.children].find(b => +b.dataset.ep === opts.ep); if (cur) { markActive(cur); play(opts.ep, cur.dataset.no); } + } else { + // default: resume last watched ep of this season, else start at ep 1 + const h = hist().find(x => x.slug_id === slug_id && x.season_id === seasonId); + const auto = h ? h.ep_id : +eps.querySelector(".ep")?.dataset.ep; + if (auto) { + const cur = [...eps.children].find(b => +b.dataset.ep === auto); + if (cur) { markActive(cur); play(auto, cur.dataset.no); } + } } if (detail.synopsis) main.append(el("p", "synopsis bottom", detail.synopsis)); @@ -164,6 +172,7 @@ async function play(ep_id, ep_no) { hls.loadSource("/stream/" + s.token); hls.attachMedia(v); v.onerror = () => showStreamError("media error: " + (v.error?.message || v.error?.code)); + v.play().catch(() => showPlayOverlay(v)); // autoplay blocked (no user gesture) -> visible prompt } catch (e) { showStreamError(e.message); } @@ -172,6 +181,12 @@ async function play(ep_id, ep_no) { document.title = `${detail.name} E${ep_no} — ani-web`; } +function showPlayOverlay(v) { + const o = el("button", "play-overlay", "▶ click to play"); + o.onclick = () => { v.play(); o.remove(); }; + v.parentElement.append(o); +} + // ---------- boot ---------- (async () => { const p = new URLSearchParams(location.search); diff --git a/static/style.css b/static/style.css index 1bc879c..2ff5185 100644 --- a/static/style.css +++ b/static/style.css @@ -23,7 +23,10 @@ h2 { margin: 0.4rem 0; } .detail-head { margin-bottom: 1rem; } .synopsis { color: var(--muted); max-width: 70ch; margin: 0.3rem 0; } +.player { position: relative; } .player video { width: 100%; max-height: 70vh; background: #000; border-radius: 10px; aspect-ratio: 16/9; } +.play-overlay { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); + font-size: 1.1rem; padding: 0.8rem 1.4rem; background: rgba(0, 0, 0, 0.75); } .controls { display: flex; align-items: center; gap: 0.4rem; margin: 0.6rem 0; } button { background: var(--card); color: var(--fg); border: 1px solid var(--bd); border-radius: 8px; padding: 0.4rem 0.7rem; cursor: pointer; }