new: display playback progress with a progress bar

This commit is contained in:
2026-06-19 13:38:32 +02:00
parent 090305dbde
commit 511e3b5b9a
8 changed files with 61 additions and 20 deletions
@@ -4,7 +4,9 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
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.material.icons.Icons
@@ -16,6 +18,7 @@ import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
@@ -85,7 +88,8 @@ fun PlayerScreen(
Box(
modifier = Modifier
.padding(innerPadding)
.fillMaxSize(),
.fillMaxSize()
.padding(16.dp),
contentAlignment = Alignment.Center,
) {
Column(
@@ -97,9 +101,11 @@ fun PlayerScreen(
style = MaterialTheme.typography.headlineMedium,
)
Text(
text = "${uiState.positionMs} ms",
style = MaterialTheme.typography.bodyMedium,
Spacer(modifier = Modifier.weight(1f))
LinearProgressIndicator(
progress = { uiState.progress },
modifier = Modifier.fillMaxWidth(),
)
Button(
@@ -137,7 +143,7 @@ private fun PlayerScreenPlayingPreview() {
GwenedegTheme {
PlayerScreen(
recordTitle = "Demat",
uiState = PlayerUiState(playbackState = PlaybackState.PLAYING, positionMs = 1234),
uiState = PlayerUiState(playbackState = PlaybackState.PLAYING, positionMs = 1234, durationMs = 5000),
onMainPlayActionButtonClicked = {},
onBackClicked = {},
)
@@ -150,7 +156,7 @@ private fun PlayerScreenPausedPreview() {
GwenedegTheme {
PlayerScreen(
recordTitle = "Demat",
uiState = PlayerUiState(playbackState = PlaybackState.PAUSED, positionMs = 1234),
uiState = PlayerUiState(playbackState = PlaybackState.PAUSED, positionMs = 1234, durationMs = 5000),
onMainPlayActionButtonClicked = {},
onBackClicked = {},
)
@@ -163,7 +169,7 @@ private fun PlayerScreenEndedPreview() {
GwenedegTheme {
PlayerScreen(
recordTitle = "Demat",
uiState = PlayerUiState(playbackState = PlaybackState.ENDED, positionMs = 1234),
uiState = PlayerUiState(playbackState = PlaybackState.ENDED, positionMs = 1234, durationMs = 5000),
onMainPlayActionButtonClicked = {},
onBackClicked = {},
)
@@ -5,4 +5,8 @@ import fr.ajaury.gwenedeg.player.PlaybackState
data class PlayerUiState(
val playbackState: PlaybackState = PlaybackState.IDLE,
val positionMs: Long = 0L,
)
val durationMs: Long = 0L,
) {
val progress: Float
get() = if (durationMs > 0) (positionMs.toFloat() / durationMs).coerceIn(0f, 1f) else 0f
}
@@ -35,12 +35,12 @@ class PlayerViewModel(
if (state == PlaybackState.PLAYING) {
flow {
while (true) {
emit(audioPlayer.currentPosition())
emit(audioPlayer.currentPosition)
delay(POSITION_POLL_INTERVAL)
}
}
} else {
flowOf(audioPlayer.currentPosition())
flowOf(audioPlayer.currentPosition)
}
}
@@ -51,6 +51,7 @@ class PlayerViewModel(
PlayerUiState(
playbackState = playbackState,
positionMs = currentPositionMs.inWholeMilliseconds,
durationMs = audioPlayer.duration.inWholeMilliseconds,
)
}.stateIn(
scope = viewModelScope,
@@ -91,6 +92,6 @@ class PlayerViewModel(
}
companion object {
private val POSITION_POLL_INTERVAL = 200.milliseconds
private val POSITION_POLL_INTERVAL = 50.milliseconds
}
}