Simplify search mode and prefer provider artwork
This commit is contained in:
+24
-18
@@ -423,12 +423,6 @@ INDEX_HTML = r"""<!doctype html>
|
||||
<label for="search-query">Anime Title / Keyword</label>
|
||||
<input type="text" id="search-query" placeholder="e.g., Attack on Titan">
|
||||
|
||||
<label for="search-mode">Episode mode</label>
|
||||
<select id="search-mode">
|
||||
<option value="sub">Subtitled (Sub)</option>
|
||||
<option value="dub">Dubbed (Dub)</option>
|
||||
</select>
|
||||
|
||||
<label for="search-quality">Quality</label>
|
||||
<select id="search-quality">
|
||||
<option value="best">Best</option>
|
||||
@@ -522,11 +516,6 @@ INDEX_HTML = r"""<!doctype html>
|
||||
if (notice) notice.textContent = text || "";
|
||||
}
|
||||
|
||||
function setMode(mode) {
|
||||
state.config.mode = mode;
|
||||
$("search-mode").value = mode;
|
||||
}
|
||||
|
||||
function coverInitials(title) {
|
||||
const parts = String(title || "")
|
||||
.trim()
|
||||
@@ -537,7 +526,12 @@ INDEX_HTML = r"""<!doctype html>
|
||||
return parts.map((part) => part[0]).join("").slice(0, 2);
|
||||
}
|
||||
|
||||
function resultThumbnailUrl(title) {
|
||||
function resultThumbnailUrl(item) {
|
||||
const providerImage = String(item && item.image || "").trim();
|
||||
return providerImage || fallbackThumbnailUrl(item && item.title);
|
||||
}
|
||||
|
||||
function fallbackThumbnailUrl(title) {
|
||||
return `/api/search/thumb?title=${encodeURIComponent(title || "")}`;
|
||||
}
|
||||
|
||||
@@ -593,7 +587,7 @@ INDEX_HTML = r"""<!doctype html>
|
||||
const img = btn.querySelector("img");
|
||||
const tile = btn.querySelector(".cover-tile");
|
||||
img.alt = item.title;
|
||||
img.src = resultThumbnailUrl(item.title);
|
||||
img.src = resultThumbnailUrl(item);
|
||||
if (img.complete && img.naturalWidth > 0) {
|
||||
tile.classList.add("has-image");
|
||||
}
|
||||
@@ -601,6 +595,11 @@ INDEX_HTML = r"""<!doctype html>
|
||||
if (img.naturalWidth > 0) tile.classList.add("has-image");
|
||||
});
|
||||
img.addEventListener("error", () => {
|
||||
const fallbackUrl = fallbackThumbnailUrl(item.title);
|
||||
if (img.src !== new URL(fallbackUrl, window.location.href).href) {
|
||||
img.src = fallbackUrl;
|
||||
return;
|
||||
}
|
||||
tile.classList.remove("has-image");
|
||||
});
|
||||
btn.addEventListener("click", () => selectResult(item, btn));
|
||||
@@ -615,6 +614,15 @@ INDEX_HTML = r"""<!doctype html>
|
||||
button.classList.add("active");
|
||||
state.selected = item;
|
||||
state.episodes = [];
|
||||
const preferredMode = state.config.mode === "dub" ? "dub" : "sub";
|
||||
const selectedMode = item[`has_${preferredMode}`]
|
||||
? preferredMode
|
||||
: item.has_sub
|
||||
? "sub"
|
||||
: item.has_dub
|
||||
? "dub"
|
||||
: preferredMode;
|
||||
state.config.mode = selectedMode;
|
||||
$("selectedTitle").textContent = item.title;
|
||||
$("animeNameInput").value = item.title;
|
||||
$("seasonInput").value = $("seasonInput").value || "1";
|
||||
@@ -623,13 +631,13 @@ INDEX_HTML = r"""<!doctype html>
|
||||
$("addBtn").disabled = true;
|
||||
$("trackBtn").disabled = false;
|
||||
try {
|
||||
const data = await api(`/api/anime/${encodeURIComponent(item.id)}/episodes?mode=${state.config.mode}`);
|
||||
const data = await api(`/api/anime/${encodeURIComponent(item.id)}/episodes?mode=${selectedMode}`);
|
||||
if (requestId !== state.episodeRequestId || state.selected !== item) return;
|
||||
state.episodes = data.episodes;
|
||||
const first = state.episodes[0] || "";
|
||||
const last = state.episodes[state.episodes.length - 1] || "";
|
||||
$("episodesInput").value = first && last ? `${first}-${last}` : "";
|
||||
$("selectedMeta").textContent = `${state.episodes.length} available episodes`;
|
||||
$("selectedMeta").textContent = `${state.episodes.length} ${selectedMode.toUpperCase()} episodes`;
|
||||
renderEpisodeChips();
|
||||
$("addBtn").disabled = !state.episodes.length;
|
||||
} catch (error) {
|
||||
@@ -655,7 +663,6 @@ INDEX_HTML = r"""<!doctype html>
|
||||
const requestId = ++state.searchRequestId;
|
||||
const query = $("search-query").value.trim();
|
||||
if (!query) return setNotice("Type a title first.");
|
||||
setMode($("search-mode").value);
|
||||
setNotice("Searching...");
|
||||
$("resultsMeta").textContent = "Searching...";
|
||||
state.selected = null;
|
||||
@@ -726,14 +733,13 @@ INDEX_HTML = r"""<!doctype html>
|
||||
state.config = await api("/api/config");
|
||||
$("jobFolder").value = state.config.download_dir;
|
||||
$("search-quality").value = state.config.quality;
|
||||
setMode(state.config.mode);
|
||||
state.config.mode = state.config.mode === "dub" ? "dub" : "sub";
|
||||
}
|
||||
|
||||
$("searchBtn").addEventListener("click", search);
|
||||
$("search-query").addEventListener("keydown", (event) => {
|
||||
if (event.key === "Enter") search();
|
||||
});
|
||||
$("search-mode").addEventListener("change", (event) => setMode(event.target.value));
|
||||
$("trackBtn").addEventListener("click", addSelectedToWatchlist);
|
||||
$("addBtn").addEventListener("click", addSelected);
|
||||
$("search-quality").addEventListener("change", () => { state.config.quality = $("search-quality").value; });
|
||||
|
||||
Reference in New Issue
Block a user