Suport passout protection (#41)

Adds a setting to configure pass out protection which, when enabled,
will stop auto playing next up episodes if the user hasn't interacted
with the app within the configurable 1-3 hours.
This commit is contained in:
damontecres 2025-10-19 18:21:23 -04:00 committed by GitHub
parent c3cc284238
commit 8904360fb5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 56 additions and 7 deletions

View file

@ -23,8 +23,11 @@ class PlaybackKeyHandler(
private val controllerViewState: ControllerViewState,
private val updateSkipIndicator: (Long) -> Unit,
private val skipBackOnResume: Duration?,
private val onInteraction: () -> Unit,
) {
fun onKeyEvent(it: KeyEvent): Boolean {
if (it.type == KeyEventType.KeyUp) onInteraction.invoke()
var result = true
if (!controlsEnabled) {
result = false

View file

@ -196,6 +196,7 @@ fun PlaybackPage(
controllerViewState = controllerViewState,
updateSkipIndicator = updateSkipIndicator,
skipBackOnResume = preferences.appPreferences.playbackPreferences.skipBackOnResume,
onInteraction = viewModel::reportInteraction,
)
val showSegment =
@ -413,12 +414,7 @@ fun PlaybackPage(
.align(Alignment.BottomCenter),
) {
nextUp?.let {
var autoPlayEnabled by
remember {
mutableStateOf(
preferences.appPreferences.playbackPreferences.autoPlayNext,
)
}
var autoPlayEnabled by remember { mutableStateOf(viewModel.shouldAutoPlayNextUp()) }
var timeLeft by remember {
mutableLongStateOf(
preferences.appPreferences.playbackPreferences.autoPlayNextDelaySeconds,
@ -452,7 +448,10 @@ fun PlaybackPage(
description = it.data.overview,
imageUrl = it.imageUrl,
aspectRatio = it.data.primaryImageAspectRatio?.toFloat() ?: (16f / 9),
onClick = { viewModel.playUpNextUp() },
onClick = {
viewModel.reportInteraction()
viewModel.playUpNextUp()
},
timeLeft = if (autoPlayEnabled) timeLeft.seconds else null,
modifier =
Modifier

View file

@ -74,6 +74,7 @@ import org.jellyfin.sdk.model.extensions.inWholeTicks
import org.jellyfin.sdk.model.extensions.ticks
import org.jellyfin.sdk.model.serializer.toUUIDOrNull
import timber.log.Timber
import java.util.Date
import java.util.UUID
import javax.inject.Inject
import kotlin.time.Duration
@ -649,6 +650,23 @@ class PlaybackViewModel
}
}
private var lastInteractionDate: Date = Date()
fun reportInteraction() {
Timber.v("reportInteraction")
lastInteractionDate = Date()
}
fun shouldAutoPlayNextUp(): Boolean =
preferences.appPreferences.playbackPreferences.let {
it.autoPlayNext &&
if (it.passOutProtectionMs > 0) {
(Date().time - lastInteractionDate.time) < it.passOutProtectionMs
} else {
true
}
}
fun playUpNextUp() {
playlist.value?.let {
if (it.hasNext()) {