diff --git a/Meshtastic.xcodeproj/project.pbxproj b/Meshtastic.xcodeproj/project.pbxproj index aa5a8a3f..a96e3707 100644 --- a/Meshtastic.xcodeproj/project.pbxproj +++ b/Meshtastic.xcodeproj/project.pbxproj @@ -1583,7 +1583,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.3.8; + MARKETING_VERSION = 2.3.9; PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTS_MACCATALYST = YES; @@ -1617,7 +1617,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.3.8; + MARKETING_VERSION = 2.3.9; PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTS_MACCATALYST = YES; @@ -1690,7 +1690,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.3.8; + MARKETING_VERSION = 2.3.9; PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient.Widgets; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1723,7 +1723,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.3.8; + MARKETING_VERSION = 2.3.9; PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient.Widgets; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/Meshtastic/Helpers/BLEManager.swift b/Meshtastic/Helpers/BLEManager.swift index dd78784e..0c997f05 100644 --- a/Meshtastic/Helpers/BLEManager.swift +++ b/Meshtastic/Helpers/BLEManager.swift @@ -1328,33 +1328,43 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate if isConnected { var i: Int32 = 0 + var myInfo: MyInfoEntity // Before we get started delete the existing channels from the myNodeInfo if !addChannels { tryClearExistingChannels() - } else { - // We are trying to add a channel so lets get the last index - let fetchMyInfoRequest: NSFetchRequest = NSFetchRequest.init(entityName: "MyInfoEntity") - fetchMyInfoRequest.predicate = NSPredicate(format: "myNodeNum == %lld", Int64(connectedPeripheral.num)) - do { - let fetchedMyInfo = try context?.fetch(fetchMyInfoRequest) as? [MyInfoEntity] ?? [] - if fetchedMyInfo.count == 1 { - if addChannels { - i = Int32(fetchedMyInfo[0].channels?.count ?? -1) - // Bail out if the index is negative or bigger than our max of 8 - if i < 0 || i > 8 { - return false - } - } - } - } catch { - print("Failed to find a node MyInfo to save these channels to") - } } + let decodedString = base64UrlString.base64urlToBase64() if let decodedData = Data(base64Encoded: decodedString) { do { let channelSet: ChannelSet = try ChannelSet(serializedData: decodedData) for cs in channelSet.settings { + if addChannels { + // We are trying to add a channel so lets get the last index + let fetchMyInfoRequest: NSFetchRequest = NSFetchRequest.init(entityName: "MyInfoEntity") + fetchMyInfoRequest.predicate = NSPredicate(format: "myNodeNum == %lld", Int64(connectedPeripheral.num)) + do { + let fetchedMyInfo = try context?.fetch(fetchMyInfoRequest) as? [MyInfoEntity] ?? [] + if fetchedMyInfo.count == 1 { + i = Int32(fetchedMyInfo[0].channels?.count ?? -1) + myInfo = fetchedMyInfo[0] + // Bail out if the index is negative or bigger than our max of 8 + if i < 0 || i > 8 { + return false + } + // Bail out if there are no channels or if the same channel name already exists + guard let mutableChannels = myInfo.channels!.mutableCopy() as? NSMutableOrderedSet else { + return false + } + if mutableChannels.first(where: {($0 as AnyObject).name == cs.name }) is ChannelEntity { + return false + } + } + } catch { + print("Failed to find a node MyInfo to save these channels to") + } + } + var chan = Channel() if i == 0 { chan.role = Channel.Role.primary @@ -1364,6 +1374,7 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate chan.settings = cs chan.index = i i += 1 + var adminPacket = AdminMessage() adminPacket.setChannel = chan var meshPacket: MeshPacket = MeshPacket() diff --git a/Meshtastic/MeshtasticApp.swift b/Meshtastic/MeshtasticApp.swift index e9de24bc..0b8275dd 100644 --- a/Meshtastic/MeshtasticApp.swift +++ b/Meshtastic/MeshtasticApp.swift @@ -28,7 +28,7 @@ struct MeshtasticAppleApp: App { .environmentObject(bleManager) .sheet(isPresented: $saveChannels) { SaveChannelQRCode(channelSetLink: channelSettings ?? "Empty Channel URL", addChannels: addChannels, bleManager: bleManager) - .presentationDetents([.medium, .large]) + .presentationDetents([.large]) .presentationDragIndicator(.visible) } .onContinueUserActivity(NSUserActivityTypeBrowsingWeb) { userActivity in diff --git a/Meshtastic/Views/Nodes/Helpers/Map/MapContent/MeshMapContent.swift b/Meshtastic/Views/Nodes/Helpers/Map/MapContent/MeshMapContent.swift index 6a03aba8..52d3a97c 100644 --- a/Meshtastic/Views/Nodes/Helpers/Map/MapContent/MeshMapContent.swift +++ b/Meshtastic/Views/Nodes/Helpers/Map/MapContent/MeshMapContent.swift @@ -142,7 +142,7 @@ struct MeshMapContent: MapContent { } } /// Reduced Precision Map Circles - if 11...16 ~= position.precisionBits { + if 2...24 ~= position.precisionBits { let pp = PositionPrecision(rawValue: Int(position.precisionBits)) let radius : CLLocationDistance = pp?.precisionMeters ?? 0 if radius > 0.0 { diff --git a/Meshtastic/Views/Nodes/Helpers/Map/MapContent/NodeMapContent.swift b/Meshtastic/Views/Nodes/Helpers/Map/MapContent/NodeMapContent.swift index 83a5ccbc..fd869c30 100644 --- a/Meshtastic/Views/Nodes/Helpers/Map/MapContent/NodeMapContent.swift +++ b/Meshtastic/Views/Nodes/Helpers/Map/MapContent/NodeMapContent.swift @@ -49,7 +49,7 @@ struct NodeMapContent: MapContent { let pf = PositionFlags(rawValue: Int(position.nodePosition?.metadata?.positionFlags ?? 771)) let headingDegrees = Angle.degrees(Double(position.heading)) /// Reduced Precision Map Circle - if position.latest && 11...16 ~= position.precisionBits { + if position.latest && 2...24 ~= position.precisionBits { let pp = PositionPrecision(rawValue: Int(position.precisionBits)) let radius : CLLocationDistance = pp?.precisionMeters ?? 0 if radius > 0.0 { diff --git a/Meshtastic/Views/Settings/Channels/ChannelForm.swift b/Meshtastic/Views/Settings/Channels/ChannelForm.swift index 60e1b2dd..560d1d70 100644 --- a/Meshtastic/Views/Settings/Channels/ChannelForm.swift +++ b/Meshtastic/Views/Settings/Channels/ChannelForm.swift @@ -160,7 +160,7 @@ struct ChannelForm: View { if !preciseLocation { VStack(alignment: .leading) { Label("Approximate Location", systemImage: "location.slash.circle.fill") - Slider(value: $positionPrecision, in: 11...18, step: 1) { + Slider(value: $positionPrecision, in: 10...19, step: 1) { } minimumValueLabel: { Image(systemName: "minus") } maximumValueLabel: { diff --git a/Meshtastic/Views/Settings/SaveChannelQRCode.swift b/Meshtastic/Views/Settings/SaveChannelQRCode.swift index f9ca2557..7de80622 100644 --- a/Meshtastic/Views/Settings/SaveChannelQRCode.swift +++ b/Meshtastic/Views/Settings/SaveChannelQRCode.swift @@ -13,6 +13,7 @@ struct SaveChannelQRCode: View { var channelSetLink: String var addChannels: Bool = false var bleManager: BLEManager + @State var showError: Bool = false @State var connectedToDevice = false var body: some View { @@ -20,26 +21,48 @@ struct SaveChannelQRCode: View { Text("\(addChannels ? "Add" : "Replace all") Channels?") .font(.title) Text("These settings will \(addChannels ? "add" : "replace all") channels. The current LoRa Config will be replaced. After everything saves your device will reboot.") + .fixedSize(horizontal: false, vertical: true) .foregroundColor(.gray) .font(.title3) .padding() + if showError { + Text("Channels being added from the QR code did not save. When adding channels the names must be unique.") + .fixedSize(horizontal: false, vertical: true) + .foregroundColor(.red) + .font(.callout) + .padding() + } HStack { - - Button { - let success = bleManager.saveChannelSet(base64UrlString: channelSetLink, addChannels: addChannels) - if success { - dismiss() + if !showError { + Button { + let success = bleManager.saveChannelSet(base64UrlString: channelSetLink, addChannels: addChannels) + if success { + dismiss() + } else { + showError = true + } + } label: { + Label("save", systemImage: "square.and.arrow.down") } + .buttonStyle(.bordered) + .buttonBorderShape(.capsule) + .controlSize(.large) + .padding() + .disabled(!connectedToDevice) + } else { + Button { + dismiss() + } label: { + Label("cancel", systemImage: "xmark") - } label: { - Label("save", systemImage: "square.and.arrow.down") + } + .buttonStyle(.bordered) + .buttonBorderShape(.capsule) + .controlSize(.large) + .padding() } - .buttonStyle(.bordered) - .buttonBorderShape(.capsule) - .controlSize(.large) - .padding() - .disabled(!connectedToDevice) + #if targetEnvironment(macCatalyst) Button {