refactor media play button and integrate into detail screens

- Replace `MediaFloatingPlayButton` with a new `MediaPlayButton` component in `EpisodeScreen` and `MovieScreen`.
- Move play action logic from screens into `EpisodeComponents` and `MovieComponents`.
- Update `MovieComponents` layout to include the play button and improve vertical spacing and dividers.
- Refactor `MediaPlayButton` to support text labels and custom styling, moving it to a standalone file.
- Remove unused `MediaFloatingPlayButton` and old `MediaPlayButton` implementation from `MediaDetailComponents.kt`.
This commit is contained in:
2026-01-22 22:15:57 +01:00
parent 8c29f681c5
commit 48a773fded
6 changed files with 150 additions and 130 deletions

View File

@@ -1,5 +1,6 @@
package hu.bbara.purefin.app.content.episode
import android.content.Intent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
@@ -19,9 +20,12 @@ import androidx.compose.material.icons.outlined.Download
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.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@@ -30,8 +34,10 @@ 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.components.MediaActionButton
import hu.bbara.purefin.common.ui.components.MediaPlayButton
import hu.bbara.purefin.common.ui.components.MediaPlaybackSettings
import hu.bbara.purefin.common.ui.toMediaDetailColors
import hu.bbara.purefin.player.PlayerActivity
@Composable
internal fun EpisodeTopBar(
@@ -66,6 +72,15 @@ internal fun EpisodeDetails(
episode: EpisodeUiModel,
modifier: Modifier = Modifier
) {
val context = LocalContext.current
val playAction = remember(episode.id) {
{
val intent = Intent(context, PlayerActivity::class.java)
intent.putExtra("MEDIA_ID", episode.id.toString())
context.startActivity(intent)
}
}
val colors = rememberEpisodeColors().toMediaDetailColors()
Column(modifier = modifier) {
Text(
@@ -108,6 +123,20 @@ internal fun EpisodeDetails(
)
Spacer(modifier = Modifier.height(24.dp))
Row() {
MediaPlayButton(
backgroundColor = MaterialTheme.colorScheme.primary,
foregroundColor = MaterialTheme.colorScheme.onPrimary,
size = 48.dp,
onClick = playAction
)
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,
@@ -123,6 +152,7 @@ internal fun EpisodeDetails(
height = 48.dp
)
}
}
Spacer(modifier = Modifier.height(24.dp))
MediaPlaybackSettings(

View File

@@ -1,6 +1,5 @@
package hu.bbara.purefin.app.content.episode
import android.content.Intent
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
@@ -12,18 +11,14 @@ import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import hu.bbara.purefin.app.content.ContentMockData
import hu.bbara.purefin.common.ui.MediaFloatingPlayButton
import hu.bbara.purefin.common.ui.PurefinWaitingScreen
import hu.bbara.purefin.common.ui.components.MediaHero
import hu.bbara.purefin.navigation.ItemDto
import hu.bbara.purefin.player.PlayerActivity
@Composable
fun EpisodeScreen(
@@ -56,14 +51,6 @@ private fun EpisodeScreenInternal(
onBack: () -> Unit,
modifier: Modifier = Modifier,
) {
val context = LocalContext.current
val playAction = remember(episode.id) {
{
val intent = Intent(context, PlayerActivity::class.java)
intent.putExtra("MEDIA_ID", episode.id.toString())
context.startActivity(intent)
}
}
Scaffold(
modifier = modifier,
@@ -73,15 +60,6 @@ private fun EpisodeScreenInternal(
onBack = onBack,
modifier = Modifier
)
},
floatingActionButton = {
MediaFloatingPlayButton(
containerColor = MaterialTheme.colorScheme.primary,
onContainerColor = MaterialTheme.colorScheme.onPrimary,
onClick = playAction,
modifier = Modifier
.padding(16.dp)
)
}
) { innerPadding ->
Column(

View File

@@ -1,5 +1,6 @@
package hu.bbara.purefin.app.content.movie
import android.content.Intent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
@@ -19,9 +20,12 @@ import androidx.compose.material.icons.outlined.Download
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.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@@ -30,8 +34,10 @@ 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.components.MediaActionButton
import hu.bbara.purefin.common.ui.components.MediaPlayButton
import hu.bbara.purefin.common.ui.components.MediaPlaybackSettings
import hu.bbara.purefin.common.ui.toMediaDetailColors
import hu.bbara.purefin.player.PlayerActivity
@Composable
internal fun MovieTopBar(
@@ -66,6 +72,15 @@ internal fun MovieDetails(
movie: MovieUiModel,
modifier: Modifier = Modifier
) {
val context = LocalContext.current
val playAction = remember(movie.id) {
{
val intent = Intent(context, PlayerActivity::class.java)
intent.putExtra("MEDIA_ID", movie.id.toString())
context.startActivity(intent)
}
}
val colors = rememberMovieColors().toMediaDetailColors()
Column(modifier = modifier) {
Text(
@@ -91,50 +106,63 @@ internal fun MovieDetails(
textColor = colors.primary
)
}
Spacer(modifier = Modifier.height(24.dp))
MediaPlaybackSettings(
backgroundColor = MaterialTheme.colorScheme.background,
foregroundColor = MaterialTheme.colorScheme.onBackground,
audioTrack = movie.audioTrack,
subtitles = movie.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 = movie.synopsis,
color = colors.textMuted,
fontSize = 15.sp,
lineHeight = 22.sp
)
Spacer(modifier = Modifier.height(24.dp))
Row() {
MediaPlayButton(
backgroundColor = MaterialTheme.colorScheme.primary,
foregroundColor = MaterialTheme.colorScheme.onPrimary,
size = 48.dp,
onClick = playAction
)
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 = 32.dp
height = 48.dp
)
Spacer(modifier = Modifier.width(12.dp))
MediaActionButton(
backgroundColor = MaterialTheme.colorScheme.secondary,
iconColor = MaterialTheme.colorScheme.onSecondary,
icon = Icons.Outlined.Download,
height = 32.dp
height = 48.dp
)
}
}
Spacer(modifier = Modifier.height(24.dp))
Spacer(modifier = Modifier.height(28.dp))
MediaPlaybackSettings(
backgroundColor = MaterialTheme.colorScheme.surface,
foregroundColor = MaterialTheme.colorScheme.onSurface,
audioTrack = movie.audioTrack,
subtitles = movie.subtitles
)
Spacer(modifier = Modifier.height(24.dp))
Text(
text = "Cast",
color = colors.textPrimary,

View File

@@ -1,6 +1,5 @@
package hu.bbara.purefin.app.content.movie
import android.content.Intent
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
@@ -12,18 +11,14 @@ import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import hu.bbara.purefin.app.content.ContentMockData
import hu.bbara.purefin.common.ui.MediaFloatingPlayButton
import hu.bbara.purefin.common.ui.PurefinWaitingScreen
import hu.bbara.purefin.common.ui.components.MediaHero
import hu.bbara.purefin.navigation.ItemDto
import hu.bbara.purefin.player.PlayerActivity
@Composable
fun MovieScreen(
@@ -52,15 +47,6 @@ private fun MovieScreenInternal(
onBack: () -> Unit,
modifier: Modifier = Modifier,
) {
val context = LocalContext.current
val playAction = remember(movie.id) {
{
val intent = Intent(context, PlayerActivity::class.java)
intent.putExtra("MEDIA_ID", movie.id.toString())
context.startActivity(intent)
}
}
Scaffold(
modifier = modifier,
containerColor = MaterialTheme.colorScheme.background,
@@ -69,15 +55,6 @@ private fun MovieScreenInternal(
onBack = onBack,
modifier = Modifier
)
},
floatingActionButton = {
MediaFloatingPlayButton(
containerColor = MaterialTheme.colorScheme.primary,
onContainerColor = MaterialTheme.colorScheme.onPrimary,
onClick = playAction,
modifier = Modifier
.padding(16.dp)
)
}
) { innerPadding ->
Column(

View File

@@ -20,7 +20,6 @@ import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
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.Icon
import androidx.compose.material3.Text
@@ -28,7 +27,6 @@ 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.draw.shadow
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.layout.ContentScale
@@ -217,52 +215,3 @@ fun MediaCastRow(
}
}
}
@Composable
fun MediaPlayButton(
colors: MediaDetailColors,
size: Dp,
onClick: () -> Unit,
modifier: Modifier = Modifier
) {
Box(
modifier = modifier
.size(size)
.shadow(24.dp, CircleShape)
.clip(CircleShape)
.background(colors.primary)
.clickable { onClick() },
contentAlignment = Alignment.Center
) {
Icon(
imageVector = Icons.Filled.PlayArrow,
contentDescription = "Play",
tint = colors.onPrimary,
modifier = Modifier.size(42.dp)
)
}
}
@Composable
fun MediaFloatingPlayButton(
containerColor: Color,
onContainerColor: Color,
onClick: () -> Unit,
modifier: Modifier = Modifier
) {
Box(
modifier = modifier
.size(56.dp)
.shadow(20.dp, CircleShape)
.clip(CircleShape)
.background(containerColor)
.clickable { onClick() },
contentAlignment = Alignment.Center
) {
Icon(
imageVector = Icons.Filled.PlayArrow,
contentDescription = "Play",
tint = onContainerColor
)
}
}

View File

@@ -0,0 +1,58 @@
package hu.bbara.purefin.common.ui.components
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material3.Icon
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.unit.Dp
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.TextUnitType
import androidx.compose.ui.unit.dp
@Composable
fun MediaPlayButton(
backgroundColor: Color,
foregroundColor: Color,
size: Dp,
onClick: () -> Unit,
modifier: Modifier = Modifier
) {
Row(
modifier = modifier
.height(size)
.clip(CircleShape)
.background(backgroundColor)
.padding(start = 16.dp, end = 32.dp)
.clickable { onClick() },
horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
imageVector = Icons.Filled.PlayArrow,
contentDescription = "Play",
tint = foregroundColor,
modifier = Modifier.size(42.dp)
)
Text(
text = "Play",
color = foregroundColor,
fontSize = TextUnit(
value = 16f,
type = TextUnitType.Sp
)
)
}
}