From d759a51acecbcc8b123eb5a94a1c5f9fba1df044 Mon Sep 17 00:00:00 2001 From: Micha Date: Sun, 16 Nov 2025 14:12:11 +0100 Subject: [PATCH] Reduce ping logging and detect API version --- CHANGELOG.md | 1 + Model/API/ApiFactory.swift | 33 ++++++++++++++++++++++++-- Views/MainView.swift | 47 ++++---------------------------------- 3 files changed, 37 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87eb985..c23ccba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,3 +6,4 @@ - Migrated the updated API layer and unified `ServerInfo` model from the previous branch. - Added verbose logging in `MainView` to trace server loading, selection, and fetch/ping activity when the list appears empty. - Switched `MainView` and `ServerFormView` to the version-aware API client (`APIFactory`/`APIv2_12`) for server summaries and introduced a shared `PingService`. +- Detection now probes `meta.api_version` so future API versions are selected automatically, and the ping loop logs only failures to keep output quiet. diff --git a/Model/API/ApiFactory.swift b/Model/API/ApiFactory.swift index decd0ca..f0fd037 100644 --- a/Model/API/ApiFactory.swift +++ b/Model/API/ApiFactory.swift @@ -77,8 +77,37 @@ class APIFactory { return createAPI(baseURL: baseURL, version: version) } - static func detectAndCreateAPI(baseURL: URL) async throws -> AnyServerAPI { - // For now we only support API v2.12, so return that implementation directly. + static func detectAndCreateAPI(baseURL: URL, apiKey: String? = nil) async throws -> AnyServerAPI { + if let apiKey, !apiKey.isEmpty { + do { + let versionURL = baseURL.appendingPathComponent("api/v2/server") + var request = URLRequest(url: versionURL) + request.httpMethod = "GET" + request.setValue(apiKey, forHTTPHeaderField: "X-API-KEY") + request.timeoutInterval = 15 + + let (data, response) = try await URLSession.shared.data(for: request) + if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 { + let decoder = JSONDecoder() + decoder.keyDecodingStrategy = .convertFromSnakeCase + let probe = try decoder.decode(ServerMetaProbe.self, from: data) + if let api = createAPI(baseURL: baseURL, versionString: probe.meta.apiVersion) { + return api + } + } + } catch { + // Fall back to default version below + } + } + return AnyServerAPIWrapper(APIv2_12(baseURL: baseURL)) } } + +private struct ServerMetaProbe: Decodable { + struct Meta: Decodable { + let apiVersion: String + } + + let meta: Meta +} diff --git a/Views/MainView.swift b/Views/MainView.swift index fbe9c81..384aabf 100644 --- a/Views/MainView.swift +++ b/Views/MainView.swift @@ -119,7 +119,6 @@ struct MainView: View { } pingAllServers() pingTimer = Timer.scheduledTimer(withTimeInterval: 10.0, repeats: true) { _ in - print("📡 [MainView] Ping timer firing") pingAllServers() } } @@ -147,7 +146,7 @@ struct MainView: View { Task { defer { isFetchingInfo = false } do { - let api = try await APIFactory.detectAndCreateAPI(baseURL: baseURL) + let api = try await APIFactory.detectAndCreateAPI(baseURL: baseURL, apiKey: apiKey) let info = try await api.fetchServerSummary(apiKey: apiKey) await MainActor.run { if let index = servers.firstIndex(where: { $0.id == id }) { @@ -177,45 +176,7 @@ struct MainView: View { private struct PingResponse: Codable { let response: String } - -// func pingServer(_ server: Server) async -> Bool { -// let hostname = server.hostname -// guard let url = URL(string: "https://\(hostname)/api/v2/ping") else { -// return false -// } -// -// var request = URLRequest(url: url) -// request.httpMethod = "GET" -// request.timeoutInterval = 5 -// request.setValue("application/json", forHTTPHeaderField: "Content-Type") -// -// let apiKey = KeychainHelper.loadApiKey(for: hostname)?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" -// request.setValue(apiKey, forHTTPHeaderField: "X-API-KEY") -// -// do { -// let (data, response) = try await URLSession.shared.data(for: request) -// if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 { -// do { -// let decoded = try JSONDecoder().decode(PingResponse.self, from: data) -// if decoded.response == "pong" { -// return true -// } else { -// print("❌ Unexpected response: \(decoded.response)") -// return false -// } -// } catch { -// print("❌ Failed to decode JSON: \(error)") -// return false -// } -// } else { -// return false -// } -// } catch { -// print("[Ping] \(server.hostname): \(error.localizedDescription)") -// return false -// } -// } - + func pingAllServers() { for (index, server) in servers.enumerated() { Task { @@ -224,7 +185,9 @@ struct MainView: View { await MainActor.run { servers[index].pingable = pingable } - print("📶 [MainView] Ping \(server.hostname): \(pingable ? "online" : "offline")") + if !pingable { + print("📶 [MainView] Ping \(server.hostname): offline") + } } } }