feature: add auto-pause playback feature
This commit is contained in:
+14
-4
@@ -186,11 +186,16 @@ internal class PlaybackRepositoryImpl(
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the configured silent break between spoken phrases: when continuous playback reaches
|
||||
* the next phrase, playback pauses just before that phrase starts, then resumes after the break.
|
||||
* Reacts to reaching the next spoken phrase during continuous playback, just before that phrase
|
||||
* starts. Depending on preferences it either:
|
||||
* - pauses and waits for the user to resume, when auto-pause is enabled, or
|
||||
* - pauses for the configured silent break and then resumes on its own.
|
||||
*
|
||||
* Breaks only happen on automatic advancement — manual seeking and previous/next navigation are
|
||||
* ignored via [suppressBreaks].
|
||||
* Auto-pause takes precedence: while it is on, the break between phrases is ignored.
|
||||
*
|
||||
* This only happens on automatic advancement — manual seeking and previous/next navigation are
|
||||
* ignored because they cancel the running break job and never re-enter [PlaybackState.PLAYING]
|
||||
* through this path.
|
||||
*/
|
||||
private suspend fun observePhraseBreaks() {
|
||||
phraseBreakJob?.cancel()
|
||||
@@ -203,6 +208,11 @@ internal class PlaybackRepositoryImpl(
|
||||
if (playbackState.firstOrNull() != PlaybackState.PLAYING) return@onEach
|
||||
|
||||
val playbackPreferences = preferencesRepository.playbackPreferences.first()
|
||||
if (playbackPreferences.autoPause) {
|
||||
audioPlayer.pause()
|
||||
return@onEach
|
||||
}
|
||||
|
||||
val breakDuration = playbackPreferences.breakBetweenPhrases
|
||||
if (breakDuration <= Duration.ZERO) return@onEach
|
||||
|
||||
|
||||
+4
@@ -43,4 +43,8 @@ internal class InMemoryPreferencesRepository : PreferencesRepository {
|
||||
override suspend fun setBreakBetweenPhrases(duration: Duration) {
|
||||
playbackState.update { it.copy(breakBetweenPhrases = duration) }
|
||||
}
|
||||
|
||||
override suspend fun setAutoPause(enabled: Boolean) {
|
||||
playbackState.update { it.copy(autoPause = enabled) }
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -21,4 +21,6 @@ interface PreferencesRepository {
|
||||
suspend fun setPlaybackSpeed(speed: Float)
|
||||
|
||||
suspend fun setBreakBetweenPhrases(duration: Duration)
|
||||
|
||||
suspend fun setAutoPause(enabled: Boolean)
|
||||
}
|
||||
|
||||
+5
@@ -10,10 +10,13 @@ import kotlin.time.Duration.Companion.seconds
|
||||
* [SPEED_STEP] increments. [DEFAULT_SPEED] is the normal, unaltered speed.
|
||||
* @property breakBetweenPhrases silent pause inserted when moving from one phrase to the next,
|
||||
* between [DEFAULT_BREAK_BETWEEN_PHRASES] and [MAX_BREAK_BETWEEN_PHRASES] in [BREAK_STEP] steps.
|
||||
* @property autoPause when enabled, playback stops at the end of every phrase and waits for the
|
||||
* user to resume. This takes precedence over [breakBetweenPhrases], which is then ignored.
|
||||
*/
|
||||
data class PlaybackPreferences(
|
||||
val speed: Float = DEFAULT_SPEED,
|
||||
val breakBetweenPhrases: Duration = DEFAULT_BREAK_BETWEEN_PHRASES,
|
||||
val autoPause: Boolean = DEFAULT_AUTO_PAUSE,
|
||||
) {
|
||||
companion object {
|
||||
const val DEFAULT_SPEED = 1f
|
||||
@@ -24,5 +27,7 @@ data class PlaybackPreferences(
|
||||
val DEFAULT_BREAK_BETWEEN_PHRASES: Duration = Duration.ZERO
|
||||
val MAX_BREAK_BETWEEN_PHRASES: Duration = 5.seconds
|
||||
val BREAK_STEP: Duration = 1.seconds
|
||||
|
||||
const val DEFAULT_AUTO_PAUSE = false
|
||||
}
|
||||
}
|
||||
|
||||
+4
@@ -44,6 +44,8 @@ internal class DataStorePreferencesRepository(
|
||||
override suspend fun setBreakBetweenPhrases(duration: Duration) =
|
||||
edit { it[BreakBetweenPhrasesSecondsKey] = duration.inWholeSeconds.toInt() }
|
||||
|
||||
override suspend fun setAutoPause(enabled: Boolean) = edit { it[AutoPauseKey] = enabled }
|
||||
|
||||
private suspend fun edit(transform: (MutablePreferences) -> Unit) {
|
||||
dataStore.edit(transform)
|
||||
}
|
||||
@@ -63,6 +65,7 @@ internal class DataStorePreferencesRepository(
|
||||
speed = this[PlaybackSpeedKey] ?: PlaybackPreferences.DEFAULT_SPEED,
|
||||
breakBetweenPhrases = this[BreakBetweenPhrasesSecondsKey]?.seconds
|
||||
?: PlaybackPreferences.DEFAULT_BREAK_BETWEEN_PHRASES,
|
||||
autoPause = this[AutoPauseKey] ?: PlaybackPreferences.DEFAULT_AUTO_PAUSE,
|
||||
)
|
||||
|
||||
private companion object {
|
||||
@@ -72,5 +75,6 @@ internal class DataStorePreferencesRepository(
|
||||
val ShowPhoneticMarkersKey = booleanPreferencesKey("show_phonetic_marker")
|
||||
val PlaybackSpeedKey = floatPreferencesKey("playback_speed")
|
||||
val BreakBetweenPhrasesSecondsKey = intPreferencesKey("break_between_phrases_seconds")
|
||||
val AutoPauseKey = booleanPreferencesKey("auto_pause")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
<string name="playback_settings_action">Arventennoù al lenn</string>
|
||||
<string name="break_between_phrases_title">Ehan etre ar frazennoù</string>
|
||||
<string name="break_between_phrases_value">%1$d s</string>
|
||||
<string name="auto_pause_title">Ehan emgefreek</string>
|
||||
<string name="auto_pause_description">Ehanañ goude pep frazenn</string>
|
||||
|
||||
<string name="player_back">Distreiñ</string>
|
||||
<string name="player_previous_sentence">Frazenn a-raok</string>
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
<string name="playback_settings_action">Réglages de lecture</string>
|
||||
<string name="break_between_phrases_title">Pause entre les phrases</string>
|
||||
<string name="break_between_phrases_value">%1$d s</string>
|
||||
<string name="auto_pause_title">Pause automatique</string>
|
||||
<string name="auto_pause_description">Mettre en pause après chaque phrase</string>
|
||||
|
||||
<string name="player_back">Retour</string>
|
||||
<string name="player_previous_sentence">Phrase précédente</string>
|
||||
|
||||
Reference in New Issue
Block a user