mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-16 15:01:59 +00:00
feat: implement swipe-to-seek toggle and sensitivity settings (#936)
This commit is contained in:
parent
11a1cf7ba9
commit
766970bce7
8 changed files with 264 additions and 3 deletions
|
|
@ -54,6 +54,8 @@ actual object PlayerSettingsStorage {
|
|||
private const val nextEpisodeThresholdMinutesBeforeEndKey = "next_episode_threshold_minutes_before_end_v2"
|
||||
private const val useLibassKey = "use_libass"
|
||||
private const val libassRenderTypeKey = "libass_render_type"
|
||||
private const val swipeToSeekEnabledKey = "swipe_to_seek_enabled"
|
||||
private const val swipeToSeekSensitivityKey = "swipe_to_seek_sensitivity"
|
||||
private val syncKeys = listOf(
|
||||
showLoadingOverlayKey,
|
||||
resizeModeKey,
|
||||
|
|
@ -88,6 +90,8 @@ actual object PlayerSettingsStorage {
|
|||
nextEpisodeThresholdMinutesBeforeEndKey,
|
||||
useLibassKey,
|
||||
libassRenderTypeKey,
|
||||
swipeToSeekEnabledKey,
|
||||
swipeToSeekSensitivityKey,
|
||||
)
|
||||
|
||||
private var preferences: SharedPreferences? = null
|
||||
|
|
@ -648,6 +652,8 @@ actual object PlayerSettingsStorage {
|
|||
loadNextEpisodeThresholdMinutesBeforeEnd()?.let { put(nextEpisodeThresholdMinutesBeforeEndKey, encodeSyncFloat(it)) }
|
||||
loadUseLibass()?.let { put(useLibassKey, encodeSyncBoolean(it)) }
|
||||
loadLibassRenderType()?.let { put(libassRenderTypeKey, encodeSyncString(it)) }
|
||||
loadSwipeToSeekEnabled()?.let { put(swipeToSeekEnabledKey, encodeSyncBoolean(it)) }
|
||||
loadSwipeToSeekSensitivity()?.let { put(swipeToSeekSensitivityKey, encodeSyncString(it)) }
|
||||
}
|
||||
|
||||
actual fun replaceFromSyncPayload(payload: JsonObject) {
|
||||
|
|
@ -690,5 +696,34 @@ actual object PlayerSettingsStorage {
|
|||
payload.decodeSyncFloat(nextEpisodeThresholdMinutesBeforeEndKey)?.let(::saveNextEpisodeThresholdMinutesBeforeEnd)
|
||||
payload.decodeSyncBoolean(useLibassKey)?.let(::saveUseLibass)
|
||||
payload.decodeSyncString(libassRenderTypeKey)?.let(::saveLibassRenderType)
|
||||
payload.decodeSyncBoolean(swipeToSeekEnabledKey)?.let(::saveSwipeToSeekEnabled)
|
||||
payload.decodeSyncString(swipeToSeekSensitivityKey)?.let(::saveSwipeToSeekSensitivity)
|
||||
}
|
||||
|
||||
actual fun loadSwipeToSeekEnabled(): Boolean? =
|
||||
preferences?.let { sharedPreferences ->
|
||||
val key = ProfileScopedKey.of(swipeToSeekEnabledKey)
|
||||
if (sharedPreferences.contains(key)) {
|
||||
sharedPreferences.getBoolean(key, true)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
actual fun saveSwipeToSeekEnabled(enabled: Boolean) {
|
||||
preferences
|
||||
?.edit()
|
||||
?.putBoolean(ProfileScopedKey.of(swipeToSeekEnabledKey), enabled)
|
||||
?.apply()
|
||||
}
|
||||
|
||||
actual fun loadSwipeToSeekSensitivity(): String? =
|
||||
preferences?.getString(ProfileScopedKey.of(swipeToSeekSensitivityKey), null)
|
||||
|
||||
actual fun saveSwipeToSeekSensitivity(sensitivity: String) {
|
||||
preferences
|
||||
?.edit()
|
||||
?.putString(ProfileScopedKey.of(swipeToSeekSensitivityKey), sensitivity)
|
||||
?.apply()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -678,6 +678,13 @@
|
|||
<string name="settings_playback_regex_matches_against">Matches against stream name/title/description/addon/url. Example: 4K|2160p|Remux</string>
|
||||
<string name="settings_playback_regex_pattern">Regex Pattern</string>
|
||||
<string name="settings_playback_regex_placeholder">No pattern set. Example: 4K|2160p|Remux</string>
|
||||
<string name="settings_playback_swipe_to_seek">Swipe to Seek</string>
|
||||
<string name="settings_playback_swipe_to_seek_description">Swipe horizontally on the player surface to seek forward or backward.</string>
|
||||
<string name="settings_playback_swipe_to_seek_sensitivity">Swipe to Seek Sensitivity</string>
|
||||
<string name="settings_playback_swipe_to_seek_sensitivity_description">Adjust the drag distance required to trigger a seek.</string>
|
||||
<string name="settings_playback_swipe_to_seek_sensitivity_low">Low</string>
|
||||
<string name="settings_playback_swipe_to_seek_sensitivity_medium">Medium</string>
|
||||
<string name="settings_playback_swipe_to_seek_sensitivity_high">High</string>
|
||||
<string name="settings_playback_regex_preset_any_1080p">Any 1080p+</string>
|
||||
<string name="settings_playback_regex_preset_avc_x264">AVC / x264</string>
|
||||
<string name="settings_playback_regex_preset_bluray_quality">BluRay Quality</string>
|
||||
|
|
|
|||
|
|
@ -1450,8 +1450,9 @@ fun PlayerScreen(
|
|||
|
||||
if (gestureMode == null) {
|
||||
val horizontalDominant =
|
||||
!isHoldToSpeedGestureActiveState.value &&
|
||||
abs(totalDx) > viewConfiguration.touchSlop &&
|
||||
playerSettingsUiState.swipeToSeekEnabled &&
|
||||
!isHoldToSpeedGestureActiveState.value &&
|
||||
abs(totalDx) > viewConfiguration.touchSlop * playerSettingsUiState.swipeToSeekSensitivity.triggerMultiplier &&
|
||||
abs(totalDx) > abs(totalDy)
|
||||
val verticalDominant =
|
||||
abs(totalDy) > viewConfiguration.touchSlop && abs(totalDy) > abs(totalDx)
|
||||
|
|
@ -1486,7 +1487,7 @@ fun PlayerScreen(
|
|||
else -> 60f
|
||||
}
|
||||
val previewOffsetMs =
|
||||
((totalDx / width) * sensitivitySeconds * 1000f).roundToLong()
|
||||
((totalDx / width) * sensitivitySeconds * playerSettingsUiState.swipeToSeekSensitivity.speedMultiplier * 1000f).roundToLong()
|
||||
val unclampedPreviewMs = horizontalSeekBaselineMs + previewOffsetMs
|
||||
horizontalSeekPreviewMs = currentDurationMsState.value
|
||||
.takeIf { it > 0L }
|
||||
|
|
|
|||
|
|
@ -8,6 +8,24 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
|||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
|
||||
enum class SwipeToSeekSensitivity {
|
||||
LOW, MEDIUM, HIGH;
|
||||
|
||||
val triggerMultiplier: Float
|
||||
get() = when (this) {
|
||||
LOW -> 4.0f
|
||||
MEDIUM -> 1.0f
|
||||
HIGH -> 0.5f
|
||||
}
|
||||
|
||||
val speedMultiplier: Float
|
||||
get() = when (this) {
|
||||
LOW -> 0.5f
|
||||
MEDIUM -> 1.0f
|
||||
HIGH -> 2.0f
|
||||
}
|
||||
}
|
||||
|
||||
data class PlayerSettingsUiState(
|
||||
val showLoadingOverlay: Boolean = true,
|
||||
val resizeMode: PlayerResizeMode = PlayerResizeMode.Fit,
|
||||
|
|
@ -29,6 +47,8 @@ data class PlayerSettingsUiState(
|
|||
val streamAutoPlaySelectedPlugins: Set<String> = emptySet(),
|
||||
val streamAutoPlayRegex: String = "",
|
||||
val streamAutoPlayTimeoutSeconds: Int = 3,
|
||||
val swipeToSeekEnabled: Boolean = true,
|
||||
val swipeToSeekSensitivity: SwipeToSeekSensitivity = SwipeToSeekSensitivity.MEDIUM,
|
||||
val skipIntroEnabled: Boolean = true,
|
||||
val animeSkipEnabled: Boolean = false,
|
||||
val animeSkipClientId: String = "",
|
||||
|
|
@ -80,6 +100,8 @@ object PlayerSettingsRepository {
|
|||
private var nextEpisodeThresholdMinutesBeforeEnd = 2f
|
||||
private var useLibass = false
|
||||
private var libassRenderType = "CUES"
|
||||
private var swipeToSeekEnabled = true
|
||||
private var swipeToSeekSensitivity = SwipeToSeekSensitivity.MEDIUM
|
||||
|
||||
fun ensureLoaded() {
|
||||
if (hasLoaded) return
|
||||
|
|
@ -195,6 +217,12 @@ object PlayerSettingsRepository {
|
|||
nextEpisodeThresholdMinutesBeforeEnd = PlayerSettingsStorage.loadNextEpisodeThresholdMinutesBeforeEnd() ?: 2f
|
||||
useLibass = PlayerSettingsStorage.loadUseLibass() ?: false
|
||||
libassRenderType = PlayerSettingsStorage.loadLibassRenderType() ?: "CUES"
|
||||
swipeToSeekEnabled = PlayerSettingsStorage.loadSwipeToSeekEnabled() ?: true
|
||||
swipeToSeekSensitivity = try {
|
||||
SwipeToSeekSensitivity.valueOf(PlayerSettingsStorage.loadSwipeToSeekSensitivity() ?: "MEDIUM")
|
||||
} catch (e: Exception) {
|
||||
SwipeToSeekSensitivity.MEDIUM
|
||||
}
|
||||
publish()
|
||||
}
|
||||
|
||||
|
|
@ -464,6 +492,22 @@ object PlayerSettingsRepository {
|
|||
PlayerSettingsStorage.saveLibassRenderType(renderType)
|
||||
}
|
||||
|
||||
fun setSwipeToSeekEnabled(enabled: Boolean) {
|
||||
ensureLoaded()
|
||||
if (swipeToSeekEnabled == enabled) return
|
||||
swipeToSeekEnabled = enabled
|
||||
publish()
|
||||
PlayerSettingsStorage.saveSwipeToSeekEnabled(enabled)
|
||||
}
|
||||
|
||||
fun setSwipeToSeekSensitivity(sensitivity: SwipeToSeekSensitivity) {
|
||||
ensureLoaded()
|
||||
if (swipeToSeekSensitivity == sensitivity) return
|
||||
swipeToSeekSensitivity = sensitivity
|
||||
publish()
|
||||
PlayerSettingsStorage.saveSwipeToSeekSensitivity(sensitivity.name)
|
||||
}
|
||||
|
||||
private fun publish() {
|
||||
_uiState.value = PlayerSettingsUiState(
|
||||
showLoadingOverlay = showLoadingOverlay,
|
||||
|
|
@ -498,6 +542,8 @@ object PlayerSettingsRepository {
|
|||
nextEpisodeThresholdMinutesBeforeEnd = nextEpisodeThresholdMinutesBeforeEnd,
|
||||
useLibass = useLibass,
|
||||
libassRenderType = libassRenderType,
|
||||
swipeToSeekEnabled = swipeToSeekEnabled,
|
||||
swipeToSeekSensitivity = swipeToSeekSensitivity,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -74,6 +74,10 @@ internal expect object PlayerSettingsStorage {
|
|||
fun saveUseLibass(enabled: Boolean)
|
||||
fun loadLibassRenderType(): String?
|
||||
fun saveLibassRenderType(renderType: String)
|
||||
fun loadSwipeToSeekEnabled(): Boolean?
|
||||
fun saveSwipeToSeekEnabled(enabled: Boolean)
|
||||
fun loadSwipeToSeekSensitivity(): String?
|
||||
fun saveSwipeToSeekSensitivity(sensitivity: String)
|
||||
fun exportToSyncPayload(): JsonObject
|
||||
fun replaceFromSyncPayload(payload: JsonObject)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ import com.nuvio.app.features.addons.AddonRepository
|
|||
import com.nuvio.app.features.player.AudioLanguageOption
|
||||
import com.nuvio.app.features.player.AvailableLanguageOptions
|
||||
import com.nuvio.app.features.player.PlayerSettingsRepository
|
||||
import com.nuvio.app.features.player.SwipeToSeekSensitivity
|
||||
import com.nuvio.app.features.player.SubtitleLanguageOption
|
||||
import com.nuvio.app.features.player.formatPlaybackSpeedLabel
|
||||
import com.nuvio.app.features.player.languageLabelForCode
|
||||
|
|
@ -84,6 +85,8 @@ internal fun LazyListScope.playbackSettingsContent(
|
|||
tunnelingEnabled: Boolean,
|
||||
useLibass: Boolean,
|
||||
libassRenderType: String,
|
||||
swipeToSeekEnabled: Boolean,
|
||||
swipeToSeekSensitivity: SwipeToSeekSensitivity,
|
||||
) {
|
||||
item {
|
||||
PlaybackSettingsSection(
|
||||
|
|
@ -102,6 +105,8 @@ internal fun LazyListScope.playbackSettingsContent(
|
|||
tunnelingEnabled = tunnelingEnabled,
|
||||
useLibass = useLibass,
|
||||
libassRenderType = libassRenderType,
|
||||
swipeToSeekEnabled = swipeToSeekEnabled,
|
||||
swipeToSeekSensitivity = swipeToSeekSensitivity,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -164,6 +169,8 @@ private fun PlaybackSettingsSection(
|
|||
tunnelingEnabled: Boolean,
|
||||
useLibass: Boolean,
|
||||
libassRenderType: String,
|
||||
swipeToSeekEnabled: Boolean,
|
||||
swipeToSeekSensitivity: SwipeToSeekSensitivity,
|
||||
) {
|
||||
var showPreferredAudioDialog by remember { mutableStateOf(false) }
|
||||
var showSecondaryAudioDialog by remember { mutableStateOf(false) }
|
||||
|
|
@ -178,6 +185,7 @@ private fun PlaybackSettingsSection(
|
|||
var showAutoPlayAddonSelectionDialog by remember { mutableStateOf(false) }
|
||||
var showAutoPlayPluginSelectionDialog by remember { mutableStateOf(false) }
|
||||
var showAutoPlayRegexDialog by remember { mutableStateOf(false) }
|
||||
var showSwipeSensitivityDialog by remember { mutableStateOf(false) }
|
||||
val pluginsEnabled = AppFeaturePolicy.pluginsEnabled
|
||||
val autoPlayPlayerSettings by PlayerSettingsRepository.uiState.collectAsStateWithLifecycle()
|
||||
val addonUiState by AddonRepository.uiState.collectAsStateWithLifecycle()
|
||||
|
|
@ -222,6 +230,27 @@ private fun PlaybackSettingsSection(
|
|||
onClick = { showHoldToSpeedValueDialog = true },
|
||||
)
|
||||
}
|
||||
SettingsGroupDivider(isTablet = isTablet)
|
||||
SettingsSwitchRow(
|
||||
title = stringResource(Res.string.settings_playback_swipe_to_seek),
|
||||
description = stringResource(Res.string.settings_playback_swipe_to_seek_description),
|
||||
checked = swipeToSeekEnabled,
|
||||
isTablet = isTablet,
|
||||
onCheckedChange = PlayerSettingsRepository::setSwipeToSeekEnabled,
|
||||
)
|
||||
if (swipeToSeekEnabled) {
|
||||
SettingsGroupDivider(isTablet = isTablet)
|
||||
SettingsNavigationRow(
|
||||
title = stringResource(Res.string.settings_playback_swipe_to_seek_sensitivity),
|
||||
description = when (swipeToSeekSensitivity) {
|
||||
SwipeToSeekSensitivity.LOW -> stringResource(Res.string.settings_playback_swipe_to_seek_sensitivity_low)
|
||||
SwipeToSeekSensitivity.MEDIUM -> stringResource(Res.string.settings_playback_swipe_to_seek_sensitivity_medium)
|
||||
SwipeToSeekSensitivity.HIGH -> stringResource(Res.string.settings_playback_swipe_to_seek_sensitivity_high)
|
||||
},
|
||||
isTablet = isTablet,
|
||||
onClick = { showSwipeSensitivityDialog = true },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -813,6 +842,14 @@ private fun PlaybackSettingsSection(
|
|||
)
|
||||
}
|
||||
|
||||
if (showSwipeSensitivityDialog) {
|
||||
SwipeToSeekSensitivityDialog(
|
||||
selected = swipeToSeekSensitivity,
|
||||
onSelect = PlayerSettingsRepository::setSwipeToSeekSensitivity,
|
||||
onDismiss = { showSwipeSensitivityDialog = false },
|
||||
)
|
||||
}
|
||||
|
||||
if (showAutoPlayModeDialog) {
|
||||
StreamAutoPlayModeDialog(
|
||||
selectedMode = autoPlayPlayerSettings.streamAutoPlayMode,
|
||||
|
|
@ -2178,3 +2215,89 @@ private fun libassRenderTypeRes(renderType: String): StringResource = when (rend
|
|||
|
||||
@Composable
|
||||
private fun libassRenderTypeLabel(renderType: String): String = stringResource(libassRenderTypeRes(renderType))
|
||||
|
||||
@Composable
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
private fun SwipeToSeekSensitivityDialog(
|
||||
selected: SwipeToSeekSensitivity,
|
||||
onSelect: (SwipeToSeekSensitivity) -> Unit,
|
||||
onDismiss: () -> Unit,
|
||||
) {
|
||||
val options = SwipeToSeekSensitivity.entries
|
||||
|
||||
BasicAlertDialog(onDismissRequest = onDismiss) {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
shape = RoundedCornerShape(20.dp),
|
||||
color = MaterialTheme.colorScheme.surface,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(20.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(Res.string.settings_playback_swipe_to_seek_sensitivity),
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
)
|
||||
Text(
|
||||
text = stringResource(Res.string.settings_playback_swipe_to_seek_sensitivity_description),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
options.forEach { option ->
|
||||
val isSelected = option == selected
|
||||
val containerColor = if (isSelected) {
|
||||
MaterialTheme.colorScheme.primary.copy(alpha = 0.14f)
|
||||
} else {
|
||||
MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.35f)
|
||||
}
|
||||
|
||||
Surface(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable {
|
||||
onSelect(option)
|
||||
onDismiss()
|
||||
},
|
||||
shape = RoundedCornerShape(12.dp),
|
||||
color = containerColor,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 14.dp, vertical = 12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
text = when (option) {
|
||||
SwipeToSeekSensitivity.LOW -> stringResource(Res.string.settings_playback_swipe_to_seek_sensitivity_low)
|
||||
SwipeToSeekSensitivity.MEDIUM -> stringResource(Res.string.settings_playback_swipe_to_seek_sensitivity_medium)
|
||||
SwipeToSeekSensitivity.HIGH -> stringResource(Res.string.settings_playback_swipe_to_seek_sensitivity_high)
|
||||
else -> stringResource(Res.string.settings_playback_swipe_to_seek_sensitivity_medium)
|
||||
},
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
if (isSelected) {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Check,
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,9 @@ import com.nuvio.app.features.mdblist.MdbListSettingsRepository
|
|||
import com.nuvio.app.features.notifications.EpisodeReleaseNotificationsRepository
|
||||
import com.nuvio.app.features.notifications.EpisodeReleaseNotificationsUiState
|
||||
import com.nuvio.app.features.player.PlayerSettingsRepository
|
||||
import com.nuvio.app.features.player.PlayerResizeMode
|
||||
import com.nuvio.app.features.player.SwipeToSeekSensitivity
|
||||
import com.nuvio.app.features.player.skip.NextEpisodeThresholdMode
|
||||
import com.nuvio.app.features.trakt.TraktAuthUiState
|
||||
import com.nuvio.app.features.trakt.TraktAuthRepository
|
||||
import com.nuvio.app.features.trakt.TraktCommentsSettings
|
||||
|
|
@ -193,6 +196,8 @@ fun SettingsScreen(
|
|||
tunnelingEnabled = playerSettingsUiState.tunnelingEnabled,
|
||||
useLibass = playerSettingsUiState.useLibass,
|
||||
libassRenderType = playerSettingsUiState.libassRenderType,
|
||||
swipeToSeekEnabled = playerSettingsUiState.swipeToSeekEnabled,
|
||||
swipeToSeekSensitivity = playerSettingsUiState.swipeToSeekSensitivity,
|
||||
selectedTheme = selectedTheme,
|
||||
onThemeSelected = ThemeSettingsRepository::setTheme,
|
||||
amoledEnabled = amoledEnabled,
|
||||
|
|
@ -238,6 +243,8 @@ fun SettingsScreen(
|
|||
tunnelingEnabled = playerSettingsUiState.tunnelingEnabled,
|
||||
useLibass = playerSettingsUiState.useLibass,
|
||||
libassRenderType = playerSettingsUiState.libassRenderType,
|
||||
swipeToSeekEnabled = playerSettingsUiState.swipeToSeekEnabled,
|
||||
swipeToSeekSensitivity = playerSettingsUiState.swipeToSeekSensitivity,
|
||||
selectedTheme = selectedTheme,
|
||||
onThemeSelected = ThemeSettingsRepository::setTheme,
|
||||
amoledEnabled = amoledEnabled,
|
||||
|
|
@ -293,6 +300,8 @@ private fun MobileSettingsScreen(
|
|||
tunnelingEnabled: Boolean,
|
||||
useLibass: Boolean,
|
||||
libassRenderType: String,
|
||||
swipeToSeekEnabled: Boolean,
|
||||
swipeToSeekSensitivity: SwipeToSeekSensitivity,
|
||||
selectedTheme: AppTheme,
|
||||
onThemeSelected: (AppTheme) -> Unit,
|
||||
amoledEnabled: Boolean,
|
||||
|
|
@ -374,6 +383,8 @@ private fun MobileSettingsScreen(
|
|||
tunnelingEnabled = tunnelingEnabled,
|
||||
useLibass = useLibass,
|
||||
libassRenderType = libassRenderType,
|
||||
swipeToSeekEnabled = swipeToSeekEnabled,
|
||||
swipeToSeekSensitivity = swipeToSeekSensitivity,
|
||||
)
|
||||
SettingsPage.Appearance -> appearanceSettingsContent(
|
||||
isTablet = false,
|
||||
|
|
@ -471,6 +482,8 @@ private fun TabletSettingsScreen(
|
|||
tunnelingEnabled: Boolean,
|
||||
useLibass: Boolean,
|
||||
libassRenderType: String,
|
||||
swipeToSeekEnabled: Boolean,
|
||||
swipeToSeekSensitivity: SwipeToSeekSensitivity,
|
||||
selectedTheme: AppTheme,
|
||||
onThemeSelected: (AppTheme) -> Unit,
|
||||
amoledEnabled: Boolean,
|
||||
|
|
@ -624,6 +637,8 @@ private fun TabletSettingsScreen(
|
|||
tunnelingEnabled = tunnelingEnabled,
|
||||
useLibass = useLibass,
|
||||
libassRenderType = libassRenderType,
|
||||
swipeToSeekEnabled = swipeToSeekEnabled,
|
||||
swipeToSeekSensitivity = swipeToSeekSensitivity,
|
||||
)
|
||||
SettingsPage.Appearance -> appearanceSettingsContent(
|
||||
isTablet = true,
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ actual object PlayerSettingsStorage {
|
|||
private const val nextEpisodeThresholdMinutesBeforeEndKey = "next_episode_threshold_minutes_before_end_v2"
|
||||
private const val useLibassKey = "use_libass"
|
||||
private const val libassRenderTypeKey = "libass_render_type"
|
||||
private const val swipeToSeekEnabledKey = "swipe_to_seek_enabled"
|
||||
private const val swipeToSeekSensitivityKey = "swipe_to_seek_sensitivity"
|
||||
private val syncKeys = listOf(
|
||||
showLoadingOverlayKey,
|
||||
resizeModeKey,
|
||||
|
|
@ -86,6 +88,8 @@ actual object PlayerSettingsStorage {
|
|||
nextEpisodeThresholdMinutesBeforeEndKey,
|
||||
useLibassKey,
|
||||
libassRenderTypeKey,
|
||||
swipeToSeekEnabledKey,
|
||||
swipeToSeekSensitivityKey,
|
||||
)
|
||||
|
||||
actual fun loadShowLoadingOverlay(): Boolean? {
|
||||
|
|
@ -552,6 +556,8 @@ actual object PlayerSettingsStorage {
|
|||
loadNextEpisodeThresholdMinutesBeforeEnd()?.let { put(nextEpisodeThresholdMinutesBeforeEndKey, encodeSyncFloat(it)) }
|
||||
loadUseLibass()?.let { put(useLibassKey, encodeSyncBoolean(it)) }
|
||||
loadLibassRenderType()?.let { put(libassRenderTypeKey, encodeSyncString(it)) }
|
||||
loadSwipeToSeekEnabled()?.let { put(swipeToSeekEnabledKey, encodeSyncBoolean(it)) }
|
||||
loadSwipeToSeekSensitivity()?.let { put(swipeToSeekSensitivityKey, encodeSyncString(it)) }
|
||||
}
|
||||
|
||||
actual fun replaceFromSyncPayload(payload: JsonObject) {
|
||||
|
|
@ -593,5 +599,29 @@ actual object PlayerSettingsStorage {
|
|||
payload.decodeSyncFloat(nextEpisodeThresholdMinutesBeforeEndKey)?.let(::saveNextEpisodeThresholdMinutesBeforeEnd)
|
||||
payload.decodeSyncBoolean(useLibassKey)?.let(::saveUseLibass)
|
||||
payload.decodeSyncString(libassRenderTypeKey)?.let(::saveLibassRenderType)
|
||||
payload.decodeSyncBoolean(swipeToSeekEnabledKey)?.let(::saveSwipeToSeekEnabled)
|
||||
payload.decodeSyncString(swipeToSeekSensitivityKey)?.let(::saveSwipeToSeekSensitivity)
|
||||
}
|
||||
|
||||
actual fun loadSwipeToSeekEnabled(): Boolean? {
|
||||
val defaults = NSUserDefaults.standardUserDefaults
|
||||
val key = ProfileScopedKey.of(swipeToSeekEnabledKey)
|
||||
return if (defaults.objectForKey(key) != null) {
|
||||
defaults.boolForKey(key)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
actual fun saveSwipeToSeekEnabled(enabled: Boolean) {
|
||||
val defaults = NSUserDefaults.standardUserDefaults
|
||||
defaults.setBool(enabled, ProfileScopedKey.of(swipeToSeekEnabledKey))
|
||||
}
|
||||
|
||||
actual fun loadSwipeToSeekSensitivity(): String? =
|
||||
NSUserDefaults.standardUserDefaults.stringForKey(ProfileScopedKey.of(swipeToSeekSensitivityKey))
|
||||
|
||||
actual fun saveSwipeToSeekSensitivity(sensitivity: String) {
|
||||
NSUserDefaults.standardUserDefaults.setObject(sensitivity, ProfileScopedKey.of(swipeToSeekSensitivityKey))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue