aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/src')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/video-app.js36
1 files changed, 26 insertions, 10 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/video-app.js b/packages/meshbay-hub/src/meshbay_hub/static/video-app.js
index 2fa22d0..19b0f0f 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/video-app.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/video-app.js
@@ -73,6 +73,28 @@ function buildSeasons(episodes) {
.map(([season, seasonEpisodes]) => ({ season, episodes: seasonEpisodes }));
}
+// The season a show's detail modal opens on.
+//
+// Deliberately not the representative episode's. `repEntry` is picked for its
+// *thumbnail* — `episodes.find((e) => e.thumb_hash)` in the poster grid, so
+// the card has a fallback frame when TMDB has no poster — which makes its
+// season an accident of which files the node has managed to thumbnail so far.
+// Found live on a show whose early seasons had none: the modal opened on
+// season 6. The two uses of "representative" were never the same thing, and
+// only one of them is about what the reader is looking at.
+//
+// Specials first is not what anyone means by the beginning of a show, so
+// season 0 wins only when it is all there is.
+function defaultSeason(show) {
+ if (!show || !show.seasons.length) return null;
+ // The lowest number rather than the first entry: `buildSeasons` does sort
+ // ascending, but reading the answer off that ordering makes this quietly
+ // depend on a caller keeping it, and there is nothing to gain by that.
+ const numbers = show.seasons.map((s) => s.season);
+ const real = numbers.filter((n) => n !== 0);
+ return Math.min(...(real.length ? real : numbers));
+}
+
function groupVideoEntries(entries, videoRoot) {
const movies = [];
const showsByTitle = new Map();
@@ -686,17 +708,11 @@ function VideoDetailModal({
setRematching(false);
}, [rematching, repEntry, transportRef]);
- // Reset whenever a different file/show is opened in this same modal
- // instance — repEntry/show change identity, selectedSeason must not
- // silently keep pointing at whatever the previous show's season 4 was.
+ // Reset whenever a different show is opened in this same modal instance —
+ // `show` changes identity, and selectedSeason must not silently keep
+ // pointing at whatever the previous show's season 4 was.
const [selectedSeason, setSelectedSeason] = useState(null);
- useEffect(() => {
- if (!show) { setSelectedSeason(null); return; }
- const preferred = repEntry.season != null && show.seasons.some((s) => s.season === repEntry.season)
- ? repEntry.season
- : (show.seasons.find((s) => s.season !== 0) || show.seasons[0]).season;
- setSelectedSeason(preferred);
- }, [show, repEntry]);
+ useEffect(() => { setSelectedSeason(defaultSeason(show)); }, [show]);
const showMultiSeason = Boolean(show && show.seasons.length > 1);
const seasonMeta = useSeasonMeta(