The bundle-ID and display-name renames weren't enough — the actual Xcode target/product name was still "Jarvis", which drives CFBundleName, Xcode's Organizer archive list, the .xcodeproj filename, and the scheme name. Renamed all the way through: - project.yml: top-level name, target key, PRODUCT_NAME, source/info paths - Jarvis/ -> Jervis/ (source folder, git-tracked as renames, no content diffs on the moved files) - .gitignore, CI workflows, README, CONTRIBUTING: Jarvis.xcodeproj / scheme Jarvis -> Jervis.xcodeproj / scheme Jervis Verified: xcodebuild -scheme Jervis succeeds, produces Jervis.app, CFBundleName/CFBundleExecutable/CFBundleDisplayName all read "Jervis". CFBundleIdentifier intentionally stays com.kisani.jarvis (per prior decision — bundle ID isn't user-facing anywhere including Organizer). Swift type names (JarvisApp, JarvisWordmark, etc.) and the Gitea repo name/URL are unchanged — pure internal source identifiers, not user or developer-facing product identity. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
49 lines
1.4 KiB
Swift
49 lines
1.4 KiB
Swift
// ServerSettings.swift
|
|
// Jarvis — persists the configured server host
|
|
|
|
import Foundation
|
|
|
|
@MainActor
|
|
final class ServerSettings: ObservableObject {
|
|
static let shared = ServerSettings()
|
|
|
|
private let key = "jarvis_server_host"
|
|
|
|
@Published var host: String? {
|
|
didSet { UserDefaults.standard.set(host, forKey: key) }
|
|
}
|
|
|
|
var isConfigured: Bool { host != nil }
|
|
|
|
private init() {
|
|
host = UserDefaults.standard.string(forKey: key)
|
|
}
|
|
|
|
func save(host: String) async throws {
|
|
try await APIClient.shared.configure(host: host)
|
|
_ = try await APIClient.shared.checkHealth()
|
|
self.host = host
|
|
WebSocketManager.shared.connect(host: host)
|
|
}
|
|
|
|
func reset() {
|
|
host = nil
|
|
WebSocketManager.shared.disconnect()
|
|
}
|
|
|
|
/// Re-establish REST + WebSocket from a previously saved host on app launch.
|
|
func reconnectIfConfigured() async {
|
|
guard let host else { return }
|
|
try? await APIClient.shared.configure(host: host)
|
|
WebSocketManager.shared.connect(host: host)
|
|
}
|
|
|
|
/// Point REST + WebSocket at a host the ConnectivityManager already verified
|
|
/// (skips the health check — the probe just confirmed it).
|
|
func activate(host: String) async {
|
|
try? await APIClient.shared.configure(host: host)
|
|
self.host = host
|
|
WebSocketManager.shared.connect(host: host)
|
|
}
|
|
}
|