Open auto-download settings in modal overlay
This commit is contained in:
@@ -1,5 +1,9 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.40.1 - 2026-05-25
|
||||||
|
|
||||||
|
- Replaced the per-card auto-download expansion with a centered overlay dialog so opening settings no longer shifts the watchlist grid layout.
|
||||||
|
|
||||||
## 0.40.0 - 2026-05-25
|
## 0.40.0 - 2026-05-25
|
||||||
|
|
||||||
- Added per-watchlist storage for downloaded sub and dub episode lists so auto-download can compare actual downloaded history instead of only refresh count deltas.
|
- Added per-watchlist storage for downloaded sub and dub episode lists so auto-download can compare actual downloaded history instead of only refresh count deltas.
|
||||||
|
|||||||
@@ -224,7 +224,7 @@ Main behavior:
|
|||||||
7. Summary cards show total tracked shows plus `sub` and `dub` counts.
|
7. Summary cards show total tracked shows plus `sub` and `dub` counts.
|
||||||
8. Pagination shows 30 cards per page.
|
8. Pagination shows 30 cards per page.
|
||||||
9. `Alternative titles` expands English alternate titles from AniDB when the watchlist refresh can match the show to an AniDB entry.
|
9. `Alternative titles` expands English alternate titles from AniDB when the watchlist refresh can match the show to an AniDB entry.
|
||||||
10. `Auto-download` opens per-series settings for language, quality, series number, and the sanitized library name used for automatically queued episodes.
|
10. `Auto-download` opens a centered overlay with per-series settings for language, quality, series number, and the sanitized library name used for automatically queued episodes.
|
||||||
|
|
||||||
Status behavior:
|
Status behavior:
|
||||||
|
|
||||||
|
|||||||
+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.40.0"
|
VERSION = "0.40.1"
|
||||||
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"
|
||||||
|
|||||||
@@ -1986,7 +1986,10 @@ class TemplateHelperTests(unittest.TestCase):
|
|||||||
|
|
||||||
def test_watchlist_page_renders_auto_download_editor(self):
|
def test_watchlist_page_renders_auto_download_editor(self):
|
||||||
self.assertIn("Auto-download", APP.WATCHLIST_HTML)
|
self.assertIn("Auto-download", APP.WATCHLIST_HTML)
|
||||||
|
self.assertIn('id="autoDownloadOverlay"', APP.WATCHLIST_HTML)
|
||||||
self.assertIn('api("/api/watchlist/update-auto-download"', APP.WATCHLIST_HTML)
|
self.assertIn('api("/api/watchlist/update-auto-download"', APP.WATCHLIST_HTML)
|
||||||
|
self.assertIn("openAutoDownloadOverlay(item)", APP.WATCHLIST_HTML)
|
||||||
|
self.assertIn("closeAutoDownloadOverlay()", APP.WATCHLIST_HTML)
|
||||||
self.assertIn("Save auto-download", APP.WATCHLIST_HTML)
|
self.assertIn("Save auto-download", APP.WATCHLIST_HTML)
|
||||||
self.assertIn("Manual add does not trigger it", APP.WATCHLIST_HTML)
|
self.assertIn("Manual add does not trigger it", APP.WATCHLIST_HTML)
|
||||||
self.assertIn("Name source", APP.WATCHLIST_HTML)
|
self.assertIn("Name source", APP.WATCHLIST_HTML)
|
||||||
|
|||||||
+184
-100
@@ -551,35 +551,63 @@ WATCHLIST_HTML = r"""<!doctype html>
|
|||||||
display: grid;
|
display: grid;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
}
|
}
|
||||||
.auto-download-panel {
|
.overlay[hidden] {
|
||||||
display: none;
|
display: none;
|
||||||
grid-column: 1 / -1;
|
|
||||||
gap: 10px;
|
|
||||||
border: 1px solid var(--line);
|
|
||||||
border-radius: 16px;
|
|
||||||
background: rgba(255, 255, 255, 0.04);
|
|
||||||
padding: 12px;
|
|
||||||
}
|
}
|
||||||
.auto-download-panel.visible {
|
.overlay {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
display: grid;
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
padding: 24px;
|
||||||
|
background: rgba(7, 10, 16, 0.74);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
z-index: 1200;
|
||||||
|
}
|
||||||
|
.auto-download-modal {
|
||||||
|
width: min(640px, 100%);
|
||||||
|
display: grid;
|
||||||
|
gap: 14px;
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
border-radius: 22px;
|
||||||
|
background: linear-gradient(180deg, rgba(20, 27, 40, 0.98), rgba(12, 17, 28, 0.98));
|
||||||
|
box-shadow: 0 24px 70px rgba(0, 0, 0, 0.45);
|
||||||
|
padding: 18px;
|
||||||
|
}
|
||||||
|
.auto-download-modal-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
.auto-download-modal-header p {
|
||||||
|
margin: 4px 0 0;
|
||||||
|
}
|
||||||
|
.auto-download-modal-close {
|
||||||
|
min-width: 36px;
|
||||||
|
min-height: 36px;
|
||||||
|
border-radius: 999px;
|
||||||
|
font-size: 18px;
|
||||||
|
line-height: 1;
|
||||||
}
|
}
|
||||||
.auto-download-grid {
|
.auto-download-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
.auto-download-panel label {
|
.auto-download-modal label {
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
}
|
}
|
||||||
.auto-download-panel input,
|
.auto-download-modal input,
|
||||||
.auto-download-panel select {
|
.auto-download-modal select {
|
||||||
min-height: 36px;
|
min-height: 36px;
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
.auto-download-actions {
|
.auto-download-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
@@ -736,6 +764,47 @@ WATCHLIST_HTML = r"""<!doctype html>
|
|||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="overlay" id="autoDownloadOverlay" hidden>
|
||||||
|
<div class="auto-download-modal" role="dialog" aria-modal="true" aria-labelledby="autoDownloadTitle">
|
||||||
|
<div class="auto-download-modal-header">
|
||||||
|
<div>
|
||||||
|
<h2 id="autoDownloadTitle">Auto-download</h2>
|
||||||
|
<p class="muted" id="autoDownloadSubtitle">Used only while this anime is in the Watching tab. Manual add does not trigger it; later refreshes do.</p>
|
||||||
|
</div>
|
||||||
|
<button class="ghost auto-download-modal-close" id="autoDownloadCloseBtn" type="button" aria-label="Close auto-download settings">×</button>
|
||||||
|
</div>
|
||||||
|
<div class="auto-download-grid">
|
||||||
|
<label>Language
|
||||||
|
<select class="auto-download-mode" id="autoDownloadMode">
|
||||||
|
<option value="dub">Dub</option>
|
||||||
|
<option value="sub">Sub</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
<label>Quality
|
||||||
|
<select class="auto-download-quality" id="autoDownloadQuality">
|
||||||
|
<option value="best">Best</option>
|
||||||
|
<option value="1080">1080p</option>
|
||||||
|
<option value="720">720p</option>
|
||||||
|
<option value="480">480p</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
<label>Series
|
||||||
|
<input class="auto-download-series" id="autoDownloadSeries" type="number" min="1" step="1" value="1">
|
||||||
|
</label>
|
||||||
|
<label>Name source
|
||||||
|
<select class="auto-download-name-select" id="autoDownloadNameSelect"></select>
|
||||||
|
</label>
|
||||||
|
<label>Name
|
||||||
|
<input class="auto-download-name" id="autoDownloadName" type="text">
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="auto-download-actions">
|
||||||
|
<div class="muted" id="autoDownloadStatus">Manual add does not trigger it; later refreshes do.</div>
|
||||||
|
<button class="ghost auto-download-save" id="autoDownloadSaveBtn" type="button">Save auto-download</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const state = {
|
const state = {
|
||||||
watchlistPage: 1,
|
watchlistPage: 1,
|
||||||
@@ -749,7 +818,8 @@ WATCHLIST_HTML = r"""<!doctype html>
|
|||||||
thumbnailWarmupPending: new Set(),
|
thumbnailWarmupPending: new Set(),
|
||||||
refreshRunning: false,
|
refreshRunning: false,
|
||||||
refreshJobId: null,
|
refreshJobId: null,
|
||||||
watchlistRequestId: 0
|
watchlistRequestId: 0,
|
||||||
|
autoDownloadDraft: null
|
||||||
};
|
};
|
||||||
const categoryLabels = {
|
const categoryLabels = {
|
||||||
watching: "Watching",
|
watching: "Watching",
|
||||||
@@ -757,6 +827,16 @@ WATCHLIST_HTML = r"""<!doctype html>
|
|||||||
finished: "Finished",
|
finished: "Finished",
|
||||||
dropped: "Dropped"
|
dropped: "Dropped"
|
||||||
};
|
};
|
||||||
|
const autoDownloadOverlay = document.getElementById("autoDownloadOverlay");
|
||||||
|
const autoDownloadCloseBtn = document.getElementById("autoDownloadCloseBtn");
|
||||||
|
const autoDownloadSubtitle = document.getElementById("autoDownloadSubtitle");
|
||||||
|
const autoDownloadStatus = document.getElementById("autoDownloadStatus");
|
||||||
|
const autoDownloadMode = document.getElementById("autoDownloadMode");
|
||||||
|
const autoDownloadQuality = document.getElementById("autoDownloadQuality");
|
||||||
|
const autoDownloadSeries = document.getElementById("autoDownloadSeries");
|
||||||
|
const autoDownloadNameSelect = document.getElementById("autoDownloadNameSelect");
|
||||||
|
const autoDownloadName = document.getElementById("autoDownloadName");
|
||||||
|
const autoDownloadSaveBtn = document.getElementById("autoDownloadSaveBtn");
|
||||||
|
|
||||||
const $ = (id) => document.getElementById(id);
|
const $ = (id) => document.getElementById(id);
|
||||||
""" + BROWSER_API_HELPER + BROWSER_POLL_HELPER + r"""
|
""" + BROWSER_API_HELPER + BROWSER_POLL_HELPER + r"""
|
||||||
@@ -876,6 +956,96 @@ WATCHLIST_HTML = r"""<!doctype html>
|
|||||||
controls.append(prev, next);
|
controls.append(prev, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function closeAutoDownloadOverlay() {
|
||||||
|
state.autoDownloadDraft = null;
|
||||||
|
autoDownloadOverlay.hidden = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function populateAutoDownloadNameChoices(item) {
|
||||||
|
const selectedName = item.auto_download_name || "";
|
||||||
|
const nameSuggestions = [];
|
||||||
|
for (const name of [item.title, ...(Array.isArray(item.alternative_titles) ? item.alternative_titles.map((entry) => entry.value) : [])]) {
|
||||||
|
if (name && !nameSuggestions.includes(name)) nameSuggestions.push(name);
|
||||||
|
}
|
||||||
|
autoDownloadNameSelect.innerHTML = "";
|
||||||
|
for (const name of nameSuggestions) {
|
||||||
|
const option = document.createElement("option");
|
||||||
|
option.value = name;
|
||||||
|
option.textContent = name;
|
||||||
|
autoDownloadNameSelect.appendChild(option);
|
||||||
|
}
|
||||||
|
const customOption = document.createElement("option");
|
||||||
|
customOption.value = "__custom__";
|
||||||
|
customOption.textContent = "Custom";
|
||||||
|
autoDownloadNameSelect.appendChild(customOption);
|
||||||
|
const matchedSuggestion = nameSuggestions.find((name) => name === selectedName);
|
||||||
|
autoDownloadNameSelect.value = matchedSuggestion || "__custom__";
|
||||||
|
autoDownloadName.value = selectedName;
|
||||||
|
}
|
||||||
|
|
||||||
|
function openAutoDownloadOverlay(item) {
|
||||||
|
state.autoDownloadDraft = { ...item };
|
||||||
|
autoDownloadSubtitle.textContent = `${item.title} · Used only while this anime is in the Watching tab. Manual add does not trigger it; later refreshes do.`;
|
||||||
|
autoDownloadStatus.textContent = "Manual add does not trigger it; later refreshes do.";
|
||||||
|
autoDownloadMode.value = item.auto_download_mode || "dub";
|
||||||
|
autoDownloadQuality.value = item.auto_download_quality || "best";
|
||||||
|
autoDownloadSeries.value = item.auto_download_series || "1";
|
||||||
|
populateAutoDownloadNameChoices(item);
|
||||||
|
autoDownloadOverlay.hidden = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
autoDownloadNameSelect.addEventListener("change", () => {
|
||||||
|
if (autoDownloadNameSelect.value !== "__custom__") {
|
||||||
|
autoDownloadName.value = autoDownloadNameSelect.value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
autoDownloadCloseBtn.addEventListener("click", closeAutoDownloadOverlay);
|
||||||
|
autoDownloadOverlay.addEventListener("click", (event) => {
|
||||||
|
if (event.target === autoDownloadOverlay) {
|
||||||
|
closeAutoDownloadOverlay();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
window.addEventListener("keydown", (event) => {
|
||||||
|
if (event.key === "Escape" && !autoDownloadOverlay.hidden) {
|
||||||
|
closeAutoDownloadOverlay();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
autoDownloadSaveBtn.addEventListener("click", async () => {
|
||||||
|
if (!state.autoDownloadDraft) return;
|
||||||
|
autoDownloadSaveBtn.disabled = true;
|
||||||
|
try {
|
||||||
|
const data = await api("/api/watchlist/update-auto-download", {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify({
|
||||||
|
show_id: state.autoDownloadDraft.show_id,
|
||||||
|
mode: autoDownloadMode.value,
|
||||||
|
quality: autoDownloadQuality.value,
|
||||||
|
name: autoDownloadName.value,
|
||||||
|
series: autoDownloadSeries.value
|
||||||
|
})
|
||||||
|
});
|
||||||
|
const savedItem = data.item || {};
|
||||||
|
state.autoDownloadDraft = {
|
||||||
|
...state.autoDownloadDraft,
|
||||||
|
auto_download_mode: savedItem.auto_download_mode || autoDownloadMode.value,
|
||||||
|
auto_download_quality: savedItem.auto_download_quality || autoDownloadQuality.value,
|
||||||
|
auto_download_name: savedItem.auto_download_name || autoDownloadName.value,
|
||||||
|
auto_download_series: savedItem.auto_download_series || autoDownloadSeries.value
|
||||||
|
};
|
||||||
|
populateAutoDownloadNameChoices(state.autoDownloadDraft);
|
||||||
|
autoDownloadSeries.value = state.autoDownloadDraft.auto_download_series || autoDownloadSeries.value;
|
||||||
|
autoDownloadStatus.textContent = data.message || "Auto-download settings saved.";
|
||||||
|
setNotice(data.message || "Auto-download settings saved.");
|
||||||
|
closeAutoDownloadOverlay();
|
||||||
|
await fetchWatchlist(state.watchlistPage, { silent: true });
|
||||||
|
} catch (error) {
|
||||||
|
autoDownloadStatus.textContent = error.message;
|
||||||
|
setNotice(error.message);
|
||||||
|
} finally {
|
||||||
|
autoDownloadSaveBtn.disabled = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
function applyThumbnail(card, item, force = false) {
|
function applyThumbnail(card, item, force = false) {
|
||||||
const tile = card.querySelector(".cover-tile");
|
const tile = card.querySelector(".cover-tile");
|
||||||
const img = card.querySelector("img");
|
const img = card.querySelector("img");
|
||||||
@@ -1064,12 +1234,6 @@ WATCHLIST_HTML = r"""<!doctype html>
|
|||||||
renderPager();
|
renderPager();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const qualityOptions = `
|
|
||||||
<option value="best">Best</option>
|
|
||||||
<option value="1080">1080p</option>
|
|
||||||
<option value="720">720p</option>
|
|
||||||
<option value="480">480p</option>
|
|
||||||
`;
|
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
const card = document.createElement("article");
|
const card = document.createElement("article");
|
||||||
const checked = item.last_checked ? new Date(item.last_checked).toLocaleString() : "Never";
|
const checked = item.last_checked ? new Date(item.last_checked).toLocaleString() : "Never";
|
||||||
@@ -1115,32 +1279,6 @@ WATCHLIST_HTML = r"""<!doctype html>
|
|||||||
<button class="ghost" type="button">Sub</button>
|
<button class="ghost" type="button">Sub</button>
|
||||||
<button class="ghost" type="button">Dub</button>
|
<button class="ghost" type="button">Dub</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="auto-download-panel">
|
|
||||||
<div class="muted">Used only while this anime is in the Watching tab. Manual add does not trigger it; later refreshes do.</div>
|
|
||||||
<div class="auto-download-grid">
|
|
||||||
<label>Language
|
|
||||||
<select class="auto-download-mode">
|
|
||||||
<option value="dub"${item.auto_download_mode === "dub" ? " selected" : ""}>Dub</option>
|
|
||||||
<option value="sub"${item.auto_download_mode === "sub" ? " selected" : ""}>Sub</option>
|
|
||||||
</select>
|
|
||||||
</label>
|
|
||||||
<label>Quality
|
|
||||||
<select class="auto-download-quality">${qualityOptions.replace(`value="${item.auto_download_quality}"`, `value="${item.auto_download_quality}" selected`)}</select>
|
|
||||||
</label>
|
|
||||||
<label>Series
|
|
||||||
<input class="auto-download-series" type="number" min="1" step="1" value="${item.auto_download_series || "1"}">
|
|
||||||
</label>
|
|
||||||
<label>Name source
|
|
||||||
<select class="auto-download-name-select"></select>
|
|
||||||
</label>
|
|
||||||
<label>Name
|
|
||||||
<input class="auto-download-name" type="text">
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="auto-download-actions">
|
|
||||||
<button class="ghost auto-download-save" type="button">Save auto-download</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
card.querySelector(".cover-fallback").textContent = coverInitials(item.title);
|
card.querySelector(".cover-fallback").textContent = coverInitials(item.title);
|
||||||
@@ -1213,35 +1351,6 @@ WATCHLIST_HTML = r"""<!doctype html>
|
|||||||
const subBtn = actionButtons[4];
|
const subBtn = actionButtons[4];
|
||||||
const dubBtn = actionButtons[5];
|
const dubBtn = actionButtons[5];
|
||||||
const downloadPicker = card.querySelector(".download-picker");
|
const downloadPicker = card.querySelector(".download-picker");
|
||||||
const autoDownloadPanel = card.querySelector(".auto-download-panel");
|
|
||||||
const autoDownloadMode = card.querySelector(".auto-download-mode");
|
|
||||||
const autoDownloadQuality = card.querySelector(".auto-download-quality");
|
|
||||||
const autoDownloadSeries = card.querySelector(".auto-download-series");
|
|
||||||
const autoDownloadNameSelect = card.querySelector(".auto-download-name-select");
|
|
||||||
const autoDownloadName = card.querySelector(".auto-download-name");
|
|
||||||
const autoDownloadSave = card.querySelector(".auto-download-save");
|
|
||||||
autoDownloadName.value = item.auto_download_name || "";
|
|
||||||
const nameSuggestions = [];
|
|
||||||
for (const name of [item.title, ...(Array.isArray(item.alternative_titles) ? item.alternative_titles.map((entry) => entry.value) : [])]) {
|
|
||||||
if (name && !nameSuggestions.includes(name)) nameSuggestions.push(name);
|
|
||||||
}
|
|
||||||
for (const name of nameSuggestions) {
|
|
||||||
const option = document.createElement("option");
|
|
||||||
option.value = name;
|
|
||||||
option.textContent = name;
|
|
||||||
autoDownloadNameSelect.appendChild(option);
|
|
||||||
}
|
|
||||||
const customOption = document.createElement("option");
|
|
||||||
customOption.value = "__custom__";
|
|
||||||
customOption.textContent = "Custom";
|
|
||||||
autoDownloadNameSelect.appendChild(customOption);
|
|
||||||
const matchedSuggestion = nameSuggestions.find((name) => name === (item.auto_download_name || ""));
|
|
||||||
autoDownloadNameSelect.value = matchedSuggestion || "__custom__";
|
|
||||||
autoDownloadNameSelect.addEventListener("change", () => {
|
|
||||||
if (autoDownloadNameSelect.value !== "__custom__") {
|
|
||||||
autoDownloadName.value = autoDownloadNameSelect.value;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const categorySelect = card.querySelector(".category-select");
|
const categorySelect = card.querySelector(".category-select");
|
||||||
categorySelect.addEventListener("change", async () => {
|
categorySelect.addEventListener("change", async () => {
|
||||||
categorySelect.disabled = true;
|
categorySelect.disabled = true;
|
||||||
@@ -1265,32 +1374,7 @@ WATCHLIST_HTML = r"""<!doctype html>
|
|||||||
downloadBtn.textContent = visible ? "Cancel download" : "Download all";
|
downloadBtn.textContent = visible ? "Cancel download" : "Download all";
|
||||||
});
|
});
|
||||||
autoDownloadBtn.addEventListener("click", () => {
|
autoDownloadBtn.addEventListener("click", () => {
|
||||||
const visible = autoDownloadPanel.classList.toggle("visible");
|
openAutoDownloadOverlay(item);
|
||||||
autoDownloadBtn.textContent = visible ? "Hide auto-download" : "Auto-download";
|
|
||||||
});
|
|
||||||
autoDownloadSave.addEventListener("click", async () => {
|
|
||||||
autoDownloadSave.disabled = true;
|
|
||||||
try {
|
|
||||||
const data = await api("/api/watchlist/update-auto-download", {
|
|
||||||
method: "POST",
|
|
||||||
body: JSON.stringify({
|
|
||||||
show_id: item.show_id,
|
|
||||||
mode: autoDownloadMode.value,
|
|
||||||
quality: autoDownloadQuality.value,
|
|
||||||
name: autoDownloadName.value,
|
|
||||||
series: autoDownloadSeries.value
|
|
||||||
})
|
|
||||||
});
|
|
||||||
autoDownloadName.value = (data.item || {}).auto_download_name || autoDownloadName.value;
|
|
||||||
autoDownloadSeries.value = (data.item || {}).auto_download_series || autoDownloadSeries.value;
|
|
||||||
const savedName = (data.item || {}).auto_download_name || "";
|
|
||||||
autoDownloadNameSelect.value = nameSuggestions.includes(savedName) ? savedName : "__custom__";
|
|
||||||
setNotice(data.message || "Auto-download settings saved.");
|
|
||||||
} catch (error) {
|
|
||||||
setNotice(error.message);
|
|
||||||
} finally {
|
|
||||||
autoDownloadSave.disabled = false;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
subBtn.addEventListener("click", () => downloadWatchlistItem(item, "sub", downloadPicker, downloadBtn));
|
subBtn.addEventListener("click", () => downloadWatchlistItem(item, "sub", downloadPicker, downloadBtn));
|
||||||
dubBtn.addEventListener("click", () => downloadWatchlistItem(item, "dub", downloadPicker, downloadBtn));
|
dubBtn.addEventListener("click", () => downloadWatchlistItem(item, "dub", downloadPicker, downloadBtn));
|
||||||
|
|||||||
Reference in New Issue
Block a user