mirror of
https://github.com/bbara04/Purefin.git
synced 2026-07-24 03:36:51 +00:00
feat(tvseries): improve focus management for season and episode selection
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ internal fun TvSeasonTabs(
|
||||
seasons: List<Season>,
|
||||
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<UUID?>(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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user