Files
meterios/meterios/views/SetupView.swift
T

148 lines
5.7 KiB
Swift

//
// SetupView.swift
// meterios
//
// (c) 2025 Martin "maride" Dessauer
//
import SwiftUI
import OSLog
struct SetupView: View {
@State private var tmpAddress: String = "mete.chaosdorf.space"
@State private var tmpUsers: Array<MeteClientUser> = []
@State private var selectedUserID: Int = 0
@FocusState private var connectionFieldFocused: Bool
@State private var connectionStatus: String?
@State private var connectionStatusColor: Color?
@State private var connectionStatusIcon: String?
@State private var connectionStatusVisible: Bool = false
@State private var connectionStatusProgressVisible: Bool = false
@State private var userListVisible: Bool = false
@State private var saveButtonEnabled: Bool = false
@Environment(\.dismiss) private var dismiss
func tryConnect() {
// If there was a previous connection attempt, the user list and save button might still be visible - hide them again
userListVisible = false
saveButtonEnabled = false
// Update status
updateConnStatus(String(format: String(localized: "CONNECTING_TO_FMT"), tmpAddress), statusIcon: "network", progressVisible: true)
// Connect to the server asynchronously
Task {
// Un-Focus the address field to hide keyboard
connectionFieldFocused = false
// Create test connector
do {
// Try out the connection
let tmpConnector = MeteClient(address: tmpAddress, userID: -1)
tmpUsers = try await tmpConnector.GetUsers()
updateConnStatus(String(localized: "CONNECTION_SUCCESSFUL"), statusIcon: "checkmark.icloud.fill", color: .green, progressVisible: false)
userListVisible = true
} catch {
updateConnStatus(error.localizedDescription, statusIcon: "bolt.horizontal.circle.fill", color: .red, progressVisible: false)
let _ = Logger().error("Failed to connect to new backend \(tmpAddress): \(error)")
}
}
}
func updateConnStatus(_ statusText: String, statusIcon: String = "", color: Color = .blue, progressVisible: Bool = true) {
connectionStatus = statusText
connectionStatusIcon = statusIcon
connectionStatusColor = color
connectionStatusProgressVisible = progressVisible
connectionStatusVisible = statusText != ""
}
var body: some View {
// Meterios banner
ZStack {
// Background color
Color(.sRGB, red: 0, green: 57/255, blue: 132/255)
.ignoresSafeArea()
.frame(maxHeight: 200)
// Logo and text
HStack {
Image(uiImage: UIImage(named: "mete-transparent")!)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(maxWidth: 100, maxHeight: 100)
.contentMargins(32.0)
.fixedSize()
Spacer()
VStack(alignment: .leading) {
Text(String(localized: "METERIOS")).font(.title).fontWeight(.heavy).foregroundStyle(.white)
Text(String(localized: "METERIOS_SLOGAN")).font(.title2).foregroundStyle(.white)
}.fixedSize()
}.fixedSize()
}
// Input fields
Form {
// Connection
Section(content: {
// Address field
TextField(text: $tmpAddress, label: { Text(tmpAddress) })
.textInputAutocapitalization(.never)
.disableAutocorrection(true)
.focused($connectionFieldFocused)
.onSubmit {
tryConnect()
}
Button(String(localized: "CONNECT"), action: {
tryConnect()
})
}, header: {
Text(String(localized: "CONNECTION"))
}, footer: {
// Status bar
if connectionStatusVisible {
HStack {
// Status text
Label(
connectionStatus ?? "",
systemImage: connectionStatusIcon ?? "questionmark.diamond.fill"
).foregroundStyle(connectionStatusColor ?? .red)
// Progress indicator
if connectionStatusProgressVisible {
ProgressView().frame(width: 8, height: 8)
}
}
}
})
// User selection
if userListVisible {
Picker(String(localized: "ACCOUNT"), selection: $selectedUserID, content: {
ForEach(tmpUsers, id: \.self.meteID) { (user: MeteClientUser) in
Text(user.displayName).tag(user.displayName)
}
})
.onChange(of: selectedUserID, {
saveButtonEnabled = true
})
}
// Save button
Section {
Button(action: {
let newAcc = Account(address: tmpAddress, userID: selectedUserID)
AccountManager.default.AddAccount(newAcc)
AccountManager.default.SelectAccount(newAcc)
dismiss()
}) {
Text(String(localized: "SAVE_CONNECTION_SETTINGS")).frame(maxWidth: .infinity)
}.tint(.green).disabled(!saveButtonEnabled)
}
}
}
}