From a8d6d8d2700245f7ccc02a5e370e013d50308a21 Mon Sep 17 00:00:00 2001 From: tapframe <85391825+tapframe@users.noreply.github.com> Date: Sat, 18 Jul 2026 16:54:50 +0530 Subject: [PATCH] fix(player): match forced subtitles to language preferences --- .../player/PlayerScreenRuntimeTrackActions.kt | 7 +- .../features/player/PlayerTrackSelection.kt | 10 +-- .../player/PlayerTrackSelectionTest.kt | 69 +++++++++++++++++++ 3 files changed, 77 insertions(+), 9 deletions(-) create mode 100644 composeApp/src/commonTest/kotlin/com/nuvio/app/features/player/PlayerTrackSelectionTest.kt 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 098c258f5..e4f5d2462 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 @@ -175,11 +175,7 @@ internal fun PlayerScreenRuntime.refreshTracks() { if (!preferredSubtitleSelectionApplied) { val preferredSubtitleTargets = resolvePreferredSubtitleLanguageTargets( - preferredSubtitleLanguage = if (subtitleStyle.useForcedSubtitles) { - SubtitleLanguageOption.FORCED - } else { - playerSettingsUiState.preferredSubtitleLanguage - }, + preferredSubtitleLanguage = playerSettingsUiState.preferredSubtitleLanguage, secondaryPreferredSubtitleLanguage = playerSettingsUiState.secondaryPreferredSubtitleLanguage, deviceLanguages = DeviceLanguagePreferences.preferredLanguageCodes(), ) @@ -196,6 +192,7 @@ internal fun PlayerScreenRuntime.refreshTracks() { val preferredSubtitleIndex = findPreferredSubtitleTrackIndex( tracks = subtitleTracks, targets = preferredSubtitleTargets, + requireForced = subtitleStyle.useForcedSubtitles, ) if (preferredSubtitleIndex >= 0 && preferredSubtitleIndex != selectedSubtitleIndex) { playerController?.selectSubtitleTrack(preferredSubtitleIndex) 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 5bd895def..1fef16145 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 @@ -68,6 +68,7 @@ internal fun findPreferredTrackIndex( internal fun findPreferredSubtitleTrackIndex( tracks: List, targets: List, + requireForced: Boolean = false, ): Int { if (targets.isEmpty()) return -1 @@ -81,10 +82,11 @@ internal fun findPreferredSubtitleTrackIndex( } val matchIndex = tracks.indexOfFirst { track -> - languageMatchesPreference( - trackLanguage = track.language, - targetLanguage = normalizedTarget, - ) + (!requireForced || track.isForced) && + languageMatchesPreference( + trackLanguage = track.language, + targetLanguage = normalizedTarget, + ) } if (matchIndex >= 0) return matchIndex } 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 new file mode 100644 index 000000000..050969f96 --- /dev/null +++ b/composeApp/src/commonTest/kotlin/com/nuvio/app/features/player/PlayerTrackSelectionTest.kt @@ -0,0 +1,69 @@ +package com.nuvio.app.features.player + +import kotlin.test.Test +import kotlin.test.assertEquals + +class PlayerTrackSelectionTest { + + @Test + fun forcedSelectionUsesPrimaryPreferredLanguageInsteadOfTrackOrder() { + val tracks = listOf( + subtitleTrack(index = 0, language = "ja", isForced = true), + subtitleTrack(index = 1, language = "en", isForced = false), + subtitleTrack(index = 2, language = "en", isForced = true), + ) + + val selectedIndex = findPreferredSubtitleTrackIndex( + tracks = tracks, + targets = listOf("en"), + requireForced = true, + ) + + assertEquals(2, selectedIndex) + } + + @Test + fun forcedSelectionFallsBackToSecondaryPreferredLanguage() { + val tracks = listOf( + subtitleTrack(index = 0, language = "ja", isForced = true), + subtitleTrack(index = 1, language = "en", isForced = false), + subtitleTrack(index = 2, language = "fr", isForced = true), + ) + + val selectedIndex = findPreferredSubtitleTrackIndex( + tracks = tracks, + targets = listOf("en", "fr"), + requireForced = true, + ) + + assertEquals(2, selectedIndex) + } + + @Test + fun forcedSelectionRejectsTracksOutsidePreferredLanguages() { + val tracks = listOf( + subtitleTrack(index = 0, language = "ja", isForced = true), + subtitleTrack(index = 1, language = "en", isForced = false), + ) + + val selectedIndex = findPreferredSubtitleTrackIndex( + tracks = tracks, + targets = listOf("en"), + requireForced = true, + ) + + assertEquals(-1, selectedIndex) + } + + private fun subtitleTrack( + index: Int, + language: String, + isForced: Boolean, + ) = SubtitleTrack( + index = index, + id = "track-$index", + label = "Track $index", + language = language, + isForced = isForced, + ) +}