diff --git a/Meshtastic.xcodeproj/project.pbxproj b/Meshtastic.xcodeproj/project.pbxproj index e177193a..e2c2b813 100644 --- a/Meshtastic.xcodeproj/project.pbxproj +++ b/Meshtastic.xcodeproj/project.pbxproj @@ -964,7 +964,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.0.1; + MARKETING_VERSION = 2.0.2; PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTS_MACCATALYST = YES; @@ -996,7 +996,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.0.1; + MARKETING_VERSION = 2.0.2; PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTS_MACCATALYST = YES; diff --git a/Meshtastic/Export/WriteCsvFile.swift b/Meshtastic/Export/WriteCsvFile.swift index 6cf3da5e..f71206cd 100644 --- a/Meshtastic/Export/WriteCsvFile.swift +++ b/Meshtastic/Export/WriteCsvFile.swift @@ -7,22 +7,15 @@ import SwiftUI - func TelemetryToCsvFile(telemetry: [TelemetryEntity], metricsType: Int) -> String { - var csvString: String = "" - if metricsType == 0 { - // Create Device Metrics Header csvString = "Battery Level, Voltage, Channel Utilization, Airtime, Timestamp" - for dm in telemetry{ - if dm.metricsType == 0 { - csvString += "\n" - csvString += String("\(dm.batteryLevel) %") + csvString += String(dm.batteryLevel) csvString += ", " csvString += String(dm.voltage) csvString += ", " @@ -33,18 +26,13 @@ func TelemetryToCsvFile(telemetry: [TelemetryEntity], metricsType: Int) -> Strin csvString += dm.time?.formattedDate(format: "yyyy-MM-dd HH:mm:ss") ?? "Unknown Age" } } - } else if metricsType == 1 { - // Create Environment Telemetry Header csvString = "Temperature, Relative Humidity, Barometric Pressure, Gas Resistance, Voltage, Current" - for dm in telemetry{ - if dm.metricsType == 1 { - csvString += "\n" - csvString += String("\(dm.temperature)°") + csvString += String(dm.temperature) csvString += ", " csvString += String(dm.relativeHumidity) csvString += ", " @@ -60,19 +48,14 @@ func TelemetryToCsvFile(telemetry: [TelemetryEntity], metricsType: Int) -> Strin } } } - return csvString } func PositionToCsvFile(positions: [PositionEntity]) -> String { - var csvString: String = "" - // Create Position Header csvString = "SeqNo, Latitude, Longitude, Alt, Sats, Speed, Heading, SNR, Timestamp" - for pos in positions { - csvString += "\n" csvString += String(pos.seqNo) csvString += ", " @@ -90,9 +73,7 @@ func PositionToCsvFile(positions: [PositionEntity]) -> String { csvString += ", " csvString += String(pos.snr) csvString += ", " - csvString += pos.time?.formattedDate(format: "yyyy-MM-dd HH:mm:ss") ?? "Unknown Age" } - return csvString } diff --git a/Meshtastic/Persistence/PositionEntityExtension.swift b/Meshtastic/Persistence/PositionEntityExtension.swift index 036e118b..a17f7e06 100644 --- a/Meshtastic/Persistence/PositionEntityExtension.swift +++ b/Meshtastic/Persistence/PositionEntityExtension.swift @@ -26,7 +26,6 @@ extension PositionEntity { var coordinate: CLLocationCoordinate2D? { if latitudeI != 0 && longitudeI != 0 { let coord = CLLocationCoordinate2D(latitude: latitude!, longitude: longitude!) - return coord } else { return nil @@ -36,10 +35,8 @@ extension PositionEntity { var annotaton: MKPointAnnotation { let pointAnn = MKPointAnnotation() if coordinate != nil { - pointAnn.coordinate = coordinate! } return pointAnn } - } diff --git a/Meshtastic/Views/Nodes/NodeDetail.swift b/Meshtastic/Views/Nodes/NodeDetail.swift index 553c2364..6016d931 100644 --- a/Meshtastic/Views/Nodes/NodeDetail.swift +++ b/Meshtastic/Views/Nodes/NodeDetail.swift @@ -14,7 +14,6 @@ struct NodeDetail: View { @State private var showingDetailsPopover = false - @State var initialLoad: Bool = true @State var satsInView = 0 @State private var showingShutdownConfirm: Bool = false @State private var showingRebootConfirm: Bool = false @@ -416,12 +415,7 @@ struct NodeDetail: View { } ) .onAppear { - - if self.initialLoad{ - - self.bleManager.context = context - self.initialLoad = false - } + self.bleManager.context = context } } } diff --git a/Meshtastic/Views/Settings/Config/BluetoothConfig.swift b/Meshtastic/Views/Settings/Config/BluetoothConfig.swift index eda12586..fed85cab 100644 --- a/Meshtastic/Views/Settings/Config/BluetoothConfig.swift +++ b/Meshtastic/Views/Settings/Config/BluetoothConfig.swift @@ -15,9 +15,7 @@ struct BluetoothConfig: View { var node: NodeInfoEntity? @State private var isPresentingSaveConfirm: Bool = false - @State var initialLoad: Bool = true @State var hasChanges = false - @State var enabled = true @State var mode = 0 @State var fixedPin = "123456" @@ -132,40 +130,27 @@ struct BluetoothConfig: View { ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????") }) .onAppear { - - if self.initialLoad{ - - self.bleManager.context = context - - self.enabled = node?.bluetoothConfig?.enabled ?? true - self.mode = Int(node?.bluetoothConfig?.mode ?? 0) - self.fixedPin = String(node?.bluetoothConfig?.fixedPin ?? 123456) - self.hasChanges = false - self.initialLoad = false - } + self.bleManager.context = context + self.enabled = node?.bluetoothConfig?.enabled ?? true + self.mode = Int(node?.bluetoothConfig?.mode ?? 0) + self.fixedPin = String(node?.bluetoothConfig?.fixedPin ?? 123456) + self.hasChanges = false } .onChange(of: enabled) { newEnabled in - if node != nil && node!.bluetoothConfig != nil { - if newEnabled != node!.bluetoothConfig!.enabled { hasChanges = true } } } .onChange(of: mode) { newMode in - if node != nil && node!.bluetoothConfig != nil { - if newMode != node!.bluetoothConfig!.mode { hasChanges = true } } } .onChange(of: fixedPin) { newFixedPin in - if node != nil && node!.bluetoothConfig != nil { - if newFixedPin != String(node!.bluetoothConfig!.fixedPin) { hasChanges = true } } } - .navigationViewStyle(StackNavigationViewStyle()) } } diff --git a/Meshtastic/Views/Settings/Config/LoRaConfig.swift b/Meshtastic/Views/Settings/Config/LoRaConfig.swift index cbac1a28..191f1f5b 100644 --- a/Meshtastic/Views/Settings/Config/LoRaConfig.swift +++ b/Meshtastic/Views/Settings/Config/LoRaConfig.swift @@ -15,9 +15,7 @@ struct LoRaConfig: View { var node: NodeInfoEntity? @State var isPresentingSaveConfirm = false - @State var initialLoad = true @State var hasChanges = false - @State var region = 0 @State var modemPreset = 0 @State var hopLimit = 0 @@ -28,10 +26,8 @@ struct LoRaConfig: View { var body: some View { VStack { - Form { Section(header: Text("Region")) { - Picker("Region", selection: $region ) { ForEach(RegionCodes.allCases) { r in Text(r.description) @@ -52,7 +48,6 @@ struct LoRaConfig: View { .font(.caption) } Section(header: Text("Mesh Options")) { - Picker("Number of hops", selection: $hopLimit) { ForEach(HopValues.allCases) { hop in Text(hop.description) @@ -64,13 +59,9 @@ struct LoRaConfig: View { } } .disabled(self.bleManager.connectedPeripheral == nil) - Button { - isPresentingSaveConfirm = true - } label: { - Label("Save", systemImage: "square.and.arrow.down") } .disabled(bleManager.connectedPeripheral == nil || !hasChanges) @@ -79,22 +70,18 @@ struct LoRaConfig: View { .controlSize(.large) .padding() .confirmationDialog( - "Are you sure you want to save?", isPresented: $isPresentingSaveConfirm, titleVisibility: .visible ) { Button("Save Config for \(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : "Unknown")") { - var lc = Config.LoRaConfig() lc.hopLimit = UInt32(hopLimit) lc.region = RegionCodes(rawValue: region)!.protoEnumValue() lc.modemPreset = ModemPresets(rawValue: modemPreset)!.protoEnumValue() lc.usePreset = true lc.txEnabled = true - let adminMessageId = bleManager.saveLoRaConfig(config: lc, fromUser: node!.user!, toUser: node!.user!) - if adminMessageId > 0 { // Should show a saved successfully alert once I know that to be true @@ -107,53 +94,36 @@ struct LoRaConfig: View { } } message: { - Text("After LoRa config saves the node will reboot.") } } .navigationTitle("LoRa Config") .navigationBarItems(trailing: - ZStack { - - ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????") + ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????") }) .onAppear { - self.bleManager.context = context - - if self.initialLoad{ - - - self.hopLimit = Int(node?.loRaConfig?.hopLimit ?? 0) - self.region = Int(node?.loRaConfig?.regionCode ?? 0) - self.usePreset = node?.loRaConfig?.usePreset ?? true - self.modemPreset = Int(node?.loRaConfig?.modemPreset ?? 0) - self.txEnabled = node?.loRaConfig?.txEnabled ?? true - self.txPower = Int(node?.loRaConfig?.txPower ?? 0) - - self.hasChanges = false - self.initialLoad = false - } + self.hopLimit = Int(node?.loRaConfig?.hopLimit ?? 0) + self.region = Int(node?.loRaConfig?.regionCode ?? 0) + self.usePreset = node?.loRaConfig?.usePreset ?? true + self.modemPreset = Int(node?.loRaConfig?.modemPreset ?? 0) + self.txEnabled = node?.loRaConfig?.txEnabled ?? true + self.txPower = Int(node?.loRaConfig?.txPower ?? 0) + self.hasChanges = false } .onChange(of: region) { newRegion in - if node != nil && node!.loRaConfig != nil { - if newRegion != node!.loRaConfig!.regionCode { hasChanges = true } } } .onChange(of: modemPreset) { newModemPreset in - if node != nil && node!.loRaConfig != nil { - if newModemPreset != node!.loRaConfig!.modemPreset { hasChanges = true } } } .onChange(of: hopLimit) { newHopLimit in - if node != nil && node!.loRaConfig != nil { - if newHopLimit != node!.loRaConfig!.hopLimit { hasChanges = true } } } diff --git a/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift b/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift index 7517edbb..27b661b0 100644 --- a/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift @@ -14,7 +14,6 @@ struct CannedMessagesConfig: View { var node: NodeInfoEntity? @State private var isPresentingSaveConfirm: Bool = false - @State var initialLoad: Bool = true @State var hasChanges = false @State var hasMessagesChanges = false @State var configPreset = 0 @@ -213,7 +212,6 @@ struct CannedMessagesConfig: View { isPresentingSaveConfirm = true } label: { - Label("Save", systemImage: "square.and.arrow.down") } .disabled(bleManager.connectedPeripheral == nil || (!hasChanges && !hasMessagesChanges)) @@ -222,7 +220,6 @@ struct CannedMessagesConfig: View { .controlSize(.large) .padding() .confirmationDialog( - "Are you sure?", isPresented: $isPresentingSaveConfirm, titleVisibility: .visible @@ -230,24 +227,18 @@ struct CannedMessagesConfig: View { Button("Save Canned Messages Module Config to \(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : "Unknown")?") { if hasChanges { - var cmc = ModuleConfig.CannedMessageConfig() cmc.enabled = enabled cmc.sendBell = sendBell cmc.rotary1Enabled = rotary1Enabled cmc.updown1Enabled = updown1Enabled if rotary1Enabled { - /// Input event origin accepted by the canned messages /// Can be e.g. "rotEnc1", "upDownEnc1", "cardkb", or keyword "_any" cmc.allowInputSource = "rotEnc1" - } else if updown1Enabled { - cmc.allowInputSource = "_any" - } else { - cmc.allowInputSource = "_any" } cmc.inputbrokerPinA = UInt32(inputbrokerPinA) @@ -256,55 +247,41 @@ struct CannedMessagesConfig: View { cmc.inputbrokerEventCw = InputEventChars(rawValue: inputbrokerEventCw)!.protoEnumValue() cmc.inputbrokerEventCcw = InputEventChars(rawValue: inputbrokerEventCcw)!.protoEnumValue() cmc.inputbrokerEventPress = InputEventChars(rawValue: inputbrokerEventPress)!.protoEnumValue() - let adminMessageId = bleManager.saveCannedMessageModuleConfig(config: cmc, fromUser: node!.user!, toUser: node!.user!) - if adminMessageId > 0 { // Should show a saved successfully alert once I know that to be true // for now just disable the button after a successful save hasChanges = false } } - if hasMessagesChanges { - let adminMessageId = bleManager.saveCannedMessageModuleMessages(messages: messages, fromUser: node!.user!, toUser: node!.user!, wantResponse: true) - if adminMessageId > 0 { // Should show a saved successfully alert once I know that to be true // for now just disable the button after a successful save hasMessagesChanges = false } - } } } - .navigationTitle("Canned Messages Config") .navigationBarItems(trailing: - ZStack { - ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????") }) .onAppear { - - if self.initialLoad{ - - self.bleManager.context = context - self.enabled = node?.cannedMessageConfig?.enabled ?? false - self.sendBell = node?.cannedMessageConfig?.sendBell ?? false - self.rotary1Enabled = node?.cannedMessageConfig?.rotary1Enabled ?? false - self.updown1Enabled = node?.cannedMessageConfig?.updown1Enabled ?? false - self.inputbrokerPinA = Int(node?.cannedMessageConfig?.inputbrokerPinA ?? 0) - self.inputbrokerPinB = Int(node?.cannedMessageConfig?.inputbrokerPinB ?? 0) - self.inputbrokerPinPress = Int(node?.cannedMessageConfig?.inputbrokerPinPress ?? 0) - self.inputbrokerEventCw = Int(node?.cannedMessageConfig?.inputbrokerEventCw ?? 0) - self.inputbrokerEventCcw = Int(node?.cannedMessageConfig?.inputbrokerEventCcw ?? 0) - self.inputbrokerEventPress = Int(node?.cannedMessageConfig?.inputbrokerEventPress ?? 0) - self.hasChanges = false - self.initialLoad = false - } + self.bleManager.context = context + self.enabled = node?.cannedMessageConfig?.enabled ?? false + self.sendBell = node?.cannedMessageConfig?.sendBell ?? false + self.rotary1Enabled = node?.cannedMessageConfig?.rotary1Enabled ?? false + self.updown1Enabled = node?.cannedMessageConfig?.updown1Enabled ?? false + self.inputbrokerPinA = Int(node?.cannedMessageConfig?.inputbrokerPinA ?? 0) + self.inputbrokerPinB = Int(node?.cannedMessageConfig?.inputbrokerPinB ?? 0) + self.inputbrokerPinPress = Int(node?.cannedMessageConfig?.inputbrokerPinPress ?? 0) + self.inputbrokerEventCw = Int(node?.cannedMessageConfig?.inputbrokerEventCw ?? 0) + self.inputbrokerEventCcw = Int(node?.cannedMessageConfig?.inputbrokerEventCcw ?? 0) + self.inputbrokerEventPress = Int(node?.cannedMessageConfig?.inputbrokerEventPress ?? 0) + self.hasChanges = false } .onChange(of: configPreset) { newPreset in diff --git a/Meshtastic/Views/Settings/Config/Module/ExternalNotificationConfig.swift b/Meshtastic/Views/Settings/Config/Module/ExternalNotificationConfig.swift index 7e85192c..0fb79150 100644 --- a/Meshtastic/Views/Settings/Config/Module/ExternalNotificationConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/ExternalNotificationConfig.swift @@ -54,9 +54,7 @@ struct ExternalNotificationConfig: View { var node: NodeInfoEntity? @State private var isPresentingSaveConfirm: Bool = false - @State var initialLoad: Bool = true @State var hasChanges = false - @State var enabled = false @State var alertBell = false @State var alertMessage = false @@ -67,50 +65,34 @@ struct ExternalNotificationConfig: View { var body: some View { VStack { - Form { - Section(header: Text("Options")) { - Toggle(isOn: $enabled) { - Label("Enabled", systemImage: "megaphone") } .toggleStyle(SwitchToggleStyle(tint: .accentColor)) - Toggle(isOn: $alertBell) { - Label("Alert when receiving a bell", systemImage: "bell") } .toggleStyle(SwitchToggleStyle(tint: .accentColor)) - Toggle(isOn: $alertMessage) { - Label("Alert when receiving a message", systemImage: "message") } .toggleStyle(SwitchToggleStyle(tint: .accentColor)) } - Section(header: Text("GPIO")) { - Toggle(isOn: $active) { - Label("Active", systemImage: "togglepower") } .toggleStyle(SwitchToggleStyle(tint: .accentColor)) Text("Specifies whether the external circuit is triggered when the device's GPIO is low or high.") .font(.caption) .listRowSeparator(.visible) - Picker("GPIO to monitor", selection: $output) { ForEach(0..<40) { - if $0 == 0 { - Text("Unset") - } else { - Text("Pin \($0)") } } @@ -118,7 +100,6 @@ struct ExternalNotificationConfig: View { .pickerStyle(DefaultPickerStyle()) Text("Specifies the GPIO that your external circuit is attached to on the device.") .font(.caption) - Picker("GPIO Output Duration", selection: $outputMilliseconds ) { ForEach(OutputIntervals.allCases) { oi in Text(oi.description) @@ -130,13 +111,9 @@ struct ExternalNotificationConfig: View { } } .disabled(bleManager.connectedPeripheral == nil) - Button { - isPresentingSaveConfirm = true - } label: { - Label("Save", systemImage: "square.and.arrow.down") } .disabled(bleManager.connectedPeripheral == nil || !hasChanges) @@ -150,7 +127,6 @@ struct ExternalNotificationConfig: View { titleVisibility: .visible ) { Button("Save External Notification Module Config to \(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : "Unknown")?") { - var enc = ModuleConfig.ExternalNotificationConfig() enc.enabled = enabled enc.alertBell = alertBell @@ -158,84 +134,58 @@ struct ExternalNotificationConfig: View { enc.active = active enc.output = UInt32(output) enc.outputMs = UInt32(outputMilliseconds) - let adminMessageId = bleManager.saveExternalNotificationModuleConfig(config: enc, fromUser: node!.user!, toUser: node!.user!) - if adminMessageId > 0{ - // Should show a saved successfully alert once I know that to be true // for now just disable the button after a successful save hasChanges = false - } else { } } } - .navigationTitle("External Notification Config") .navigationBarItems(trailing: - ZStack { - - ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????") + ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????") }) .onAppear { - - if self.initialLoad{ - - self.bleManager.context = context - - self.enabled = node?.externalNotificationConfig?.enabled ?? false - self.alertBell = node?.externalNotificationConfig?.alertBell ?? false - self.alertMessage = node?.externalNotificationConfig?.alertMessage ?? false - self.active = node?.externalNotificationConfig?.active ?? false - self.output = Int(node?.externalNotificationConfig?.output ?? 0) - self.outputMilliseconds = Int(node?.externalNotificationConfig?.outputMilliseconds ?? 0) - - self.hasChanges = false - self.initialLoad = false - } + self.bleManager.context = context + self.enabled = node?.externalNotificationConfig?.enabled ?? false + self.alertBell = node?.externalNotificationConfig?.alertBell ?? false + self.alertMessage = node?.externalNotificationConfig?.alertMessage ?? false + self.active = node?.externalNotificationConfig?.active ?? false + self.output = Int(node?.externalNotificationConfig?.output ?? 0) + self.outputMilliseconds = Int(node?.externalNotificationConfig?.outputMilliseconds ?? 0) + self.hasChanges = false } .onChange(of: enabled) { newEnabled in - if node != nil && node!.externalNotificationConfig != nil { - if newEnabled != node!.externalNotificationConfig!.enabled { hasChanges = true } } } .onChange(of: alertBell) { newAlertBell in - if node != nil && node!.externalNotificationConfig != nil { - if newAlertBell != node!.externalNotificationConfig!.alertBell { hasChanges = true } } } .onChange(of: alertMessage) { newAlertMessage in - if node != nil && node!.externalNotificationConfig != nil { - if newAlertMessage != node!.externalNotificationConfig!.alertMessage { hasChanges = true } } } .onChange(of: active) { newActuve in - if node != nil && node!.externalNotificationConfig != nil { - if newActuve != node!.externalNotificationConfig!.active { hasChanges = true } } } .onChange(of: output) { newOutput in - if node != nil && node!.externalNotificationConfig != nil { - if newOutput != node!.externalNotificationConfig!.output { hasChanges = true } } } .onChange(of: outputMilliseconds) { newOutputMs in - if node != nil && node!.externalNotificationConfig != nil { - if newOutputMs != node!.externalNotificationConfig!.outputMilliseconds { hasChanges = true } } } diff --git a/Meshtastic/Views/Settings/Config/Module/RangeTestConfig.swift b/Meshtastic/Views/Settings/Config/Module/RangeTestConfig.swift index 311fec72..f8265571 100644 --- a/Meshtastic/Views/Settings/Config/Module/RangeTestConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/RangeTestConfig.swift @@ -52,27 +52,20 @@ struct RangeTestConfig: View { var node: NodeInfoEntity? @State private var isPresentingSaveConfirm: Bool = false - @State var initialLoad: Bool = true @State var hasChanges = false - @State var enabled = false @State var sender = 0 @State var save = false var body: some View { - VStack { - Form { - Section(header: Text("Options")) { - Toggle(isOn: $enabled) { Label("Enabled", systemImage: "figure.walk") } .toggleStyle(SwitchToggleStyle(tint: .accentColor)) - Picker("Sender Interval", selection: $sender ) { ForEach(SenderIntervals.allCases) { sci in Text(sci.description) @@ -81,26 +74,19 @@ struct RangeTestConfig: View { .pickerStyle(DefaultPickerStyle()) Text("This device will send out range test messages on the selected interval.") .font(.caption) - Toggle(isOn: $save) { - Label("Save", systemImage: "square.and.arrow.down.fill") } .toggleStyle(SwitchToggleStyle(tint: .accentColor)) .disabled(!(node != nil && node!.myInfo?.hasWifi ?? false)) - Text("Saves a CSV with the range test message details, currently only available on ESP32 devices with a web server.") .font(.caption) } } .disabled(!(node != nil && node!.myInfo?.hasWifi ?? false)) - Button { - isPresentingSaveConfirm = true - } label: { - Label("Save", systemImage: "square.and.arrow.down") } .disabled(bleManager.connectedPeripheral == nil || !hasChanges || !(node!.myInfo?.hasWifi ?? false)) @@ -114,63 +100,44 @@ struct RangeTestConfig: View { titleVisibility: .visible ) { Button("Save Range Test Module Config to \(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : "Unknown")?") { - var rtc = ModuleConfig.RangeTestConfig() rtc.enabled = enabled rtc.save = save rtc.sender = UInt32(sender) - let adminMessageId = bleManager.saveRangeTestModuleConfig(config: rtc, fromUser: node!.user!, toUser: node!.user!) - if adminMessageId > 0 { - // Should show a saved successfully alert once I know that to be true // for now just disable the button after a successful save hasChanges = false - } else { } } } - .navigationTitle("Range Test Config") .navigationBarItems(trailing: - ZStack { - ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????") }) .onAppear { - - if self.initialLoad{ - - self.bleManager.context = context - self.enabled = node?.rangeTestConfig?.enabled ?? false - self.save = node?.rangeTestConfig?.save ?? false - self.sender = Int(node?.rangeTestConfig?.sender ?? 0) - self.hasChanges = false - self.initialLoad = false - } + self.bleManager.context = context + self.enabled = node?.rangeTestConfig?.enabled ?? false + self.save = node?.rangeTestConfig?.save ?? false + self.sender = Int(node?.rangeTestConfig?.sender ?? 0) + self.hasChanges = false } .onChange(of: enabled) { newEnabled in - if node != nil && node!.rangeTestConfig != nil { - if newEnabled != node!.rangeTestConfig!.enabled { hasChanges = true } } } .onChange(of: save) { newSave in - if node != nil && node!.rangeTestConfig != nil { - if newSave != node!.rangeTestConfig!.save { hasChanges = true } } } .onChange(of: sender) { newSender in - if node != nil && node!.rangeTestConfig != nil { - if newSender != node!.rangeTestConfig!.sender { hasChanges = true } } } diff --git a/Meshtastic/Views/Settings/Config/Module/TelemetryConfig.swift b/Meshtastic/Views/Settings/Config/Module/TelemetryConfig.swift index 4567bcd5..2289aa2e 100644 --- a/Meshtastic/Views/Settings/Config/Module/TelemetryConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/TelemetryConfig.swift @@ -74,9 +74,7 @@ struct TelemetryConfig: View { var node: NodeInfoEntity? @State private var isPresentingSaveConfirm: Bool = false - @State var initialLoad: Bool = true @State var hasChanges = false - @State var deviceUpdateInterval = 0 @State var environmentUpdateInterval = 0 @State var environmentMeasurementEnabled = false @@ -86,11 +84,8 @@ struct TelemetryConfig: View { var body: some View { VStack { - Form { - Section(header: Text("Update Intervals")) { - Picker("Device Metrics", selection: $deviceUpdateInterval ) { ForEach(UpdateIntervals.allCases) { ui in Text(ui.description) @@ -99,7 +94,6 @@ struct TelemetryConfig: View { .pickerStyle(DefaultPickerStyle()) Text("How often device metrics are sent out over the mesh. Default is 15 minutes.") .font(.caption) - Picker("Sensor Metrics", selection: $environmentUpdateInterval ) { ForEach(UpdateIntervals.allCases) { ui in Text(ui.description) @@ -109,39 +103,27 @@ struct TelemetryConfig: View { Text("How often sensor metrics are sent out over the mesh. Default is 15 minutes.") .font(.caption) } - Section(header: Text("Sensor Options")) { - Text("Supported I2C Connected sensors will be detected automatically, sensors are BMP280, BME280, BME680, MCP9808, INA219, INA260, LPS22 and SHTC3.") .font(.caption) - Toggle(isOn: $environmentMeasurementEnabled) { - Label("Enabled", systemImage: "chart.xyaxis.line") } .toggleStyle(SwitchToggleStyle(tint: .accentColor)) - Toggle(isOn: $environmentScreenEnabled) { - Label("Show on device screen", systemImage: "display") } .toggleStyle(SwitchToggleStyle(tint: .accentColor)) - Toggle(isOn: $environmentDisplayFahrenheit) { - Label("Display Fahrenheit", systemImage: "thermometer") } .toggleStyle(SwitchToggleStyle(tint: .accentColor)) } } .disabled(bleManager.connectedPeripheral == nil) - Button { - isPresentingSaveConfirm = true - } label: { - Label("Save", systemImage: "square.and.arrow.down") } .disabled(bleManager.connectedPeripheral == nil || !hasChanges || node!.telemetryConfig == nil) @@ -150,28 +132,22 @@ struct TelemetryConfig: View { .controlSize(.large) .padding() .confirmationDialog( - "Are you sure?", isPresented: $isPresentingSaveConfirm, titleVisibility: .visible ) { Button("Save Telemetry Module Config to \(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : "Unknown")?") { - var tc = ModuleConfig.TelemetryConfig() tc.deviceUpdateInterval = UInt32(deviceUpdateInterval) tc.environmentUpdateInterval = UInt32(environmentUpdateInterval) tc.environmentMeasurementEnabled = environmentMeasurementEnabled tc.environmentScreenEnabled = environmentScreenEnabled tc.environmentDisplayFahrenheit = environmentDisplayFahrenheit - let adminMessageId = bleManager.saveTelemetryModuleConfig(config: tc, fromUser: node!.user!, toUser: node!.user!) - if adminMessageId > 0 { - // Should show a saved successfully alert once I know that to be true // for now just disable the button after a successful save hasChanges = false - } else { } @@ -180,57 +156,40 @@ struct TelemetryConfig: View { .navigationTitle("Telemetry Config") .navigationBarItems(trailing: - ZStack { - - ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????") + ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????") }) .onAppear { - - if self.initialLoad{ - - self.bleManager.context = context - self.deviceUpdateInterval = Int(node?.telemetryConfig?.deviceUpdateInterval ?? 0) - self.environmentUpdateInterval = Int(node?.telemetryConfig?.environmentUpdateInterval ?? 0) - self.environmentMeasurementEnabled = node?.telemetryConfig?.environmentMeasurementEnabled ?? false - self.environmentScreenEnabled = node?.telemetryConfig?.environmentScreenEnabled ?? false - self.environmentDisplayFahrenheit = node?.telemetryConfig?.environmentDisplayFahrenheit ?? false - self.hasChanges = false - self.initialLoad = false - } + self.bleManager.context = context + self.deviceUpdateInterval = Int(node?.telemetryConfig?.deviceUpdateInterval ?? 0) + self.environmentUpdateInterval = Int(node?.telemetryConfig?.environmentUpdateInterval ?? 0) + self.environmentMeasurementEnabled = node?.telemetryConfig?.environmentMeasurementEnabled ?? false + self.environmentScreenEnabled = node?.telemetryConfig?.environmentScreenEnabled ?? false + self.environmentDisplayFahrenheit = node?.telemetryConfig?.environmentDisplayFahrenheit ?? false + self.hasChanges = false } .onChange(of: deviceUpdateInterval) { newDeviceInterval in - if node != nil && node!.telemetryConfig != nil { - if newDeviceInterval != node!.telemetryConfig!.deviceUpdateInterval { hasChanges = true } } } .onChange(of: environmentUpdateInterval) { newEnvInterval in - if node != nil && node!.telemetryConfig != nil { - if newEnvInterval != node!.telemetryConfig!.environmentUpdateInterval { hasChanges = true } } } .onChange(of: environmentMeasurementEnabled) { newEnvEnabled in - if node != nil && node!.telemetryConfig != nil { - if newEnvEnabled != node!.telemetryConfig!.environmentMeasurementEnabled { hasChanges = true } } } .onChange(of: environmentScreenEnabled) { newEnvScreenEnabled in - if node!.telemetryConfig != nil { - if newEnvScreenEnabled != node!.telemetryConfig!.environmentScreenEnabled { hasChanges = true } } } .onChange(of: environmentDisplayFahrenheit) { newEnvDisplayF in - if node != nil && node!.telemetryConfig != nil { - if newEnvDisplayF != node!.telemetryConfig!.environmentDisplayFahrenheit { hasChanges = true } } } diff --git a/Meshtastic/Views/Settings/Config/NetworkConfig.swift b/Meshtastic/Views/Settings/Config/NetworkConfig.swift index fb1939d7..89c2eb79 100644 --- a/Meshtastic/Views/Settings/Config/NetworkConfig.swift +++ b/Meshtastic/Views/Settings/Config/NetworkConfig.swift @@ -15,9 +15,7 @@ struct NetworkConfig: View { var node: NodeInfoEntity? @State private var isPresentingSaveConfirm: Bool = false - @State var initialLoad: Bool = true @State var hasChanges: Bool = false - @State var wifiEnabled = false @State var wifiSsid = "" @State var wifiPsk = "" @@ -27,20 +25,14 @@ struct NetworkConfig: View { var body: some View { VStack { - Form { - Section(header: Text("WiFi Options")) { - Text("Enabling WiFi will disable the bluetooth connection to the app.") .font(.title3) - Toggle(isOn: $wifiEnabled) { - Label("Enabled", systemImage: "wifi") } .toggleStyle(SwitchToggleStyle(tint: .accentColor)) - HStack { Label("SSID", systemImage: "network") TextField("SSID", text: $wifiSsid) @@ -48,16 +40,11 @@ struct NetworkConfig: View { .autocapitalization(.none) .disableAutocorrection(true) .onChange(of: wifiSsid, perform: { value in - let totalBytes = wifiSsid.utf8.count - // Only mess with the value if it is too big if totalBytes > 32 { - let firstNBytes = Data(wifiSsid.utf8.prefix(32)) - if let maxBytesString = String(data: firstNBytes, encoding: String.Encoding.utf8) { - // Set the shortName back to the last place where it was the right size wifiSsid = maxBytesString } @@ -67,7 +54,6 @@ struct NetworkConfig: View { .foregroundColor(.gray) } .keyboardType(.default) - HStack { Label("Password", systemImage: "wallet.pass") TextField("Password", text: $wifiPsk) @@ -75,16 +61,11 @@ struct NetworkConfig: View { .autocapitalization(.none) .disableAutocorrection(true) .onChange(of: wifiPsk, perform: { value in - let totalBytes = wifiPsk.utf8.count - // Only mess with the value if it is too big if totalBytes > 63 { - let firstNBytes = Data(wifiPsk.utf8.prefix(63)) - if let maxBytesString = String(data: firstNBytes, encoding: String.Encoding.utf8) { - // Set the shortName back to the last place where it was the right size wifiPsk = maxBytesString } @@ -98,13 +79,9 @@ struct NetworkConfig: View { } .scrollDismissesKeyboard(.interactively) .disabled(!(node != nil && node!.myInfo?.hasWifi ?? false)) - Button { - isPresentingSaveConfirm = true - } label: { - Label("Save", systemImage: "square.and.arrow.down") } .disabled(bleManager.connectedPeripheral == nil || !hasChanges) @@ -113,22 +90,17 @@ struct NetworkConfig: View { .controlSize(.large) .padding() .confirmationDialog( - "Are you sure you want to save?", isPresented: $isPresentingSaveConfirm, titleVisibility: .visible ) { Button("Save Config for \(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : "Unknown")") { - var network = Config.NetworkConfig() network.wifiEnabled = self.wifiEnabled network.wifiSsid = self.wifiSsid network.wifiPsk = self.wifiPsk - let adminMessageId = bleManager.saveWiFiConfig(config: network, fromUser: node!.user!, toUser: node!.user!) - if adminMessageId > 0 { - // Should show a saved successfully alert once I know that to be true // for now just disable the button after a successful save self.hasChanges = false @@ -138,57 +110,39 @@ struct NetworkConfig: View { } } } message: { - Text("After network config saves the node will reboot.") } } .navigationTitle("Network Config") .navigationBarItems(trailing: - ZStack { - - ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????") + ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????") }) .onAppear { - - if self.initialLoad{ - - self.bleManager.context = context - - self.wifiEnabled = (node?.networkConfig?.wifiEnabled ?? false) - self.wifiSsid = node?.networkConfig?.wifiSsid ?? "" - self.wifiPsk = node?.networkConfig?.wifiPsk ?? "" - self.wifiMode = Int(node?.networkConfig?.wifiMode ?? 0) - - self.hasChanges = false - self.initialLoad = false - } + self.bleManager.context = context + self.wifiEnabled = (node?.networkConfig?.wifiEnabled ?? false) + self.wifiSsid = node?.networkConfig?.wifiSsid ?? "" + self.wifiPsk = node?.networkConfig?.wifiPsk ?? "" + self.wifiMode = Int(node?.networkConfig?.wifiMode ?? 0) + self.hasChanges = false } .onChange(of: wifiEnabled) { newEnabled in - if node != nil && node!.networkConfig != nil { - if newEnabled != node!.networkConfig!.wifiEnabled { hasChanges = true } } } .onChange(of: wifiSsid) { newSSID in - if node != nil && node!.networkConfig != nil { - if newSSID != node!.networkConfig!.wifiSsid { hasChanges = true } } } .onChange(of: wifiPsk) { newPsk in - if node != nil && node!.networkConfig != nil { - if newPsk != node!.networkConfig!.wifiPsk { hasChanges = true } } } .onChange(of: wifiMode) { newMode in - if node != nil && node!.networkConfig != nil { - if newMode != node!.networkConfig!.wifiMode { hasChanges = true } } } diff --git a/Meshtastic/Views/Settings/UserConfig.swift b/Meshtastic/Views/Settings/UserConfig.swift index ec563943..97c6fa5a 100644 --- a/Meshtastic/Views/Settings/UserConfig.swift +++ b/Meshtastic/Views/Settings/UserConfig.swift @@ -15,61 +15,44 @@ struct UserConfig: View { @State private var isPresentingFactoryResetConfirm: Bool = false @State private var isPresentingSaveConfirm: Bool = false - @State var initialLoad: Bool = true @State var hasChanges = false - @State var shortName = "" @State var longName = "" var body: some View { VStack { - Form { - Section(header: Text("USER DETAILS")) { - HStack { Label("Long Name", systemImage: "person.crop.rectangle.fill") TextField("Long Name", text: $longName) .onChange(of: longName, perform: { value in - let totalBytes = longName.utf8.count - // Only mess with the value if it is too big if totalBytes > 36 { - let firstNBytes = Data(longName.utf8.prefix(36)) - if let maxBytesString = String(data: firstNBytes, encoding: String.Encoding.utf8) { - // Set the longName back to the last place where it was the right size longName = maxBytesString } } }) - } .keyboardType(.default) .disableAutocorrection(true) Text("Long name can be up to 36 bytes long.") .font(.caption) - HStack { Label("Short Name", systemImage: "circlebadge.fill") TextField("Long Name", text: $shortName) .foregroundColor(.gray) .onChange(of: shortName, perform: { value in - let totalBytes = shortName.utf8.count - // Only mess with the value if it is too big if totalBytes > 4 { - let firstNBytes = Data(shortName.utf8.prefix(4)) - if let maxBytesString = String(data: firstNBytes, encoding: String.Encoding.utf8) { - // Set the shortName back to the last place where it was the right size shortName = maxBytesString } @@ -81,20 +64,13 @@ struct UserConfig: View { .disableAutocorrection(true) Text("The short name is used in maps and messaging and will be appended to the last 4 of the device MAC address to set the device's BLE Name. It can be up to 4 bytes long.") .font(.caption) - } - } .disabled(bleManager.connectedPeripheral == nil) - HStack { - Button { - isPresentingSaveConfirm = true - } label: { - Label("Save", systemImage: "square.and.arrow.down") } .disabled(bleManager.connectedPeripheral == nil || !hasChanges) @@ -103,63 +79,43 @@ struct UserConfig: View { .controlSize(.large) .padding() .confirmationDialog( - "Are you sure you want to save?", isPresented: $isPresentingSaveConfirm, titleVisibility: .visible ) { Button("Save User Config to \(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : "Unknown")?") { - var u = User() u.shortName = shortName u.longName = longName - let adminMessageId = bleManager.saveUser(config: u, fromUser: node!.user!, toUser: node!.user!) - if adminMessageId > 0 { - hasChanges = false } } } message: { - Text("After user config saves the node will reboot.") } - } Spacer() } - .navigationTitle("User Config") .navigationBarItems(trailing: - ZStack { - - ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????") + ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????") }) .onAppear { - - if self.initialLoad{ - - self.bleManager.context = context - - self.shortName = node?.user!.shortName ?? "" - self.longName = node?.user!.longName ?? "" - self.hasChanges = false - self.initialLoad = false - } + self.bleManager.context = context + self.shortName = node?.user!.shortName ?? "" + self.longName = node?.user!.longName ?? "" + self.hasChanges = false } .onChange(of: shortName) { newShort in - if node != nil && node!.user != nil { - if newShort != node?.user!.shortName { hasChanges = true } } } .onChange(of: longName) { newLong in - if node != nil && node!.user != nil { - if newLong != node?.user!.longName { hasChanges = true } } }