mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-07-26 22:42:17 +00:00
Merge branch 'sub/forced' into cmp-rewrite
This commit is contained in:
commit
3c253b1b78
4 changed files with 409 additions and 74 deletions
|
|
@ -1024,7 +1024,7 @@
|
|||
<string name="settings_playback_subtitle_size">Subtitle Size</string>
|
||||
<string name="settings_playback_subtitle_text_color">Text Color</string>
|
||||
<string name="settings_playback_subtitle_use_forced">Use Forced Subtitles</string>
|
||||
<string name="settings_playback_subtitle_use_forced_description">Prefer forced subtitles when matching your subtitle language settings.</string>
|
||||
<string name="settings_playback_subtitle_use_forced_description">Prefer forced subtitles when audio matches the subtitle language; if unavailable, select nothing.</string>
|
||||
<string name="settings_playback_subtitle_vertical_offset">Vertical Offset</string>
|
||||
<string name="settings_playback_skip_intro_outro_recap">Skip Intro</string>
|
||||
<string name="settings_playback_skip_intro_outro_recap_description">Use introdb.app to detect intros and recaps.</string>
|
||||
|
|
|
|||
|
|
@ -17,11 +17,10 @@ internal val PlayerScreenRuntime.visibleAddonSubtitles: List<AddonSubtitle>
|
|||
get() = filterAddonSubtitlesForSettings(
|
||||
subtitles = addonSubtitles,
|
||||
settings = playerSettingsUiState,
|
||||
selectedAddonSubtitleId = selectedAddonSubtitleId,
|
||||
)
|
||||
|
||||
internal val PlayerScreenRuntime.selectedAddonSubtitle: AddonSubtitle?
|
||||
get() = addonSubtitles.firstOrNull { subtitle ->
|
||||
get() = visibleAddonSubtitles.firstOrNull { subtitle ->
|
||||
subtitle.id == selectedAddonSubtitleId || subtitle.url == selectedAddonSubtitleId
|
||||
}
|
||||
|
||||
|
|
@ -147,23 +146,24 @@ internal fun PlayerScreenRuntime.refreshTracks() {
|
|||
|
||||
restorePersistedTrackPreferenceIfNeeded()
|
||||
|
||||
val preferredAudioTargets = resolvePreferredAudioLanguageTargets(
|
||||
preferredAudioLanguage = playerSettingsUiState.preferredAudioLanguage,
|
||||
secondaryPreferredAudioLanguage = playerSettingsUiState.secondaryPreferredAudioLanguage,
|
||||
deviceLanguages = DeviceLanguagePreferences.preferredLanguageCodes(),
|
||||
contentOriginalLanguage = resolveContentLanguage(
|
||||
language = metaUiState.meta?.language,
|
||||
country = metaUiState.meta?.country,
|
||||
) ?: args.contentLanguage,
|
||||
)
|
||||
|
||||
if (!preferredAudioSelectionApplied) {
|
||||
val preferredAudioTargets = resolvePreferredAudioLanguageTargets(
|
||||
preferredAudioLanguage = playerSettingsUiState.preferredAudioLanguage,
|
||||
secondaryPreferredAudioLanguage = playerSettingsUiState.secondaryPreferredAudioLanguage,
|
||||
deviceLanguages = DeviceLanguagePreferences.preferredLanguageCodes(),
|
||||
contentOriginalLanguage = resolveContentLanguage(
|
||||
language = metaUiState.meta?.language,
|
||||
country = metaUiState.meta?.country,
|
||||
) ?: args.contentLanguage,
|
||||
)
|
||||
if (preferredAudioTargets.isEmpty()) {
|
||||
preferredAudioSelectionApplied = true
|
||||
} else if (audioTracks.isNotEmpty()) {
|
||||
val preferredAudioIndex = findPreferredTrackIndex(
|
||||
tracks = audioTracks,
|
||||
targets = preferredAudioTargets,
|
||||
language = { track -> track.language },
|
||||
language = ::resolveAudioTrackLanguageTarget,
|
||||
)
|
||||
if (preferredAudioIndex >= 0 && preferredAudioIndex != selectedAudioIndex) {
|
||||
playerController?.selectAudioTrack(preferredAudioIndex)
|
||||
|
|
@ -174,48 +174,69 @@ internal fun PlayerScreenRuntime.refreshTracks() {
|
|||
}
|
||||
|
||||
if (!preferredSubtitleSelectionApplied) {
|
||||
val preferredSubtitleTargets = resolvePreferredSubtitleLanguageTargets(
|
||||
preferredSubtitleLanguage = if (subtitleStyle.useForcedSubtitles) {
|
||||
SubtitleLanguageOption.FORCED
|
||||
} else {
|
||||
playerSettingsUiState.preferredSubtitleLanguage
|
||||
},
|
||||
secondaryPreferredSubtitleLanguage = playerSettingsUiState.secondaryPreferredSubtitleLanguage,
|
||||
deviceLanguages = DeviceLanguagePreferences.preferredLanguageCodes(),
|
||||
val preferredSubtitleLanguage = normalizeLanguageCode(
|
||||
playerSettingsUiState.preferredSubtitleLanguage,
|
||||
)
|
||||
val preferredSubtitleTargets = if (
|
||||
preferredSubtitleLanguage == SubtitleLanguageOption.NONE ||
|
||||
preferredSubtitleLanguage == SubtitleLanguageOption.FORCED
|
||||
) {
|
||||
emptyList()
|
||||
} else {
|
||||
resolvePreferredSubtitleLanguageTargets(
|
||||
preferredSubtitleLanguage = playerSettingsUiState.preferredSubtitleLanguage,
|
||||
secondaryPreferredSubtitleLanguage = playerSettingsUiState.secondaryPreferredSubtitleLanguage,
|
||||
deviceLanguages = DeviceLanguagePreferences.preferredLanguageCodes(),
|
||||
)
|
||||
}
|
||||
val selectedAudioTrack = audioTracks.firstOrNull { track -> track.index == selectedAudioIndex }
|
||||
?: audioTracks.firstOrNull { it.isSelected }
|
||||
val selectionPlan = resolveSubtitleAutoSelectionPlan(
|
||||
selectedAudioLanguage = resolveAudioTrackLanguageTarget(selectedAudioTrack),
|
||||
preferredAudioTargets = preferredAudioTargets,
|
||||
preferredSubtitleTargets = preferredSubtitleTargets,
|
||||
useForcedSubtitles = subtitleStyle.useForcedSubtitles,
|
||||
)
|
||||
if (selectionPlan == null) {
|
||||
disableAutomaticSubtitleSelection()
|
||||
return
|
||||
}
|
||||
|
||||
if (preferredSubtitleTargets.isEmpty()) {
|
||||
if (selectedSubtitleIndex != -1 || subtitleTracks.any { it.isSelected }) {
|
||||
playerController?.selectSubtitleTrack(-1)
|
||||
}
|
||||
selectedSubtitleIndex = -1
|
||||
selectedAddonSubtitleId = null
|
||||
useCustomSubtitles = false
|
||||
if (selectionPlan.targets.isEmpty()) {
|
||||
disableAutomaticSubtitleSelection()
|
||||
preferredSubtitleSelectionApplied = true
|
||||
} else if (subtitleTracks.isNotEmpty()) {
|
||||
val preferredSubtitleIndex = findPreferredSubtitleTrackIndex(
|
||||
tracks = subtitleTracks,
|
||||
targets = preferredSubtitleTargets,
|
||||
targets = selectionPlan.targets,
|
||||
mode = selectionPlan.mode,
|
||||
)
|
||||
if (preferredSubtitleIndex >= 0 && preferredSubtitleIndex != selectedSubtitleIndex) {
|
||||
playerController?.selectSubtitleTrack(preferredSubtitleIndex)
|
||||
selectedSubtitleIndex = preferredSubtitleIndex
|
||||
selectedAddonSubtitleId = null
|
||||
useCustomSubtitles = false
|
||||
} else if (
|
||||
preferredSubtitleIndex < 0 &&
|
||||
(subtitleStyle.useForcedSubtitles ||
|
||||
normalizeLanguageCode(playerSettingsUiState.preferredSubtitleLanguage) ==
|
||||
SubtitleLanguageOption.FORCED)
|
||||
) {
|
||||
if (selectedSubtitleIndex != -1 || subtitleTracks.any { it.isSelected }) {
|
||||
playerController?.selectSubtitleTrack(-1)
|
||||
} else if (preferredSubtitleIndex < 0) {
|
||||
val activeSubtitleTrack = subtitleTracks.firstOrNull { track ->
|
||||
track.index == selectedSubtitleIndex
|
||||
} ?: subtitleTracks.firstOrNull { it.isSelected }
|
||||
if (
|
||||
selectionPlan.mode == SubtitleAutoSelectionMode.FORCED_ONLY ||
|
||||
activeSubtitleTrack?.isForced == true
|
||||
) {
|
||||
disableAutomaticSubtitleSelection()
|
||||
}
|
||||
selectedSubtitleIndex = -1
|
||||
selectedAddonSubtitleId = null
|
||||
useCustomSubtitles = false
|
||||
}
|
||||
preferredSubtitleSelectionApplied = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun PlayerScreenRuntime.disableAutomaticSubtitleSelection() {
|
||||
if (selectedSubtitleIndex != -1 || subtitleTracks.any { it.isSelected }) {
|
||||
playerController?.selectSubtitleTrack(-1)
|
||||
}
|
||||
selectedSubtitleIndex = -1
|
||||
selectedAddonSubtitleId = null
|
||||
useCustomSubtitles = false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,26 +65,93 @@ internal fun <T> findPreferredTrackIndex(
|
|||
return -1
|
||||
}
|
||||
|
||||
internal enum class SubtitleAutoSelectionMode {
|
||||
FORCED_ONLY,
|
||||
NORMAL_ONLY,
|
||||
}
|
||||
|
||||
internal data class SubtitleAutoSelectionPlan(
|
||||
val targets: List<String>,
|
||||
val mode: SubtitleAutoSelectionMode,
|
||||
)
|
||||
|
||||
internal fun resolveAudioTrackLanguageTarget(track: AudioTrack?): String? {
|
||||
if (track == null) return null
|
||||
|
||||
val directLanguage = normalizeLanguageCode(track.language)
|
||||
?.takeUnless { it == "und" || it == "unknown" }
|
||||
if (directLanguage != null) return directLanguage
|
||||
|
||||
val selectableLanguages = AvailableLanguageOptions
|
||||
.mapNotNull { option -> normalizeLanguageCode(option.code) }
|
||||
.toSet()
|
||||
return listOf(track.label, track.id).firstNotNullOfOrNull { value ->
|
||||
normalizeLanguageCode(value)?.takeIf(selectableLanguages::contains)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun resolveSubtitleAutoSelectionPlan(
|
||||
selectedAudioLanguage: String?,
|
||||
preferredAudioTargets: List<String>,
|
||||
preferredSubtitleTargets: List<String>,
|
||||
useForcedSubtitles: Boolean,
|
||||
): SubtitleAutoSelectionPlan? {
|
||||
val normalizedAudioLanguage = normalizeLanguageCode(selectedAudioLanguage)
|
||||
if (useForcedSubtitles && normalizedAudioLanguage == null) return null
|
||||
|
||||
val subtitleTargets = preferredSubtitleTargets
|
||||
.mapNotNull(::normalizeLanguageCode)
|
||||
.filterNot { target ->
|
||||
target == SubtitleLanguageOption.NONE ||
|
||||
target == SubtitleLanguageOption.FORCED ||
|
||||
target == AudioLanguageOption.DEFAULT
|
||||
}
|
||||
.distinct()
|
||||
val primarySubtitleTarget = subtitleTargets.firstOrNull()
|
||||
val forcedTarget = when {
|
||||
!useForcedSubtitles -> null
|
||||
primarySubtitleTarget != null &&
|
||||
normalizedAudioLanguage != null &&
|
||||
languageMatchesPreference(normalizedAudioLanguage, primarySubtitleTarget) ->
|
||||
primarySubtitleTarget
|
||||
primarySubtitleTarget == null &&
|
||||
normalizedAudioLanguage != null &&
|
||||
preferredAudioTargets.any { target ->
|
||||
languageMatchesPreference(normalizedAudioLanguage, target)
|
||||
} -> normalizedAudioLanguage
|
||||
else -> null
|
||||
}
|
||||
|
||||
return SubtitleAutoSelectionPlan(
|
||||
targets = forcedTarget?.let(::listOf) ?: subtitleTargets,
|
||||
mode = if (forcedTarget != null) {
|
||||
SubtitleAutoSelectionMode.FORCED_ONLY
|
||||
} else {
|
||||
SubtitleAutoSelectionMode.NORMAL_ONLY
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
internal fun findPreferredSubtitleTrackIndex(
|
||||
tracks: List<SubtitleTrack>,
|
||||
targets: List<String>,
|
||||
mode: SubtitleAutoSelectionMode,
|
||||
): Int {
|
||||
if (targets.isEmpty()) return -1
|
||||
|
||||
for ((targetPosition, target) in targets.withIndex()) {
|
||||
for (target in targets) {
|
||||
val normalizedTarget = normalizeLanguageCode(target) ?: continue
|
||||
if (normalizedTarget == SubtitleLanguageOption.FORCED) {
|
||||
val forcedIndex = tracks.indexOfFirst { it.isForced }
|
||||
if (forcedIndex >= 0) return forcedIndex
|
||||
if (targetPosition == 0) return -1
|
||||
continue
|
||||
}
|
||||
|
||||
val matchIndex = tracks.indexOfFirst { track ->
|
||||
languageMatchesPreference(
|
||||
trackLanguage = track.language,
|
||||
targetLanguage = normalizedTarget,
|
||||
)
|
||||
when (mode) {
|
||||
SubtitleAutoSelectionMode.FORCED_ONLY -> track.isForced
|
||||
SubtitleAutoSelectionMode.NORMAL_ONLY -> !track.isForced
|
||||
} &&
|
||||
listOf(track.language, track.label, track.id).any { trackLanguage ->
|
||||
languageMatchesPreference(
|
||||
trackLanguage = trackLanguage,
|
||||
targetLanguage = normalizedTarget,
|
||||
)
|
||||
}
|
||||
}
|
||||
if (matchIndex >= 0) return matchIndex
|
||||
}
|
||||
|
|
@ -95,40 +162,27 @@ internal fun findPreferredSubtitleTrackIndex(
|
|||
internal fun filterAddonSubtitlesForSettings(
|
||||
subtitles: List<AddonSubtitle>,
|
||||
settings: PlayerSettingsUiState,
|
||||
selectedAddonSubtitleId: String?,
|
||||
): List<AddonSubtitle> {
|
||||
val shouldFilter = settings.subtitleStyle.showOnlyPreferredLanguages ||
|
||||
settings.addonSubtitleStartupMode == AddonSubtitleStartupMode.PREFERRED_ONLY
|
||||
if (!shouldFilter) return subtitles
|
||||
|
||||
val targets = preferredSubtitleTargetsForSettings(settings)
|
||||
if (targets.isEmpty()) {
|
||||
return subtitles.filter { subtitle ->
|
||||
subtitle.id == selectedAddonSubtitleId || subtitle.url == selectedAddonSubtitleId
|
||||
if (targets.isEmpty()) return emptyList()
|
||||
|
||||
return subtitles.filter { subtitle ->
|
||||
targets.any { target ->
|
||||
languageMatchesPreference(
|
||||
trackLanguage = subtitle.language,
|
||||
targetLanguage = target,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val filtered = subtitles.filter { subtitle ->
|
||||
subtitle.id == selectedAddonSubtitleId ||
|
||||
subtitle.url == selectedAddonSubtitleId ||
|
||||
targets.any { target ->
|
||||
languageMatchesPreference(
|
||||
trackLanguage = subtitle.language,
|
||||
targetLanguage = target,
|
||||
)
|
||||
}
|
||||
}
|
||||
return filtered
|
||||
}
|
||||
|
||||
internal fun preferredSubtitleTargetsForSettings(settings: PlayerSettingsUiState): List<String> {
|
||||
val preferredLanguage = if (settings.subtitleStyle.useForcedSubtitles) {
|
||||
SubtitleLanguageOption.FORCED
|
||||
} else {
|
||||
settings.preferredSubtitleLanguage
|
||||
}
|
||||
return resolvePreferredSubtitleLanguageTargets(
|
||||
preferredSubtitleLanguage = preferredLanguage,
|
||||
preferredSubtitleLanguage = settings.preferredSubtitleLanguage,
|
||||
secondaryPreferredSubtitleLanguage = settings.secondaryPreferredSubtitleLanguage,
|
||||
deviceLanguages = DeviceLanguagePreferences.preferredLanguageCodes(),
|
||||
).filterNot { it == SubtitleLanguageOption.FORCED }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,260 @@
|
|||
package com.nuvio.app.features.player
|
||||
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertNotNull
|
||||
import kotlin.test.assertNull
|
||||
|
||||
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"),
|
||||
mode = SubtitleAutoSelectionMode.FORCED_ONLY,
|
||||
)
|
||||
|
||||
assertEquals(2, selectedIndex)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun matchingAudioUsesForcedOnlyPrimarySubtitleTarget() {
|
||||
val plan = assertNotNull(
|
||||
resolveSubtitleAutoSelectionPlan(
|
||||
selectedAudioLanguage = "en",
|
||||
preferredAudioTargets = listOf("en"),
|
||||
preferredSubtitleTargets = listOf("en", "fr"),
|
||||
useForcedSubtitles = true,
|
||||
),
|
||||
)
|
||||
|
||||
assertEquals(listOf("en"), plan.targets)
|
||||
assertEquals(SubtitleAutoSelectionMode.FORCED_ONLY, plan.mode)
|
||||
}
|
||||
|
||||
@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"),
|
||||
mode = SubtitleAutoSelectionMode.FORCED_ONLY,
|
||||
)
|
||||
|
||||
assertEquals(-1, selectedIndex)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun differentAudioUsesNormalPreferredSubtitles() {
|
||||
val tracks = listOf(
|
||||
subtitleTrack(index = 0, language = "en", isForced = true),
|
||||
subtitleTrack(index = 1, language = "en", isForced = false),
|
||||
)
|
||||
val plan = assertNotNull(
|
||||
resolveSubtitleAutoSelectionPlan(
|
||||
selectedAudioLanguage = "ja",
|
||||
preferredAudioTargets = listOf("ja"),
|
||||
preferredSubtitleTargets = listOf("en", "fr"),
|
||||
useForcedSubtitles = true,
|
||||
),
|
||||
)
|
||||
|
||||
val selectedIndex = findPreferredSubtitleTrackIndex(
|
||||
tracks = tracks,
|
||||
targets = plan.targets,
|
||||
mode = plan.mode,
|
||||
)
|
||||
|
||||
assertEquals(SubtitleAutoSelectionMode.NORMAL_ONLY, plan.mode)
|
||||
assertEquals(1, selectedIndex)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun audioMatchingOnlySecondarySubtitleTargetUsesNormalSubtitles() {
|
||||
val plan = assertNotNull(
|
||||
resolveSubtitleAutoSelectionPlan(
|
||||
selectedAudioLanguage = "fr",
|
||||
preferredAudioTargets = listOf("fr"),
|
||||
preferredSubtitleTargets = listOf("en", "fr"),
|
||||
useForcedSubtitles = true,
|
||||
),
|
||||
)
|
||||
|
||||
assertEquals(listOf("en", "fr"), plan.targets)
|
||||
assertEquals(SubtitleAutoSelectionMode.NORMAL_ONLY, plan.mode)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun forcedToggleOffExcludesForcedTracks() {
|
||||
val tracks = listOf(
|
||||
subtitleTrack(index = 0, language = "en", isForced = true),
|
||||
subtitleTrack(index = 1, language = "en", isForced = false),
|
||||
)
|
||||
val plan = assertNotNull(
|
||||
resolveSubtitleAutoSelectionPlan(
|
||||
selectedAudioLanguage = "en",
|
||||
preferredAudioTargets = listOf("en"),
|
||||
preferredSubtitleTargets = listOf("en"),
|
||||
useForcedSubtitles = false,
|
||||
),
|
||||
)
|
||||
|
||||
val selectedIndex = findPreferredSubtitleTrackIndex(
|
||||
tracks = tracks,
|
||||
targets = plan.targets,
|
||||
mode = plan.mode,
|
||||
)
|
||||
|
||||
assertEquals(SubtitleAutoSelectionMode.NORMAL_ONLY, plan.mode)
|
||||
assertEquals(1, selectedIndex)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun forcedToggleOffRejectsForcedOnlyTrackList() {
|
||||
val selectedIndex = findPreferredSubtitleTrackIndex(
|
||||
tracks = listOf(subtitleTrack(index = 0, language = "en", isForced = true)),
|
||||
targets = listOf("en"),
|
||||
mode = SubtitleAutoSelectionMode.NORMAL_ONLY,
|
||||
)
|
||||
|
||||
assertEquals(-1, selectedIndex)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun forcedModeWithoutSubtitleTargetUsesMatchingSelectedAudioLanguage() {
|
||||
val plan = assertNotNull(
|
||||
resolveSubtitleAutoSelectionPlan(
|
||||
selectedAudioLanguage = "ja",
|
||||
preferredAudioTargets = listOf("ja"),
|
||||
preferredSubtitleTargets = emptyList(),
|
||||
useForcedSubtitles = true,
|
||||
),
|
||||
)
|
||||
|
||||
assertEquals(listOf("ja"), plan.targets)
|
||||
assertEquals(SubtitleAutoSelectionMode.FORCED_ONLY, plan.mode)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun forcedModeWaitsUntilSelectedAudioIsKnown() {
|
||||
val plan = resolveSubtitleAutoSelectionPlan(
|
||||
selectedAudioLanguage = null,
|
||||
preferredAudioTargets = listOf("en"),
|
||||
preferredSubtitleTargets = listOf("en"),
|
||||
useForcedSubtitles = true,
|
||||
)
|
||||
|
||||
assertNull(plan)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun resolvesSelectedAudioLanguageFromTrackLabel() {
|
||||
val target = resolveAudioTrackLanguageTarget(
|
||||
AudioTrack(
|
||||
index = 0,
|
||||
id = "audio-0",
|
||||
label = "English Original",
|
||||
language = null,
|
||||
isSelected = true,
|
||||
),
|
||||
)
|
||||
|
||||
assertEquals("en", target)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun forcedSelectionMatchesSubtitleLanguageFromTrackLabel() {
|
||||
val selectedIndex = findPreferredSubtitleTrackIndex(
|
||||
tracks = listOf(
|
||||
subtitleTrack(
|
||||
index = 0,
|
||||
language = null,
|
||||
label = "English Forced",
|
||||
isForced = true,
|
||||
),
|
||||
),
|
||||
targets = listOf("en"),
|
||||
mode = SubtitleAutoSelectionMode.FORCED_ONLY,
|
||||
)
|
||||
|
||||
assertEquals(0, selectedIndex)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun preferredOnlyFilteringRemovesNonPreferredAddons() {
|
||||
val subtitles = listOf(
|
||||
addonSubtitle(id = "english", language = "en"),
|
||||
addonSubtitle(id = "japanese", language = "ja"),
|
||||
)
|
||||
val settings = PlayerSettingsUiState(
|
||||
preferredSubtitleLanguage = "en",
|
||||
subtitleStyle = SubtitleStyleState.DEFAULT.copy(showOnlyPreferredLanguages = true),
|
||||
)
|
||||
|
||||
val visibleSubtitles = filterAddonSubtitlesForSettings(
|
||||
subtitles = subtitles,
|
||||
settings = settings,
|
||||
)
|
||||
|
||||
assertEquals(listOf("english"), visibleSubtitles.map { it.id })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun forcedToggleKeepsPreferredLanguagesForAddonFiltering() {
|
||||
val subtitles = listOf(
|
||||
addonSubtitle(id = "japanese", language = "ja"),
|
||||
addonSubtitle(id = "french", language = "fr"),
|
||||
addonSubtitle(id = "english", language = "en"),
|
||||
)
|
||||
val settings = PlayerSettingsUiState(
|
||||
preferredSubtitleLanguage = "en",
|
||||
secondaryPreferredSubtitleLanguage = "fr",
|
||||
subtitleStyle = SubtitleStyleState.DEFAULT.copy(
|
||||
useForcedSubtitles = true,
|
||||
showOnlyPreferredLanguages = true,
|
||||
),
|
||||
)
|
||||
|
||||
val visibleSubtitles = filterAddonSubtitlesForSettings(
|
||||
subtitles = subtitles,
|
||||
settings = settings,
|
||||
)
|
||||
|
||||
assertEquals(listOf("french", "english"), visibleSubtitles.map { it.id })
|
||||
}
|
||||
|
||||
private fun subtitleTrack(
|
||||
index: Int,
|
||||
language: String?,
|
||||
label: String = "Track $index",
|
||||
isForced: Boolean,
|
||||
) = SubtitleTrack(
|
||||
index = index,
|
||||
id = "track-$index",
|
||||
label = label,
|
||||
language = language,
|
||||
isForced = isForced,
|
||||
)
|
||||
|
||||
private fun addonSubtitle(
|
||||
id: String,
|
||||
language: String,
|
||||
) = AddonSubtitle(
|
||||
id = id,
|
||||
url = "https://example.com/$id.srt",
|
||||
language = language,
|
||||
display = id,
|
||||
addonName = "Addon",
|
||||
)
|
||||
}
|
||||
Loading…
Reference in a new issue