// // ClientEnvironmentKey.swift // // Copyright 2026 Brendan Szymanski // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // // SPDX-License-Identifier: GPL-3.0-or-later // import LuminateCore import Portico /// The environment slot that carries the Jellyfin service down the view tree. /// /// Read it with `@Environment(\.client)` and inject it with `.environment(\.client, service)`. package enum ClientEnvironmentKey: EnvironmentKey { /// The placeholder used when no client has been injected. /// /// Every call on it throws ``JellyfinClientError/notConfigured``, so a subtree mounted without /// `.environment(\.client, ...)` reports a precise failure at its first request instead of /// silently talking to a placeholder host. /// /// Declared `nonisolated` because `LuminateUI` builds with `.defaultIsolation(MainActor.self)` /// while the value it returns is a plain `Sendable` object; a `nonisolated` witness satisfies /// the requirement whichever isolation `EnvironmentKey` itself carries. nonisolated package static var defaultValue: any JellyfinService { UnconfiguredJellyfinService.shared } } extension EnvironmentValues { /// The Jellyfin service visible to this subtree. /// /// ```swift /// // Injection, once, near the root: /// RootView().environment(\.client, jellyfinClient) /// /// // Consumption, anywhere below it: /// @Environment(\.client) private var jellyfinClient /// ``` /// /// The accessors deliberately route through `self[ClientEnvironmentKey.self]`: Portico resolves /// a key path by reading it with a probe installed and capturing the state box the subscript /// hands over. A computed property that bypassed the subscript would leave the slot unresolvable /// and make `@Environment(\.client)` trap at mount. package var client: any JellyfinService { get { self[ClientEnvironmentKey.self] } set { self[ClientEnvironmentKey.self] = newValue } } }