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.
This commit is contained in:
Miguel Palhas
2026-08-24 14:42:29 +01:00
parent fb03fc3808
commit 8a672c1dcf
2 changed files with 20 additions and 49 deletions
+1 -1
View File
@@ -431,7 +431,7 @@
<h2 class="releases-title" id="tv-releases-title"></h2>
<span class="releases-year readout dim" id="tv-releases-sub"></span>
</div>
<button type="button" class="control" id="tv-releases-sweep">search indexers</button>
<button type="button" class="control" id="tv-releases-sweep">re-search</button>
</header>
<p class="deck-status readout" id="tv-releases-status" role="status" hidden></p>
<div id="tv-buckets"></div>
+19 -48
View File
@@ -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";