// // ServerSetupView.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 Adwaita import Foundation import LuminateCore import LuminateDI public struct ServerSetupView: View { @State private var serverURL = "" @State private var username = "" @State private var password = "" @State private var isLoading = false @State private var error: String? public var onLogin: (JellyfinClient, String) -> Void public init(onLogin: @escaping (JellyfinClient, String) -> Void) { self.onLogin = onLogin } public var view: Body { VStack { StatusPage( "Connect to Server", icon: .custom(name: "dev.bscubed.Luminate"), description: "Enter your Jellyfin server details" ) { VStack(spacing: 16) { PreferencesGroup("Server configuration") { EntryRow("Server URL", text: $serverURL) EntryRow("Username", text: $username) PasswordEntryRow("Password", text: $password) } Button("Connect") { connect() } .suggested() if isLoading { Spinner() } if let error { Text(error) .error() } } .padding() } } } private func connect() { var urlString = serverURL.trimmingCharacters(in: .whitespacesAndNewlines) if !urlString.hasPrefix("http://") && !urlString.hasPrefix("https://") { urlString = "https://" + urlString } urlString = urlString.trimmingCharacters(in: CharacterSet(charactersIn: "/")) guard let url = URL(string: urlString), !username.isEmpty else { error = "Please enter a valid server URL and username" return } isLoading = true error = nil Task { do { let client = JellyfinClient(serverURL: url) let result = try await client.authenticate(username: username, password: password) let userId = result.user?.value1.id ?? "" let auth = AuthData( serverURL: url.absoluteString, token: result.accessToken ?? "", userId: userId, username: username ) try? await DIContainer.shared.values.persistence?.saveAuth(auth) isLoading = false onLogin(client, userId) } catch (JellyfinError.httpError(let code)) { isLoading = false self.error = "Failed to login. HTTP code \(code)" } catch { isLoading = false self.error = error.localizedDescription print(error.localizedDescription) } } } }