feat(web): route season and episode release decks

This commit is contained in:
Miguel Palhas
2026-08-23 20:44:28 +01:00
parent 06a68372e6
commit cf36a4302c
3 changed files with 101 additions and 2 deletions
+59 -1
View File
@@ -63,6 +63,7 @@ import {
type ApiSeries,
type EpisodeFile,
episodeTarget,
fetchEpisode,
fetchSeasons,
fetchSeries,
fetchSeriesFiles,
@@ -305,7 +306,7 @@ function main() {
// the surface underneath must be live before the detail view covers
// it, so back and Esc land somewhere real (same as a movie deep link)
library.open();
seriesDetail.open(
await seriesDetail.open(
route.seriesId,
must<HTMLElement>("#nav-library"),
must<HTMLElement>("#library"),
@@ -315,6 +316,61 @@ function main() {
);
break;
}
case "seasonReleases":
case "episodeReleases": {
// both deck routes live over the series detail view, exactly as a
// click on a deck button does; resolve what that click would have
let title: string;
let sub: string;
let seriesId: number;
let target: TvTarget;
if (route.kind === "seasonReleases") {
seriesId = route.seriesId;
target = seasonTarget(route.seriesId, route.seasonNumber);
sub = `season ${PAD_TWO(route.seasonNumber)} · packs`;
title = (await fetchSeries(route.seriesId))?.title ?? "";
if (title === "") {
navigate({ kind: "library" }, { replace: true });
library.open();
return;
}
} else {
const episode = await fetchEpisode(route.episodeId);
if (!episode) {
navigate({ kind: "library" }, { replace: true });
library.open();
return;
}
seriesId = episode.series_id;
target = episodeTarget(episode.id);
sub = `S${PAD_TWO(episode.season_number)}E${PAD_TWO(episode.number)} · ${episode.title}`;
title = (await fetchSeries(seriesId))?.title ?? "";
if (title === "") {
navigate({ kind: "library" }, { replace: true });
library.open();
return;
}
}
library.open();
await seriesDetail.open(
seriesId,
must<HTMLElement>("#nav-library"),
must<HTMLElement>("#library"),
{ kind: "library" },
);
// no origin click to restore focus to on a deep link — the series
// view's back control is the closest stand-in
tvDeck.open({
title,
sub,
seriesId,
target,
origin: must<HTMLButtonElement>("#series-back"),
returnTo: must<HTMLElement>("#series"),
parentRoute: { kind: "series", seriesId },
});
break;
}
}
}
@@ -2327,6 +2383,7 @@ function seriesMain(board: HTMLElement, tvDeck: TvReleasesView, views: HideableV
if (currentId === null) {
return;
}
navigate({ kind: "seasonReleases", seriesId: currentId, seasonNumber: season.number });
tvDeck.open({
title: currentTitle,
sub: `season ${PAD_TWO(season.number)} · packs`,
@@ -2470,6 +2527,7 @@ function seriesMain(board: HTMLElement, tvDeck: TvReleasesView, views: HideableV
if (currentId === null) {
return;
}
navigate({ kind: "episodeReleases", episodeId: episode.id });
tvDeck.open({
title: currentTitle,
sub: `S${PAD_TWO(seasonNumber)}E${PAD_TWO(episode.number)} · ${episode.title}`,