mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-08-19 05:45:41 +00:00
feat: add binge group fallback toggle for manual mode auto-play
When auto-play next episode is enabled in manual mode, add option to control whether first stream is auto-selected when binge group fails. Default on (preserves existing behavior). When off, shows the stream picker instead.
This commit is contained in:
parent
1d2ec889a0
commit
f2c9b9f9e7
8 changed files with 71 additions and 1 deletions
|
|
@ -65,6 +65,7 @@ actual object PlayerSettingsStorage {
|
|||
private const val introDbApiKeyKey = "introdb_api_key"
|
||||
private const val introSubmitEnabledKey = "intro_submit_enabled"
|
||||
private const val streamAutoPlayNextEpisodeEnabledKey = "stream_auto_play_next_episode_enabled"
|
||||
private const val streamAutoPlayNextEpisodeFallbackEnabledKey = "stream_auto_play_next_episode_fallback_enabled"
|
||||
private const val streamAutoPlayPreferBingeGroupKey = "stream_auto_play_prefer_binge_group"
|
||||
private const val streamAutoPlayReuseBingeGroupKey = "stream_auto_play_reuse_binge_group"
|
||||
private const val nextEpisodeThresholdModeKey = "next_episode_threshold_mode"
|
||||
|
|
@ -132,6 +133,7 @@ actual object PlayerSettingsStorage {
|
|||
animeSkipEnabledKey,
|
||||
animeSkipClientIdKey,
|
||||
streamAutoPlayNextEpisodeEnabledKey,
|
||||
streamAutoPlayNextEpisodeFallbackEnabledKey,
|
||||
streamAutoPlayPreferBingeGroupKey,
|
||||
streamAutoPlayReuseBingeGroupKey,
|
||||
nextEpisodeThresholdModeKey,
|
||||
|
|
@ -846,6 +848,23 @@ actual object PlayerSettingsStorage {
|
|||
?.apply()
|
||||
}
|
||||
|
||||
actual fun loadStreamAutoPlayNextEpisodeFallbackEnabled(): Boolean? =
|
||||
preferences?.let { sharedPreferences ->
|
||||
val key = ProfileScopedKey.of(streamAutoPlayNextEpisodeFallbackEnabledKey)
|
||||
if (sharedPreferences.contains(key)) {
|
||||
sharedPreferences.getBoolean(key, true)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
actual fun saveStreamAutoPlayNextEpisodeFallbackEnabled(enabled: Boolean) {
|
||||
preferences
|
||||
?.edit()
|
||||
?.putBoolean(ProfileScopedKey.of(streamAutoPlayNextEpisodeFallbackEnabledKey), enabled)
|
||||
?.apply()
|
||||
}
|
||||
|
||||
actual fun loadStreamAutoPlayPreferBingeGroup(): Boolean? =
|
||||
preferences?.let { sharedPreferences ->
|
||||
val key = ProfileScopedKey.of(streamAutoPlayPreferBingeGroupKey)
|
||||
|
|
@ -1119,6 +1138,7 @@ actual object PlayerSettingsStorage {
|
|||
loadAnimeSkipEnabled()?.let { put(animeSkipEnabledKey, encodeSyncBoolean(it)) }
|
||||
loadAnimeSkipClientId()?.let { put(animeSkipClientIdKey, encodeSyncString(it)) }
|
||||
loadStreamAutoPlayNextEpisodeEnabled()?.let { put(streamAutoPlayNextEpisodeEnabledKey, encodeSyncBoolean(it)) }
|
||||
loadStreamAutoPlayNextEpisodeFallbackEnabled()?.let { put(streamAutoPlayNextEpisodeFallbackEnabledKey, encodeSyncBoolean(it)) }
|
||||
loadStreamAutoPlayPreferBingeGroup()?.let { put(streamAutoPlayPreferBingeGroupKey, encodeSyncBoolean(it)) }
|
||||
loadStreamAutoPlayReuseBingeGroup()?.let { put(streamAutoPlayReuseBingeGroupKey, encodeSyncBoolean(it)) }
|
||||
loadNextEpisodeThresholdMode()?.let { put(nextEpisodeThresholdModeKey, encodeSyncString(it)) }
|
||||
|
|
@ -1195,6 +1215,7 @@ actual object PlayerSettingsStorage {
|
|||
payload.decodeSyncString(introDbApiKeyKey)?.let(::saveIntroDbApiKey)
|
||||
payload.decodeSyncBoolean(introSubmitEnabledKey)?.let(::saveIntroSubmitEnabled)
|
||||
payload.decodeSyncBoolean(streamAutoPlayNextEpisodeEnabledKey)?.let(::saveStreamAutoPlayNextEpisodeEnabled)
|
||||
payload.decodeSyncBoolean(streamAutoPlayNextEpisodeFallbackEnabledKey)?.let(::saveStreamAutoPlayNextEpisodeFallbackEnabled)
|
||||
payload.decodeSyncBoolean(streamAutoPlayPreferBingeGroupKey)?.let(::saveStreamAutoPlayPreferBingeGroup)
|
||||
payload.decodeSyncBoolean(streamAutoPlayReuseBingeGroupKey)?.let(::saveStreamAutoPlayReuseBingeGroup)
|
||||
payload.decodeSyncString(nextEpisodeThresholdModeKey)?.let(::saveNextEpisodeThresholdMode)
|
||||
|
|
|
|||
|
|
@ -767,6 +767,8 @@
|
|||
<string name="settings_playback_anime_skip_description">Wyszukuj również w AnimeSkip znaczniki pomijania (wymaga ID klienta).</string>
|
||||
<string name="settings_playback_auto_play_next_episode">Automatyczne odtwarzanie następnego odcinka</string>
|
||||
<string name="settings_playback_auto_play_next_episode_description">Automatycznie znajdź i odtwórz następny odcinek po osiągnięciu progu.</string>
|
||||
<string name="settings_playback_auto_play_next_episode_fallback">Fallback gdy grupa binge nie zostanie znaleziona</string>
|
||||
<string name="settings_playback_auto_play_next_episode_fallback_description">Automatycznie wybierz pierwszy dostępny strumień jeśli grupa binge nie zostanie znaleziona. Gdy wyłączone, wyświetla wybór źródła.</string>
|
||||
<string name="settings_playback_decoder_device_only">Tylko urządzenie</string>
|
||||
<string name="settings_playback_decoder_prefer_app">Preferuj aplikację (FFmpeg)</string>
|
||||
<string name="settings_playback_decoder_prefer_device">Preferuj urządzenie</string>
|
||||
|
|
|
|||
|
|
@ -928,6 +928,8 @@
|
|||
<string name="settings_playback_anime_skip_description">Also search AnimeSkip for skip timestamps (requires client ID).</string>
|
||||
<string name="settings_playback_auto_play_next_episode">Auto-play Next Episode</string>
|
||||
<string name="settings_playback_auto_play_next_episode_description">Start next episode automatically when prompt appears.</string>
|
||||
<string name="settings_playback_auto_play_next_episode_fallback">Fallback when binge group fails</string>
|
||||
<string name="settings_playback_auto_play_next_episode_fallback_description">Auto-select first available stream if binge group is not found. When off, shows the stream picker instead.</string>
|
||||
<string name="settings_playback_decoder_device_only">Device decoders only</string>
|
||||
<string name="settings_playback_decoder_prefer_app">Prefer app decoders (FFmpeg)</string>
|
||||
<string name="settings_playback_decoder_prefer_device">Prefer device decoders</string>
|
||||
|
|
|
|||
|
|
@ -66,7 +66,8 @@ internal fun CoroutineScope.launchPlayerNextEpisodeAutoPlay(
|
|||
|
||||
val bingeGroupOnlyManualMode =
|
||||
shouldAutoSelectInManualMode &&
|
||||
!settings.streamAutoPlayNextEpisodeEnabled &&
|
||||
(!settings.streamAutoPlayNextEpisodeEnabled ||
|
||||
!settings.streamAutoPlayNextEpisodeFallbackEnabled) &&
|
||||
settings.streamAutoPlayPreferBingeGroup
|
||||
|
||||
val effectiveMode = if (shouldAutoSelectInManualMode) {
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ data class PlayerSettingsUiState(
|
|||
val introDbApiKey: String = "",
|
||||
val introSubmitEnabled: Boolean = false,
|
||||
val streamAutoPlayNextEpisodeEnabled: Boolean = false,
|
||||
val streamAutoPlayNextEpisodeFallbackEnabled: Boolean = true,
|
||||
val streamAutoPlayPreferBingeGroup: Boolean = true,
|
||||
val streamAutoPlayReuseBingeGroup: Boolean = true,
|
||||
val nextEpisodeThresholdMode: NextEpisodeThresholdMode = NextEpisodeThresholdMode.PERCENTAGE,
|
||||
|
|
@ -135,6 +136,7 @@ object PlayerSettingsRepository {
|
|||
private var introDbApiKey = ""
|
||||
private var introSubmitEnabled = false
|
||||
private var streamAutoPlayNextEpisodeEnabled = false
|
||||
private var streamAutoPlayNextEpisodeFallbackEnabled = true
|
||||
private var streamAutoPlayPreferBingeGroup = true
|
||||
private var streamAutoPlayReuseBingeGroup = true
|
||||
private var nextEpisodeThresholdMode = NextEpisodeThresholdMode.PERCENTAGE
|
||||
|
|
@ -206,6 +208,7 @@ object PlayerSettingsRepository {
|
|||
introDbApiKey = ""
|
||||
introSubmitEnabled = false
|
||||
streamAutoPlayNextEpisodeEnabled = false
|
||||
streamAutoPlayNextEpisodeFallbackEnabled = true
|
||||
streamAutoPlayPreferBingeGroup = true
|
||||
streamAutoPlayReuseBingeGroup = true
|
||||
nextEpisodeThresholdMode = NextEpisodeThresholdMode.PERCENTAGE
|
||||
|
|
@ -329,6 +332,7 @@ object PlayerSettingsRepository {
|
|||
introDbApiKey = PlayerSettingsStorage.loadIntroDbApiKey() ?: ""
|
||||
introSubmitEnabled = PlayerSettingsStorage.loadIntroSubmitEnabled() ?: false
|
||||
streamAutoPlayNextEpisodeEnabled = PlayerSettingsStorage.loadStreamAutoPlayNextEpisodeEnabled() ?: false
|
||||
streamAutoPlayNextEpisodeFallbackEnabled = PlayerSettingsStorage.loadStreamAutoPlayNextEpisodeFallbackEnabled() ?: true
|
||||
streamAutoPlayPreferBingeGroup = PlayerSettingsStorage.loadStreamAutoPlayPreferBingeGroup() ?: true
|
||||
streamAutoPlayReuseBingeGroup = PlayerSettingsStorage.loadStreamAutoPlayReuseBingeGroup() ?: true
|
||||
nextEpisodeThresholdMode = PlayerSettingsStorage.loadNextEpisodeThresholdMode()
|
||||
|
|
@ -687,6 +691,14 @@ object PlayerSettingsRepository {
|
|||
PlayerSettingsStorage.saveStreamAutoPlayNextEpisodeEnabled(enabled)
|
||||
}
|
||||
|
||||
fun setStreamAutoPlayNextEpisodeFallbackEnabled(enabled: Boolean) {
|
||||
ensureLoaded()
|
||||
if (streamAutoPlayNextEpisodeFallbackEnabled == enabled) return
|
||||
streamAutoPlayNextEpisodeFallbackEnabled = enabled
|
||||
publish()
|
||||
PlayerSettingsStorage.saveStreamAutoPlayNextEpisodeFallbackEnabled(enabled)
|
||||
}
|
||||
|
||||
fun setStreamAutoPlayPreferBingeGroup(enabled: Boolean) {
|
||||
ensureLoaded()
|
||||
if (streamAutoPlayPreferBingeGroup == enabled) return
|
||||
|
|
@ -947,6 +959,7 @@ object PlayerSettingsRepository {
|
|||
introDbApiKey = introDbApiKey,
|
||||
introSubmitEnabled = introSubmitEnabled,
|
||||
streamAutoPlayNextEpisodeEnabled = streamAutoPlayNextEpisodeEnabled,
|
||||
streamAutoPlayNextEpisodeFallbackEnabled = streamAutoPlayNextEpisodeFallbackEnabled,
|
||||
streamAutoPlayPreferBingeGroup = streamAutoPlayPreferBingeGroup,
|
||||
streamAutoPlayReuseBingeGroup = streamAutoPlayReuseBingeGroup,
|
||||
nextEpisodeThresholdMode = nextEpisodeThresholdMode,
|
||||
|
|
|
|||
|
|
@ -96,6 +96,8 @@ internal expect object PlayerSettingsStorage {
|
|||
fun saveIntroSubmitEnabled(enabled: Boolean)
|
||||
fun loadStreamAutoPlayNextEpisodeEnabled(): Boolean?
|
||||
fun saveStreamAutoPlayNextEpisodeEnabled(enabled: Boolean)
|
||||
fun loadStreamAutoPlayNextEpisodeFallbackEnabled(): Boolean?
|
||||
fun saveStreamAutoPlayNextEpisodeFallbackEnabled(enabled: Boolean)
|
||||
fun loadStreamAutoPlayPreferBingeGroup(): Boolean?
|
||||
fun saveStreamAutoPlayPreferBingeGroup(enabled: Boolean)
|
||||
fun loadStreamAutoPlayReuseBingeGroup(): Boolean?
|
||||
|
|
|
|||
|
|
@ -1100,6 +1100,17 @@ private fun PlaybackSettingsSection(
|
|||
isTablet = isTablet,
|
||||
onCheckedChange = PlayerSettingsRepository::setStreamAutoPlayNextEpisodeEnabled,
|
||||
)
|
||||
if (autoPlayPlayerSettings.streamAutoPlayNextEpisodeEnabled &&
|
||||
autoPlayPlayerSettings.streamAutoPlayMode == StreamAutoPlayMode.MANUAL) {
|
||||
SettingsGroupDivider(isTablet = isTablet)
|
||||
SettingsSwitchRow(
|
||||
title = stringResource(Res.string.settings_playback_auto_play_next_episode_fallback),
|
||||
description = stringResource(Res.string.settings_playback_auto_play_next_episode_fallback_description),
|
||||
checked = autoPlayPlayerSettings.streamAutoPlayNextEpisodeFallbackEnabled,
|
||||
isTablet = isTablet,
|
||||
onCheckedChange = PlayerSettingsRepository::setStreamAutoPlayNextEpisodeFallbackEnabled,
|
||||
)
|
||||
}
|
||||
SettingsGroupDivider(isTablet = isTablet)
|
||||
SettingsSwitchRow(
|
||||
title = stringResource(Res.string.settings_playback_prefer_binge_group),
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ actual object PlayerSettingsStorage {
|
|||
private const val introDbApiKeyKey = "introdb_api_key"
|
||||
private const val introSubmitEnabledKey = "intro_submit_enabled"
|
||||
private const val streamAutoPlayNextEpisodeEnabledKey = "stream_auto_play_next_episode_enabled"
|
||||
private const val streamAutoPlayNextEpisodeFallbackEnabledKey = "stream_auto_play_next_episode_fallback_enabled"
|
||||
private const val streamAutoPlayPreferBingeGroupKey = "stream_auto_play_prefer_binge_group"
|
||||
private const val streamAutoPlayReuseBingeGroupKey = "stream_auto_play_reuse_binge_group"
|
||||
private const val nextEpisodeThresholdModeKey = "next_episode_threshold_mode"
|
||||
|
|
@ -130,6 +131,7 @@ actual object PlayerSettingsStorage {
|
|||
animeSkipEnabledKey,
|
||||
animeSkipClientIdKey,
|
||||
streamAutoPlayNextEpisodeEnabledKey,
|
||||
streamAutoPlayNextEpisodeFallbackEnabledKey,
|
||||
streamAutoPlayPreferBingeGroupKey,
|
||||
streamAutoPlayReuseBingeGroupKey,
|
||||
nextEpisodeThresholdModeKey,
|
||||
|
|
@ -718,6 +720,20 @@ actual object PlayerSettingsStorage {
|
|||
NSUserDefaults.standardUserDefaults.setBool(enabled, forKey = ProfileScopedKey.of(streamAutoPlayNextEpisodeEnabledKey))
|
||||
}
|
||||
|
||||
actual fun loadStreamAutoPlayNextEpisodeFallbackEnabled(): Boolean? {
|
||||
val defaults = NSUserDefaults.standardUserDefaults
|
||||
val key = ProfileScopedKey.of(streamAutoPlayNextEpisodeFallbackEnabledKey)
|
||||
return if (defaults.objectForKey(key) != null) {
|
||||
defaults.boolForKey(key)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
actual fun saveStreamAutoPlayNextEpisodeFallbackEnabled(enabled: Boolean) {
|
||||
NSUserDefaults.standardUserDefaults.setBool(enabled, forKey = ProfileScopedKey.of(streamAutoPlayNextEpisodeFallbackEnabledKey))
|
||||
}
|
||||
|
||||
actual fun loadStreamAutoPlayPreferBingeGroup(): Boolean? {
|
||||
val defaults = NSUserDefaults.standardUserDefaults
|
||||
val key = ProfileScopedKey.of(streamAutoPlayPreferBingeGroupKey)
|
||||
|
|
@ -939,6 +955,7 @@ actual object PlayerSettingsStorage {
|
|||
loadAnimeSkipEnabled()?.let { put(animeSkipEnabledKey, encodeSyncBoolean(it)) }
|
||||
loadAnimeSkipClientId()?.let { put(animeSkipClientIdKey, encodeSyncString(it)) }
|
||||
loadStreamAutoPlayNextEpisodeEnabled()?.let { put(streamAutoPlayNextEpisodeEnabledKey, encodeSyncBoolean(it)) }
|
||||
loadStreamAutoPlayNextEpisodeFallbackEnabled()?.let { put(streamAutoPlayNextEpisodeFallbackEnabledKey, encodeSyncBoolean(it)) }
|
||||
loadStreamAutoPlayPreferBingeGroup()?.let { put(streamAutoPlayPreferBingeGroupKey, encodeSyncBoolean(it)) }
|
||||
loadStreamAutoPlayReuseBingeGroup()?.let { put(streamAutoPlayReuseBingeGroupKey, encodeSyncBoolean(it)) }
|
||||
loadNextEpisodeThresholdMode()?.let { put(nextEpisodeThresholdModeKey, encodeSyncString(it)) }
|
||||
|
|
@ -1013,6 +1030,7 @@ actual object PlayerSettingsStorage {
|
|||
payload.decodeSyncString(animeSkipClientIdKey)?.let(::saveAnimeSkipClientId)
|
||||
payload.decodeSyncString(introDbApiKeyKey)?.let(::saveIntroDbApiKey)
|
||||
payload.decodeSyncBoolean(streamAutoPlayNextEpisodeEnabledKey)?.let(::saveStreamAutoPlayNextEpisodeEnabled)
|
||||
payload.decodeSyncBoolean(streamAutoPlayNextEpisodeFallbackEnabledKey)?.let(::saveStreamAutoPlayNextEpisodeFallbackEnabled)
|
||||
payload.decodeSyncBoolean(streamAutoPlayPreferBingeGroupKey)?.let(::saveStreamAutoPlayPreferBingeGroup)
|
||||
payload.decodeSyncBoolean(streamAutoPlayReuseBingeGroupKey)?.let(::saveStreamAutoPlayReuseBingeGroup)
|
||||
payload.decodeSyncString(nextEpisodeThresholdModeKey)?.let(::saveNextEpisodeThresholdMode)
|
||||
|
|
|
|||
Loading…
Reference in a new issue