get episode rating for pause overlay

This commit is contained in:
Pas 2026-02-25 11:42:59 -07:00
parent 2811c4b3e6
commit a467dbbe05
2 changed files with 49 additions and 5 deletions

View file

@ -13,6 +13,7 @@ import {
ExternalIdMovieSearchResult, ExternalIdMovieSearchResult,
TMDBContentTypes, TMDBContentTypes,
TMDBCredits, TMDBCredits,
TMDBEpisode,
TMDBEpisodeShort, TMDBEpisodeShort,
TMDBMediaResult, TMDBMediaResult,
TMDBMovieData, TMDBMovieData,
@ -357,6 +358,24 @@ type MediaDetailReturn<T extends TMDBContentTypes> =
? TMDBShowData ? TMDBShowData
: never; : never;
export async function getEpisodeDetails(
showId: string,
seasonNumber: number,
episodeNumber: number,
): Promise<{ vote_average: number } | null> {
try {
const data = await get<TMDBEpisode>(
`/tv/${showId}/season/${seasonNumber}/episode/${episodeNumber}`,
);
return {
vote_average:
typeof data.vote_average === "number" ? data.vote_average : 0,
};
} catch {
return null;
}
}
export async function getSeasonDetails( export async function getSeasonDetails(
id: string, id: string,
season: number, season: number,

View file

@ -1,7 +1,11 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useIdle } from "react-use"; import { useIdle } from "react-use";
import { getMediaDetails, getMediaLogo } from "@/backend/metadata/tmdb"; import {
getEpisodeDetails,
getMediaDetails,
getMediaLogo,
} from "@/backend/metadata/tmdb";
import { TMDBContentTypes } from "@/backend/metadata/types/tmdb"; import { TMDBContentTypes } from "@/backend/metadata/types/tmdb";
import { useShouldShowControls } from "@/components/player/hooks/useShouldShowControls"; import { useShouldShowControls } from "@/components/player/hooks/useShouldShowControls";
import { useIsMobile } from "@/hooks/useIsMobile"; import { useIsMobile } from "@/hooks/useIsMobile";
@ -67,14 +71,35 @@ export function PauseOverlay() {
try { try {
const type = const type =
meta.type === "movie" ? TMDBContentTypes.MOVIE : TMDBContentTypes.TV; meta.type === "movie" ? TMDBContentTypes.MOVIE : TMDBContentTypes.TV;
// For shows with episode, fetch episode-specific rating
const isShowWithEpisode =
meta.type === "show" && meta.season && meta.episode;
let voteAverage: number | null = null;
if (isShowWithEpisode) {
const episodeData = await getEpisodeDetails(
meta.tmdbId,
meta.season?.number ?? 0,
meta.episode?.number ?? 0,
);
if (mounted && episodeData?.vote_average != null) {
voteAverage = episodeData.vote_average;
}
}
const data = await getMediaDetails(meta.tmdbId, type, false); const data = await getMediaDetails(meta.tmdbId, type, false);
if (mounted && data) { if (mounted && data) {
const voteAverage =
typeof data.vote_average === "number" ? data.vote_average : null;
const genres = (data.genres ?? []).map( const genres = (data.genres ?? []).map(
(g: { name: string }) => g.name, (g: { name: string }) => g.name,
); );
setDetails({ voteAverage, genres }); // Use episode rating for shows (never fall back to show rating)
const finalVoteAverage = isShowWithEpisode
? voteAverage
: typeof data.vote_average === "number"
? data.vote_average
: null;
setDetails({ voteAverage: finalVoteAverage, genres });
} }
} catch { } catch {
if (mounted) setDetails({ voteAverage: null, genres: [] }); if (mounted) setDetails({ voteAverage: null, genres: [] });
@ -85,7 +110,7 @@ export function PauseOverlay() {
return () => { return () => {
mounted = false; mounted = false;
}; };
}, [meta?.tmdbId, meta?.type]); }, [meta?.tmdbId, meta?.type, meta?.season, meta?.episode]);
if (!meta) return null; if (!meta) return null;