diff --git a/server/lib/scanners/baseScanner.ts b/server/lib/scanners/baseScanner.ts index 2547b7a1d8..db84cef0c3 100644 --- a/server/lib/scanners/baseScanner.ts +++ b/server/lib/scanners/baseScanner.ts @@ -306,7 +306,14 @@ class BaseScanner { ) ?? [] ).length; - for (const season of seasons) { + for (const rawSeason of seasons) { + // Files can't promote a season the provider reports as empty. + // Zeroing the counts leaves any existing status for availabilitySync to judge. + const season = + rawSeason.totalEpisodes > 0 + ? rawSeason + : { ...rawSeason, episodes: 0, episodes4k: 0 }; + const existingSeason = media?.seasons.find( (es) => es.seasonNumber === season.seasonNumber ); diff --git a/src/components/RequestModal/TvRequestModal.tsx b/src/components/RequestModal/TvRequestModal.tsx index 09bb289396..2906e31e74 100644 --- a/src/components/RequestModal/TvRequestModal.tsx +++ b/src/components/RequestModal/TvRequestModal.tsx @@ -418,7 +418,7 @@ const TvRequestModal = ({ : hasPermission(Permission.MANAGE_REQUESTS) ? intl.formatMessage(messages.approve) : intl.formatMessage(messages.edit) - : getAllRequestedSeasons().length >= getAllSeasons().length + : unrequestedSeasons.length === 0 ? intl.formatMessage(messages.alreadyrequested) : !settings.currentSettings.partialRequestsEnabled ? intl.formatMessage( @@ -441,7 +441,7 @@ const TvRequestModal = ({ unrequestedSeasons.length > quota.tv.limit && !requestOverrides?.ignoreQuota ? true - : getAllRequestedSeasons().length >= getAllSeasons().length || + : unrequestedSeasons.length === 0 || (settings.currentSettings.partialRequestsEnabled && selectedSeasons.length === 0) } diff --git a/src/components/TvDetails/index.tsx b/src/components/TvDetails/index.tsx index 3a905dbdf7..8050beb846 100644 --- a/src/components/TvDetails/index.tsx +++ b/src/components/TvDetails/index.tsx @@ -309,19 +309,26 @@ const TvDetails = ({ tv }: TvDetailsProps) => { return [...requestedSeasons, ...availableSeasons]; }; - const showHasSpecials = data.seasons.some( - (season) => - season.seasonNumber === 0 && - settings.currentSettings.enableSpecialEpisodes - ); + // Mirrors the season list the request modal offers, so the two agree. + const requestableSeasons = data.seasons + .filter( + (season) => + season.episodeCount !== 0 && + (settings.currentSettings.enableSpecialEpisodes || + season.seasonNumber !== 0) + ) + .map((season) => season.seasonNumber); + + const isSeasonSetComplete = (is4k: boolean) => { + const requested = getAllRequestedSeasons(is4k); + return requestableSeasons.every((seasonNumber) => + requested.includes(seasonNumber) + ); + }; - const isComplete = - (showHasSpecials ? seasonCount + 1 : seasonCount) <= - getAllRequestedSeasons(false).length; + const isComplete = isSeasonSetComplete(false); - const is4kComplete = - (showHasSpecials ? seasonCount + 1 : seasonCount) <= - getAllRequestedSeasons(true).length; + const is4kComplete = isSeasonSetComplete(true); const streamingRegion = user?.settings?.streamingRegion ? user.settings.streamingRegion