Add preference for skipping back on resume

This commit is contained in:
Damontecres 2025-10-07 01:17:17 -04:00
parent c1e64beb74
commit e412c3da48
No known key found for this signature in database
9 changed files with 63 additions and 1 deletions

View file

@ -212,6 +212,28 @@ sealed interface AppPreference<T> {
summaryOff = R.string.disabled, summaryOff = R.string.disabled,
) )
val SkipBackOnResume =
AppSliderPreference(
title = R.string.skip_back_on_resume_preference,
defaultValue = 0,
min = 0,
max = 10,
interval = 1,
getter = { it.playbackPreferences.skipBackOnResumeSeconds.milliseconds.inWholeSeconds },
setter = { prefs, value ->
prefs.updatePlaybackPreferences {
skipBackOnResumeSeconds = value.seconds.inWholeMilliseconds
}
},
summarizer = { value ->
if (value == 0L) {
"Disabled"
} else {
"${value}s"
}
},
)
val AutoPlayNextDelay = val AutoPlayNextDelay =
AppSliderPreference( AppSliderPreference(
title = R.string.auto_play_next_delay, title = R.string.auto_play_next_delay,
@ -290,6 +312,7 @@ val basicPreferences =
AppPreference.ControllerTimeout, AppPreference.ControllerTimeout,
AppPreference.AutoPlayNextUp, AppPreference.AutoPlayNextUp,
AppPreference.AutoPlayNextDelay, AppPreference.AutoPlayNextDelay,
AppPreference.SkipBackOnResume,
AppPreference.PlaybackDebugInfo, AppPreference.PlaybackDebugInfo,
), ),
), ),

View file

@ -29,6 +29,8 @@ class AppPreferencesSerializer
autoPlayNext = AppPreference.AutoPlayNextUp.defaultValue autoPlayNext = AppPreference.AutoPlayNextUp.defaultValue
autoPlayNextDelaySeconds = autoPlayNextDelaySeconds =
AppPreference.AutoPlayNextDelay.defaultValue AppPreference.AutoPlayNextDelay.defaultValue
skipBackOnResumeSeconds =
AppPreference.SkipBackOnResume.defaultValue.seconds.inWholeMilliseconds
}.build() }.build()
homePagePreferences = homePagePreferences =
HomePagePreferences HomePagePreferences

View file

@ -0,0 +1,12 @@
package com.github.damontecres.dolphin.preferences
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
val PlaybackPreferences.skipBackOnResume: Duration?
get() =
if (skipBackOnResumeSeconds > 0) {
skipBackOnResumeSeconds.milliseconds
} else {
null
}

View file

@ -57,6 +57,7 @@ import androidx.media3.ui.compose.state.rememberPreviousButtonState
import androidx.tv.material3.MaterialTheme import androidx.tv.material3.MaterialTheme
import androidx.tv.material3.surfaceColorAtElevation import androidx.tv.material3.surfaceColorAtElevation
import com.github.damontecres.dolphin.preferences.UserPreferences import com.github.damontecres.dolphin.preferences.UserPreferences
import com.github.damontecres.dolphin.preferences.skipBackOnResume
import com.github.damontecres.dolphin.ui.OneTimeLaunchedEffect import com.github.damontecres.dolphin.ui.OneTimeLaunchedEffect
import com.github.damontecres.dolphin.ui.components.LoadingPage import com.github.damontecres.dolphin.ui.components.LoadingPage
import com.github.damontecres.dolphin.ui.nav.Destination import com.github.damontecres.dolphin.ui.nav.Destination
@ -171,6 +172,7 @@ fun PlaybackContent(
seekBack = preferences.appPreferences.playbackPreferences.skipBackMs.milliseconds, seekBack = preferences.appPreferences.playbackPreferences.skipBackMs.milliseconds,
controllerViewState = controllerViewState, controllerViewState = controllerViewState,
updateSkipIndicator = updateSkipIndicator, updateSkipIndicator = updateSkipIndicator,
skipBackOnResume = preferences.appPreferences.playbackPreferences.skipBackOnResume,
) )
Box( Box(
@ -255,6 +257,7 @@ fun PlaybackContent(
seekEnabled = true, seekEnabled = true,
seekForward = preferences.appPreferences.playbackPreferences.skipForwardMs.milliseconds, seekForward = preferences.appPreferences.playbackPreferences.skipForwardMs.milliseconds,
seekBack = preferences.appPreferences.playbackPreferences.skipBackMs.milliseconds, seekBack = preferences.appPreferences.playbackPreferences.skipBackMs.milliseconds,
skipBackOnResume = preferences.appPreferences.playbackPreferences.skipBackOnResume,
onPlaybackActionClick = { onPlaybackActionClick = {
when (it) { when (it) {
is PlaybackAction.PlaybackSpeed -> { is PlaybackAction.PlaybackSpeed -> {

View file

@ -114,6 +114,7 @@ fun PlaybackControls(
scale: ContentScale, scale: ContentScale,
seekBarIntervals: Int, seekBarIntervals: Int,
seekBack: Duration, seekBack: Duration,
skipBackOnResume: Duration?,
seekForward: Duration, seekForward: Duration,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
initialFocusRequester: FocusRequester = remember { FocusRequester() }, initialFocusRequester: FocusRequester = remember { FocusRequester() },
@ -178,6 +179,7 @@ fun PlaybackControls(
nextEnabled = nextEnabled, nextEnabled = nextEnabled,
seekBack = seekBack, seekBack = seekBack,
seekForward = seekForward, seekForward = seekForward,
skipBackOnResume = skipBackOnResume,
modifier = Modifier.align(Alignment.Center), modifier = Modifier.align(Alignment.Center),
) )
RightPlaybackButtons( RightPlaybackButtons(
@ -446,6 +448,7 @@ fun PlaybackButtons(
previousEnabled: Boolean, previousEnabled: Boolean,
nextEnabled: Boolean, nextEnabled: Boolean,
seekBack: Duration, seekBack: Duration,
skipBackOnResume: Duration?,
seekForward: Duration, seekForward: Duration,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
@ -475,7 +478,14 @@ fun PlaybackButtons(
iconRes = if (showPlay) R.drawable.baseline_play_arrow_24 else R.drawable.baseline_pause_24, iconRes = if (showPlay) R.drawable.baseline_play_arrow_24 else R.drawable.baseline_pause_24,
onClick = { onClick = {
onControllerInteraction.invoke() onControllerInteraction.invoke()
if (showPlay) player.play() else player.pause() if (showPlay) {
player.play()
skipBackOnResume?.let {
player.seekBack(it)
}
} else {
player.pause()
}
}, },
onControllerInteraction = onControllerInteraction, onControllerInteraction = onControllerInteraction,
) )

View file

@ -19,6 +19,7 @@ class PlaybackKeyHandler(
private val seekForward: Duration, private val seekForward: Duration,
private val controllerViewState: ControllerViewState, private val controllerViewState: ControllerViewState,
private val updateSkipIndicator: (Long) -> Unit, private val updateSkipIndicator: (Long) -> Unit,
private val skipBackOnResume: Duration?,
) { ) {
fun onKeyEvent(it: KeyEvent): Boolean { fun onKeyEvent(it: KeyEvent): Boolean {
var result = true var result = true
@ -44,6 +45,9 @@ class PlaybackKeyHandler(
when (it.key) { when (it.key) {
Key.MediaPlay -> { Key.MediaPlay -> {
Util.handlePlayButtonAction(player) Util.handlePlayButtonAction(player)
skipBackOnResume?.let {
player.seekBack(it)
}
} }
Key.MediaPause -> { Key.MediaPause -> {
@ -55,6 +59,10 @@ class PlaybackKeyHandler(
Util.handlePlayPauseButtonAction(player) Util.handlePlayPauseButtonAction(player)
if (!player.isPlaying) { if (!player.isPlaying) {
controllerViewState.showControls() controllerViewState.showControls()
} else {
skipBackOnResume?.let {
player.seekBack(it)
}
} }
} }

View file

@ -57,6 +57,7 @@ fun PlaybackOverlay(
nextEnabled: Boolean, nextEnabled: Boolean,
seekEnabled: Boolean, seekEnabled: Boolean,
seekBack: Duration, seekBack: Duration,
skipBackOnResume: Duration?,
seekForward: Duration, seekForward: Duration,
onPlaybackActionClick: (PlaybackAction) -> Unit, onPlaybackActionClick: (PlaybackAction) -> Unit,
onSeekBarChange: (Long) -> Unit, onSeekBarChange: (Long) -> Unit,
@ -183,6 +184,7 @@ fun PlaybackOverlay(
seekBarIntervals = 16, seekBarIntervals = 16,
seekBack = seekBack, seekBack = seekBack,
seekForward = seekForward, seekForward = seekForward,
skipBackOnResume = skipBackOnResume,
) )
} }
} }

View file

@ -11,6 +11,7 @@ message PlaybackPreferences {
bool show_debug_info = 5; bool show_debug_info = 5;
bool auto_play_next = 6; bool auto_play_next = 6;
int64 auto_play_next_delay_seconds = 7; int64 auto_play_next_delay_seconds = 7;
int64 skip_back_on_resume_seconds = 8;
} }
message HomePagePreferences{ message HomePagePreferences{

View file

@ -55,5 +55,6 @@
<string name="sort_by_date_added">Date Added</string> <string name="sort_by_date_added">Date Added</string>
<string name="sort_by_date_played">Date Played</string> <string name="sort_by_date_played">Date Played</string>
<string name="sort_by_date_released">Date Released</string> <string name="sort_by_date_released">Date Released</string>
<string name="skip_back_on_resume_preference">Skip back when resuming playback</string>
</resources> </resources>