diff --git a/composeApp/src/androidMain/kotlin/com/nuvio/app/features/player/PlayerSettingsStorage.android.kt b/composeApp/src/androidMain/kotlin/com/nuvio/app/features/player/PlayerSettingsStorage.android.kt index f93a409d..ddcc8a9f 100644 --- a/composeApp/src/androidMain/kotlin/com/nuvio/app/features/player/PlayerSettingsStorage.android.kt +++ b/composeApp/src/androidMain/kotlin/com/nuvio/app/features/player/PlayerSettingsStorage.android.kt @@ -20,6 +20,7 @@ import kotlinx.serialization.json.put actual object PlayerSettingsStorage { private const val preferencesName = "nuvio_player_settings" private const val showLoadingOverlayKey = "show_loading_overlay" + private const val resizeModeKey = "resize_mode" private const val holdToSpeedEnabledKey = "hold_to_speed_enabled" private const val holdToSpeedValueKey = "hold_to_speed_value" private const val preferredAudioLanguageKey = "preferred_audio_language" @@ -53,6 +54,7 @@ actual object PlayerSettingsStorage { private const val libassRenderTypeKey = "libass_render_type" private val syncKeys = listOf( showLoadingOverlayKey, + resizeModeKey, holdToSpeedEnabledKey, holdToSpeedValueKey, preferredAudioLanguageKey, @@ -109,6 +111,16 @@ actual object PlayerSettingsStorage { ?.apply() } + actual fun loadResizeMode(): String? = + preferences?.getString(ProfileScopedKey.of(resizeModeKey), null) + + actual fun saveResizeMode(mode: String) { + preferences + ?.edit() + ?.putString(ProfileScopedKey.of(resizeModeKey), mode) + ?.apply() + } + actual fun loadHoldToSpeedEnabled(): Boolean? = preferences?.let { sharedPreferences -> val key = ProfileScopedKey.of(holdToSpeedEnabledKey) @@ -575,6 +587,7 @@ actual object PlayerSettingsStorage { actual fun exportToSyncPayload(): JsonObject = buildJsonObject { loadShowLoadingOverlay()?.let { put(showLoadingOverlayKey, encodeSyncBoolean(it)) } + loadResizeMode()?.let { put(resizeModeKey, encodeSyncString(it)) } loadHoldToSpeedEnabled()?.let { put(holdToSpeedEnabledKey, encodeSyncBoolean(it)) } loadHoldToSpeedValue()?.let { put(holdToSpeedValueKey, encodeSyncFloat(it)) } loadPreferredAudioLanguage()?.let { put(preferredAudioLanguageKey, encodeSyncString(it)) } @@ -614,6 +627,7 @@ actual object PlayerSettingsStorage { }?.apply() payload.decodeSyncBoolean(showLoadingOverlayKey)?.let(::saveShowLoadingOverlay) + payload.decodeSyncString(resizeModeKey)?.let(::saveResizeMode) payload.decodeSyncBoolean(holdToSpeedEnabledKey)?.let(::saveHoldToSpeedEnabled) payload.decodeSyncFloat(holdToSpeedValueKey)?.let(::saveHoldToSpeedValue) payload.decodeSyncString(preferredAudioLanguageKey)?.let(::savePreferredAudioLanguage) diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerScreen.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerScreen.kt index 7b2b5c9c..21960cba 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerScreen.kt @@ -174,7 +174,9 @@ fun PlayerScreen( var activeInitialPositionMs by rememberSaveable { mutableStateOf(initialPositionMs) } var activeInitialProgressFraction by rememberSaveable { mutableStateOf(initialProgressFraction) } var shouldPlay by rememberSaveable(activeSourceUrl) { mutableStateOf(true) } - var resizeMode by rememberSaveable { mutableStateOf(PlayerResizeMode.Fit) } + var resizeMode by rememberSaveable(playerSettingsUiState.resizeMode) { + mutableStateOf(playerSettingsUiState.resizeMode) + } var layoutSize by remember { mutableStateOf(IntSize.Zero) } var playbackSnapshot by remember { mutableStateOf(PlayerPlaybackSnapshot()) } var playerController by remember { mutableStateOf(null) } @@ -610,8 +612,10 @@ fun PlayerScreen( } fun cycleResizeMode() { - resizeMode = resizeMode.next() - showGestureMessage(resizeMode.label) + val nextMode = resizeMode.next() + resizeMode = nextMode + PlayerSettingsRepository.setResizeMode(nextMode) + showGestureMessage(nextMode.label) controlsVisible = true } diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerSettingsRepository.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerSettingsRepository.kt index 6d07096d..df32f47d 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerSettingsRepository.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerSettingsRepository.kt @@ -10,6 +10,7 @@ import kotlinx.coroutines.flow.asStateFlow data class PlayerSettingsUiState( val showLoadingOverlay: Boolean = true, + val resizeMode: PlayerResizeMode = PlayerResizeMode.Fit, val holdToSpeedEnabled: Boolean = true, val holdToSpeedValue: Float = 2f, val preferredAudioLanguage: String = AudioLanguageOption.DEVICE, @@ -46,6 +47,7 @@ object PlayerSettingsRepository { private var hasLoaded = false private var showLoadingOverlay = true + private var resizeMode = PlayerResizeMode.Fit private var holdToSpeedEnabled = true private var holdToSpeedValue = 2f private var preferredAudioLanguage = AudioLanguageOption.DEVICE @@ -87,6 +89,7 @@ object PlayerSettingsRepository { fun clearLocalState() { hasLoaded = false showLoadingOverlay = true + resizeMode = PlayerResizeMode.Fit holdToSpeedEnabled = true holdToSpeedValue = 2f preferredAudioLanguage = AudioLanguageOption.DEVICE @@ -121,6 +124,9 @@ object PlayerSettingsRepository { private fun loadFromDisk() { hasLoaded = true showLoadingOverlay = PlayerSettingsStorage.loadShowLoadingOverlay() ?: true + resizeMode = PlayerSettingsStorage.loadResizeMode() + ?.let { runCatching { PlayerResizeMode.valueOf(it) }.getOrNull() } + ?: PlayerResizeMode.Fit holdToSpeedEnabled = PlayerSettingsStorage.loadHoldToSpeedEnabled() ?: true holdToSpeedValue = PlayerSettingsStorage.loadHoldToSpeedValue() ?: 2f preferredAudioLanguage = @@ -192,6 +198,14 @@ object PlayerSettingsRepository { PlayerSettingsStorage.saveShowLoadingOverlay(enabled) } + fun setResizeMode(mode: PlayerResizeMode) { + ensureLoaded() + if (resizeMode == mode) return + resizeMode = mode + publish() + PlayerSettingsStorage.saveResizeMode(mode.name) + } + fun setHoldToSpeedEnabled(enabled: Boolean) { ensureLoaded() if (holdToSpeedEnabled == enabled) return @@ -429,6 +443,7 @@ object PlayerSettingsRepository { private fun publish() { _uiState.value = PlayerSettingsUiState( showLoadingOverlay = showLoadingOverlay, + resizeMode = resizeMode, holdToSpeedEnabled = holdToSpeedEnabled, holdToSpeedValue = holdToSpeedValue, preferredAudioLanguage = preferredAudioLanguage, diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerSettingsStorage.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerSettingsStorage.kt index ba19ee86..929d7deb 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerSettingsStorage.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerSettingsStorage.kt @@ -5,6 +5,8 @@ import kotlinx.serialization.json.JsonObject internal expect object PlayerSettingsStorage { fun loadShowLoadingOverlay(): Boolean? fun saveShowLoadingOverlay(enabled: Boolean) + fun loadResizeMode(): String? + fun saveResizeMode(mode: String) fun loadHoldToSpeedEnabled(): Boolean? fun saveHoldToSpeedEnabled(enabled: Boolean) fun loadHoldToSpeedValue(): Float? diff --git a/composeApp/src/iosMain/kotlin/com/nuvio/app/features/player/PlayerSettingsStorage.ios.kt b/composeApp/src/iosMain/kotlin/com/nuvio/app/features/player/PlayerSettingsStorage.ios.kt index bf78feb7..c4e9795e 100644 --- a/composeApp/src/iosMain/kotlin/com/nuvio/app/features/player/PlayerSettingsStorage.ios.kt +++ b/composeApp/src/iosMain/kotlin/com/nuvio/app/features/player/PlayerSettingsStorage.ios.kt @@ -18,6 +18,7 @@ import platform.Foundation.NSUserDefaults actual object PlayerSettingsStorage { private const val showLoadingOverlayKey = "show_loading_overlay" + private const val resizeModeKey = "resize_mode" private const val holdToSpeedEnabledKey = "hold_to_speed_enabled" private const val holdToSpeedValueKey = "hold_to_speed_value" private const val preferredAudioLanguageKey = "preferred_audio_language" @@ -51,6 +52,7 @@ actual object PlayerSettingsStorage { private const val libassRenderTypeKey = "libass_render_type" private val syncKeys = listOf( showLoadingOverlayKey, + resizeModeKey, holdToSpeedEnabledKey, holdToSpeedValueKey, preferredAudioLanguageKey, @@ -98,6 +100,16 @@ actual object PlayerSettingsStorage { NSUserDefaults.standardUserDefaults.setBool(enabled, forKey = ProfileScopedKey.of(showLoadingOverlayKey)) } + actual fun loadResizeMode(): String? { + val defaults = NSUserDefaults.standardUserDefaults + val key = ProfileScopedKey.of(resizeModeKey) + return defaults.stringForKey(key) + } + + actual fun saveResizeMode(mode: String) { + NSUserDefaults.standardUserDefaults.setObject(mode, forKey = ProfileScopedKey.of(resizeModeKey)) + } + actual fun loadHoldToSpeedEnabled(): Boolean? { val defaults = NSUserDefaults.standardUserDefaults val key = ProfileScopedKey.of(holdToSpeedEnabledKey) @@ -482,6 +494,7 @@ actual object PlayerSettingsStorage { actual fun exportToSyncPayload(): JsonObject = buildJsonObject { loadShowLoadingOverlay()?.let { put(showLoadingOverlayKey, encodeSyncBoolean(it)) } + loadResizeMode()?.let { put(resizeModeKey, encodeSyncString(it)) } loadHoldToSpeedEnabled()?.let { put(holdToSpeedEnabledKey, encodeSyncBoolean(it)) } loadHoldToSpeedValue()?.let { put(holdToSpeedValueKey, encodeSyncFloat(it)) } loadPreferredAudioLanguage()?.let { put(preferredAudioLanguageKey, encodeSyncString(it)) } @@ -521,6 +534,7 @@ actual object PlayerSettingsStorage { } payload.decodeSyncBoolean(showLoadingOverlayKey)?.let(::saveShowLoadingOverlay) + payload.decodeSyncString(resizeModeKey)?.let(::saveResizeMode) payload.decodeSyncBoolean(holdToSpeedEnabledKey)?.let(::saveHoldToSpeedEnabled) payload.decodeSyncFloat(holdToSpeedValueKey)?.let(::saveHoldToSpeedValue) payload.decodeSyncString(preferredAudioLanguageKey)?.let(::savePreferredAudioLanguage)