diff --git a/CHANGELOG.md b/CHANGELOG.md index cf2d538..fcfafd3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,5 @@ # Changelog -## 0.37.1 - 2026-05-23 - -- Fixed AllManga alternative title parsing to read the visible `span.altnames` markup and changed watchlist cards to reveal those titles only when the new `Alternative titles` button is pressed. - ## 0.37.0 - 2026-05-23 - Added watchlist support for alternative English and synonym titles pulled from the AllManga show page and shown directly on each watchlist card. diff --git a/README.md b/README.md index c33bbd1..13153de 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Small local web UI for a system-wide `ani-cli` install. -Current version: `0.37.1` +Current version: `0.37.0` ## Project Layout @@ -242,8 +242,7 @@ Thumbnail behavior: Title behavior: - Watchlist refreshes also try to pull alternative English and synonym titles from the AllManga show page. -- Watchlist cards show an `Alternative titles` button when names are available. -- Pressing that button expands the stored alternative titles on demand. +- Up to three alternate names are shown as a muted secondary line under the main watchlist title. - Missing covers are warmed in small batches. - Failed lookups back off before retrying. - You can force `Reload` or use `Upload` when no thumbnail exists. diff --git a/VERSION b/VERSION index 9b1bb85..0f1a7df 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.37.1 +0.37.0 diff --git a/app.py b/app.py index 3d869e7..840cc0d 100644 --- a/app.py +++ b/app.py @@ -199,16 +199,6 @@ def parse_allmanga_alternative_titles(html_text, primary_title=""): for match in re.findall(r'"([^"]+)"', body): add_candidate(match, english_preferred=english_preferred) - for match in re.findall( - r']*class="[^"]*\baltnames\b[^"]*"[^>]*>\s*(.*?)\s*', - text, - flags=re.IGNORECASE | re.DOTALL, - ): - cleaned = re.sub(r"<[^>]+>", " ", match) - cleaned = cleaned.replace(" ", " ") - cleaned = re.sub(r"^[\s\u25cf\u26aa\u2022]+", "", cleaned) - add_candidate(cleaned, english_preferred=not preferred_english) - deduped = unique_title_values(candidates, primary) english_title = "" for candidate in unique_title_values([preferred_english], primary): diff --git a/app_support.py b/app_support.py index ece506c..7af5d56 100644 --- a/app_support.py +++ b/app_support.py @@ -19,7 +19,7 @@ from uuid import uuid4 PROJECT_ROOT = Path(__file__).resolve().parent ANI_CLI = os.environ.get("ANI_CLI_BIN") or shutil.which("ani-cli") or "ani-cli" APP_NAME = "ani-cli-web" -VERSION = "0.37.1" +VERSION = "0.37.0" ALLANIME_BASE = "allanime.day" ALLANIME_API = f"https://api.{ALLANIME_BASE}" ALLANIME_REFERER = "https://allmanga.to" diff --git a/test_app.py b/test_app.py index 58d72fd..8a67001 100644 --- a/test_app.py +++ b/test_app.py @@ -1746,10 +1746,8 @@ class TemplateHelperTests(unittest.TestCase): self.assertIn("Enter sub or dub", APP.WATCHLIST_HTML) def test_watchlist_page_shows_alternative_titles(self): - self.assertIn('class="ghost alt-toggle"', APP.WATCHLIST_HTML) - self.assertIn('class="alt-titles"', APP.WATCHLIST_HTML) - self.assertIn('Alternative titles', APP.WATCHLIST_HTML) - self.assertIn('altTitlesNode.classList.toggle("visible")', APP.WATCHLIST_HTML) + self.assertIn('class="alt-title"', APP.WATCHLIST_HTML) + self.assertIn('Alt: ${item.display_alt_titles.join(" · ")}', APP.WATCHLIST_HTML) def test_watchlist_thumbnail_warmup_skips_repeated_attempts(self): self.assertIn("thumbnailWarmupPending: new Set()", APP.WATCHLIST_HTML) @@ -1759,11 +1757,9 @@ class TemplateHelperTests(unittest.TestCase): def test_parse_allmanga_alternative_titles_extracts_english_and_synonyms(self): html_text = """ -
- ⚪ Example Show English   - ⚪ Sample Alias   - ⚪ Example Show   -
+ """ parsed = APP.parse_allmanga_alternative_titles(html_text, primary_title="Example Show") self.assertEqual(parsed["english_title"], "Example Show English") diff --git a/watchlist_page.py b/watchlist_page.py index 73cdccf..b19a23c 100644 --- a/watchlist_page.py +++ b/watchlist_page.py @@ -413,23 +413,13 @@ WATCHLIST_HTML = r""" flex: 1; min-width: 0; } - .alt-toggle { - min-height: 30px; - padding: 0 10px; - border-radius: 999px; - font-size: 11px; - font-weight: 700; - } - .alt-titles { + .alt-title { color: var(--muted); font-size: 12px; line-height: 1.35; - margin-top: 8px; + margin-top: 4px; overflow-wrap: anywhere; - display: none; - } - .alt-titles.visible { - display: block; + min-height: 1.35em; } .card-title a { color: inherit; @@ -1011,8 +1001,7 @@ WATCHLIST_HTML = r"""
- - +
${item.finished_badge ? "✓" : ""}
@@ -1041,21 +1030,10 @@ WATCHLIST_HTML = r""" titleLink.rel = "noopener noreferrer"; titleLink.textContent = item.title; titleNode.replaceChildren(titleLink); - const altToggle = card.querySelector(".alt-toggle"); - const altTitlesNode = card.querySelector(".alt-titles"); - const altTitles = item.display_alt_titles || []; - if (altTitles.length) { - altToggle.hidden = false; - altTitlesNode.hidden = false; - altTitlesNode.textContent = altTitles.join(" · "); - altToggle.setAttribute("aria-expanded", "false"); - altToggle.addEventListener("click", () => { - const visible = altTitlesNode.classList.toggle("visible"); - altToggle.setAttribute("aria-expanded", visible ? "true" : "false"); - altToggle.textContent = visible ? "Hide alternative titles" : "Alternative titles"; - }); - altToggle.textContent = "Alternative titles"; - } + const altTitleNode = card.querySelector(".alt-title"); + altTitleNode.textContent = (item.display_alt_titles || []).length + ? `Alt: ${item.display_alt_titles.join(" · ")}` + : ""; const finishCheck = card.querySelector(".finish-check"); if (finishCheck && item.finished_badge) { finishCheck.title = item.finished_badge === "downloaded"