mirror of
https://github.com/bbara04/Purefin.git
synced 2026-03-31 17:10:08 +02:00
Fix TV detail top bar focus navigation
This commit is contained in:
@@ -2,15 +2,18 @@ package hu.bbara.purefin.app.content.episode
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import hu.bbara.purefin.common.ui.components.MediaDetailsTopBar
|
||||
|
||||
@Composable
|
||||
internal fun EpisodeTopBar(
|
||||
onBack: () -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
modifier: Modifier = Modifier,
|
||||
downFocusRequester: FocusRequester? = null
|
||||
) {
|
||||
MediaDetailsTopBar(
|
||||
onBack = onBack,
|
||||
modifier = modifier
|
||||
modifier = modifier,
|
||||
downFocusRequester = downFocusRequester
|
||||
)
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
@@ -94,98 +95,104 @@ private fun EpisodeScreenInternal(
|
||||
playFocusRequester.requestFocus()
|
||||
}
|
||||
|
||||
LazyColumn(
|
||||
Box(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.background(scheme.background)
|
||||
) {
|
||||
item {
|
||||
Box {
|
||||
LazyColumn(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
item {
|
||||
MediaHero(
|
||||
imageUrl = episode.heroImageUrl,
|
||||
backgroundColor = scheme.background,
|
||||
heightFraction = 0.30f,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
EpisodeTopBar(onBack = onBack)
|
||||
}
|
||||
}
|
||||
item {
|
||||
Column(modifier = hPad) {
|
||||
Text(
|
||||
text = episode.title,
|
||||
color = scheme.onBackground,
|
||||
fontSize = 32.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
lineHeight = 38.sp
|
||||
)
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
Text(
|
||||
text = "Episode ${episode.index}",
|
||||
color = scheme.onBackground,
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Medium
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
FlowRow(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
MediaMetaChip(text = episode.releaseDate)
|
||||
MediaMetaChip(text = episode.rating)
|
||||
MediaMetaChip(text = episode.runtime)
|
||||
MediaMetaChip(
|
||||
text = episode.format,
|
||||
background = scheme.primary.copy(alpha = 0.2f),
|
||||
border = scheme.primary.copy(alpha = 0.3f),
|
||||
textColor = scheme.primary
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
MediaSynopsis(
|
||||
synopsis = episode.synopsis,
|
||||
modifier = hPad
|
||||
)
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
Row(modifier = hPad) {
|
||||
MediaResumeButton(
|
||||
text = if (episode.progress == null) "Play" else "Resume",
|
||||
progress = episode.progress?.div(100)?.toFloat() ?: 0f,
|
||||
onClick = onPlay,
|
||||
modifier = Modifier.sizeIn(maxWidth = 200.dp).focusRequester(playFocusRequester)
|
||||
)
|
||||
}
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
MediaPlaybackSettings(
|
||||
backgroundColor = scheme.surface,
|
||||
foregroundColor = scheme.onSurface,
|
||||
audioTrack = "ENG",
|
||||
subtitles = "ENG",
|
||||
modifier = hPad
|
||||
)
|
||||
}
|
||||
if (episode.cast.isNotEmpty()) {
|
||||
item {
|
||||
Column(modifier = hPad) {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
Text(
|
||||
text = "Cast",
|
||||
text = episode.title,
|
||||
color = scheme.onBackground,
|
||||
fontSize = 18.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
fontSize = 32.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
lineHeight = 38.sp
|
||||
)
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
Text(
|
||||
text = "Episode ${episode.index}",
|
||||
color = scheme.onBackground,
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Medium
|
||||
)
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
MediaCastRow(cast = episode.cast)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
FlowRow(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
MediaMetaChip(text = episode.releaseDate)
|
||||
MediaMetaChip(text = episode.rating)
|
||||
MediaMetaChip(text = episode.runtime)
|
||||
MediaMetaChip(
|
||||
text = episode.format,
|
||||
background = scheme.primary.copy(alpha = 0.2f),
|
||||
border = scheme.primary.copy(alpha = 0.3f),
|
||||
textColor = scheme.primary
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
MediaSynopsis(
|
||||
synopsis = episode.synopsis,
|
||||
modifier = hPad
|
||||
)
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
Row(modifier = hPad) {
|
||||
MediaResumeButton(
|
||||
text = if (episode.progress == null) "Play" else "Resume",
|
||||
progress = episode.progress?.div(100)?.toFloat() ?: 0f,
|
||||
onClick = onPlay,
|
||||
modifier = Modifier.sizeIn(maxWidth = 200.dp).focusRequester(playFocusRequester)
|
||||
)
|
||||
}
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
MediaPlaybackSettings(
|
||||
backgroundColor = scheme.surface,
|
||||
foregroundColor = scheme.onSurface,
|
||||
audioTrack = "ENG",
|
||||
subtitles = "ENG",
|
||||
modifier = hPad
|
||||
)
|
||||
}
|
||||
if (episode.cast.isNotEmpty()) {
|
||||
item {
|
||||
Column(modifier = hPad) {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
Text(
|
||||
text = "Cast",
|
||||
color = scheme.onBackground,
|
||||
fontSize = 18.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
MediaCastRow(cast = episode.cast)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
EpisodeTopBar(
|
||||
onBack = onBack,
|
||||
downFocusRequester = playFocusRequester,
|
||||
modifier = Modifier.align(Alignment.TopStart)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,15 +2,18 @@ package hu.bbara.purefin.app.content.movie
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import hu.bbara.purefin.common.ui.components.MediaDetailsTopBar
|
||||
|
||||
@Composable
|
||||
internal fun MovieTopBar(
|
||||
onBack: () -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
modifier: Modifier = Modifier,
|
||||
downFocusRequester: FocusRequester? = null
|
||||
) {
|
||||
MediaDetailsTopBar(
|
||||
onBack = onBack,
|
||||
modifier = modifier
|
||||
modifier = modifier,
|
||||
downFocusRequester = downFocusRequester
|
||||
)
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
@@ -76,91 +77,97 @@ private fun MovieScreenInternal(
|
||||
playFocusRequester.requestFocus()
|
||||
}
|
||||
|
||||
LazyColumn(
|
||||
Box(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.background(scheme.background)
|
||||
) {
|
||||
item {
|
||||
Box {
|
||||
LazyColumn(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
item {
|
||||
MediaHero(
|
||||
imageUrl = movie.heroImageUrl,
|
||||
backgroundColor = scheme.background,
|
||||
heightFraction = 0.30f,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
MovieTopBar(onBack = onBack)
|
||||
}
|
||||
}
|
||||
item {
|
||||
Column(modifier = hPad) {
|
||||
Text(
|
||||
text = movie.title,
|
||||
color = scheme.onBackground,
|
||||
fontSize = 32.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
lineHeight = 38.sp
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
FlowRow(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
MediaMetaChip(text = movie.year)
|
||||
MediaMetaChip(text = movie.rating)
|
||||
MediaMetaChip(text = movie.runtime)
|
||||
MediaMetaChip(
|
||||
text = movie.format,
|
||||
background = scheme.primary.copy(alpha = 0.2f),
|
||||
border = scheme.primary.copy(alpha = 0.3f),
|
||||
textColor = scheme.primary
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
MediaSynopsis(
|
||||
synopsis = movie.synopsis,
|
||||
modifier = hPad
|
||||
)
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
Row(modifier = hPad) {
|
||||
MediaResumeButton(
|
||||
text = if (movie.progress == null) "Play" else "Resume",
|
||||
progress = movie.progress?.div(100)?.toFloat() ?: 0f,
|
||||
onClick = onPlay,
|
||||
modifier = Modifier.sizeIn(maxWidth = 200.dp).focusRequester(playFocusRequester)
|
||||
)
|
||||
}
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
MediaPlaybackSettings(
|
||||
backgroundColor = scheme.surface,
|
||||
foregroundColor = scheme.onSurface,
|
||||
audioTrack = movie.audioTrack,
|
||||
subtitles = movie.subtitles,
|
||||
modifier = hPad
|
||||
)
|
||||
}
|
||||
if (movie.cast.isNotEmpty()) {
|
||||
item {
|
||||
Column(modifier = hPad) {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
Text(
|
||||
text = "Cast",
|
||||
text = movie.title,
|
||||
color = scheme.onBackground,
|
||||
fontSize = 18.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
fontSize = 32.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
lineHeight = 38.sp
|
||||
)
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
MediaCastRow(cast = movie.cast)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
FlowRow(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
MediaMetaChip(text = movie.year)
|
||||
MediaMetaChip(text = movie.rating)
|
||||
MediaMetaChip(text = movie.runtime)
|
||||
MediaMetaChip(
|
||||
text = movie.format,
|
||||
background = scheme.primary.copy(alpha = 0.2f),
|
||||
border = scheme.primary.copy(alpha = 0.3f),
|
||||
textColor = scheme.primary
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
MediaSynopsis(
|
||||
synopsis = movie.synopsis,
|
||||
modifier = hPad
|
||||
)
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
Row(modifier = hPad) {
|
||||
MediaResumeButton(
|
||||
text = if (movie.progress == null) "Play" else "Resume",
|
||||
progress = movie.progress?.div(100)?.toFloat() ?: 0f,
|
||||
onClick = onPlay,
|
||||
modifier = Modifier.sizeIn(maxWidth = 200.dp).focusRequester(playFocusRequester)
|
||||
)
|
||||
}
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
MediaPlaybackSettings(
|
||||
backgroundColor = scheme.surface,
|
||||
foregroundColor = scheme.onSurface,
|
||||
audioTrack = movie.audioTrack,
|
||||
subtitles = movie.subtitles,
|
||||
modifier = hPad
|
||||
)
|
||||
}
|
||||
if (movie.cast.isNotEmpty()) {
|
||||
item {
|
||||
Column(modifier = hPad) {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
Text(
|
||||
text = "Cast",
|
||||
color = scheme.onBackground,
|
||||
fontSize = 18.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
MediaCastRow(cast = movie.cast)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
MovieTopBar(
|
||||
onBack = onBack,
|
||||
downFocusRequester = playFocusRequester,
|
||||
modifier = Modifier.align(Alignment.TopStart)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.focus.onFocusChanged
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
@@ -62,11 +64,13 @@ import hu.bbara.purefin.feature.shared.content.series.SeriesViewModel
|
||||
@Composable
|
||||
internal fun SeriesTopBar(
|
||||
onBack: () -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
modifier: Modifier = Modifier,
|
||||
downFocusRequester: FocusRequester? = null
|
||||
) {
|
||||
MediaDetailsTopBar(
|
||||
onBack = onBack,
|
||||
modifier = modifier
|
||||
modifier = modifier,
|
||||
downFocusRequester = downFocusRequester
|
||||
)
|
||||
}
|
||||
|
||||
@@ -88,6 +92,7 @@ internal fun SeasonTabs(
|
||||
seasons: List<Season>,
|
||||
selectedSeason: Season?,
|
||||
modifier: Modifier = Modifier,
|
||||
firstItemFocusRequester: FocusRequester? = null,
|
||||
onSelect: (Season) -> Unit
|
||||
) {
|
||||
Row(
|
||||
@@ -96,11 +101,16 @@ internal fun SeasonTabs(
|
||||
.horizontalScroll(rememberScrollState()),
|
||||
horizontalArrangement = Arrangement.spacedBy(20.dp)
|
||||
) {
|
||||
seasons.forEach { season ->
|
||||
seasons.forEachIndexed { index, season ->
|
||||
SeasonTab(
|
||||
name = season.name,
|
||||
isSelected = season == selectedSeason,
|
||||
onSelect = { onSelect(season) }
|
||||
onSelect = { onSelect(season) },
|
||||
modifier = if (index == 0 && firstItemFocusRequester != null) {
|
||||
Modifier.focusRequester(firstItemFocusRequester)
|
||||
} else {
|
||||
Modifier
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,9 @@ import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
@@ -71,77 +73,85 @@ private fun SeriesScreenInternal(
|
||||
return series.seasons.first()
|
||||
}
|
||||
val selectedSeason = remember { mutableStateOf<Season>(getDefaultSeason()) }
|
||||
val firstContentFocusRequester = remember { FocusRequester() }
|
||||
|
||||
LazyColumn(
|
||||
Box(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.background(scheme.background)
|
||||
) {
|
||||
item {
|
||||
Box {
|
||||
LazyColumn(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
item {
|
||||
MediaHero(
|
||||
imageUrl = series.heroImageUrl,
|
||||
heightFraction = 0.30f,
|
||||
backgroundColor = scheme.background,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
SeriesTopBar(onBack = onBack)
|
||||
}
|
||||
}
|
||||
item {
|
||||
Column(modifier = hPad) {
|
||||
Text(
|
||||
text = series.name,
|
||||
color = scheme.onBackground,
|
||||
fontSize = 30.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
lineHeight = 36.sp
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
SeriesMetaChips(series = series)
|
||||
}
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
MediaSynopsis(
|
||||
synopsis = series.synopsis,
|
||||
bodyColor = textMutedStrong,
|
||||
bodyFontSize = 13.sp,
|
||||
bodyLineHeight = null,
|
||||
titleSpacing = 8.dp,
|
||||
modifier = hPad
|
||||
)
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
SeasonTabs(
|
||||
seasons = series.seasons,
|
||||
selectedSeason = selectedSeason.value,
|
||||
onSelect = { selectedSeason.value = it },
|
||||
modifier = hPad
|
||||
)
|
||||
}
|
||||
item {
|
||||
EpisodeCarousel(
|
||||
episodes = selectedSeason.value.episodes,
|
||||
modifier = hPad
|
||||
)
|
||||
}
|
||||
if (series.cast.isNotEmpty()) {
|
||||
item {
|
||||
Column(modifier = hPad) {
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
Text(
|
||||
text = "Cast",
|
||||
text = series.name,
|
||||
color = scheme.onBackground,
|
||||
fontSize = 18.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
fontSize = 30.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
lineHeight = 36.sp
|
||||
)
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
CastRow(cast = series.cast)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
SeriesMetaChips(series = series)
|
||||
}
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
MediaSynopsis(
|
||||
synopsis = series.synopsis,
|
||||
bodyColor = textMutedStrong,
|
||||
bodyFontSize = 13.sp,
|
||||
bodyLineHeight = null,
|
||||
titleSpacing = 8.dp,
|
||||
modifier = hPad
|
||||
)
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
SeasonTabs(
|
||||
seasons = series.seasons,
|
||||
selectedSeason = selectedSeason.value,
|
||||
firstItemFocusRequester = firstContentFocusRequester,
|
||||
onSelect = { selectedSeason.value = it },
|
||||
modifier = hPad
|
||||
)
|
||||
}
|
||||
item {
|
||||
EpisodeCarousel(
|
||||
episodes = selectedSeason.value.episodes,
|
||||
modifier = hPad
|
||||
)
|
||||
}
|
||||
if (series.cast.isNotEmpty()) {
|
||||
item {
|
||||
Column(modifier = hPad) {
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
Text(
|
||||
text = "Cast",
|
||||
color = scheme.onBackground,
|
||||
fontSize = 18.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
CastRow(cast = series.cast)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SeriesTopBar(
|
||||
onBack = onBack,
|
||||
downFocusRequester = firstContentFocusRequester,
|
||||
modifier = Modifier.align(Alignment.TopStart)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ import androidx.compose.material.icons.outlined.MoreVert
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusProperties
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
@@ -19,8 +21,15 @@ fun MediaDetailsTopBar(
|
||||
onBack: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
onCastClick: () -> Unit = {},
|
||||
onMoreClick: () -> Unit = {}
|
||||
onMoreClick: () -> Unit = {},
|
||||
downFocusRequester: FocusRequester? = null
|
||||
) {
|
||||
val downModifier = if (downFocusRequester != null) {
|
||||
Modifier.focusProperties { down = downFocusRequester }
|
||||
} else {
|
||||
Modifier
|
||||
}
|
||||
|
||||
Row(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
@@ -32,11 +41,22 @@ fun MediaDetailsTopBar(
|
||||
GhostIconButton(
|
||||
icon = Icons.AutoMirrored.Outlined.ArrowBack,
|
||||
contentDescription = "Back",
|
||||
onClick = onBack
|
||||
onClick = onBack,
|
||||
modifier = downModifier
|
||||
)
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) {
|
||||
GhostIconButton(icon = Icons.Outlined.Cast, contentDescription = "Cast", onClick = onCastClick)
|
||||
GhostIconButton(icon = Icons.Outlined.MoreVert, contentDescription = "More", onClick = onMoreClick)
|
||||
GhostIconButton(
|
||||
icon = Icons.Outlined.Cast,
|
||||
contentDescription = "Cast",
|
||||
onClick = onCastClick,
|
||||
modifier = downModifier
|
||||
)
|
||||
GhostIconButton(
|
||||
icon = Icons.Outlined.MoreVert,
|
||||
contentDescription = "More",
|
||||
onClick = onMoreClick,
|
||||
modifier = downModifier
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user