Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@ data class JellyfinCredentials(
val normalizedHttpUrlOrNull: HttpUrl?
get() {
val trimmed = serverUrl.trim().trimEnd('/')
// Auto-prepend https:// if no scheme is provided
val withScheme = if (!trimmed.startsWith("http://", ignoreCase = true) &&
!trimmed.startsWith("https://", ignoreCase = true)
) {
"https://$trimmed"
val hasScheme = trimmed.startsWith("http://", ignoreCase = true) ||
trimmed.startsWith("https://", ignoreCase = true)

val withScheme = if (!hasScheme) {
val host = "http://$trimmed".toHttpUrlOrNull()?.host?.lowercase()
val scheme = if (host != null && isHttpAllowedHost(host)) "http" else "https"
"$scheme://$trimmed"
} else {
trimmed
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -347,16 +347,20 @@ fun JellyfinLoginScreen(

FilledTonalButton(
onClick = {
if (serverUrl.isBlank()) {
serverUrl = "http://"
serverUrl = when {
serverUrl.isBlank() -> "http://"
serverUrl.startsWith("https://", ignoreCase = true) ->
"http://" + serverUrl.drop("https://".length)
serverUrl.startsWith("http://", ignoreCase = true) -> serverUrl
else -> "http://$serverUrl"
}
},
enabled = !isLoading && serverUrl.isBlank(),
enabled = !isLoading && !serverUrl.startsWith("http://", ignoreCase = true),
shape = inputShape,
contentPadding = PaddingValues(horizontal = 14.dp, vertical = 10.dp)
) {
Text(
text = stringResource(R.string.auth_prefill_http),
text = stringResource(R.string.auth_use_http),
fontFamily = RoundedSans,
fontWeight = FontWeight.Medium
)
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/res/values/strings_auth.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
<string name="auth_navidrome_password_hint">App password also works if your server supports it.</string>
<string name="auth_navidrome_пароль_hint">App password also works if your server supports it.</string>
<string name="auth_prefill_http">Prefill http://</string>
<string name="auth_use_http">Use HTTP / VPN</string>
<string name="auth_navidrome_footer">Compatible with Navidrome, Gonic, Airsonic, and other Subsonic-compatible servers</string>
<string name="cd_navidrome_logo">Navidrome</string>
<string name="cd_subsonic_logo">Subsonic</string>
Expand All @@ -35,7 +36,7 @@
<string name="auth_jellyfin_subtitle">Connect to your Jellyfin media server</string>
<string name="auth_jellyfin_connection_subtitle">Enter your Jellyfin server URL and account credentials.</string>
<string name="auth_jellyfin_server_placeholder">http://192.168.1.100:8096</string>
<string name="auth_jellyfin_server_url_hint">Full URL of your Jellyfin server, including port.</string>
<string name="auth_jellyfin_server_url_hint">Full URL including port. Local, Tailscale, and .local addresses can use HTTP.</string>
<string name="auth_jellyfin_username_hint">Your Jellyfin account username.</string>
<string name="auth_jellyfin_password_hint">Your Jellyfin account password.</string>
<string name="auth_jellyfin_footer">Connects to Jellyfin servers for streaming your music library</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,23 @@ class JellyfinCredentialsTest {
}

@Test
fun `normalization prepends https and trims trailing slash`() {
fun `normalization prepends https for public hosts and trims trailing slash`() {
assertEquals(
"https://jellyfin.example.com",
JellyfinCredentials(serverUrl = "jellyfin.example.com/", username = "u", password = "p").normalizedServerUrl
)
}

@Test
fun `normalization prepends http for local and vpn hosts`() {
mapOf(
"192.168.1.50:8096/" to "http://192.168.1.50:8096",
"100.64.12.34:8096/" to "http://100.64.12.34:8096",
"jellyfin.tailnet.ts.net:8096/" to "http://jellyfin.tailnet.ts.net:8096",
"musicbox:8096/" to "http://musicbox:8096"
).forEach { (input, expected) ->
assertEquals(expected, creds(input).normalizedServerUrl)
assertNull(creds(input).connectionValidationError())
}
}
}