From e412c3da481b7355eb863d2c576ad90bdaa135f6 Mon Sep 17 00:00:00 2001 From: Damontecres Date: Tue, 7 Oct 2025 01:17:17 -0400 Subject: [PATCH] Add preference for skipping back on resume --- .../dolphin/preferences/AppPreference.kt | 23 +++++++++++++++++++ .../preferences/AppPreferencesSerializer.kt | 2 ++ .../dolphin/preferences/Extensions.kt | 12 ++++++++++ .../dolphin/ui/playback/PlaybackContent.kt | 3 +++ .../dolphin/ui/playback/PlaybackControls.kt | 12 +++++++++- .../dolphin/ui/playback/PlaybackKeyHandler.kt | 8 +++++++ .../dolphin/ui/playback/PlaybackOverlay.kt | 2 ++ app/src/main/proto/DolphinDataStore.proto | 1 + app/src/main/res/values/strings.xml | 1 + 9 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/com/github/damontecres/dolphin/preferences/Extensions.kt diff --git a/app/src/main/java/com/github/damontecres/dolphin/preferences/AppPreference.kt b/app/src/main/java/com/github/damontecres/dolphin/preferences/AppPreference.kt index 194fc0af..a2bb8308 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/preferences/AppPreference.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/preferences/AppPreference.kt @@ -212,6 +212,28 @@ sealed interface AppPreference { 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 = AppSliderPreference( title = R.string.auto_play_next_delay, @@ -290,6 +312,7 @@ val basicPreferences = AppPreference.ControllerTimeout, AppPreference.AutoPlayNextUp, AppPreference.AutoPlayNextDelay, + AppPreference.SkipBackOnResume, AppPreference.PlaybackDebugInfo, ), ), diff --git a/app/src/main/java/com/github/damontecres/dolphin/preferences/AppPreferencesSerializer.kt b/app/src/main/java/com/github/damontecres/dolphin/preferences/AppPreferencesSerializer.kt index 850bafc9..17a76b35 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/preferences/AppPreferencesSerializer.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/preferences/AppPreferencesSerializer.kt @@ -29,6 +29,8 @@ class AppPreferencesSerializer autoPlayNext = AppPreference.AutoPlayNextUp.defaultValue autoPlayNextDelaySeconds = AppPreference.AutoPlayNextDelay.defaultValue + skipBackOnResumeSeconds = + AppPreference.SkipBackOnResume.defaultValue.seconds.inWholeMilliseconds }.build() homePagePreferences = HomePagePreferences diff --git a/app/src/main/java/com/github/damontecres/dolphin/preferences/Extensions.kt b/app/src/main/java/com/github/damontecres/dolphin/preferences/Extensions.kt new file mode 100644 index 00000000..c797070d --- /dev/null +++ b/app/src/main/java/com/github/damontecres/dolphin/preferences/Extensions.kt @@ -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 + } diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackContent.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackContent.kt index ede7409a..18e368f6 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackContent.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackContent.kt @@ -57,6 +57,7 @@ import androidx.media3.ui.compose.state.rememberPreviousButtonState import androidx.tv.material3.MaterialTheme import androidx.tv.material3.surfaceColorAtElevation 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.components.LoadingPage import com.github.damontecres.dolphin.ui.nav.Destination @@ -171,6 +172,7 @@ fun PlaybackContent( seekBack = preferences.appPreferences.playbackPreferences.skipBackMs.milliseconds, controllerViewState = controllerViewState, updateSkipIndicator = updateSkipIndicator, + skipBackOnResume = preferences.appPreferences.playbackPreferences.skipBackOnResume, ) Box( @@ -255,6 +257,7 @@ fun PlaybackContent( seekEnabled = true, seekForward = preferences.appPreferences.playbackPreferences.skipForwardMs.milliseconds, seekBack = preferences.appPreferences.playbackPreferences.skipBackMs.milliseconds, + skipBackOnResume = preferences.appPreferences.playbackPreferences.skipBackOnResume, onPlaybackActionClick = { when (it) { is PlaybackAction.PlaybackSpeed -> { diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackControls.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackControls.kt index d44a7b38..dc4a7b72 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackControls.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackControls.kt @@ -114,6 +114,7 @@ fun PlaybackControls( scale: ContentScale, seekBarIntervals: Int, seekBack: Duration, + skipBackOnResume: Duration?, seekForward: Duration, modifier: Modifier = Modifier, initialFocusRequester: FocusRequester = remember { FocusRequester() }, @@ -178,6 +179,7 @@ fun PlaybackControls( nextEnabled = nextEnabled, seekBack = seekBack, seekForward = seekForward, + skipBackOnResume = skipBackOnResume, modifier = Modifier.align(Alignment.Center), ) RightPlaybackButtons( @@ -446,6 +448,7 @@ fun PlaybackButtons( previousEnabled: Boolean, nextEnabled: Boolean, seekBack: Duration, + skipBackOnResume: Duration?, seekForward: Duration, modifier: Modifier = Modifier, ) { @@ -475,7 +478,14 @@ fun PlaybackButtons( iconRes = if (showPlay) R.drawable.baseline_play_arrow_24 else R.drawable.baseline_pause_24, onClick = { onControllerInteraction.invoke() - if (showPlay) player.play() else player.pause() + if (showPlay) { + player.play() + skipBackOnResume?.let { + player.seekBack(it) + } + } else { + player.pause() + } }, onControllerInteraction = onControllerInteraction, ) diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackKeyHandler.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackKeyHandler.kt index 4d4f7b5f..ca697fa8 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackKeyHandler.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackKeyHandler.kt @@ -19,6 +19,7 @@ class PlaybackKeyHandler( private val seekForward: Duration, private val controllerViewState: ControllerViewState, private val updateSkipIndicator: (Long) -> Unit, + private val skipBackOnResume: Duration?, ) { fun onKeyEvent(it: KeyEvent): Boolean { var result = true @@ -44,6 +45,9 @@ class PlaybackKeyHandler( when (it.key) { Key.MediaPlay -> { Util.handlePlayButtonAction(player) + skipBackOnResume?.let { + player.seekBack(it) + } } Key.MediaPause -> { @@ -55,6 +59,10 @@ class PlaybackKeyHandler( Util.handlePlayPauseButtonAction(player) if (!player.isPlaying) { controllerViewState.showControls() + } else { + skipBackOnResume?.let { + player.seekBack(it) + } } } diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackOverlay.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackOverlay.kt index fc721695..f3013ab8 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackOverlay.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackOverlay.kt @@ -57,6 +57,7 @@ fun PlaybackOverlay( nextEnabled: Boolean, seekEnabled: Boolean, seekBack: Duration, + skipBackOnResume: Duration?, seekForward: Duration, onPlaybackActionClick: (PlaybackAction) -> Unit, onSeekBarChange: (Long) -> Unit, @@ -183,6 +184,7 @@ fun PlaybackOverlay( seekBarIntervals = 16, seekBack = seekBack, seekForward = seekForward, + skipBackOnResume = skipBackOnResume, ) } } diff --git a/app/src/main/proto/DolphinDataStore.proto b/app/src/main/proto/DolphinDataStore.proto index 30e000ba..38f5b938 100644 --- a/app/src/main/proto/DolphinDataStore.proto +++ b/app/src/main/proto/DolphinDataStore.proto @@ -11,6 +11,7 @@ message PlaybackPreferences { bool show_debug_info = 5; bool auto_play_next = 6; int64 auto_play_next_delay_seconds = 7; + int64 skip_back_on_resume_seconds = 8; } message HomePagePreferences{ diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 23b4dee7..4d7b1ddb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -55,5 +55,6 @@ Date Added Date Played Date Released + Skip back when resuming playback