diff --git a/app-tv/src/main/java/hu/bbara/purefin/ui/screen/series/TvSeriesScreen.kt b/app-tv/src/main/java/hu/bbara/purefin/ui/screen/series/TvSeriesScreen.kt index 01f08099..426aa8e3 100644 --- a/app-tv/src/main/java/hu/bbara/purefin/ui/screen/series/TvSeriesScreen.kt +++ b/app-tv/src/main/java/hu/bbara/purefin/ui/screen/series/TvSeriesScreen.kt @@ -77,20 +77,22 @@ internal fun TvSeriesScreenContent( mutableStateOf(defaultSeason.id) } val selectedSeason = series.seasons.firstOrNull { it.id == selectedSeasonId } ?: defaultSeason - val initialFocusedEpisodeId = remember(series.id, focusedSeasonId, focusedEpisodeId) { - val focusedEpisode = defaultSeason.episodes.firstOrNull { it.id == focusedEpisodeId } - focusedEpisode?.id ?: defaultSeason.nextUpEpisode()?.id - } - val firstContentFocusRequester = remember { FocusRequester() } + val initialFocusSeasonId = remember(series.id, focusedSeasonId) { defaultSeason.id } + val initialFocusSeason = series.seasons.firstOrNull { it.id == initialFocusSeasonId } ?: defaultSeason + val initialFocusedEpisodeId = initialFocusSeason.focusTargetEpisodeId(focusedEpisodeId) + val seasonTabFocusRequester = remember { FocusRequester() } + val waitingForInitialEpisodes = initialFocusedEpisodeId == null && + initialFocusSeason.episodes.isEmpty() && + initialFocusSeason.episodeCount > 0 LaunchedEffect(series.id, selectedSeason.id) { onLoadSeasonEpisodes(series.id, selectedSeason.id) } - LaunchedEffect(series.id, initialFocusedEpisodeId) { - if (initialFocusedEpisodeId != null) return@LaunchedEffect + LaunchedEffect(series.id, initialFocusedEpisodeId, waitingForInitialEpisodes) { + if (initialFocusedEpisodeId != null || waitingForInitialEpisodes) return@LaunchedEffect withFrameNanos { } - firstContentFocusRequester.requestFocus() + seasonTabFocusRequester.requestFocus() } TvMediaDetailScaffold( @@ -115,7 +117,7 @@ internal fun TvSeriesScreenContent( TvSeasonTabs( seasons = series.seasons, selectedSeason = selectedSeason, - firstItemFocusRequester = firstContentFocusRequester, + selectedItemFocusRequester = seasonTabFocusRequester, firstItemTestTag = SeriesFirstSeasonTabTag, onSelect = { selectedSeasonId = it.id }, modifier = Modifier.fillMaxWidth() @@ -143,3 +145,8 @@ private fun Series.defaultSeason(focusedSeasonId: UUID?): Season { private fun Season.nextUpEpisode(): Episode? { return episodes.firstOrNull { !it.watched } ?: episodes.firstOrNull() } + +private fun Season.focusTargetEpisodeId(focusedEpisodeId: UUID?): UUID? { + val focusedEpisode = episodes.firstOrNull { it.id == focusedEpisodeId } + return focusedEpisode?.id ?: nextUpEpisode()?.id +} diff --git a/app-tv/src/main/java/hu/bbara/purefin/ui/screen/series/components/TvSeriesComponents.kt b/app-tv/src/main/java/hu/bbara/purefin/ui/screen/series/components/TvSeriesComponents.kt index 13166b57..305932c5 100644 --- a/app-tv/src/main/java/hu/bbara/purefin/ui/screen/series/components/TvSeriesComponents.kt +++ b/app-tv/src/main/java/hu/bbara/purefin/ui/screen/series/components/TvSeriesComponents.kt @@ -82,7 +82,7 @@ internal fun TvSeasonTabs( seasons: List, selectedSeason: Season?, modifier: Modifier = Modifier, - firstItemFocusRequester: FocusRequester? = null, + selectedItemFocusRequester: FocusRequester? = null, firstItemTestTag: String? = null, onSelect: (Season) -> Unit ) { @@ -104,8 +104,8 @@ internal fun TvSeasonTabs( colors = TabDefaults.underlinedIndicatorTabColors(), modifier = Modifier .then( - if (index == 0 && firstItemFocusRequester != null) { - Modifier.focusRequester(firstItemFocusRequester) + if (index == selectedSeasonIndex && selectedItemFocusRequester != null) { + Modifier.focusRequester(selectedItemFocusRequester) } else { Modifier } @@ -145,6 +145,7 @@ internal fun TvEpisodeCarousel( ) { val listState = rememberLazyListState() val focusedEpisodeFocusRequester = remember { FocusRequester() } + var requestedFocusEpisodeId by remember { mutableStateOf(null) } LaunchedEffect(episodes, focusedEpisodeId) { val focusedEpisodeIndex = focusedEpisodeId?.let { id -> @@ -159,9 +160,10 @@ internal fun TvEpisodeCarousel( listState.scrollToItem(0) } - if (focusedEpisodeIndex >= 0) { + if (focusedEpisodeIndex >= 0 && requestedFocusEpisodeId != focusedEpisodeId) { withFrameNanos { } focusedEpisodeFocusRequester.requestFocus() + requestedFocusEpisodeId = focusedEpisodeId } }