ui: watched-episode state (dimmed + check, next-up highlight), favicon

This commit is contained in:
jozamudi committed 2026-08-19 18:49:29 +00:00
1 parent 98fb4e5461
commit bb1297f8e2
5 files changed
+54 -2

No files matched your search

+18 -2
View File
@@ -255,8 +255,20 @@ async function showAnime(slug_id, opts = {}) {
eps.append(el("p", "muted", "loading episodes\u2026"));
main.append(eps);
// default: resume last watched ep of this season, else start at ep 1
// watched state: dim completed eps, highlight the first unwatched one
// (ponytail: "first unwatched in list order" is wrong if you skip around;
// good enough for sequential viewing)
epsList = await api(`/api/anime/${seasonId}/episodes`);
watchDone = new Set();
let started = false;
try {
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));
}
} catch {}
watchNext = started ? (epsList.find(e => !watchDone.has(String(e.id))) || {}).id : null;
renderEps();
const h = history.find(x => x.slug_id === slug_id && x.season_id === seasonId);
const start = opts.ep || (h ? h.ep_id : null) || epsList[0]?.id;
@@ -315,6 +327,7 @@ function markActive(b) {
}
let epsList = [], hideFiller = false;
let watchDone = new Set(), watchNext = null;
function renderEps() {
const eps = document.getElementById("eps");
@@ -323,7 +336,10 @@ function renderEps() {
for (const e of epsList) {
if (hideFiller && e.filler) continue;
const b = el("button", "ep" + (e.filler ? " filler" : ""));
b.textContent = "E" + e.number;
const done = watchDone.has(String(e.id));
b.textContent = done ? "E" + e.number + " \u2713" : "E" + e.number;
if (done) b.classList.add("done");
if (watchNext != null && String(watchNext) === String(e.id)) b.classList.add("nextup");
if (e.filler) b.append(el("span", "badge", " filler"));
b.dataset.ep = e.id; b.dataset.no = e.number;
b.onclick = () => { markActive(b); play(e.id, e.number); };
+2
View File
@@ -4,6 +4,8 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ani-web</title>
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Crect width='64' height='64' rx='14' fill='%23f97316'/%3E%3Ctext x='32' y='45' font-family='sans-serif' font-size='42' font-weight='700' text-anchor='middle' fill='%230e0f13'%3Ea%3C/text%3E%3C/svg%3E">
<link rel="stylesheet" href="style.css">
</head>
<body>
+2
View File
@@ -115,5 +115,7 @@ button.tiny.on { border-color: var(--acc); color: var(--acc); }
.ep { position: relative; font-size: 0.9rem; }
.ep.active { border-color: var(--acc); color: var(--acc); }
.ep.filler { opacity: 0.55; }
.ep.done { opacity: 0.5; }
.ep.nextup { border-color: #4b5568; background: #1f2130; }
.badge { font-size: 0.6rem; color: var(--muted); }