// // UnconfiguredJellyfinService.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 Foundation /// A ``JellyfinService`` that has no server and fails every call. /// /// This fills the `\.client` environment slot when nothing has been injected. Every operation /// throws ``JellyfinClientError/notConfigured``, so a view mounted without /// `.environment(\.client, ...)` reports a precise, actionable failure at its first call rather /// than silently talking to a placeholder host or trapping at mount time. /// /// It is stateless, so the single ``shared`` instance serves every unresolved slot. package final class UnconfiguredJellyfinService: JellyfinService { /// The shared placeholder instance. package static let shared = UnconfiguredJellyfinService() private init() {} /// Always `false`: a service with no server can hold no token. package var isAuthenticated: Bool { false } /// - Throws: Always ``JellyfinClientError/notConfigured``. package func publicServerInfo() async throws -> JellyfinServerInfo { throw JellyfinClientError.notConfigured } /// - Throws: Always ``JellyfinClientError/notConfigured``. package func serverInfo() async throws -> JellyfinServerInfo { throw JellyfinClientError.notConfigured } /// - Throws: Always ``JellyfinClientError/notConfigured``. package func publicUsers() async throws -> [JellyfinUser] { throw JellyfinClientError.notConfigured } /// - Throws: Always ``JellyfinClientError/notConfigured``. package func authenticate(username: String, password: String) async throws -> JellyfinAuthentication { throw JellyfinClientError.notConfigured } /// - Throws: Always ``JellyfinClientError/notConfigured``. package func quickConnectEnabled() async throws -> Bool { throw JellyfinClientError.notConfigured } /// - Throws: Always ``JellyfinClientError/notConfigured``. package func initiateQuickConnect() async throws -> JellyfinQuickConnectState { throw JellyfinClientError.notConfigured } /// - Throws: Always ``JellyfinClientError/notConfigured``. package func quickConnectState(secret: String) async throws -> JellyfinQuickConnectState { throw JellyfinClientError.notConfigured } /// - Throws: Always ``JellyfinClientError/notConfigured``. package func authenticateWithQuickConnect(secret: String) async throws -> JellyfinAuthentication { throw JellyfinClientError.notConfigured } /// - Throws: Always ``JellyfinClientError/notConfigured``. package func updateUserPassword( userID: String?, currentPassword: String?, currentPIN: String?, newPassword: String?, resetPassword: Bool? ) async throws { throw JellyfinClientError.notConfigured } /// - Throws: Always ``JellyfinClientError/notConfigured``. package func libraries(_ options: JellyfinListOptions) async throws -> [JellyfinLibrary] { throw JellyfinClientError.notConfigured } /// - Throws: Always ``JellyfinClientError/notConfigured``. package func items(_ query: JellyfinMediaQuery) async throws -> JellyfinMediaPage { throw JellyfinClientError.notConfigured } /// - Throws: Always ``JellyfinClientError/notConfigured``. package func item(id: String, userID: String?) async throws -> JellyfinMediaItem { throw JellyfinClientError.notConfigured } /// - Throws: Always ``JellyfinClientError/notConfigured``. package func resumeItems(_ options: JellyfinListOptions) async throws -> JellyfinMediaPage { throw JellyfinClientError.notConfigured } /// - Throws: Always ``JellyfinClientError/notConfigured``. package func nextUp(seriesID: String?, options: JellyfinListOptions) async throws -> JellyfinMediaPage { throw JellyfinClientError.notConfigured } /// - Throws: Always ``JellyfinClientError/notConfigured``. package func latestMedia(_ options: JellyfinListOptions) async throws -> [JellyfinMediaItem] { throw JellyfinClientError.notConfigured } /// - Throws: Always ``JellyfinClientError/notConfigured``. package func seasons(seriesID: String, options: JellyfinListOptions) async throws -> JellyfinMediaPage { throw JellyfinClientError.notConfigured } /// - Throws: Always ``JellyfinClientError/notConfigured``. package func episodes(seriesID: String, options: JellyfinListOptions) async throws -> JellyfinMediaPage { throw JellyfinClientError.notConfigured } /// - Throws: Always ``JellyfinClientError/notConfigured``. package func searchHints(term: String, options: JellyfinListOptions) async throws -> [JellyfinSearchHint] { throw JellyfinClientError.notConfigured } /// - Throws: Always ``JellyfinClientError/notConfigured``. package func image( itemID: String, type: JellyfinImageType, index: Int32?, request: JellyfinImageRequest ) async throws -> Data { throw JellyfinClientError.notConfigured } /// - Throws: Always ``JellyfinClientError/notConfigured``. package func markPlayed(itemID: String, userID: String?, datePlayed: Date?) async throws -> JellyfinUserData { throw JellyfinClientError.notConfigured } /// - Throws: Always ``JellyfinClientError/notConfigured``. package func markUnplayed(itemID: String, userID: String?) async throws -> JellyfinUserData { throw JellyfinClientError.notConfigured } /// - Throws: Always ``JellyfinClientError/notConfigured``. package func markFavorite(itemID: String, userID: String?) async throws -> JellyfinUserData { throw JellyfinClientError.notConfigured } /// - Throws: Always ``JellyfinClientError/notConfigured``. package func unmarkFavorite(itemID: String, userID: String?) async throws -> JellyfinUserData { throw JellyfinClientError.notConfigured } }