diff --git a/composeApp/src/androidMain/kotlin/com/nuvio/app/features/player/PlayerTrackPreferenceStorage.android.kt b/composeApp/src/androidMain/kotlin/com/nuvio/app/features/player/PlayerTrackPreferenceStorage.android.kt index bbd98327d..5855bf5be 100644 --- a/composeApp/src/androidMain/kotlin/com/nuvio/app/features/player/PlayerTrackPreferenceStorage.android.kt +++ b/composeApp/src/androidMain/kotlin/com/nuvio/app/features/player/PlayerTrackPreferenceStorage.android.kt @@ -13,6 +13,7 @@ internal actual object PlayerTrackPreferenceStorage { private const val addonSubtitleIdKey = "addon_subtitle_id" private const val addonSubtitleUrlKey = "addon_subtitle_url" private const val addonSubtitleAddonNameKey = "addon_subtitle_addon_name" + private const val addonSubtitleVideoIdKey = "addon_subtitle_video_id" private const val audioLanguageKey = "audio_language" private const val audioNameKey = "audio_name" private const val audioTrackIdKey = "audio_track_id" @@ -34,6 +35,7 @@ internal actual object PlayerTrackPreferenceStorage { addonSubtitleId = loadString(addonSubtitleIdKey, id), addonSubtitleUrl = loadString(addonSubtitleUrlKey, id), addonSubtitleAddonName = loadString(addonSubtitleAddonNameKey, id), + addonSubtitleVideoId = loadString(addonSubtitleVideoIdKey, id), audioLanguage = loadString(audioLanguageKey, id), audioName = loadString(audioNameKey, id), audioTrackId = loadString(audioTrackIdKey, id), @@ -47,6 +49,7 @@ internal actual object PlayerTrackPreferenceStorage { it.addonSubtitleId, it.addonSubtitleUrl, it.addonSubtitleAddonName, + it.addonSubtitleVideoId, it.audioLanguage, it.audioName, it.audioTrackId, @@ -64,6 +67,7 @@ internal actual object PlayerTrackPreferenceStorage { putOptionalString(addonSubtitleIdKey, id, preference.addonSubtitleId) putOptionalString(addonSubtitleUrlKey, id, preference.addonSubtitleUrl) putOptionalString(addonSubtitleAddonNameKey, id, preference.addonSubtitleAddonName) + putOptionalString(addonSubtitleVideoIdKey, id, preference.addonSubtitleVideoId) putOptionalString(audioLanguageKey, id, preference.audioLanguage) putOptionalString(audioNameKey, id, preference.audioName) putOptionalString(audioTrackIdKey, id, preference.audioTrackId) diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerScreenRuntimePlaybackActions.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerScreenRuntimePlaybackActions.kt index 516548999..0061754e6 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerScreenRuntimePlaybackActions.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerScreenRuntimePlaybackActions.kt @@ -65,6 +65,10 @@ internal fun PlayerScreenRuntime.resetIdentityStateIfNeeded() { val videoIdentity = "$identity:$activeVideoId:$activeSeasonNumber:$activeEpisodeNumber" if (lastResetVideoIdentity != videoIdentity) { lastResetVideoIdentity = videoIdentity + trackPreferenceRestoreApplied = false + preferredSubtitleSelectionApplied = false + selectedAddonSubtitleId = null + useCustomSubtitles = false hasRequestedScrobbleStartForCurrentItem = false scrobbleStartRequestGeneration = 0L pendingScrobbleStartAfterSeek = false diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerScreenRuntimeTrackActions.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerScreenRuntimeTrackActions.kt index c4715427c..58e25d992 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerScreenRuntimeTrackActions.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerScreenRuntimeTrackActions.kt @@ -56,6 +56,7 @@ internal fun PlayerScreenRuntime.persistInternalSubtitlePreference(track: Subtit addonSubtitleId = null, addonSubtitleUrl = null, addonSubtitleAddonName = null, + addonSubtitleVideoId = null, ) } } @@ -70,6 +71,7 @@ internal fun PlayerScreenRuntime.persistAddonSubtitlePreference(subtitle: AddonS addonSubtitleId = subtitle.id, addonSubtitleUrl = subtitle.url, addonSubtitleAddonName = subtitle.addonName, + addonSubtitleVideoId = playbackSession.videoId, ) } } @@ -121,13 +123,21 @@ internal fun PlayerScreenRuntime.restorePersistedTrackPreferenceIfNeeded() { } } PersistedSubtitleSelectionType.ADDON -> { - val url = preference.addonSubtitleUrl?.takeIf { it.isNotBlank() } + val url = persistedAddonSubtitleUrlForVideo( + preference = preference, + videoId = playbackSession.videoId, + ) if (url != null) { selectedAddonSubtitleId = preference.addonSubtitleId ?: url selectedSubtitleIndex = -1 useCustomSubtitles = true playerController?.setSubtitleUri(url) preferredSubtitleSelectionApplied = true + } else { + playerController?.clearExternalSubtitle() + selectedAddonSubtitleId = null + selectedSubtitleIndex = -1 + useCustomSubtitles = false } } } diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerTrackPreferenceStorage.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerTrackPreferenceStorage.kt index e941f20a6..1c5dec51d 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerTrackPreferenceStorage.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerTrackPreferenceStorage.kt @@ -8,6 +8,7 @@ data class PersistedPlayerTrackPreference( val addonSubtitleId: String? = null, val addonSubtitleUrl: String? = null, val addonSubtitleAddonName: String? = null, + val addonSubtitleVideoId: String? = null, val audioLanguage: String? = null, val audioName: String? = null, val audioTrackId: String? = null, diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerTrackSelection.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerTrackSelection.kt index a9bdeb4aa..e56ebbf04 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerTrackSelection.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerTrackSelection.kt @@ -219,3 +219,12 @@ internal fun findPersistedSubtitleTrackIndex( } return -1 } + +internal fun persistedAddonSubtitleUrlForVideo( + preference: PersistedPlayerTrackPreference, + videoId: String, +): String? { + val persistedVideoId = preference.addonSubtitleVideoId?.takeIf { it.isNotBlank() } ?: return null + if (persistedVideoId != videoId.takeIf { it.isNotBlank() }) return null + return preference.addonSubtitleUrl?.takeIf { it.isNotBlank() } +} diff --git a/composeApp/src/commonTest/kotlin/com/nuvio/app/features/player/PlayerTrackSelectionTest.kt b/composeApp/src/commonTest/kotlin/com/nuvio/app/features/player/PlayerTrackSelectionTest.kt index 3e6f98a8b..b3f7a0616 100644 --- a/composeApp/src/commonTest/kotlin/com/nuvio/app/features/player/PlayerTrackSelectionTest.kt +++ b/composeApp/src/commonTest/kotlin/com/nuvio/app/features/player/PlayerTrackSelectionTest.kt @@ -234,6 +234,38 @@ class PlayerTrackSelectionTest { assertEquals(listOf("french", "english"), visibleSubtitles.map { it.id }) } + @Test + fun addonSubtitleUrlIsRestoredForTheSameEpisode() { + val preference = PersistedPlayerTrackPreference( + addonSubtitleUrl = "https://example.com/episode-1.srt", + addonSubtitleVideoId = "series:1:1", + ) + + assertEquals( + "https://example.com/episode-1.srt", + persistedAddonSubtitleUrlForVideo(preference, "series:1:1"), + ) + } + + @Test + fun addonSubtitleUrlIsNotReusedForAnotherEpisode() { + val preference = PersistedPlayerTrackPreference( + addonSubtitleUrl = "https://example.com/episode-1.srt", + addonSubtitleVideoId = "series:1:1", + ) + + assertEquals(null, persistedAddonSubtitleUrlForVideo(preference, "series:1:2")) + } + + @Test + fun legacyUnscopedAddonSubtitleUrlIsNotRestored() { + val preference = PersistedPlayerTrackPreference( + addonSubtitleUrl = "https://example.com/episode-1.srt", + ) + + assertEquals(null, persistedAddonSubtitleUrlForVideo(preference, "series:1:1")) + } + private fun subtitleTrack( index: Int, language: String?, diff --git a/composeApp/src/iosMain/kotlin/com/nuvio/app/features/player/PlayerTrackPreferenceStorage.ios.kt b/composeApp/src/iosMain/kotlin/com/nuvio/app/features/player/PlayerTrackPreferenceStorage.ios.kt index f48941f86..8a0bcda6f 100644 --- a/composeApp/src/iosMain/kotlin/com/nuvio/app/features/player/PlayerTrackPreferenceStorage.ios.kt +++ b/composeApp/src/iosMain/kotlin/com/nuvio/app/features/player/PlayerTrackPreferenceStorage.ios.kt @@ -11,6 +11,7 @@ internal actual object PlayerTrackPreferenceStorage { private const val addonSubtitleIdKey = "addon_subtitle_id" private const val addonSubtitleUrlKey = "addon_subtitle_url" private const val addonSubtitleAddonNameKey = "addon_subtitle_addon_name" + private const val addonSubtitleVideoIdKey = "addon_subtitle_video_id" private const val audioLanguageKey = "audio_language" private const val audioNameKey = "audio_name" private const val audioTrackIdKey = "audio_track_id" @@ -26,6 +27,7 @@ internal actual object PlayerTrackPreferenceStorage { addonSubtitleId = loadString(addonSubtitleIdKey, id), addonSubtitleUrl = loadString(addonSubtitleUrlKey, id), addonSubtitleAddonName = loadString(addonSubtitleAddonNameKey, id), + addonSubtitleVideoId = loadString(addonSubtitleVideoIdKey, id), audioLanguage = loadString(audioLanguageKey, id), audioName = loadString(audioNameKey, id), audioTrackId = loadString(audioTrackIdKey, id), @@ -39,6 +41,7 @@ internal actual object PlayerTrackPreferenceStorage { it.addonSubtitleId, it.addonSubtitleUrl, it.addonSubtitleAddonName, + it.addonSubtitleVideoId, it.audioLanguage, it.audioName, it.audioTrackId, @@ -55,6 +58,7 @@ internal actual object PlayerTrackPreferenceStorage { saveOptionalString(addonSubtitleIdKey, id, preference.addonSubtitleId) saveOptionalString(addonSubtitleUrlKey, id, preference.addonSubtitleUrl) saveOptionalString(addonSubtitleAddonNameKey, id, preference.addonSubtitleAddonName) + saveOptionalString(addonSubtitleVideoIdKey, id, preference.addonSubtitleVideoId) saveOptionalString(audioLanguageKey, id, preference.audioLanguage) saveOptionalString(audioNameKey, id, preference.audioName) saveOptionalString(audioTrackIdKey, id, preference.audioTrackId)