diff --git a/Meshtastic/Helpers/BLEManager.swift b/Meshtastic/Helpers/BLEManager.swift index ae52b23d..bdc28320 100644 --- a/Meshtastic/Helpers/BLEManager.swift +++ b/Meshtastic/Helpers/BLEManager.swift @@ -459,7 +459,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph MeshLogger.log("â„šī¸ Requesting Device Metadata for \(connectedPeripheral!.peripheral.name ?? "Unknown")") var adminPacket = AdminMessage() - adminPacket.getDeviceMetadataRequest = 0 + adminPacket.getDeviceMetadataRequest = true var meshPacket: MeshPacket = MeshPacket() meshPacket.id = UInt32.random(in: UInt32(UInt8.max).. Bool { + public func getChannel(channelIndex: UInt32, fromUser: UserEntity, toUser: UserEntity, wantResponse: Bool) -> Bool { var adminPacket = AdminMessage() adminPacket.getChannelRequest = channelIndex var meshPacket: MeshPacket = MeshPacket() - meshPacket.to = UInt32(nodeNum) + meshPacket.to = UInt32(toUser.num) meshPacket.from = 0 //UInt32(cnodeNum) meshPacket.id = UInt32.random(in: UInt32(UInt8.max).. NodeInfoEntity? { + + print(try! channel.jsonString()) + + if channel.isInitialized { + + let fetchedMyInfoRequest: NSFetchRequest = NSFetchRequest.init(entityName: "MyInfoEntity") + fetchedMyInfoRequest.predicate = NSPredicate(format: "myNodeNum == %lld", fromNum) + + do { + + let fetchedMyInfo = try context.fetch(fetchedMyInfoRequest) as! [MyInfoEntity] + + if fetchedMyInfo.count == 1 { + + // Update + if fetchedMyInfo[0].channels?.count ?? 0 >= 1 { + + let newChannel = ChannelEntity(context: context) + newChannel.index = Int32(channel.index) + newChannel.uplinkEnabled = channel.settings.uplinkEnabled + newChannel.downlinkEnabled = channel.settings.downlinkEnabled + newChannel.name = channel.settings.name + newChannel.role = Int32(channel.role.rawValue) + + let mutableChannels = fetchedMyInfo[0].channels!.mutableCopy() as! NSMutableOrderedSet + + mutableChannels.add(newChannel) + fetchedMyInfo[0].channels = mutableChannels.copy() as? NSOrderedSet + + } else { + + let newChannel = ChannelEntity(context: context) + newChannel.index = Int32(channel.index) + newChannel.uplinkEnabled = channel.settings.uplinkEnabled + newChannel.downlinkEnabled = channel.settings.downlinkEnabled + newChannel.name = channel.settings.name + newChannel.role = Int32(channel.role.rawValue) + + var newChannels = [ChannelEntity]() + newChannels.append(newChannel) + fetchedMyInfo[0].channels! = NSOrderedSet(array: newChannels) + } + + } else { + print("đŸ’Ĩ Trying to save a channel to a MyInfo that does not exist: \(fromNum)") + } + + try context.save() + + if meshLogging { + + MeshLogger.log("💾 Updated MyInfo channel \(channel.settings.channelNum + 1) from Channel App Packet For: \(fetchedMyInfo[0].myNodeNum)") + } + + } catch { + + context.rollback() + + let nsError = error as NSError + print("đŸ’Ĩ Error Saving MyInfo Channel from ADMIN_APP \(nsError)") + } + } + //} + + + + + return nil + +} + func nodeInfoPacket (nodeInfo: NodeInfo, meshLogging: Bool, context: NSManagedObjectContext) -> NodeInfoEntity? { let fetchNodeInfoRequest: NSFetchRequest = NSFetchRequest.init(entityName: "NodeInfoEntity") @@ -1012,6 +1084,7 @@ func nodeInfoPacket (nodeInfo: NodeInfo, meshLogging: Bool, context: NSManagedOb return nil } + func nodeInfoAppPacket (packet: MeshPacket, meshLogging: Bool, context: NSManagedObjectContext) { let fetchNodeInfoAppRequest: NSFetchRequest = NSFetchRequest.init(entityName: "NodeInfoEntity") @@ -1076,71 +1149,7 @@ func nodeInfoAppPacket (packet: MeshPacket, meshLogging: Bool, context: NSManage func adminAppPacket (packet: MeshPacket, meshLogging: Bool, context: NSManagedObjectContext) { - if let channelMessage = try? Channel(serializedData: packet.decoded.payload) { - - if channelMessage.hasSettings { - - let fetchedMyInfoRequest: NSFetchRequest = NSFetchRequest.init(entityName: "MyInfoEntity") - fetchedMyInfoRequest.predicate = NSPredicate(format: "myNodeNum == %lld", Int64(packet.from)) - - do { - - let fetchedMyInfo = try context.fetch(fetchedMyInfoRequest) as! [MyInfoEntity] - - if fetchedMyInfo.count == 1 { - - // Update - if fetchedMyInfo[0].channels?.count ?? 0 >= 1 { - - let newChannel = ChannelEntity(context: context) - newChannel.index = Int32(channelMessage.settings.channelNum) - newChannel.uplinkEnabled = channelMessage.settings.uplinkEnabled - newChannel.downlinkEnabled = channelMessage.settings.downlinkEnabled - newChannel.name = channelMessage.settings.name - newChannel.role = Int32(channelMessage.role.rawValue) - - let mutableChannels = fetchedMyInfo[0].channels!.mutableCopy() as! NSMutableOrderedSet - - mutableChannels.add(newChannel) - fetchedMyInfo[0].channels = mutableChannels.copy() as? NSOrderedSet - - } else { - - let newChannel = ChannelEntity(context: context) - newChannel.index = Int32(channelMessage.settings.channelNum) - newChannel.uplinkEnabled = channelMessage.settings.uplinkEnabled - newChannel.downlinkEnabled = channelMessage.settings.downlinkEnabled - newChannel.name = channelMessage.settings.name - newChannel.role = Int32(channelMessage.role.rawValue) - - var newChannels = [ChannelEntity]() - newChannels.append(newChannel) - fetchedMyInfo[0].channels! = NSOrderedSet(array: newChannels) - } - - } else { - print("đŸ’Ĩ Trying to save a channel to a MyInfo that does not exist: \(packet.from)") - } - - try context.save() - - if meshLogging { - - MeshLogger.log("💾 Updated MyInfo channel \(channelMessage.settings.channelNum + 1) from Channel App Packet For: \(fetchedMyInfo[0].myNodeNum)") - } - - } catch { - - context.rollback() - - let nsError = error as NSError - print("đŸ’Ĩ Error Saving MyInfo Channel from ADMIN_APP \(nsError)") - } - } - } else { - print(try! packet.decoded.jsonString()) - } } diff --git a/Meshtastic/MeshtasticApp.swift b/Meshtastic/MeshtasticApp.swift index 6dce5257..539b11f1 100644 --- a/Meshtastic/MeshtasticApp.swift +++ b/Meshtastic/MeshtasticApp.swift @@ -11,8 +11,8 @@ struct MeshtasticAppleApp: App { @ObservedObject private var bleManager: BLEManager = BLEManager.shared @ObservedObject private var userSettings: UserSettings = UserSettings() - @State var saveQR = false - @State var channelUrl: URL? + @State var saveChannels = false + @State var incomingUrl: URL? @Environment(\.scenePhase) var scenePhase @@ -25,32 +25,30 @@ struct MeshtasticAppleApp: App { .onContinueUserActivity(NSUserActivityTypeBrowsingWeb) { userActivity in - print("QR Code URL received from the Camera \(userActivity)") - channelUrl = userActivity.webpageURL - if channelUrl!.absoluteString.lowercased().contains("https://meshtastic.org/e/#") { - saveQR = true + print("URL received \(userActivity)") + incomingUrl = userActivity.webpageURL + if incomingUrl!.absoluteString.lowercased().contains("https://meshtastic.org/e/#") { + saveChannels = true + } + if saveChannels { + print("User wants to open Channel Settings URL: \(String(describing: incomingUrl!.relativeString))") } - - print("User wants to open URL: \(String(describing: channelUrl?.relativeString))") - } - .sheet(isPresented: $saveQR) { - - SaveChannelQRCode(channelHash: channelUrl?.absoluteString ?? "Empty Channel URL") + .sheet(isPresented: $saveChannels) { + SaveChannelQRCode(channelHash: incomingUrl?.absoluteString ?? "Empty Channel URL") .presentationDetents([.medium, .large]) .presentationDragIndicator(.visible) } .onOpenURL(perform: { (url) in print("Some sort of URL was received \(url)") - channelUrl = url - + incomingUrl = url if url.absoluteString.lowercased().contains("https://meshtastic.org/e/#") { - saveQR = true - print("User wants to open a Channel Settings URL: \(channelUrl?.absoluteString ?? "No QR Code Link")") + saveChannels = true + print("User wants to open a Channel Settings URL: \(incomingUrl?.absoluteString ?? "No QR Code Link")") } else { - print("User wants to import a MBTILES offline map file: \(channelUrl?.absoluteString ?? "No Tiles link")") + print("User wants to import a MBTILES offline map file: \(incomingUrl?.absoluteString ?? "No Tiles link")") } //we are expecting a .mbtiles map file that contains raster data diff --git a/Meshtastic/Protobufs/admin.pb.swift b/Meshtastic/Protobufs/admin.pb.swift index e43a6564..83169e01 100644 --- a/Meshtastic/Protobufs/admin.pb.swift +++ b/Meshtastic/Protobufs/admin.pb.swift @@ -114,16 +114,6 @@ struct AdminMessage { set {payloadVariant = .getModuleConfigResponse(newValue)} } - /// - /// Send all channels in the response to this message - var getAllChannelRequest: Bool { - get { - if case .getAllChannelRequest(let v)? = payloadVariant {return v} - return false - } - set {payloadVariant = .getAllChannelRequest(newValue)} - } - /// /// Get the Canned Message Module messages in the response to this message. var getCannedMessageModuleMessagesRequest: Bool { @@ -146,10 +136,10 @@ struct AdminMessage { /// /// Request the node to send device metadata (firmware, protobuf version, etc) - var getDeviceMetadataRequest: UInt32 { + var getDeviceMetadataRequest: Bool { get { if case .getDeviceMetadataRequest(let v)? = payloadVariant {return v} - return 0 + return false } set {payloadVariant = .getDeviceMetadataRequest(newValue)} } @@ -261,6 +251,17 @@ struct AdminMessage { set {payloadVariant = .confirmSetRadio(newValue)} } + /// + /// Tell the node to reboot into the OTA Firmware in this many seconds (or <0 to cancel reboot) + /// Only Implemented for ESP32 Devices. This needs to be issued to send a new main firmware via bluetooth. + var rebootOtaSeconds: Int32 { + get { + if case .rebootOtaSeconds(let v)? = payloadVariant {return v} + return 0 + } + set {payloadVariant = .rebootOtaSeconds(newValue)} + } + /// /// This message is only supported for the simulator porduino build. /// If received the simulator will exit successfully. @@ -343,9 +344,6 @@ struct AdminMessage { /// Send the current Config in the response to this message. case getModuleConfigResponse(ModuleConfig) /// - /// Send all channels in the response to this message - case getAllChannelRequest(Bool) - /// /// Get the Canned Message Module messages in the response to this message. case getCannedMessageModuleMessagesRequest(Bool) /// @@ -353,7 +351,7 @@ struct AdminMessage { case getCannedMessageModuleMessagesResponse(String) /// /// Request the node to send device metadata (firmware, protobuf version, etc) - case getDeviceMetadataRequest(UInt32) + case getDeviceMetadataRequest(Bool) /// /// Device metadata response case getDeviceMetadataResponse(DeviceMetadata) @@ -392,6 +390,10 @@ struct AdminMessage { /// TODO: REPLACE case confirmSetRadio(Bool) /// + /// Tell the node to reboot into the OTA Firmware in this many seconds (or <0 to cancel reboot) + /// Only Implemented for ESP32 Devices. This needs to be issued to send a new main firmware via bluetooth. + case rebootOtaSeconds(Int32) + /// /// This message is only supported for the simulator porduino build. /// If received the simulator will exit successfully. case exitSimulator(Bool) @@ -446,10 +448,6 @@ struct AdminMessage { guard case .getModuleConfigResponse(let l) = lhs, case .getModuleConfigResponse(let r) = rhs else { preconditionFailure() } return l == r }() - case (.getAllChannelRequest, .getAllChannelRequest): return { - guard case .getAllChannelRequest(let l) = lhs, case .getAllChannelRequest(let r) = rhs else { preconditionFailure() } - return l == r - }() case (.getCannedMessageModuleMessagesRequest, .getCannedMessageModuleMessagesRequest): return { guard case .getCannedMessageModuleMessagesRequest(let l) = lhs, case .getCannedMessageModuleMessagesRequest(let r) = rhs else { preconditionFailure() } return l == r @@ -502,6 +500,10 @@ struct AdminMessage { guard case .confirmSetRadio(let l) = lhs, case .confirmSetRadio(let r) = rhs else { preconditionFailure() } return l == r }() + case (.rebootOtaSeconds, .rebootOtaSeconds): return { + guard case .rebootOtaSeconds(let l) = lhs, case .rebootOtaSeconds(let r) = rhs else { preconditionFailure() } + return l == r + }() case (.exitSimulator, .exitSimulator): return { guard case .exitSimulator(let l) = lhs, case .exitSimulator(let r) = rhs else { preconditionFailure() } return l == r @@ -713,7 +715,6 @@ extension AdminMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat 6: .standard(proto: "get_config_response"), 7: .standard(proto: "get_module_config_request"), 8: .standard(proto: "get_module_config_response"), - 9: .standard(proto: "get_all_channel_request"), 10: .standard(proto: "get_canned_message_module_messages_request"), 11: .standard(proto: "get_canned_message_module_messages_response"), 12: .standard(proto: "get_device_metadata_request"), @@ -727,6 +728,7 @@ extension AdminMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat 65: .standard(proto: "confirm_set_module_config"), 66: .standard(proto: "confirm_set_channel"), 67: .standard(proto: "confirm_set_radio"), + 95: .standard(proto: "reboot_ota_seconds"), 96: .standard(proto: "exit_simulator"), 97: .standard(proto: "reboot_seconds"), 98: .standard(proto: "shutdown_seconds"), @@ -824,14 +826,6 @@ extension AdminMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat self.payloadVariant = .getModuleConfigResponse(v) } }() - case 9: try { - var v: Bool? - try decoder.decodeSingularBoolField(value: &v) - if let v = v { - if self.payloadVariant != nil {try decoder.handleConflictingOneOf()} - self.payloadVariant = .getAllChannelRequest(v) - } - }() case 10: try { var v: Bool? try decoder.decodeSingularBoolField(value: &v) @@ -849,8 +843,8 @@ extension AdminMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat } }() case 12: try { - var v: UInt32? - try decoder.decodeSingularUInt32Field(value: &v) + var v: Bool? + try decoder.decodeSingularBoolField(value: &v) if let v = v { if self.payloadVariant != nil {try decoder.handleConflictingOneOf()} self.payloadVariant = .getDeviceMetadataRequest(v) @@ -961,6 +955,14 @@ extension AdminMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat self.payloadVariant = .confirmSetRadio(v) } }() + case 95: try { + var v: Int32? + try decoder.decodeSingularInt32Field(value: &v) + if let v = v { + if self.payloadVariant != nil {try decoder.handleConflictingOneOf()} + self.payloadVariant = .rebootOtaSeconds(v) + } + }() case 96: try { var v: Bool? try decoder.decodeSingularBoolField(value: &v) @@ -1044,10 +1046,6 @@ extension AdminMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat guard case .getModuleConfigResponse(let v)? = self.payloadVariant else { preconditionFailure() } try visitor.visitSingularMessageField(value: v, fieldNumber: 8) }() - case .getAllChannelRequest?: try { - guard case .getAllChannelRequest(let v)? = self.payloadVariant else { preconditionFailure() } - try visitor.visitSingularBoolField(value: v, fieldNumber: 9) - }() case .getCannedMessageModuleMessagesRequest?: try { guard case .getCannedMessageModuleMessagesRequest(let v)? = self.payloadVariant else { preconditionFailure() } try visitor.visitSingularBoolField(value: v, fieldNumber: 10) @@ -1058,7 +1056,7 @@ extension AdminMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat }() case .getDeviceMetadataRequest?: try { guard case .getDeviceMetadataRequest(let v)? = self.payloadVariant else { preconditionFailure() } - try visitor.visitSingularUInt32Field(value: v, fieldNumber: 12) + try visitor.visitSingularBoolField(value: v, fieldNumber: 12) }() case .getDeviceMetadataResponse?: try { guard case .getDeviceMetadataResponse(let v)? = self.payloadVariant else { preconditionFailure() } @@ -1100,6 +1098,10 @@ extension AdminMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat guard case .confirmSetRadio(let v)? = self.payloadVariant else { preconditionFailure() } try visitor.visitSingularBoolField(value: v, fieldNumber: 67) }() + case .rebootOtaSeconds?: try { + guard case .rebootOtaSeconds(let v)? = self.payloadVariant else { preconditionFailure() } + try visitor.visitSingularInt32Field(value: v, fieldNumber: 95) + }() case .exitSimulator?: try { guard case .exitSimulator(let v)? = self.payloadVariant else { preconditionFailure() } try visitor.visitSingularBoolField(value: v, fieldNumber: 96) diff --git a/Meshtastic/Protobufs/config.pb.swift b/Meshtastic/Protobufs/config.pb.swift index b7215ece..97e28992 100644 --- a/Meshtastic/Protobufs/config.pb.swift +++ b/Meshtastic/Protobufs/config.pb.swift @@ -675,7 +675,7 @@ struct Config { /// /// The denominator of the coding rate. - /// ie for 4/8, the value is 8. 5/8 the value is 5. + /// ie for 4/5, the value is 5. 4/8 the value is 8. var codingRate: UInt32 = 0 /// diff --git a/Meshtastic/Protobufs/mesh.pb.swift b/Meshtastic/Protobufs/mesh.pb.swift index 1f674306..a548b47f 100644 --- a/Meshtastic/Protobufs/mesh.pb.swift +++ b/Meshtastic/Protobufs/mesh.pb.swift @@ -1850,6 +1850,16 @@ struct FromRadio { set {_uniqueStorage()._payloadVariant = .moduleConfig(newValue)} } + /// + /// One packet is sent for each channel + var channel: Channel { + get { + if case .channel(let v)? = _storage._payloadVariant {return v} + return Channel() + } + set {_uniqueStorage()._payloadVariant = .channel(newValue)} + } + var unknownFields = SwiftProtobuf.UnknownStorage() /// @@ -1887,6 +1897,9 @@ struct FromRadio { /// /// Include module config case moduleConfig(ModuleConfig) + /// + /// One packet is sent for each channel + case channel(Channel) #if !swift(>=4.1) static func ==(lhs: FromRadio.OneOf_PayloadVariant, rhs: FromRadio.OneOf_PayloadVariant) -> Bool { @@ -1926,6 +1939,10 @@ struct FromRadio { guard case .moduleConfig(let l) = lhs, case .moduleConfig(let r) = rhs else { preconditionFailure() } return l == r }() + case (.channel, .channel): return { + guard case .channel(let l) = lhs, case .channel(let r) = rhs else { preconditionFailure() } + return l == r + }() default: return false } } @@ -3244,6 +3261,7 @@ extension FromRadio: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation 7: .standard(proto: "config_complete_id"), 8: .same(proto: "rebooted"), 9: .same(proto: "moduleConfig"), + 10: .same(proto: "channel"), ] fileprivate class _StorageClass { @@ -3370,6 +3388,19 @@ extension FromRadio: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation _storage._payloadVariant = .moduleConfig(v) } }() + case 10: try { + var v: Channel? + var hadOneofValue = false + if let current = _storage._payloadVariant { + hadOneofValue = true + if case .channel(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + _storage._payloadVariant = .channel(v) + } + }() default: break } } @@ -3418,6 +3449,10 @@ extension FromRadio: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation guard case .moduleConfig(let v)? = _storage._payloadVariant else { preconditionFailure() } try visitor.visitSingularMessageField(value: v, fieldNumber: 9) }() + case .channel?: try { + guard case .channel(let v)? = _storage._payloadVariant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 10) + }() case nil: break } } diff --git a/Meshtastic/Protobufs/telemetry.pb.swift b/Meshtastic/Protobufs/telemetry.pb.swift index 73f89cc0..3e745000 100644 --- a/Meshtastic/Protobufs/telemetry.pb.swift +++ b/Meshtastic/Protobufs/telemetry.pb.swift @@ -60,6 +60,14 @@ enum TelemetrySensorType: SwiftProtobuf.Enum { /// /// High accuracy pressure case lps22 // = 8 + + /// + /// 3-Axis magnetic sensor + case qmc6310 // = 9 + + /// + /// 6-Axis inertial measurement sensor + case qmi8658 // = 10 case UNRECOGNIZED(Int) init() { @@ -77,6 +85,8 @@ enum TelemetrySensorType: SwiftProtobuf.Enum { case 6: self = .bmp280 case 7: self = .shtc3 case 8: self = .lps22 + case 9: self = .qmc6310 + case 10: self = .qmi8658 default: self = .UNRECOGNIZED(rawValue) } } @@ -92,6 +102,8 @@ enum TelemetrySensorType: SwiftProtobuf.Enum { case .bmp280: return 6 case .shtc3: return 7 case .lps22: return 8 + case .qmc6310: return 9 + case .qmi8658: return 10 case .UNRECOGNIZED(let i): return i } } @@ -112,6 +124,8 @@ extension TelemetrySensorType: CaseIterable { .bmp280, .shtc3, .lps22, + .qmc6310, + .qmi8658, ] } @@ -272,6 +286,8 @@ extension TelemetrySensorType: SwiftProtobuf._ProtoNameProviding { 6: .same(proto: "BMP280"), 7: .same(proto: "SHTC3"), 8: .same(proto: "LPS22"), + 9: .same(proto: "QMC6310"), + 10: .same(proto: "QMI8658"), ] } diff --git a/Meshtastic/Views/Settings/ShareChannels.swift b/Meshtastic/Views/Settings/ShareChannels.swift index 445903e0..631c8a57 100644 --- a/Meshtastic/Views/Settings/ShareChannels.swift +++ b/Meshtastic/Views/Settings/ShareChannels.swift @@ -34,15 +34,17 @@ struct ShareChannels: View { @Environment(\.managedObjectContext) var context @EnvironmentObject var bleManager: BLEManager @EnvironmentObject var userSettings: UserSettings + @State var initialLoad: Bool = true + @State var channels: [ChannelEntity] = [ChannelEntity]() @State var includeChannel0 = true - @State var includeChannel1 = true - @State var includeChannel2 = true + @State var includeChannel1 = false + @State var includeChannel2 = false @State var includeChannel3 = false @State var includeChannel4 = false @State var includeChannel5 = false @State var includeChannel6 = false - @State var includeChannel7 = true + @State var includeChannel7 = false var node: NodeInfoEntity? @@ -76,56 +78,60 @@ struct ShareChannels: View { } Divider() - ForEach(node!.myInfo!.channels?.array.sorted(by: { ($0 as! ChannelEntity).index < ($1 as! ChannelEntity).index }) as! [ChannelEntity], id: \.self) { (channel: ChannelEntity) in + ForEach(node!.myInfo!.channels?.array as! [ChannelEntity], id: \.self) { (channel: ChannelEntity) in GridRow { Spacer() if channel.index == 0 { + Toggle("Channel 0 Included", isOn: $includeChannel0) .toggleStyle(.switch) .labelsHidden() .disabled(true) - Text("Primary Channel") + Text((channel.name!.isEmpty ? "Primary Channel" : channel.name) ?? "Primary Channel") } else if channel.index == 1 { Toggle("Channel 1 Included", isOn: $includeChannel1) .toggleStyle(.switch) .labelsHidden() - Text("Public Channel") + .disabled(channel.role == 0) + Text((channel.name!.isEmpty ? "Channel \(channel.index)" : channel.name) ?? "Channel \(channel.index)") } else if channel.index == 2 { Toggle("Channel 2 Included", isOn: $includeChannel2) .toggleStyle(.switch) .labelsHidden() + .disabled(channel.role == 0) + Text((channel.name!.isEmpty ? "Channel \(channel.index)" : channel.name) ?? "Channel \(channel.index)") } else if channel.index == 3 { Toggle("Channel 3 Included", isOn: $includeChannel3) .toggleStyle(.switch) .labelsHidden() + .disabled(channel.role == 0) + Text((channel.name!.isEmpty ? "Channel \(channel.index)" : channel.name) ?? "Channel \(channel.index)") } else if channel.index == 4 { Toggle("Channel 4 Included", isOn: $includeChannel4) .toggleStyle(.switch) .labelsHidden() - .disabled(true) + .disabled(channel.role == 0) + Text((channel.name!.isEmpty ? "Channel \(channel.index)" : channel.name) ?? "Channel \(channel.index)") } else if channel.index == 5 { Toggle("Channel 5 Included", isOn: $includeChannel5) .toggleStyle(.switch) .labelsHidden() - .disabled(true) + .disabled(channel.role == 0) + Text((channel.name!.isEmpty ? "Channel \(channel.index)" : channel.name) ?? "Channel \(channel.index)") } else if channel.index == 6 { Toggle("Channel 6 Included", isOn: $includeChannel6) .toggleStyle(.switch) .labelsHidden() - .disabled(true) + .disabled(channel.role == 0) + Text((channel.name!.isEmpty ? "Channel \(channel.index)" : channel.name) ?? "Channel \(channel.index)") } else if channel.index == 7 { Toggle("Channel 7 Included", isOn: $includeChannel7) .toggleStyle(.switch) .labelsHidden() - Text("Admin Channel") - } - if channel.index > 1 && channel.index < 4{ - Text("Private Chat - \(channel.index)") - } - if channel.index > 3 && channel.index < 7{ - Text("Channel - \(channel.index)") + .disabled(channel.role == 0) + Text((channel.name!.isEmpty ? "Admin Channel" : channel.name) ?? "Admin Channel") } Spacer() } @@ -171,7 +177,12 @@ struct ShareChannels: View { }) .onAppear { - self.bleManager.context = context + if self.initialLoad{ + + self.bleManager.context = context + + self.initialLoad = false + } } } .navigationViewStyle(StackNavigationViewStyle())