fix: scope addon subtitles to the current episode

This commit is contained in:
Hassan 2026-07-19 04:41:45 +03:00
parent 0ac38dce43
commit 84bd1525cc
7 changed files with 65 additions and 1 deletions

View file

@ -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)

View file

@ -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

View file

@ -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
}
}
}

View file

@ -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,

View file

@ -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() }
}

View file

@ -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?,

View file

@ -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)