refactor: prefer using Duration than milliseconds
This commit is contained in:
+2
-2
@@ -56,8 +56,8 @@ internal class PlaybackRepositoryImpl(
|
||||
|
||||
private val playbackTiming = currentPosition.map { currentPosition ->
|
||||
PlaybackTiming(
|
||||
positionMs = currentPosition.inWholeMilliseconds,
|
||||
durationMs = duration.inWholeMilliseconds,
|
||||
position = currentPosition,
|
||||
duration = duration,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -1,9 +1,9 @@
|
||||
package fr.ajaury.gwenedeg.player.model
|
||||
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
data class PlaybackTiming(
|
||||
val positionMs: Long = 0L,
|
||||
val durationMs: Long = 0L,
|
||||
) {
|
||||
val progress: Float
|
||||
get() = if (durationMs > 0) (positionMs.toFloat() / durationMs).coerceIn(0f, 1f) else 0f
|
||||
}
|
||||
val position: Duration = 0.milliseconds,
|
||||
val duration: Duration = 0.milliseconds,
|
||||
)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package fr.ajaury.gwenedeg.subtitle.data
|
||||
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
import kotlin.time.Duration.Companion.minutes
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
/**
|
||||
* Parses [LRC](https://en.wikipedia.org/wiki/LRC_(file_format)) subtitle content.
|
||||
@@ -26,15 +29,15 @@ internal class LrcParser {
|
||||
.findAll(tags.value)
|
||||
.mapNotNull { match ->
|
||||
TimeCodedText(
|
||||
startTime = match.toMs().milliseconds,
|
||||
startTime = match.asDuration(),
|
||||
text = text,
|
||||
).takeIf { text.isNotBlank() }
|
||||
}.toList()
|
||||
}
|
||||
|
||||
private fun MatchResult.toMs(): Long {
|
||||
private fun MatchResult.asDuration(): Duration {
|
||||
val (minutes, seconds, fraction) = destructured
|
||||
val fractionMs = if (fraction.length == 2) fraction.toLong() * 10 else fraction.toLong()
|
||||
return minutes.toLong() * 60_000 + seconds.toLong() * 1_000 + fractionMs
|
||||
return minutes.toInt().minutes + seconds.toInt().seconds + fractionMs.toInt().milliseconds
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ import fr.ajaury.gwenedeg.player.ui.components.PreviousButton
|
||||
import fr.ajaury.gwenedeg.player.ui.components.SpeedPreferenceButton
|
||||
import fr.ajaury.gwenedeg.preferences.model.PlaybackPreferences
|
||||
import fr.ajaury.gwenedeg.theme.GwenedegTheme
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
@Composable
|
||||
fun PlayerControl(
|
||||
@@ -30,7 +32,7 @@ fun PlayerControl(
|
||||
canGoToNextSentence: Boolean,
|
||||
isSpeedActive: Boolean,
|
||||
playbackSpeed: Float,
|
||||
onSeek: (Float) -> Unit = {},
|
||||
onSeek: (Duration) -> Unit = {},
|
||||
onMainPlayActionButtonClicked: () -> Unit = {},
|
||||
onPreviousSentenceClicked: () -> Unit = {},
|
||||
onNextSentenceClicked: () -> Unit = {},
|
||||
@@ -95,7 +97,7 @@ private fun PlayerControlPreview() {
|
||||
GwenedegTheme {
|
||||
PlayerControl(
|
||||
playbackState = PlaybackState.PLAYING,
|
||||
playbackTiming = PlaybackTiming(positionMs = 1234, durationMs = 5000),
|
||||
playbackTiming = PlaybackTiming(position = 1.2.seconds, duration = 5.seconds),
|
||||
canGoToPreviousSentence = true,
|
||||
canGoToNextSentence = true,
|
||||
isSpeedActive = false,
|
||||
@@ -110,7 +112,7 @@ private fun PlayerControlFirstSentencePreview() {
|
||||
GwenedegTheme {
|
||||
PlayerControl(
|
||||
playbackState = PlaybackState.PLAYING,
|
||||
playbackTiming = PlaybackTiming(positionMs = 1234, durationMs = 5000),
|
||||
playbackTiming = PlaybackTiming(position = 1.2.seconds, duration = 5.seconds),
|
||||
canGoToPreviousSentence = false,
|
||||
canGoToNextSentence = true,
|
||||
playbackSpeed = PlaybackPreferences.DEFAULT_SPEED,
|
||||
@@ -125,7 +127,7 @@ private fun PlayerControlActiveSpeedPreview() {
|
||||
GwenedegTheme {
|
||||
PlayerControl(
|
||||
playbackState = PlaybackState.PLAYING,
|
||||
playbackTiming = PlaybackTiming(positionMs = 1234, durationMs = 5000),
|
||||
playbackTiming = PlaybackTiming(position = 1.2.seconds, duration = 5.seconds),
|
||||
canGoToPreviousSentence = true,
|
||||
canGoToNextSentence = true,
|
||||
playbackSpeed = 0.7f,
|
||||
@@ -140,7 +142,7 @@ private fun PlayerControlLastSentencePreview() {
|
||||
GwenedegTheme {
|
||||
PlayerControl(
|
||||
playbackState = PlaybackState.PLAYING,
|
||||
playbackTiming = PlaybackTiming(positionMs = 1234, durationMs = 5000),
|
||||
playbackTiming = PlaybackTiming(position = 1.2.seconds, duration = 5.seconds),
|
||||
canGoToPreviousSentence = true,
|
||||
canGoToNextSentence = false,
|
||||
playbackSpeed = PlaybackPreferences.DEFAULT_SPEED,
|
||||
|
||||
@@ -38,7 +38,9 @@ import fr.ajaury.gwenedeg.subtitle.model.SubtitleLine
|
||||
import fr.ajaury.gwenedeg.theme.GwenedegTheme
|
||||
import org.koin.compose.viewmodel.koinViewModel
|
||||
import org.koin.core.parameter.parametersOf
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
@Composable
|
||||
fun PlayerScreen(
|
||||
@@ -75,7 +77,7 @@ fun PlayerScreen(
|
||||
fun PlayerScreen(
|
||||
uiState: PlayerUiState,
|
||||
onMainPlayActionButtonClicked: () -> Unit = {},
|
||||
onSeekToTimePart: (progress: Float) -> Unit = {},
|
||||
onSeekToTimePart: (progress: Duration) -> Unit = {},
|
||||
onSeekToSentence: (position: Int) -> Unit = {},
|
||||
onPreviousSentenceClicked: () -> Unit = {},
|
||||
onNextSentenceClicked: () -> Unit = {},
|
||||
@@ -218,7 +220,7 @@ private fun PlayerScreenPlayingPreview() {
|
||||
),
|
||||
playerState = PlayerState(
|
||||
playbackState = PlaybackState.PLAYING,
|
||||
playbackTiming = PlaybackTiming(positionMs = 1234, durationMs = 5000),
|
||||
playbackTiming = PlaybackTiming(position = 1.2.seconds, duration = 5.seconds),
|
||||
subtitleLines = previewSubtitleLines,
|
||||
currentSubtitleIndex = 1,
|
||||
),
|
||||
@@ -242,7 +244,7 @@ private fun PlayerScreenPausedPreview() {
|
||||
),
|
||||
playerState = PlayerState(
|
||||
playbackState = PlaybackState.PAUSED,
|
||||
playbackTiming = PlaybackTiming(positionMs = 1234, durationMs = 5000),
|
||||
playbackTiming = PlaybackTiming(position = 1.2.seconds, duration = 5.seconds),
|
||||
subtitleLines = previewSubtitleLines,
|
||||
currentSubtitleIndex = 1,
|
||||
),
|
||||
@@ -266,7 +268,7 @@ private fun PlayerScreenEndedPreview() {
|
||||
),
|
||||
playerState = PlayerState(
|
||||
playbackState = PlaybackState.ENDED,
|
||||
playbackTiming = PlaybackTiming(positionMs = 1234, durationMs = 5000),
|
||||
playbackTiming = PlaybackTiming(position = 1.2.seconds, duration = 5.seconds),
|
||||
subtitleLines = previewSubtitleLines,
|
||||
currentSubtitleIndex = 2,
|
||||
),
|
||||
|
||||
+11
-7
@@ -11,21 +11,25 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import fr.ajaury.gwenedeg.player.model.PlaybackTiming
|
||||
import fr.ajaury.gwenedeg.theme.GwenedegTheme
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
|
||||
@Composable
|
||||
fun PlaybackProgress(
|
||||
playbackTiming: PlaybackTiming,
|
||||
onSeek: (Float) -> Unit = {},
|
||||
onSeek: (Duration) -> Unit = {},
|
||||
) {
|
||||
var seekProgress by remember { mutableStateOf<Float?>(null) }
|
||||
Slider(
|
||||
value = seekProgress ?: playbackTiming.progress,
|
||||
value = seekProgress ?: playbackTiming.position.inWholeMilliseconds.toFloat(),
|
||||
valueRange = 0f..playbackTiming.duration.inWholeMilliseconds.toFloat(),
|
||||
onValueChange = { seekProgress = it },
|
||||
onValueChangeFinished = {
|
||||
seekProgress?.let { fraction ->
|
||||
if (playbackTiming.durationMs > 0) {
|
||||
onSeek(fraction)
|
||||
if (playbackTiming.duration.isPositive()) {
|
||||
onSeek(fraction.toInt().milliseconds)
|
||||
}
|
||||
}
|
||||
seekProgress = null
|
||||
@@ -39,7 +43,7 @@ fun PlaybackProgress(
|
||||
private fun PlaybackProgressPreview() {
|
||||
GwenedegTheme {
|
||||
PlaybackProgress(
|
||||
playbackTiming = PlaybackTiming(0, 0),
|
||||
playbackTiming = PlaybackTiming(0.seconds, 0.seconds),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -49,7 +53,7 @@ private fun PlaybackProgressPreview() {
|
||||
private fun PlaybackProgressInProgressPreview() {
|
||||
GwenedegTheme {
|
||||
PlaybackProgress(
|
||||
playbackTiming = PlaybackTiming(7000, 10000),
|
||||
playbackTiming = PlaybackTiming(7.seconds, 10.seconds),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -59,7 +63,7 @@ private fun PlaybackProgressInProgressPreview() {
|
||||
private fun PlaybackProgressEndedPreview() {
|
||||
GwenedegTheme {
|
||||
PlaybackProgress(
|
||||
playbackTiming = PlaybackTiming(10000, 10000),
|
||||
playbackTiming = PlaybackTiming(10.seconds, 10.seconds),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -4,6 +4,7 @@ import fr.ajaury.gwenedeg.core.model.Phrase
|
||||
import fr.ajaury.gwenedeg.player.model.PlayerState
|
||||
import fr.ajaury.gwenedeg.preferences.model.PlaybackPreferences
|
||||
import fr.ajaury.gwenedeg.preferences.model.SubtitlePreferences
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
data class PlayerUiState(
|
||||
val recordTitle: Phrase = Phrase(transcription = ""),
|
||||
@@ -12,7 +13,7 @@ data class PlayerUiState(
|
||||
val playbackSpeed: Float = PlaybackPreferences.DEFAULT_SPEED,
|
||||
) {
|
||||
val canGoToPreviousSentence: Boolean
|
||||
get() = playerState.playbackTiming.positionMs > 2000
|
||||
get() = playerState.playbackTiming.position > 2.seconds
|
||||
|
||||
val canGoToNextSentence: Boolean
|
||||
get() = (playerState.currentSubtitleIndex ?: Int.MAX_VALUE) < playerState.subtitleLines.lastIndex
|
||||
|
||||
+3
-5
@@ -19,7 +19,7 @@ import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
class PlayerViewModel(
|
||||
@@ -89,10 +89,8 @@ class PlayerViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
fun seekToTimePart(progress: Float) {
|
||||
val playbackTiming = uiState.value.playerState.playbackTiming
|
||||
val position = (progress.toDouble() * playbackTiming.durationMs).milliseconds
|
||||
playbackRepository.seekTo(position)
|
||||
fun seekToTimePart(progress: Duration) {
|
||||
playbackRepository.seekTo(progress)
|
||||
}
|
||||
|
||||
fun seekToSentence(sentenceIndex: Int) {
|
||||
|
||||
Reference in New Issue
Block a user