From de4e2698799c2acf4a07f67e0bcdac6001d25f52 Mon Sep 17 00:00:00 2001 From: tapframe <85391825+tapframe@users.noreply.github.com> Date: Sat, 11 Jul 2026 09:09:09 +0530 Subject: [PATCH] fix: restore unaired next up episodes --- .../watching/domain/WatchingPolicies.kt | 9 ++++- .../watching/domain/SeriesContinuityTest.kt | 20 ++++++++++ .../watching/domain/WatchingPoliciesTest.kt | 39 +++++++++++++++++++ 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/watching/domain/WatchingPolicies.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/watching/domain/WatchingPolicies.kt index 963a5f7a..49e38623 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/watching/domain/WatchingPolicies.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/watching/domain/WatchingPolicies.kt @@ -48,8 +48,15 @@ internal fun shouldSurfaceNextEpisode( showUnairedNextUp: Boolean, available: Boolean = true, ): Boolean { - if (!available) return false val isSeasonRollover = normalizeSeasonNumber(candidateSeasonNumber) != normalizeSeasonNumber(watchedSeasonNumber) + if (!available) { + val daysUntilRelease = daysUntilExplicitRelease( + todayIsoDate = todayIsoDate, + releasedDate = releasedDate, + ) ?: return false + if (!showUnairedNextUp || daysUntilRelease <= 0) return false + return !isSeasonRollover || daysUntilRelease <= UpcomingNextSeasonWindowDays + } if (!isSeasonRollover) { if (showUnairedNextUp) return true return isReleasedBy(todayIsoDate = todayIsoDate, releasedDate = releasedDate) diff --git a/composeApp/src/commonTest/kotlin/com/nuvio/app/features/watching/domain/SeriesContinuityTest.kt b/composeApp/src/commonTest/kotlin/com/nuvio/app/features/watching/domain/SeriesContinuityTest.kt index 92a3bd23..cedfcee4 100644 --- a/composeApp/src/commonTest/kotlin/com/nuvio/app/features/watching/domain/SeriesContinuityTest.kt +++ b/composeApp/src/commonTest/kotlin/com/nuvio/app/features/watching/domain/SeriesContinuityTest.kt @@ -141,6 +141,26 @@ class SeriesContinuityTest { assertNull(nextEpisode) } + @Test + fun nextReleasedEpisodeAfter_surfaces_dated_unavailable_upcoming_episode_when_enabled() { + val episodes = listOf( + WatchingReleasedEpisode(videoId = "s1e1", seasonNumber = 1, episodeNumber = 1, title = "Episode 1", releasedDate = "2026-07-01"), + WatchingReleasedEpisode(videoId = "s1e2", seasonNumber = 1, episodeNumber = 2, title = "Episode 2", releasedDate = "2026-07-12", available = false), + ) + + val nextEpisode = nextReleasedEpisodeAfter( + content = show, + episodes = episodes, + seasonNumber = 1, + episodeNumber = 1, + todayIsoDate = "2026-07-05", + showUnairedNextUp = true, + ) + + assertNotNull(nextEpisode) + assertEquals("s1e2", nextEpisode.videoId) + } + @Test fun decideSeriesPrimaryAction_falls_back_to_specials_when_no_main_season() { val specialsOnly = listOf( diff --git a/composeApp/src/commonTest/kotlin/com/nuvio/app/features/watching/domain/WatchingPoliciesTest.kt b/composeApp/src/commonTest/kotlin/com/nuvio/app/features/watching/domain/WatchingPoliciesTest.kt index 62ea8e1a..f9942e7f 100644 --- a/composeApp/src/commonTest/kotlin/com/nuvio/app/features/watching/domain/WatchingPoliciesTest.kt +++ b/composeApp/src/commonTest/kotlin/com/nuvio/app/features/watching/domain/WatchingPoliciesTest.kt @@ -2,6 +2,7 @@ package com.nuvio.app.features.watching.domain import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.assertFalse import kotlin.test.assertNotNull import kotlin.test.assertTrue @@ -49,6 +50,44 @@ class WatchingPoliciesTest { assertTrue(result) } + @Test + fun shouldSurfaceNextEpisode_allows_dated_unavailable_upcoming_episode_only_when_enabled() { + assertTrue( + shouldSurfaceNextEpisode( + watchedSeasonNumber = 1, + candidateSeasonNumber = 1, + todayIsoDate = "2026-07-05", + releasedDate = "2026-07-12", + showUnairedNextUp = true, + available = false, + ), + ) + assertFalse( + shouldSurfaceNextEpisode( + watchedSeasonNumber = 1, + candidateSeasonNumber = 1, + todayIsoDate = "2026-07-05", + releasedDate = "2026-07-12", + showUnairedNextUp = false, + available = false, + ), + ) + } + + @Test + fun shouldSurfaceNextEpisode_keeps_unavailable_phantom_episode_hidden() { + assertFalse( + shouldSurfaceNextEpisode( + watchedSeasonNumber = 1, + candidateSeasonNumber = 3, + todayIsoDate = "2026-07-05", + releasedDate = null, + showUnairedNextUp = true, + available = false, + ), + ) + } + @Test fun latestCompletedSeriesEpisode_prefers_newer_manual_watch_marker() { val latestCompleted = latestCompletedSeriesEpisode(