new: add support for record title translations

This commit is contained in:
2026-06-26 14:39:20 +02:00
parent 184610fa20
commit d4e5990a5f
5 changed files with 46 additions and 18 deletions
@@ -72,12 +72,23 @@ fun PlayerScreen(
topBar = {
TopAppBar(
title = {
Text(
text = uiState.recordTitle,
style = MaterialTheme.typography.headlineSmall,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
Column {
Text(
text = uiState.recordTitle,
style = MaterialTheme.typography.headlineSmall,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
uiState.recordTitleTranslation?.let { translation ->
Text(
text = translation,
style = MaterialTheme.typography.titleSmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}
}
},
navigationIcon = {
IconButton(onClick = onBackClicked) {
@@ -132,6 +143,7 @@ private fun PlayerScreenPlayingPreview() {
PlayerScreen(
uiState = PlayerUiState(
recordTitle = "Demat",
recordTitleTranslation = "Bonjour",
playbackState = PlaybackState.PLAYING,
playbackTiming = PlaybackTiming(positionMs = 1234, durationMs = 5000),
subtitleLines = previewSubtitleLines,
@@ -151,6 +163,7 @@ private fun PlayerScreenPausedPreview() {
PlayerScreen(
uiState = PlayerUiState(
recordTitle = "Demat",
recordTitleTranslation = "Bonjour",
playbackState = PlaybackState.PAUSED,
playbackTiming = PlaybackTiming(positionMs = 1234, durationMs = 5000),
subtitleLines = previewSubtitleLines,
@@ -170,6 +183,7 @@ private fun PlayerScreenEndedPreview() {
PlayerScreen(
uiState = PlayerUiState(
recordTitle = "Demat",
recordTitleTranslation = "Bonjour",
playbackState = PlaybackState.ENDED,
playbackTiming = PlaybackTiming(positionMs = 1234, durationMs = 5000),
subtitleLines = previewSubtitleLines,
@@ -6,6 +6,7 @@ import fr.ajaury.gwenedeg.subtitle.domain.SubtitleLine
data class PlayerUiState(
val recordTitle: String = "",
val recordTitleTranslation: String? = null,
val playbackState: PlaybackState = PlaybackState.IDLE,
val playbackTiming: PlaybackTiming = PlaybackTiming(),
val subtitleLines: List<SubtitleLine> = emptyList(),
@@ -6,7 +6,7 @@ import fr.ajaury.gwenedeg.core.logging.domain.Logger
import fr.ajaury.gwenedeg.player.domain.AudioSessionManager
import fr.ajaury.gwenedeg.player.domain.PlaybackRepository
import fr.ajaury.gwenedeg.player.model.PlaybackState
import fr.ajaury.gwenedeg.player.model.PlaybackTiming
import fr.ajaury.gwenedeg.records.domain.Record
import fr.ajaury.gwenedeg.records.domain.RecordRepository
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
@@ -26,26 +26,26 @@ class PlayerViewModel(
private val audioSessionManager: AudioSessionManager,
private val logger: Logger,
) : ViewModel() {
private val recordTitle = MutableStateFlow("")
private val record = MutableStateFlow<Record?>(null)
private var recordLoaded = false
val uiState: StateFlow<PlayerUiState> = combine(
recordTitle,
record,
playbackRepository.playbackState,
playbackRepository.playbackTiming,
playbackRepository.subtitle,
playbackRepository.currentSubtitleIndex,
) { recordTitle, playbackState, playbackTiming, subtitle, currentSubtitleIndex ->
) { record, playbackState, playbackTiming, subtitle, currentSubtitleIndex ->
PlayerUiState(
recordTitle = recordTitle,
recordTitle = record?.title.orEmpty(),
recordTitleTranslation = record?.titleTranslation,
playbackState = playbackState,
playbackTiming = playbackTiming,
subtitleLines = subtitle.lines,
currentSubtitleIndex = currentSubtitleIndex,
)
}
.onStart { loadRecord() }
}.onStart { loadRecord() }
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5.seconds),
@@ -65,14 +65,14 @@ class PlayerViewModel(
recordLoaded = true
viewModelScope.launch {
val record = recordRepository.getRecord(id = recordId)
if (record == null) {
val loadedRecord = recordRepository.getRecord(id = recordId)
if (loadedRecord == null) {
logger.error(message = "Record not found: $recordId")
return@launch
}
recordTitle.value = record.title
playbackRepository.load(record = record)
record.value = loadedRecord
playbackRepository.load(record = loadedRecord)
}
}
@@ -4,6 +4,7 @@ data class Record(
val id: Int,
val index: Int,
val title: String,
val titleTranslation: String? = null,
val audioResourcePath: String,
val subtitleResourcePath: String,
val translationSubtitleResourcePath: String? = null,
@@ -2,9 +2,11 @@ package fr.ajaury.gwenedeg.records.ui
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
@@ -32,7 +34,16 @@ fun RecordView(
text = record.index.toString().padStart(2),
fontFamily = FontFamily.Monospace,
)
Text(text = record.title)
Column {
Text(text = record.title)
record.titleTranslation?.let { translation ->
Text(
text = translation,
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
}
}
}
}
@@ -45,6 +56,7 @@ private fun RecordViewPreview() {
id = 1,
index = 1,
title = "Sample Record",
titleTranslation = "Exemple d'enregistrement",
audioResourcePath = "files/Chom_bev_01.ogg",
subtitleResourcePath = "files/Chom_bev_01_st_bzh.lrc",
),