Revert "Collapse watchlist alternative titles"

This reverts commit 0c1b46e395.
This commit is contained in:
Dymas
2026-05-23 19:14:34 +02:00
parent 5b0f4043ed
commit bead7da60a
7 changed files with 17 additions and 58 deletions
-4
View File
@@ -1,9 +1,5 @@
# Changelog # 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 ## 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. - Added watchlist support for alternative English and synonym titles pulled from the AllManga show page and shown directly on each watchlist card.
+2 -3
View File
@@ -2,7 +2,7 @@
Small local web UI for a system-wide `ani-cli` install. Small local web UI for a system-wide `ani-cli` install.
Current version: `0.37.1` Current version: `0.37.0`
## Project Layout ## Project Layout
@@ -242,8 +242,7 @@ Thumbnail behavior:
Title behavior: Title behavior:
- Watchlist refreshes also try to pull alternative English and synonym titles from the AllManga show page. - 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. - Up to three alternate names are shown as a muted secondary line under the main watchlist title.
- Pressing that button expands the stored alternative titles on demand.
- Missing covers are warmed in small batches. - Missing covers are warmed in small batches.
- Failed lookups back off before retrying. - Failed lookups back off before retrying.
- You can force `Reload` or use `Upload` when no thumbnail exists. - You can force `Reload` or use `Upload` when no thumbnail exists.
+1 -1
View File
@@ -1 +1 @@
0.37.1 0.37.0
-10
View File
@@ -199,16 +199,6 @@ def parse_allmanga_alternative_titles(html_text, primary_title=""):
for match in re.findall(r'"([^"]+)"', body): for match in re.findall(r'"([^"]+)"', body):
add_candidate(match, english_preferred=english_preferred) add_candidate(match, english_preferred=english_preferred)
for match in re.findall(
r'<span[^>]*class="[^"]*\baltnames\b[^"]*"[^>]*>\s*(.*?)\s*</span>',
text,
flags=re.IGNORECASE | re.DOTALL,
):
cleaned = re.sub(r"<[^>]+>", " ", match)
cleaned = cleaned.replace("&nbsp;", " ")
cleaned = re.sub(r"^[\s\u25cf\u26aa\u2022]+", "", cleaned)
add_candidate(cleaned, english_preferred=not preferred_english)
deduped = unique_title_values(candidates, primary) deduped = unique_title_values(candidates, primary)
english_title = "" english_title = ""
for candidate in unique_title_values([preferred_english], primary): for candidate in unique_title_values([preferred_english], primary):
+1 -1
View File
@@ -19,7 +19,7 @@ from uuid import uuid4
PROJECT_ROOT = Path(__file__).resolve().parent PROJECT_ROOT = Path(__file__).resolve().parent
ANI_CLI = os.environ.get("ANI_CLI_BIN") or shutil.which("ani-cli") or "ani-cli" ANI_CLI = os.environ.get("ANI_CLI_BIN") or shutil.which("ani-cli") or "ani-cli"
APP_NAME = "ani-cli-web" APP_NAME = "ani-cli-web"
VERSION = "0.37.1" VERSION = "0.37.0"
ALLANIME_BASE = "allanime.day" ALLANIME_BASE = "allanime.day"
ALLANIME_API = f"https://api.{ALLANIME_BASE}" ALLANIME_API = f"https://api.{ALLANIME_BASE}"
ALLANIME_REFERER = "https://allmanga.to" ALLANIME_REFERER = "https://allmanga.to"
+5 -9
View File
@@ -1746,10 +1746,8 @@ class TemplateHelperTests(unittest.TestCase):
self.assertIn("Enter sub or dub", APP.WATCHLIST_HTML) self.assertIn("Enter sub or dub", APP.WATCHLIST_HTML)
def test_watchlist_page_shows_alternative_titles(self): def test_watchlist_page_shows_alternative_titles(self):
self.assertIn('class="ghost alt-toggle"', APP.WATCHLIST_HTML) self.assertIn('class="alt-title"', APP.WATCHLIST_HTML)
self.assertIn('class="alt-titles"', APP.WATCHLIST_HTML) self.assertIn('Alt: ${item.display_alt_titles.join(" · ")}', APP.WATCHLIST_HTML)
self.assertIn('Alternative titles', APP.WATCHLIST_HTML)
self.assertIn('altTitlesNode.classList.toggle("visible")', APP.WATCHLIST_HTML)
def test_watchlist_thumbnail_warmup_skips_repeated_attempts(self): def test_watchlist_thumbnail_warmup_skips_repeated_attempts(self):
self.assertIn("thumbnailWarmupPending: new Set()", APP.WATCHLIST_HTML) 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): def test_parse_allmanga_alternative_titles_extracts_english_and_synonyms(self):
html_text = """ html_text = """
<div class="show-more-content card-text p-0" style=""> <script>
<span class="mr-1 altnames"> ⚪ Example Show English &nbsp; </span> {"englishTitle":"Example Show English","synonyms":["Sample Alias","Example Show"]}
<span class="mr-1 altnames"> ⚪ Sample Alias &nbsp; </span> </script>
<span class="mr-1 altnames"> ⚪ Example Show &nbsp; </span>
</div>
""" """
parsed = APP.parse_allmanga_alternative_titles(html_text, primary_title="Example Show") parsed = APP.parse_allmanga_alternative_titles(html_text, primary_title="Example Show")
self.assertEqual(parsed["english_title"], "Example Show English") self.assertEqual(parsed["english_title"], "Example Show English")
+8 -30
View File
@@ -413,23 +413,13 @@ WATCHLIST_HTML = r"""<!doctype html>
flex: 1; flex: 1;
min-width: 0; min-width: 0;
} }
.alt-toggle { .alt-title {
min-height: 30px;
padding: 0 10px;
border-radius: 999px;
font-size: 11px;
font-weight: 700;
}
.alt-titles {
color: var(--muted); color: var(--muted);
font-size: 12px; font-size: 12px;
line-height: 1.35; line-height: 1.35;
margin-top: 8px; margin-top: 4px;
overflow-wrap: anywhere; overflow-wrap: anywhere;
display: none; min-height: 1.35em;
}
.alt-titles.visible {
display: block;
} }
.card-title a { .card-title a {
color: inherit; color: inherit;
@@ -1011,8 +1001,7 @@ WATCHLIST_HTML = r"""<!doctype html>
<div class="title-row"> <div class="title-row">
<div> <div>
<div class="card-title"></div> <div class="card-title"></div>
<button class="ghost alt-toggle" type="button" hidden>Alternative titles</button> <div class="alt-title"></div>
<div class="alt-titles" hidden></div>
</div> </div>
<span class="finish-check ${item.finished_badge || ""}" ${item.finished_badge ? "" : "hidden"}>${item.finished_badge ? "&check;" : ""}</span> <span class="finish-check ${item.finished_badge || ""}" ${item.finished_badge ? "" : "hidden"}>${item.finished_badge ? "&check;" : ""}</span>
</div> </div>
@@ -1041,21 +1030,10 @@ WATCHLIST_HTML = r"""<!doctype html>
titleLink.rel = "noopener noreferrer"; titleLink.rel = "noopener noreferrer";
titleLink.textContent = item.title; titleLink.textContent = item.title;
titleNode.replaceChildren(titleLink); titleNode.replaceChildren(titleLink);
const altToggle = card.querySelector(".alt-toggle"); const altTitleNode = card.querySelector(".alt-title");
const altTitlesNode = card.querySelector(".alt-titles"); altTitleNode.textContent = (item.display_alt_titles || []).length
const altTitles = item.display_alt_titles || []; ? `Alt: ${item.display_alt_titles.join(" · ")}`
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 finishCheck = card.querySelector(".finish-check"); const finishCheck = card.querySelector(".finish-check");
if (finishCheck && item.finished_badge) { if (finishCheck && item.finished_badge) {
finishCheck.title = item.finished_badge === "downloaded" finishCheck.title = item.finished_badge === "downloaded"