From 8a672c1dcf19c70724cfa78c8dc01232e35bf261 Mon Sep 17 00:00:00 2001 From: Miguel Palhas Date: Mon, 24 Aug 2026 14:42:29 +0100 Subject: [PATCH] feat(web): tv deck sweeps on open when empty Drop the standalone search button from season and episode rows; the deck is the one control. An empty deck fires a targeted sweep on open and reports progress in place; a deck with results never sweeps on open. re-search inside the deck forces a fresh sweep. --- web/index.html | 2 +- web/src/main.ts | 67 ++++++++++++++----------------------------------- 2 files changed, 20 insertions(+), 49 deletions(-) diff --git a/web/index.html b/web/index.html index 2c437a5..8891f4c 100644 --- a/web/index.html +++ b/web/index.html @@ -431,7 +431,7 @@

—

- +
diff --git a/web/src/main.ts b/web/src/main.ts index aaabfa5..38bc21b 100644 --- a/web/src/main.ts +++ b/web/src/main.ts @@ -2834,7 +2834,7 @@ function tvReleasesMain(): TvReleasesView { }, }; - async function load() { + async function load(sweepIfEmpty = false) { const current = request; if (!current) { return; @@ -2853,7 +2853,12 @@ function tvReleasesMain(): TvReleasesView { return; } if (!paintBuckets(dom, outcome.releases, actions)) { - setStatus("no releases indexed yet — search indexers queues a targeted sweep"); + // issue 167: an empty deck sweeps on open instead of describing a sweep + if (sweepIfEmpty) { + startSweep(current); + } else { + setStatus("no releases indexed yet — re-search queues a targeted sweep"); + } return; } setStatus(null); @@ -2898,11 +2903,8 @@ function tvReleasesMain(): TvReleasesView { }, TV_SWEEP_POLL_MS); } - sweep.addEventListener("click", () => { - const current = request; - if (!current) { - return; - } + /** Queue a targeted sweep, then watch for its releases to land (§6.2). */ + function startSweep(current: TvDeckRequest) { sweep.disabled = true; void (async () => { const outcome = await current.target.search(); @@ -2918,6 +2920,14 @@ function tvReleasesMain(): TvReleasesView { window.clearTimeout(pollTimer); watchSweep(current, sequence); })(); + } + + sweep.addEventListener("click", () => { + const current = request; + if (!current) { + return; + } + startSweep(current); }); function open(next: TvDeckRequest) { @@ -2929,7 +2939,7 @@ function tvReleasesMain(): TvReleasesView { clearBuckets(dom); sweep.disabled = false; back.focus(); - void load(); + void load(true); } function hide() { @@ -3217,27 +3227,6 @@ function seriesMain(board: HTMLElement, tvDeck: TvReleasesView, views: HideableV const space = document.createElement("span"); space.className = "season-space"; - const searchBtn = document.createElement("button"); - searchBtn.type = "button"; - searchBtn.className = "control"; - searchBtn.textContent = "search"; - searchBtn.addEventListener("click", () => { - const currentId = seriesId; - if (currentId === null) { - return; - } - searchBtn.disabled = true; - void (async () => { - const outcome = await seasonTarget(currentId, season.number).search(); - searchBtn.disabled = false; - if (outcome.kind === "error") { - setStatus(`search failed — ${outcome.detail}`, "fault"); - return; - } - setStatus(`season ${PAD_TWO(season.number)} sweep queued — results land in its deck`); - })(); - }); - const deckBtn = document.createElement("button"); deckBtn.type = "button"; deckBtn.className = "control"; @@ -3270,7 +3259,7 @@ function seriesMain(board: HTMLElement, tvDeck: TvReleasesView, views: HideableV }), ); } - line.append(space, searchBtn, deckBtn); + line.append(space, deckBtn); item.append(line); const episodes = document.createElement("ul"); @@ -3360,24 +3349,6 @@ function seriesMain(board: HTMLElement, tvDeck: TvReleasesView, views: HideableV }); actions.append(want); - const searchBtn = document.createElement("button"); - searchBtn.type = "button"; - searchBtn.className = "control"; - searchBtn.textContent = "search"; - searchBtn.addEventListener("click", () => { - searchBtn.disabled = true; - void (async () => { - const outcome = await episodeTarget(episode.id).search(); - searchBtn.disabled = false; - if (outcome.kind === "error") { - setStatus(`search failed — ${outcome.detail}`, "fault"); - return; - } - setStatus(`S${PAD_TWO(seasonNumber)}E${PAD_TWO(episode.number)} sweep queued`); - })(); - }); - actions.append(searchBtn); - const deckBtn = document.createElement("button"); deckBtn.type = "button"; deckBtn.className = "control";