feat: add MediaProgressBar component and integrate into SeriesComponents for episode progress display

This commit is contained in:
2026-02-04 14:20:34 +01:00
parent 0ebd5c5afe
commit 4300c8ce84
3 changed files with 69 additions and 23 deletions

View File

@@ -50,6 +50,7 @@ import hu.bbara.purefin.common.ui.MediaCastRow
import hu.bbara.purefin.common.ui.MediaMetaChip import hu.bbara.purefin.common.ui.MediaMetaChip
import hu.bbara.purefin.common.ui.components.GhostIconButton import hu.bbara.purefin.common.ui.components.GhostIconButton
import hu.bbara.purefin.common.ui.components.MediaActionButton import hu.bbara.purefin.common.ui.components.MediaActionButton
import hu.bbara.purefin.common.ui.components.MediaProgressBar
import hu.bbara.purefin.common.ui.components.PurefinAsyncImage import hu.bbara.purefin.common.ui.components.PurefinAsyncImage
import hu.bbara.purefin.common.ui.components.WatchStateIndicator import hu.bbara.purefin.common.ui.components.WatchStateIndicator
import hu.bbara.purefin.data.model.CastMember import hu.bbara.purefin.data.model.CastMember
@@ -255,13 +256,21 @@ private fun EpisodeCard(
fontWeight = FontWeight.Bold fontWeight = FontWeight.Bold
) )
} }
WatchStateIndicator( if (episode.watched.not() && (episode.progress ?: 0.0) > 0) {
watched = episode.watched, MediaProgressBar(
started = (episode.progress ?: 0.0) > 0.0, progress = (episode.progress ?: 0.0).toFloat().div(100),
modifier = Modifier modifier = Modifier
.align(Alignment.TopEnd) .align(Alignment.BottomStart)
.padding(8.dp) )
) } else {
WatchStateIndicator(
watched = episode.watched,
started = (episode.progress ?: 0.0) > 0.0,
modifier = Modifier
.align(Alignment.TopEnd)
.padding(8.dp)
)
}
} }
Column( Column(
) { ) {

View File

@@ -10,10 +10,8 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
@@ -42,6 +40,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import coil3.request.ImageRequest import coil3.request.ImageRequest
import hu.bbara.purefin.common.ui.PosterCard import hu.bbara.purefin.common.ui.PosterCard
import hu.bbara.purefin.common.ui.components.MediaProgressBar
import hu.bbara.purefin.common.ui.components.PurefinAsyncImage import hu.bbara.purefin.common.ui.components.PurefinAsyncImage
import hu.bbara.purefin.player.PlayerActivity import hu.bbara.purefin.player.PlayerActivity
import org.jellyfin.sdk.model.UUID import org.jellyfin.sdk.model.UUID
@@ -136,22 +135,13 @@ fun ContinueWatchingCard(
}, },
contentScale = ContentScale.Crop, contentScale = ContentScale.Crop,
) )
Box( MediaProgressBar(
progress = item.progress.toFloat().nextUp().div(100),
foregroundColor = scheme.onSurface,
backgroundColor = scheme.primary,
modifier = Modifier modifier = Modifier
.align(Alignment.BottomStart) .align(Alignment.BottomStart)
.padding(bottom = 8.dp, start = 8.dp, end = 8.dp) )
.clip(RoundedCornerShape(24.dp))
.fillMaxWidth()
.height(4.dp)
.background(scheme.onBackground.copy(alpha = 0.2f))
) {
Box(
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth(item.progress.toFloat().nextUp().div(100))
.background(scheme.primary)
)
}
IconButton( IconButton(
modifier = Modifier modifier = Modifier
.align(Alignment.BottomEnd) .align(Alignment.BottomEnd)

View File

@@ -0,0 +1,47 @@
package hu.bbara.purefin.common.ui.components
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
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
/**
* A progress bar component for displaying media playback progress.
*
* @param progress The progress value between 0f and 1f, where 0f is no progress and 1f is complete.
* @param foregroundColor The color of the progress indicator.
* @param backgroundColor The color of the background/unfilled portion of the progress bar.
* @param modifier The modifier to be applied to the Box. Modifier should contain the Alignment.
*/
@Composable
fun MediaProgressBar(
progress: Float,
foregroundColor: Color = MaterialTheme.colorScheme.onSurface,
backgroundColor: Color = MaterialTheme.colorScheme.primary,
modifier: Modifier
) {
Box(
modifier = modifier
.padding(bottom = 8.dp, start = 8.dp, end = 8.dp)
.clip(RoundedCornerShape(24.dp))
.fillMaxWidth()
.height(4.dp)
.background(backgroundColor.copy(alpha = 0.2f))
) {
Box(
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth(progress)
.background(foregroundColor)
)
}
}