From 87cab0e58701ab9320912663775b7b822fb7a6aa Mon Sep 17 00:00:00 2001 From: Arvin Date: Sun, 5 Apr 2026 14:43:42 +0200 Subject: [PATCH] fix: focus first unwatched episode in details view (#117) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously `initialEpisodeIndex` defaulted to 0 when the caller did not pass an explicit episode target (e.g., navigating to a show from the home grid rather than from a Continue Watching tile). That always focused episode 1 of the current season, forcing users to scroll past every episode they had already watched before reaching the next unwatched one — particularly painful on long-running anime with hundreds of episodes. `nextUnwatchedEpisode` was already computed on the line below and used to build the "Continue SxEy" play button label, but was never fed back into the initial focus index. Now: - If the caller passed an explicit episode target, focus it (unchanged). - Otherwise focus the first unwatched episode in the loaded season. - If every episode in the current season is already watched, fall back to episode 1 so the user can switch seasons from the normal starting point. This reuses the watched-status decoration that already runs a few lines earlier (from Trakt for Trakt-linked users, falling back to local season progress), so there is no extra work or network call. The `> 0` guard in DetailsScreen.LaunchedEffect still handles the index-0 case correctly because the screen-level `episodeIndex` default is also 0. Closes #117 --- .../tv/ui/screens/details/DetailsViewModel.kt | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/app/src/main/kotlin/com/arflix/tv/ui/screens/details/DetailsViewModel.kt b/app/src/main/kotlin/com/arflix/tv/ui/screens/details/DetailsViewModel.kt index 0d601f1b9..0ba81b849 100644 --- a/app/src/main/kotlin/com/arflix/tv/ui/screens/details/DetailsViewModel.kt +++ b/app/src/main/kotlin/com/arflix/tv/ui/screens/details/DetailsViewModel.kt @@ -490,10 +490,20 @@ class DetailsViewModel @Inject constructor( } val targetEpisodeForRow = if (initialSeason == seasonToLoad) initialEpisode else null - val initialEpisodeIndex = if (targetEpisodeForRow != null) { - decoratedEpisodes.indexOfFirst { it.episodeNumber == targetEpisodeForRow }.coerceAtLeast(0) - } else 0 val nextUnwatchedEpisode = decoratedEpisodes.firstOrNull { !it.isWatched } + // Focus the explicit target episode if the caller passed one (deeplink / + // Continue Watching tile), otherwise focus the first unwatched episode so + // users don't have to scroll past every episode they've already seen. + // When every episode in the current season is watched we fall back to + // the first episode (index 0) — from there the user can jump to the next + // season via the season selector. See issue #117. + val initialEpisodeIndex = when { + targetEpisodeForRow != null -> + decoratedEpisodes.indexOfFirst { it.episodeNumber == targetEpisodeForRow }.coerceAtLeast(0) + nextUnwatchedEpisode != null -> + decoratedEpisodes.indexOf(nextUnwatchedEpisode).coerceAtLeast(0) + else -> 0 + } val hasWatchedEpisodes = decoratedEpisodes.any { it.isWatched } updateState { state -> val shouldUseEpisodeTarget = !hasExplicitEpisodeTarget &&