From 24d7423f9cc6f1bb0e80e1ffd181e1637a239851 Mon Sep 17 00:00:00 2001 From: Scarriffle Date: Sun, 27 Sep 2026 18:37:16 +0200 Subject: [PATCH] Bei Jellyfin galt zuhause als unterwegs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Beinahe-Regression, gefunden bevor sie jemanden traf: `isLocalConnection` kam aus `session.server?.connection.local`, und `server` ist ein `PlexServer` — bei Jellyfin immer `nil`. Jede Jellyfin-Wiedergabe galt damit als entfernt, auch zuhause am Kabel. Der neue Deckel hätte dort ein 67-Mbit-Remux ohne Not auf acht Megabit heruntergerechnet. Jetzt wird gefragt statt geraten: `/System/Endpoint` beantwortet es mit **demselben** Aufruf, mit dem Jellyfin auch selbst entscheidet, ob es eine Bitratenleiter ausliefert. Ein Blick auf die Adresse hätte nicht genügt — wer über einen Reverse Proxy geht, erreicht seinen Server auch von der Couch aus unter einem öffentlichen Namen, und über ein VPN kommt eine private Adresse von weit her. Gefragt wird bei beiden Wegen, beim Anmelden und beim Wiederherstellen: dasselbe Konto kann heute zuhause und morgen im Zug aufwachen. Im Zweifel `false` — lieber einmal zu vorsichtig gedeckelt als eine Wiedergabe, die über eine Fernverbindung gar nicht erst anläuft. Co-Authored-By: Claude Opus 5 --- Flixy/Session/FlixySession.swift | 17 +++++++++++++ Flixy/Views/Navigation/RootView.swift | 6 ++++- .../Sources/JellyfinKit/JellyfinBackend.swift | 25 +++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/Flixy/Session/FlixySession.swift b/Flixy/Session/FlixySession.swift index 7355715..bb58fdb 100644 --- a/Flixy/Session/FlixySession.swift +++ b/Flixy/Session/FlixySession.swift @@ -93,6 +93,18 @@ final class FlixySession { private(set) var pendingCode: String? private(set) var showsManualCode = false + /// Ob der Server in **demselben** Netz steht wie wir. + /// + /// Entscheidet, ob „Auto" gedeckelt anfängt: zuhause trägt die Leitung + /// das Original, unterwegs nicht. Bei Plex steht es im gewählten Weg; bei + /// Jellyfin wird der Server gefragt, weil ein Blick auf die Adresse nicht + /// genügt — wer über einen Reverse Proxy geht, erreicht seinen Server + /// auch von der Couch aus unter einem öffentlichen Namen. + /// + /// Im Zweifel `false`: lieber einmal zu vorsichtig gedeckelt als eine + /// Wiedergabe, die über eine Fernverbindung gar nicht erst anläuft. + private(set) var isLocalConnection = false + private(set) var phase: Phase = .launching /// Welche Serverart gerade bedient wird — `nil`, solange niemand /// angemeldet ist. @@ -476,6 +488,7 @@ final class FlixySession { defaults.set(resource.clientIdentifier, forKey: Key.preferredServer) defaults.set(connection.uri, forKey: Key.cachedConnectionURI) defaults.set(connection.local, forKey: Key.cachedConnectionIsLocal) + isLocalConnection = connection.local defaults.set(resource.name, forKey: Key.cachedServerName) if let token = resource.accessToken { try? tokenStore.store(token, for: Self.plexTokenAccount) @@ -549,6 +562,7 @@ final class FlixySession { kind = .jellyfin jellyfinAccount = account self.backend = backend + isLocalConnection = await backend.isInLocalNetwork() do { libraries = try await backend.libraries().filter(\.isSupported) @@ -594,6 +608,9 @@ final class FlixySession { kind = .jellyfin jellyfinAccount = account self.backend = backend + // Auch hier fragen: dasselbe Konto kann heute zuhause und morgen im + // Zug wiederhergestellt werden, und die Antwort gilt je Sitzung. + isLocalConnection = await backend.isInLocalNetwork() do { libraries = try await backend.libraries().filter(\.isSupported) diff --git a/Flixy/Views/Navigation/RootView.swift b/Flixy/Views/Navigation/RootView.swift index b7e21e9..3325a25 100644 --- a/Flixy/Views/Navigation/RootView.swift +++ b/Flixy/Views/Navigation/RootView.swift @@ -185,7 +185,11 @@ struct RootView: View { diagnostics: diagnostics, policy: settings.policy(for: network), settings: settings, - isLocalConnection: session.server?.connection.local ?? false, + // **Nicht mehr über `server`.** Der ist ein `PlexServer` und bei + // Jellyfin immer `nil` — damit galt dort jede Wiedergabe als + // entfernt, auch zuhause am Kabel, und „Auto" hätte ein + // 67-Mbit-Remux ohne Not heruntergerechnet. + isLocalConnection: session.isLocalConnection, connectionDescription: session.connectionDescription, unavailableMessage: session.playbackUnavailableMessage ) diff --git a/Packages/FlixyKit/Sources/JellyfinKit/JellyfinBackend.swift b/Packages/FlixyKit/Sources/JellyfinKit/JellyfinBackend.swift index 83fff09..eb1eb25 100644 --- a/Packages/FlixyKit/Sources/JellyfinKit/JellyfinBackend.swift +++ b/Packages/FlixyKit/Sources/JellyfinKit/JellyfinBackend.swift @@ -30,6 +30,31 @@ public struct JellyfinBackend: MediaBackend { // MARK: - Blättern + /// Ob der Server diese Verbindung als „im eigenen Netz" ansieht. +/// +/// **Gefragt, nicht geraten.** Ein Blick auf die Adresse taugt nicht: wer +/// über einen Reverse Proxy geht, erreicht seinen Server auch von der +/// Couch aus unter einem öffentlichen Namen. Umgekehrt kann eine private +/// Adresse über ein VPN von weit her kommen. +/// +/// `/System/Endpoint` beantwortet es mit **demselben** Aufruf, mit dem +/// Jellyfin auch selbst entscheidet, ob es eine Bitratenleiter ausliefert. +/// Näher an der Wahrheit kommt man nicht heran. +/// +/// Bei Zweifeln `false`: lieber einmal zu vorsichtig gedeckelt als eine +/// Wiedergabe, die über eine Fernverbindung gar nicht erst anläuft. +public func isInLocalNetwork() async -> Bool { + struct Lage: Decodable { + let isInNetwork: Bool + private enum CodingKeys: String, CodingKey { case isInNetwork = "IsInNetwork" } + } + let lage = try? await client.send( + JellyfinRequest(path: "/System/Endpoint"), + as: Lage.self + ) + return lage?.isInNetwork ?? false + } + public func libraries() async throws(MediaBackendError) -> [MediaLibrary] { let page = try await client.send( JellyfinRequest(path: "/Users/\(account.userID)/Views"),