luminate-old/Sources/Luminate/ServerSetupView.swift

108 lines
3.7 KiB
Swift

//
// ServerSetupView.swift
//
// Copyright 2026 Brendan Szymanski <hello@bscubed.dev>
//
// 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 <https://www.gnu.org/licenses/>.
//
// 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)
}
}
}
}