diff --git a/app-tv/src/main/java/hu/bbara/purefin/app/content/episode/EpisodeComponents.kt b/app-tv/src/main/java/hu/bbara/purefin/app/content/episode/EpisodeComponents.kt index eb97bc7..947895c 100644 --- a/app-tv/src/main/java/hu/bbara/purefin/app/content/episode/EpisodeComponents.kt +++ b/app-tv/src/main/java/hu/bbara/purefin/app/content/episode/EpisodeComponents.kt @@ -1,153 +1,16 @@ package hu.bbara.purefin.app.content.episode -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.ExperimentalLayoutApi -import androidx.compose.foundation.layout.FlowRow -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.sizeIn -import androidx.compose.foundation.layout.statusBarsPadding -import androidx.compose.foundation.layout.width -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.Add -import androidx.compose.material.icons.outlined.ArrowBack -import androidx.compose.material.icons.outlined.Cast -import androidx.compose.material.icons.outlined.MoreVert -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.material3.VerticalDivider import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import hu.bbara.purefin.common.ui.MediaCastRow -import hu.bbara.purefin.common.ui.MediaMetaChip -import hu.bbara.purefin.common.ui.MediaSynopsis -import hu.bbara.purefin.common.ui.components.GhostIconButton -import hu.bbara.purefin.common.ui.components.MediaActionButton -import hu.bbara.purefin.common.ui.components.MediaPlaybackSettings -import hu.bbara.purefin.common.ui.components.MediaResumeButton -import hu.bbara.purefin.core.model.Episode +import hu.bbara.purefin.common.ui.components.MediaDetailsTopBar @Composable internal fun EpisodeTopBar( onBack: () -> Unit, modifier: Modifier = Modifier ) { - Row( + MediaDetailsTopBar( + onBack = onBack, modifier = modifier - .fillMaxWidth() - .statusBarsPadding() - .padding(16.dp), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - GhostIconButton( - icon = Icons.Outlined.ArrowBack, - contentDescription = "Back", - onClick = onBack - ) - Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) { - GhostIconButton(icon = Icons.Outlined.Cast, contentDescription = "Cast", onClick = { }) - GhostIconButton(icon = Icons.Outlined.MoreVert, contentDescription = "More", onClick = { }) - } - } -} - -@OptIn(ExperimentalLayoutApi::class) -@Composable -internal fun EpisodeDetails( - episode: Episode, - onPlay: () -> Unit, - modifier: Modifier = Modifier -) { - val scheme = MaterialTheme.colorScheme - - Column(modifier = modifier) { - 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 - ) - } - Spacer(modifier = Modifier.height(24.dp)) - - MediaSynopsis( - synopsis = episode.synopsis - ) - Spacer(modifier = Modifier.height(24.dp)) - - Row() { - MediaResumeButton( - text = if (episode.progress == null) "Play" else "Resume", - progress = episode.progress?.div(100)?.toFloat() ?: 0f, - onClick = onPlay, - modifier = Modifier.sizeIn(maxWidth = 200.dp) - ) - VerticalDivider( - color = MaterialTheme.colorScheme.secondary, - thickness = 4.dp, - modifier = Modifier - .height(48.dp) - .padding(horizontal = 16.dp, vertical = 8.dp) - ) - Row() { - MediaActionButton( - backgroundColor = MaterialTheme.colorScheme.secondary, - iconColor = MaterialTheme.colorScheme.onSecondary, - icon = Icons.Outlined.Add, - height = 48.dp - ) - } - } - Spacer(modifier = Modifier.height(24.dp)) - - MediaPlaybackSettings( - backgroundColor = MaterialTheme.colorScheme.surface, - foregroundColor = MaterialTheme.colorScheme.onSurface, - audioTrack = "ENG", - subtitles = "ENG" - ) - 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 = emptyList() - ) - } + ) } diff --git a/app-tv/src/main/java/hu/bbara/purefin/app/content/movie/MovieComponents.kt b/app-tv/src/main/java/hu/bbara/purefin/app/content/movie/MovieComponents.kt index b4b090e..d887bfe 100644 --- a/app-tv/src/main/java/hu/bbara/purefin/app/content/movie/MovieComponents.kt +++ b/app-tv/src/main/java/hu/bbara/purefin/app/content/movie/MovieComponents.kt @@ -1,149 +1,16 @@ package hu.bbara.purefin.app.content.movie -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.ExperimentalLayoutApi -import androidx.compose.foundation.layout.FlowRow -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.sizeIn -import androidx.compose.foundation.layout.statusBarsPadding -import androidx.compose.foundation.layout.width -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.Add -import androidx.compose.material.icons.outlined.ArrowBack -import androidx.compose.material.icons.outlined.Cast -import androidx.compose.material.icons.outlined.MoreVert -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.material3.VerticalDivider import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import hu.bbara.purefin.common.ui.MediaCastRow -import hu.bbara.purefin.common.ui.MediaMetaChip -import hu.bbara.purefin.common.ui.MediaSynopsis -import hu.bbara.purefin.common.ui.components.GhostIconButton -import hu.bbara.purefin.common.ui.components.MediaActionButton -import hu.bbara.purefin.common.ui.components.MediaPlaybackSettings -import hu.bbara.purefin.common.ui.components.MediaResumeButton -import hu.bbara.purefin.core.model.Movie +import hu.bbara.purefin.common.ui.components.MediaDetailsTopBar @Composable internal fun MovieTopBar( onBack: () -> Unit, modifier: Modifier = Modifier ) { - val scheme = MaterialTheme.colorScheme - Row( + MediaDetailsTopBar( + onBack = onBack, modifier = modifier - .fillMaxWidth() - .statusBarsPadding() - .padding(16.dp), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - GhostIconButton( - icon = Icons.Outlined.ArrowBack, - contentDescription = "Back", - onClick = onBack - ) - Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) { - GhostIconButton(icon = Icons.Outlined.Cast, contentDescription = "Cast", onClick = { }) - GhostIconButton(icon = Icons.Outlined.MoreVert, contentDescription = "More", onClick = { }) - } - } -} - -@OptIn(ExperimentalLayoutApi::class) -@Composable -internal fun MovieDetails( - movie: Movie, - onPlay: () -> Unit, - modifier: Modifier = Modifier -) { - val scheme = MaterialTheme.colorScheme - - Column(modifier = modifier) { - 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 - ) - } - Spacer(modifier = Modifier.height(24.dp)) - - MediaSynopsis( - synopsis = movie.synopsis - ) - Spacer(modifier = Modifier.height(24.dp)) - - Row() { - MediaResumeButton( - text = if (movie.progress == null) "Play" else "Resume", - progress = movie.progress?.div(100)?.toFloat() ?: 0f, - onClick = onPlay, - modifier = Modifier.sizeIn(maxWidth = 200.dp) - ) - VerticalDivider( - color = MaterialTheme.colorScheme.secondary, - thickness = 4.dp, - modifier = Modifier - .height(48.dp) - .padding(horizontal = 16.dp, vertical = 8.dp) - ) - Row() { - MediaActionButton( - backgroundColor = MaterialTheme.colorScheme.secondary, - iconColor = MaterialTheme.colorScheme.onSecondary, - icon = Icons.Outlined.Add, - height = 48.dp - ) - } - } - Spacer(modifier = Modifier.height(24.dp)) - - MediaPlaybackSettings( - backgroundColor = MaterialTheme.colorScheme.surface, - foregroundColor = MaterialTheme.colorScheme.onSurface, - audioTrack = movie.audioTrack, - subtitles = movie.subtitles - ) - - if (movie.cast.isNotEmpty()) { - 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 - ) - } - } + ) } diff --git a/app-tv/src/main/java/hu/bbara/purefin/app/content/series/SeriesComponents.kt b/app-tv/src/main/java/hu/bbara/purefin/app/content/series/SeriesComponents.kt index 3639614..b31aa86 100644 --- a/app-tv/src/main/java/hu/bbara/purefin/app/content/series/SeriesComponents.kt +++ b/app-tv/src/main/java/hu/bbara/purefin/app/content/series/SeriesComponents.kt @@ -18,7 +18,6 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items @@ -27,9 +26,6 @@ import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Add -import androidx.compose.material.icons.outlined.ArrowBack -import androidx.compose.material.icons.outlined.Cast -import androidx.compose.material.icons.outlined.MoreVert import androidx.compose.material.icons.outlined.PlayCircle import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme @@ -54,8 +50,8 @@ import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel import hu.bbara.purefin.common.ui.MediaCastRow import hu.bbara.purefin.common.ui.MediaMetaChip -import hu.bbara.purefin.common.ui.components.GhostIconButton import hu.bbara.purefin.common.ui.components.MediaActionButton +import hu.bbara.purefin.common.ui.components.MediaDetailsTopBar import hu.bbara.purefin.common.ui.components.MediaProgressBar import hu.bbara.purefin.common.ui.components.PurefinAsyncImage import hu.bbara.purefin.common.ui.components.WatchStateIndicator @@ -70,23 +66,10 @@ internal fun SeriesTopBar( onBack: () -> Unit, modifier: Modifier = Modifier ) { - Row( + MediaDetailsTopBar( + onBack = onBack, modifier = modifier - .fillMaxWidth() - .statusBarsPadding() - .padding(16.dp), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - GhostIconButton( - onClick = onBack, - icon = Icons.Outlined.ArrowBack, - contentDescription = "Back") - Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) { - GhostIconButton(icon = Icons.Outlined.Cast, contentDescription = "Cast", onClick = { }) - GhostIconButton(icon = Icons.Outlined.MoreVert, contentDescription = "More", onClick = { }) - } - } + ) } @OptIn(ExperimentalLayoutApi::class) diff --git a/app-tv/src/main/java/hu/bbara/purefin/common/ui/components/MediaDetailsTopBar.kt b/app-tv/src/main/java/hu/bbara/purefin/common/ui/components/MediaDetailsTopBar.kt new file mode 100644 index 0000000..c51d2c1 --- /dev/null +++ b/app-tv/src/main/java/hu/bbara/purefin/common/ui/components/MediaDetailsTopBar.kt @@ -0,0 +1,42 @@ +package hu.bbara.purefin.common.ui.components + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.statusBarsPadding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.outlined.ArrowBack +import androidx.compose.material.icons.outlined.Cast +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.unit.dp + +@Composable +fun MediaDetailsTopBar( + onBack: () -> Unit, + modifier: Modifier = Modifier, + onCastClick: () -> Unit = {}, + onMoreClick: () -> Unit = {} +) { + Row( + modifier = modifier + .fillMaxWidth() + .statusBarsPadding() + .padding(16.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + GhostIconButton( + icon = Icons.AutoMirrored.Outlined.ArrowBack, + contentDescription = "Back", + onClick = onBack + ) + Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) { + GhostIconButton(icon = Icons.Outlined.Cast, contentDescription = "Cast", onClick = onCastClick) + GhostIconButton(icon = Icons.Outlined.MoreVert, contentDescription = "More", onClick = onMoreClick) + } + } +} diff --git a/app-tv/src/main/java/hu/bbara/purefin/common/ui/components/PurefinIconButton.kt b/app-tv/src/main/java/hu/bbara/purefin/common/ui/components/PurefinIconButton.kt index e640dc1..73f6f7e 100644 --- a/app-tv/src/main/java/hu/bbara/purefin/common/ui/components/PurefinIconButton.kt +++ b/app-tv/src/main/java/hu/bbara/purefin/common/ui/components/PurefinIconButton.kt @@ -1,6 +1,5 @@ package hu.bbara.purefin.common.ui.components -import androidx.compose.animation.animateColorAsState import androidx.compose.animation.core.animateFloatAsState import androidx.compose.foundation.background import androidx.compose.foundation.border diff --git a/app-tv/src/main/java/hu/bbara/purefin/common/ui/components/SearchField.kt b/app-tv/src/main/java/hu/bbara/purefin/common/ui/components/SearchField.kt deleted file mode 100644 index 21856d9..0000000 --- a/app-tv/src/main/java/hu/bbara/purefin/common/ui/components/SearchField.kt +++ /dev/null @@ -1,56 +0,0 @@ -package hu.bbara.purefin.common.ui.components - -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.Search -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.material3.TextField -import androidx.compose.material3.TextFieldDefaults -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.unit.dp - -@Composable -fun SearchField( - value: String, - onValueChange: (String) -> Unit, - placeholder: String, - backgroundColor: Color = Color.Unspecified, - textColor: Color = Color.Unspecified, - cursorColor: Color = Color.Unspecified, - modifier: Modifier = Modifier, -) { - val scheme = MaterialTheme.colorScheme - val resolvedBackgroundColor = - if (backgroundColor == Color.Unspecified) scheme.surfaceVariant else backgroundColor - val resolvedTextColor = if (textColor == Color.Unspecified) scheme.onSurface else textColor - val resolvedCursorColor = if (cursorColor == Color.Unspecified) scheme.primary else cursorColor - - TextField( - value = value, - onValueChange = onValueChange, - modifier = modifier - .fillMaxWidth() - .clip(RoundedCornerShape(12.dp)), - singleLine = true, - placeholder = { Text(placeholder) }, - leadingIcon = { Icon(imageVector = Icons.Outlined.Search, contentDescription = null) }, - colors = TextFieldDefaults.colors( - focusedContainerColor = resolvedBackgroundColor, - unfocusedContainerColor = resolvedBackgroundColor, - focusedIndicatorColor = Color.Transparent, - unfocusedIndicatorColor = Color.Transparent, - cursorColor = resolvedCursorColor, - focusedTextColor = resolvedTextColor, - unfocusedTextColor = resolvedTextColor, - focusedLeadingIconColor = scheme.onSurfaceVariant, - unfocusedLeadingIconColor = scheme.onSurfaceVariant, - focusedPlaceholderColor = scheme.onSurfaceVariant, - unfocusedPlaceholderColor = scheme.onSurfaceVariant, - )) -} diff --git a/app-tv/src/main/java/hu/bbara/purefin/tv/home/ui/TvHomeAvatar.kt b/app-tv/src/main/java/hu/bbara/purefin/tv/home/ui/TvHomeAvatar.kt deleted file mode 100644 index 6a49b9a..0000000 --- a/app-tv/src/main/java/hu/bbara/purefin/tv/home/ui/TvHomeAvatar.kt +++ /dev/null @@ -1,41 +0,0 @@ -package hu.bbara.purefin.tv.home.ui - -import androidx.compose.foundation.background -import androidx.compose.foundation.border -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.material3.Icon -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.unit.Dp - -@Composable -fun TvHomeAvatar( - size: Dp, - borderWidth: Dp, - borderColor: Color, - backgroundColor: Color, - icon: ImageVector, - iconTint: Color, - modifier: Modifier = Modifier -) { - Box( - modifier = modifier - .size(size) - .clip(CircleShape) - .border(borderWidth, borderColor, CircleShape) - .background(backgroundColor), - contentAlignment = Alignment.Center - ) { - Icon( - imageVector = icon, - contentDescription = null, - tint = iconTint - ) - } -} diff --git a/app-tv/src/main/java/hu/bbara/purefin/tv/home/ui/TvHomeDrawer.kt b/app-tv/src/main/java/hu/bbara/purefin/tv/home/ui/TvHomeDrawer.kt deleted file mode 100644 index 7f33cfd..0000000 --- a/app-tv/src/main/java/hu/bbara/purefin/tv/home/ui/TvHomeDrawer.kt +++ /dev/null @@ -1,217 +0,0 @@ -package hu.bbara.purefin.tv.home.ui - -import androidx.compose.foundation.background -import androidx.compose.foundation.border -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.PlayArrow -import androidx.compose.material.icons.outlined.Person -import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.focus.onFocusChanged -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp - -@Composable -fun TvHomeDrawerContent( - title: String, - subtitle: String, - primaryNavItems: List, - secondaryNavItems: List, - user: TvHomeUser, - onLibrarySelected: (TvHomeNavItem) -> Unit, - onLogout: () -> Unit, - modifier: Modifier = Modifier, -) { - Column(modifier = modifier.fillMaxSize()) { - TvHomeDrawerHeader( - title = title, - subtitle = subtitle - ) - TvHomeDrawerNav( - primaryItems = primaryNavItems, - secondaryItems = secondaryNavItems, - onLibrarySelected = onLibrarySelected - ) - Spacer(modifier = Modifier.weight(1f)) - TvHomeDrawerFooter(user = user, onLogout = onLogout) - } -} - -@Composable -fun TvHomeDrawerHeader( - title: String, - subtitle: String, - modifier: Modifier = Modifier -) { - val scheme = MaterialTheme.colorScheme - - Row( - modifier = modifier - .fillMaxWidth() - .padding(start = 24.dp, end = 16.dp, top = 24.dp, bottom = 20.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Row( - modifier = Modifier - .size(40.dp) - .background(scheme.primary, RoundedCornerShape(12.dp)), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.Center - ) { - Icon( - imageVector = Icons.Filled.PlayArrow, - contentDescription = "Play", - tint = scheme.onPrimary - ) - } - Column(modifier = Modifier.padding(start = 12.dp)) { - Text( - text = title, - color = scheme.onBackground, - fontSize = 20.sp, - fontWeight = FontWeight.Bold - ) - Text( - text = subtitle, - color = scheme.onSurfaceVariant, - fontSize = 12.sp - ) - } - } - HorizontalDivider(color = scheme.onSurfaceVariant.copy(alpha = 0.2f)) -} - -@Composable -fun TvHomeDrawerNav( - primaryItems: List, - secondaryItems: List, - onLibrarySelected: (TvHomeNavItem) -> Unit, - modifier: Modifier = Modifier, -) { - Column( - modifier = modifier - .fillMaxWidth() - .padding(vertical = 16.dp) - ) { - primaryItems.forEach { item -> - TvHomeDrawerNavItem(item = item, onLibrarySelected = onLibrarySelected) - } - if (secondaryItems.isNotEmpty()) { - HorizontalDivider( - modifier = Modifier - .padding(horizontal = 20.dp, vertical = 12.dp), - color = MaterialTheme.colorScheme.outlineVariant - ) - secondaryItems.forEach { item -> - TvHomeDrawerNavItem(item = item, onLibrarySelected = onLibrarySelected) - } - } - } -} - -@Composable -fun TvHomeDrawerNavItem( - item: TvHomeNavItem, - modifier: Modifier = Modifier, - onLibrarySelected: (TvHomeNavItem) -> Unit -) { - val scheme = MaterialTheme.colorScheme - var isFocused by remember { mutableStateOf(false) } - val background = when { - isFocused -> scheme.primary.copy(alpha = 0.28f) - item.selected -> scheme.primary.copy(alpha = 0.12f) - else -> Color.Transparent - } - val tint = if (item.selected || isFocused) scheme.primary else scheme.onSurfaceVariant - Row( - modifier = modifier - .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 4.dp) - .then(if (isFocused) Modifier.border(2.dp, scheme.primary, RoundedCornerShape(12.dp)) else Modifier) - .background(background, RoundedCornerShape(12.dp)) - .onFocusChanged { isFocused = it.isFocused } - .clickable { onLibrarySelected(item) } - .padding(horizontal = 16.dp, vertical = 12.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - imageVector = item.icon, - contentDescription = item.label, - tint = tint - ) - Text( - text = item.label, - color = if (item.selected || isFocused) scheme.primary else scheme.onBackground, - fontSize = 15.sp, - fontWeight = FontWeight.Medium, - modifier = Modifier.padding(start = 12.dp) - ) - } -} - -@Composable -fun TvHomeDrawerFooter( - user: TvHomeUser, - onLogout: () -> Unit, - modifier: Modifier = Modifier, -) { - val scheme = MaterialTheme.colorScheme - - Row( - modifier = modifier - .fillMaxWidth() - .padding(16.dp) - .background(scheme.surfaceVariant, RoundedCornerShape(12.dp)) - .padding(12.dp), - verticalAlignment = Alignment.CenterVertically - ) { - TvHomeAvatar( - size = 32.dp, - borderWidth = 1.dp, - borderColor = scheme.outlineVariant, - backgroundColor = scheme.primaryContainer, - icon = Icons.Outlined.Person, - iconTint = scheme.onBackground - ) - Column(modifier = Modifier.padding(start = 12.dp) - .clickable { onLogout() }) { - Text( - text = user.name, - color = scheme.onBackground, - fontSize = 14.sp, - fontWeight = FontWeight.SemiBold, - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) - Text( - text = user.plan, - color = scheme.onSurfaceVariant, - fontSize = 11.sp, - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) - } - } -}