mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-11-06 18:54:49 +01:00
Add option to override user profile settings for audio & subtitle languages (#1680)
## Description Adds settings under the "User profile settings" section which allows for specifying preferred languages for audio and subtitles and the preferred subtitle mode. By default (matching existing Wholphin behavior), the preferred languages and subtitle mode are derived from the user's profile settings provided by the server which can be set on the WebUI: User->Settings->Playback or Subtitles. However, this isn't well understood and Wholphin doesn't display these values anywhere, so many users were confused. The preferred languages and subtitle mode can now be configured from within Wholphin. Setting these will **not** update the server. The settings are **only** used locally. ### Related issues Related to #319 Closes #790 ### Testing Emulator manually changing some settings, added additional unit tests to ensure the overrides are respected when choosing tracks ## Screenshots ### Settings page <img width="1280" height="720" alt="settings_01 Large" src="https://github.com/user-attachments/assets/28cc2f6b-3a60-42a4-b268-48695086d566" /> ### Clicking into "More user profile settings" <img width="1280" height="720" alt="settings_02 Large" src="https://github.com/user-attachments/assets/6c3be3aa-c177-4d44-8060-b76d15fb10d7" /> ### Language choice dialog Can filter languages by typing in the search box at the top <img width="1280" height="720" alt="settings_03 Large" src="https://github.com/user-attachments/assets/c014d0ba-8d5b-4201-a6ee-4876b478148c" /> ## AI or LLM usage None
This commit is contained in:
parent
077b7e4570
commit
3f60fa7550
26 changed files with 1751 additions and 48 deletions
|
|
@ -3,11 +3,14 @@ package com.github.damontecres.wholphin.services
|
|||
import com.github.damontecres.wholphin.data.PlaybackLanguageChoiceDao
|
||||
import com.github.damontecres.wholphin.data.ServerRepository
|
||||
import com.github.damontecres.wholphin.data.model.ItemPlayback
|
||||
import com.github.damontecres.wholphin.data.model.JellyfinUserPreferences
|
||||
import com.github.damontecres.wholphin.data.model.PlaybackLanguageChoice
|
||||
import com.github.damontecres.wholphin.data.model.TrackIndex
|
||||
import com.github.damontecres.wholphin.preferences.AppPreferences
|
||||
import com.github.damontecres.wholphin.preferences.DefaultUserConfiguration
|
||||
import com.github.damontecres.wholphin.preferences.SubtitleModePreference
|
||||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||
import com.github.damontecres.wholphin.preferences.UserProfileSettings
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import org.jellyfin.sdk.model.UUID
|
||||
|
|
@ -800,6 +803,80 @@ class TestStreamChoiceServiceOnlyForcedClientOverride(
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for client-side "Only Forced" override (TrackIndex.ONLY_FORCED).
|
||||
* This tests the findForcedTrack function with user subtitle language preference.
|
||||
*/
|
||||
@RunWith(Parameterized::class)
|
||||
class TestStreamChoiceServiceAppPreferences(
|
||||
val input: TestInput,
|
||||
) {
|
||||
@Test
|
||||
fun test() {
|
||||
runTest(input)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
@Parameterized.Parameters(name = "{index}: {0}")
|
||||
fun data(): Collection<TestInput> =
|
||||
listOf(
|
||||
TestInput(
|
||||
expectedIndex = 1,
|
||||
userSubtitleMode = SubtitlePlaybackMode.ALWAYS,
|
||||
userSubtitleLang = "spa",
|
||||
subtitles =
|
||||
listOf(
|
||||
subtitle(0, "eng", default = true),
|
||||
subtitle(1, "spa"),
|
||||
),
|
||||
streamAudioLang = "eng",
|
||||
itemPlayback = null,
|
||||
appSubtitleLang = UserProfileSettings.USE_USER_PROFILE,
|
||||
),
|
||||
TestInput(
|
||||
expectedIndex = 0,
|
||||
userSubtitleMode = SubtitlePlaybackMode.ALWAYS,
|
||||
userSubtitleLang = "spa",
|
||||
subtitles =
|
||||
listOf(
|
||||
subtitle(0, "eng", default = true),
|
||||
subtitle(1, "spa"),
|
||||
),
|
||||
streamAudioLang = "eng",
|
||||
itemPlayback = null,
|
||||
appSubtitleLang = "eng",
|
||||
),
|
||||
TestInput(
|
||||
expectedIndex = 1,
|
||||
userSubtitleMode = SubtitlePlaybackMode.ALWAYS,
|
||||
userSubtitleLang = "spa",
|
||||
subtitles =
|
||||
listOf(
|
||||
subtitle(0, "eng", default = true),
|
||||
subtitle(1, "spa"),
|
||||
),
|
||||
streamAudioLang = "eng",
|
||||
itemPlayback = null,
|
||||
appSubtitleLang = "spa",
|
||||
),
|
||||
TestInput(
|
||||
expectedIndex = 1, // ItemPlayback
|
||||
userSubtitleMode = SubtitlePlaybackMode.ALWAYS,
|
||||
userSubtitleLang = "spa",
|
||||
subtitles =
|
||||
listOf(
|
||||
subtitle(0, "eng", default = true),
|
||||
subtitle(1, "spa"),
|
||||
),
|
||||
streamAudioLang = "eng",
|
||||
itemPlayback = itemPlayback(subtitleIndex = 1),
|
||||
appSubtitleLang = "spa",
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
data class TestInput(
|
||||
val expectedIndex: Int?,
|
||||
val userSubtitleMode: SubtitlePlaybackMode?,
|
||||
|
|
@ -809,6 +886,9 @@ data class TestInput(
|
|||
val subtitles: List<MediaStream>,
|
||||
val itemPlayback: ItemPlayback? = null,
|
||||
val plc: PlaybackLanguageChoice? = null,
|
||||
val appAudioLang: String = UserProfileSettings.USE_USER_PROFILE,
|
||||
val appSubtitleLang: String = UserProfileSettings.USE_USER_PROFILE,
|
||||
val appSubtitleMode: SubtitleModePreference = SubtitleModePreference.USE_USER_PROFILE,
|
||||
) {
|
||||
override fun toString(): String = "test(mode=$userSubtitleMode, subtitles=${subtitles.map { it.toShortString() }})"
|
||||
}
|
||||
|
|
@ -850,7 +930,15 @@ private fun runTest(input: TestInput) {
|
|||
candidates = input.subtitles,
|
||||
itemPlayback = input.itemPlayback,
|
||||
playbackLanguageChoice = input.plc,
|
||||
prefs = UserPreferences(AppPreferences.getDefaultInstance()),
|
||||
prefs =
|
||||
UserPreferences(
|
||||
AppPreferences.getDefaultInstance(),
|
||||
JellyfinUserPreferences(
|
||||
preferredAudioLanguage = input.appAudioLang,
|
||||
preferredSubtitleLanguage = input.appSubtitleLang,
|
||||
subtitleMode = input.appSubtitleMode,
|
||||
),
|
||||
),
|
||||
)
|
||||
Assert.assertEquals(input.expectedIndex, result?.index)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ class PlaybackViewModelTests {
|
|||
|
||||
private fun setupPreferences(block: PlaybackPreferences.Builder.() -> Unit) {
|
||||
val appPrefs = AppPreferences.getDefaultInstance().updatePlaybackPreferences(block)
|
||||
val prefs = UserPreferences(appPrefs)
|
||||
val prefs = UserPreferences(appPrefs, null)
|
||||
coEvery { mockUserPreferencesService.getCurrent() } returns prefs
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue