refactor: Move MediaPlaybackSettings to a separate component and update usage in Episode and Movie screens

This commit is contained in:
2026-01-22 19:33:43 +01:00
parent ce45139f74
commit ee43178622
5 changed files with 124 additions and 123 deletions

View File

@@ -14,6 +14,7 @@ import androidx.compose.material.icons.Icons
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.runtime.Composable
import androidx.compose.ui.Alignment
@@ -26,7 +27,7 @@ import hu.bbara.purefin.common.ui.MediaCastMember
import hu.bbara.purefin.common.ui.MediaCastRow
import hu.bbara.purefin.common.ui.MediaGhostIconButton
import hu.bbara.purefin.common.ui.MediaMetaChip
import hu.bbara.purefin.common.ui.MediaPlaybackSettings
import hu.bbara.purefin.common.ui.components.MediaPlaybackSettings
import hu.bbara.purefin.common.ui.toMediaDetailColors
@Composable
@@ -87,33 +88,34 @@ internal fun EpisodeDetails(
textColor = colors.primary
)
}
Spacer(modifier = Modifier.height(24.dp))
MediaPlaybackSettings(
colors = colors,
audioTrack = episode.audioTrack,
subtitles = episode.subtitles
)
Spacer(modifier = Modifier.height(24.dp))
Text(
text = "Synopsis",
color = colors.textPrimary,
fontSize = 18.sp,
fontWeight = FontWeight.Bold
)
Spacer(modifier = Modifier.height(8.dp))
Spacer(modifier = Modifier.height(12.dp))
Text(
text = episode.synopsis,
color = colors.textMuted,
fontSize = 15.sp,
lineHeight = 22.sp
)
Spacer(modifier = Modifier.height(24.dp))
MediaActionButtons(colors = colors)
Spacer(modifier = Modifier.height(28.dp))
MediaActionButtons(colors = colors)
Spacer(modifier = Modifier.height(24.dp))
MediaPlaybackSettings(
backgroundColor = MaterialTheme.colorScheme.surface,
foregroundColor = MaterialTheme.colorScheme.onSurface,
audioTrack = episode.audioTrack,
subtitles = episode.subtitles
)
Spacer(modifier = Modifier.height(24.dp))
Text(
text = "Cast",
color = colors.textPrimary,

View File

@@ -14,6 +14,7 @@ import androidx.compose.material.icons.Icons
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.runtime.Composable
import androidx.compose.ui.Alignment
@@ -26,7 +27,7 @@ import hu.bbara.purefin.common.ui.MediaCastMember
import hu.bbara.purefin.common.ui.MediaCastRow
import hu.bbara.purefin.common.ui.MediaGhostIconButton
import hu.bbara.purefin.common.ui.MediaMetaChip
import hu.bbara.purefin.common.ui.MediaPlaybackSettings
import hu.bbara.purefin.common.ui.components.MediaPlaybackSettings
import hu.bbara.purefin.common.ui.toMediaDetailColors
@Composable
@@ -90,7 +91,8 @@ internal fun MovieDetails(
Spacer(modifier = Modifier.height(24.dp))
MediaPlaybackSettings(
colors = colors,
backgroundColor = MaterialTheme.colorScheme.background,
foregroundColor = MaterialTheme.colorScheme.onBackground,
audioTrack = movie.audioTrack,
subtitles = movie.subtitles
)

View File

@@ -24,12 +24,8 @@ 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.Add
import androidx.compose.material.icons.outlined.ClosedCaption
import androidx.compose.material.icons.outlined.Download
import androidx.compose.material.icons.outlined.ExpandMore
import androidx.compose.material.icons.outlined.Person
import androidx.compose.material.icons.outlined.Tune
import androidx.compose.material.icons.outlined.VolumeUp
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@@ -155,97 +151,6 @@ fun MediaMetaChip(
}
}
@Composable
fun MediaPlaybackSettings(
colors: MediaDetailColors,
audioTrack: String,
subtitles: String,
headerIcon: ImageVector = Icons.Outlined.Tune,
audioIcon: ImageVector = Icons.Outlined.VolumeUp,
subtitleIcon: ImageVector = Icons.Outlined.ClosedCaption,
modifier: Modifier = Modifier
) {
Column(
modifier = modifier
.fillMaxWidth()
.clip(RoundedCornerShape(16.dp))
.background(colors.surfaceAlt)
.border(1.dp, colors.surfaceBorder, RoundedCornerShape(16.dp))
.padding(20.dp)
) {
Row(
verticalAlignment = Alignment.CenterVertically
) {
Icon(
imageVector = headerIcon,
contentDescription = null,
tint = colors.primary
)
Spacer(modifier = Modifier.width(8.dp))
Text(
text = "Playback Settings",
color = colors.textMuted,
fontSize = 12.sp,
fontWeight = FontWeight.Bold,
letterSpacing = 2.sp
)
}
Spacer(modifier = Modifier.height(16.dp))
Column(verticalArrangement = Arrangement.spacedBy(12.dp)) {
MediaSettingDropdown(
colors = colors,
label = "Audio Track",
value = audioTrack,
icon = audioIcon
)
MediaSettingDropdown(
colors = colors,
label = "Subtitles",
value = subtitles,
icon = subtitleIcon
)
}
}
}
@Composable
private fun MediaSettingDropdown(
colors: MediaDetailColors,
label: String,
value: String,
icon: ImageVector? = null
) {
Column {
Text(
text = label,
color = colors.textMutedStrong,
fontSize = 12.sp,
fontWeight = FontWeight.Medium,
modifier = Modifier.padding(start = 4.dp, bottom = 6.dp)
)
Row(
modifier = Modifier
.fillMaxWidth()
.height(48.dp)
.clip(RoundedCornerShape(12.dp))
.background(colors.surface)
.border(1.dp, colors.surfaceBorder, RoundedCornerShape(12.dp))
.padding(horizontal = 16.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
Row(verticalAlignment = Alignment.CenterVertically) {
if (icon != null) {
Icon(imageVector = icon, contentDescription = null, tint = colors.textMutedStrong)
Spacer(modifier = Modifier.width(10.dp))
}
Text(text = value, color = colors.textPrimary, fontSize = 14.sp)
}
Icon(imageVector = Icons.Outlined.ExpandMore, contentDescription = null, tint = colors.textMutedStrong)
}
}
}
@Composable
fun MediaActionButtons(
colors: MediaDetailColors,

View File

@@ -30,6 +30,7 @@ fun MediaHero(
modifier = Modifier.fillMaxSize(),
contentScale = ContentScale.Crop
)
// Vertical gradient for transition to content
Box(
modifier = Modifier
.matchParentSize()
@@ -37,23 +38,11 @@ fun MediaHero(
Brush.verticalGradient(
colors = listOf(
Color.Transparent,
backgroundColor.copy(alpha = 0.4f),
backgroundColor.copy(alpha = 0.5f),
backgroundColor
)
)
)
)
Box(
modifier = Modifier
.matchParentSize()
.background(
Brush.horizontalGradient(
colors = listOf(
Color.Transparent,
backgroundColor.copy(alpha = 0.8f)
)
)
)
)
}
}
}

View File

@@ -0,0 +1,103 @@
package hu.bbara.purefin.common.ui.components
import androidx.compose.foundation.background
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.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.ClosedCaption
import androidx.compose.material.icons.outlined.ExpandMore
import androidx.compose.material.icons.outlined.VolumeUp
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
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.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@Composable
fun MediaPlaybackSettings(
backgroundColor: Color,
foregroundColor: Color,
audioTrack: String,
subtitles: String,
audioIcon: ImageVector = Icons.Outlined.VolumeUp,
subtitleIcon: ImageVector = Icons.Outlined.ClosedCaption,
modifier: Modifier = Modifier
) {
Column(
modifier = modifier
.fillMaxWidth()
) {
MediaSettingDropdown(
backgroundColor = backgroundColor,
foregroundColor = foregroundColor,
label = "Audio Track",
value = audioTrack,
icon = audioIcon
)
Spacer(modifier = Modifier.height(12.dp))
MediaSettingDropdown(
backgroundColor = backgroundColor,
foregroundColor = foregroundColor,
label = "Subtitles",
value = subtitles,
icon = subtitleIcon
)
}
}
@Composable
private fun MediaSettingDropdown(
backgroundColor: Color,
foregroundColor: Color,
label: String,
value: String,
icon: ImageVector
) {
Row (
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = label,
color = foregroundColor,
fontSize = 14.sp,
fontWeight = FontWeight.Medium,
)
Spacer(modifier = Modifier.width(12.dp))
Row(
modifier = Modifier
.height(38.dp)
.clip(RoundedCornerShape(12.dp))
.background(backgroundColor)
.padding(horizontal = 16.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
Row(verticalAlignment = Alignment.CenterVertically) {
Icon(
imageVector = icon, contentDescription = null, tint = MaterialTheme.colorScheme.onBackground
)
Spacer(modifier = Modifier.width(10.dp))
Text(text = value, color = foregroundColor, fontSize = 14.sp)
}
Icon(
imageVector = Icons.Outlined.ExpandMore,
contentDescription = null,
tint = foregroundColor
)
}
}
}