import SwiftUI struct SettingsView: View { @Binding var keyManager: KeyManagement @Binding var serverAddress: String @Binding var localAddress: String @Binding var deviceID: Int @Binding var nextMessageCounter: Int @Binding var isCompensatingDaylightTime: Bool @Binding var useLocalConnection: Bool @State private var showDeviceIdInput = false @State private var deviceIdText = "" @State private var showCounterInput = false @State private var counterText = "" var body: some View { NavigationView { ScrollView { VStack(alignment: .leading, spacing: 8) { VStack(alignment: .leading) { Text("Server address") .bold() TextField("Server address", text: $serverAddress) .foregroundColor(.secondary) .padding(.leading, 8) }.padding(.vertical, 8) VStack(alignment: .leading) { Text("Local address") .bold() TextField("Local address", text: $localAddress) .foregroundColor(.secondary) .padding(.leading, 8) }.padding(.vertical, 8) Toggle(isOn: $useLocalConnection) { Text("Use direct connection to device") } Text("Attempt to communicate directly with the device. This is useful if the server is unavailable. Requires a WiFi connection on the same network as the device.") .font(.caption) .foregroundColor(.secondary) VStack(alignment: .leading) { Text("Device id") .bold() HStack(alignment: .bottom) { Text("\(deviceID)") .font(.system(.body, design: .monospaced)) .foregroundColor(.secondary) .padding([.trailing, .bottom]) Button("Edit", action: showAlertToChangeDeviceID) .padding([.horizontal, .bottom]) .padding(.top, 4) } }.padding(.vertical, 8) VStack(alignment: .leading) { Text("Message counter") .bold() HStack(alignment: .bottom) { Text("\(nextMessageCounter)") .font(.system(.body, design: .monospaced)) .foregroundColor(.secondary) .padding([.trailing, .bottom]) Button("Edit", action: showAlertToChangeCounter) .padding([.horizontal, .bottom]) .padding(.top, 4) } }.padding(.vertical, 8) ForEach(KeyManagement.KeyType.allCases) { keyType in SingleKeyView( keyManager: $keyManager, type: keyType) } Toggle(isOn: $isCompensatingDaylightTime) { Text("Compensate daylight savings time") } Text("If the remote has daylight savings time wrongly set, then the time validation will fail. Use this option to send messages with adjusted timestamps. Warning: Incorrect use of this option will allow replay attacks.") .font(.caption) .foregroundColor(.secondary) }.padding() }.onDisappear { if !localAddress.hasSuffix("/") { localAddress += "/" } } .navigationTitle("Settings") .alert("Update device ID", isPresented: $showDeviceIdInput, actions: { TextField("Device ID", text: $deviceIdText) .keyboardType(.decimalPad) .font(.system(.body, design: .monospaced)) .foregroundColor(.black) Button("Save", action: saveDeviceID) Button("Cancel", role: .cancel, action: {}) }, message: { Text("Enter the device ID") }) .alert("Update message counter", isPresented: $showCounterInput, actions: { TextField("Message counter", text: $counterText) .keyboardType(.decimalPad) .font(.system(.body, design: .monospaced)) .foregroundColor(.black) Button("Save", action: saveCounter) Button("Cancel", role: .cancel, action: {}) }, message: { Text("Enter the message counter") }) } } private func showAlertToChangeDeviceID() { deviceIdText = "\(deviceID)" showDeviceIdInput = true } private func saveDeviceID() { guard let id = UInt8(deviceIdText) else { print("Invalid device id '\(deviceIdText)'") return } self.deviceID = Int(id) } private func showAlertToChangeCounter() { counterText = "\(nextMessageCounter)" showCounterInput = true } private func saveCounter() { guard let id = UInt32(counterText) else { print("Invalid message counter '\(counterText)'") return } self.nextMessageCounter = Int(id) } } struct SettingsView_Previews: PreviewProvider { static var previews: some View { SettingsView( keyManager: .constant(KeyManagement()), serverAddress: .constant("https://example.com"), localAddress: .constant("192.168.178.42"), deviceID: .constant(0), nextMessageCounter: .constant(12345678), isCompensatingDaylightTime: .constant(true), useLocalConnection: .constant(false)) } }