home polish: continue-watching hero, progress bars, posters, time-ago

- showHome(): most recent entry renders as a hero card (poster,
  episode/lang/position, progress bar, Resume); the rest become
  mini poster cards with progress + relative timestamp
- history entries now persist dur (video.duration) and poster;
  /api/anime returns poster (parsed from the details page)
- old entries without dur render without a bar (backward compatible)
- browser test asserts the seeded entry, not a section header that
  only existed via a cross-test side effect
This commit is contained in:
jozamudi committed 2026-08-19 17:01:04 +00:00
1 parent e0f5427002
commit 2efb537edc
4 files changed
+89 -12

No files matched your search

+3 -1
View File
@@ -42,11 +42,12 @@ def search(q):
def details(slug_id):
"""Step 2: details page -> {name, synopsis, mal_id, seasons}"""
"""Step 2: details page -> {name, synopsis, mal_id, poster, seasons}"""
p = _get(f"{BASE}/anime/{slug_id}").text
mal = re.search(r'myanimelist\.net/anime/(\d+)', p)
syn = re.search(r'>Synopsis</h2>.*?<p[^>]*>(.*?)</p>', p, re.S)
h1 = re.search(r'<h1[^>]*>(.*?)</h1>', p, re.S)
post = re.search(r'src="(https://cdn\.xlsbox\.com/poster/[^"\']+)"', p)
seasons, seen = [], set()
i = p.find(">Seasons<")
if i > 0:
@@ -64,6 +65,7 @@ def details(slug_id):
"name": h1.group(1).strip() if h1 else None,
"synopsis": re.sub(r"<[^>]+>", "", syn.group(1)).strip() if syn else None,
"mal_id": int(mal.group(1)) if mal else None,
"poster": post.group(1) if post else None,
"seasons": seasons}