watched: single DONE_RATIO source constant replaces the seven hardcoded 0.95 literals

server/app.py DONE_RATIO is injected into index.html like {{VERSION}}, app.js
reads it as window.DONE_RATIO (fallback = same default). Change the threshold
in exactly one place now.
This commit is contained in:
jozamudi committed 2026-09-21 01:41:44 +00:00
1 parent 5f7aa010f1
commit 731f44b99c
3 files changed
+22 -9

No files matched your search

+9 -6
View File
@@ -10,6 +10,9 @@ const BASE = (() => {
return p.endsWith("/") ? p : p.slice(0, p.lastIndexOf("/") + 1);
})();
const main = document.getElementById("main");
// Watched threshold (fraction of duration) — injected inline by the server
// from DONE_RATIO in server/app.py; fallback matches that default.
const DONE_RATIO = Number(window.DONE_RATIO ?? 0.95);
let hls = null, detail = null, lang = "jpn", seasonId = null;
async function api(path) {
@@ -190,7 +193,7 @@ const homeCard = x => {
c.append(poster(x.poster, x.title));
let meta = `E${x.ep} \u00b7 ${x.lang === "eng" ? "dub" : "sub"}`;
if (done) meta += " \u00b7 \u2713";
else if (x.dur > 0 && x.pos < x.dur * 0.95) meta += ` \u00b7 ${fmtMin((x.dur - x.pos) / 60)} left`;
else if (x.dur > 0 && x.pos < x.dur * DONE_RATIO) meta += ` \u00b7 ${fmtMin((x.dur - x.pos) / 60)} left`;
else if (hold) meta += ` \u00b7 ${Math.round(Date.now() / 1000 / 86400 - x.t / 86400)}d ago`;
const info = el("div", "mini-info");
info.append(el("div", "card-name", x.title), el("div", "mini-meta", meta));
@@ -250,11 +253,11 @@ function showHome() {
body.append(el("div", "hero-kicker", "continue watching"),
el("h2", null, hero.title),
el("div", "muted", `Ep ${hero.ep} · ${hero.lang === "eng" ? "dub" : "sub"} · ${fmtPos(hero.pos)} in` +
(hero.dur > 0 && hero.pos < hero.dur * 0.95 ? ` · ${fmtMin((hero.dur - hero.pos) / 60)} left` : "") +
(hero.dur > 0 && hero.pos < hero.dur * DONE_RATIO ? ` · ${fmtMin((hero.dur - hero.pos) / 60)} left` : "") +
` · ${timeago(hero.t)}`));
const p = bar(hero);
if (p) body.append(p);
const heroDone = hero.dur > 0 && hero.pos >= hero.dur * 0.95;
const heroDone = hero.dur > 0 && hero.pos >= hero.dur * DONE_RATIO;
const go = el("button", "btn resume", heroDone ? "\u25b6 Next ep" : "\u25b6 Resume");
go.onclick = () => location.href = histHref(hero);
right.append(body, go);
@@ -503,7 +506,7 @@ async function showAnime(slug_id, opts = {}) {
for (const x of await api("/api/history?all=1")) {
if (x.slug_id !== slug_id || x.season_id !== seasonId) continue;
started = true;
if (x.dur > 0 && x.pos >= x.dur * 0.95) watchDone.add(String(x.ep_id));
if (x.dur > 0 && x.pos >= x.dur * DONE_RATIO) watchDone.add(String(x.ep_id));
else if (x.dur > 0) epProg.set(String(x.ep_id), Math.min(100, Math.round(100 * x.pos / x.dur)));
}
} catch {}
@@ -529,7 +532,7 @@ async function showAnime(slug_id, opts = {}) {
function langLabel() { return lang === "eng" ? "▶ dub" : "▶ sub"; }
// ---------- history page (full list + delete + client-side filter) ----------
const histClass = x => x.dur > 0 && x.pos >= x.dur * 0.95 ? "done"
const histClass = x => x.dur > 0 && x.pos >= x.dur * DONE_RATIO ? "done"
: (x.t && Date.now() / 1000 - x.t > 7 * 86400 ? "hold" : "watching");
function remapBoard() {
// home: one stale card per stale anime (latest row), above the hero, so a
@@ -1215,7 +1218,7 @@ async function play(ep_id, ep_no) {
}
if (saved?.pos > 10) {
v.addEventListener("loadedmetadata", () => {
if (saved.pos < v.duration * 0.95) v.currentTime = saved.pos;
if (saved.pos < v.duration * DONE_RATIO) v.currentTime = saved.pos;
}, {once: true});
}
v.onerror = () => playerFail("media error");
+3
View File
@@ -35,6 +35,9 @@
route) with the git SHA at startup — a correct cache key per commit.
No hand-bumping; JSV in app.js reads the same value from its own URL. -->
<script src="hls.min.js"></script>
<!-- Watched threshold: server injects its DONE_RATIO source constant here;
app.js reads it as DONE_RATIO. Server uses the same value for its stats. -->
<script>window.DONE_RATIO = {{DONE_RATIO}};</script>
<script src="app.js?v={{VERSION}}"></script>
</body>
</html>