Revert "Collapse watchlist alternative titles"
This reverts commit 0c1b46e395.
This commit is contained in:
@@ -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,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.
|
||||||
|
|||||||
@@ -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(" ", " ")
|
|
||||||
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
@@ -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
@@ -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 </span>
|
{"englishTitle":"Example Show English","synonyms":["Sample Alias","Example Show"]}
|
||||||
<span class="mr-1 altnames"> ⚪ Sample Alias </span>
|
</script>
|
||||||
<span class="mr-1 altnames"> ⚪ Example Show </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
@@ -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 ? "✓" : ""}</span>
|
<span class="finish-check ${item.finished_badge || ""}" ${item.finished_badge ? "" : "hidden"}>${item.finished_badge ? "✓" : ""}</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"
|
||||||
|
|||||||
Reference in New Issue
Block a user