diff --git a/Meshtastic/Extensions/Url.swift b/Meshtastic/Extensions/Url.swift index a8589e55..20d3ca6e 100644 --- a/Meshtastic/Extensions/Url.swift +++ b/Meshtastic/Extensions/Url.swift @@ -8,13 +8,26 @@ import Foundation extension URL { - - func regularFileAllocatedSize() throws -> UInt64 { - let resourceValues = try self.resourceValues(forKeys: allocatedSizeResourceKeys) - - guard resourceValues.isRegularFile ?? false else { - return 0 + + func regularFileAllocatedSize() throws -> UInt64 { + let resourceValues = try self.resourceValues(forKeys: allocatedSizeResourceKeys) + + guard resourceValues.isRegularFile ?? false else { + return 0 + } + return UInt64(resourceValues.totalFileAllocatedSize ?? resourceValues.fileAllocatedSize ?? 0) + } + subscript(queryParam: String) -> String? { + guard let url = URLComponents(string: self.absoluteString) else { return nil } + if let parameters = url.queryItems { + return parameters.first(where: { $0.name == queryParam })?.value + } else if let paramPairs = url.fragment?.components(separatedBy: "?").last?.components(separatedBy: "&") { + for pair in paramPairs where pair.contains(queryParam) { + return pair.components(separatedBy: "=").last + } + return nil + } else { + return nil + } } - return UInt64(resourceValues.totalFileAllocatedSize ?? resourceValues.fileAllocatedSize ?? 0) - } } diff --git a/Meshtastic/Helpers/BLEManager.swift b/Meshtastic/Helpers/BLEManager.swift index d5ca39ef..c28363e1 100644 --- a/Meshtastic/Helpers/BLEManager.swift +++ b/Meshtastic/Helpers/BLEManager.swift @@ -1304,13 +1304,14 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate return 0 } - public func saveChannelSet(base64UrlString: String) -> Bool { + public func saveChannelSet(base64UrlString: String, addChannel: Bool = false) -> Bool { if isConnected { // Before we get started delete the existing channels from the myNodeInfo let fetchMyInfoRequest: NSFetchRequest = NSFetchRequest.init(entityName: "MyInfoEntity") fetchMyInfoRequest.predicate = NSPredicate(format: "myNodeNum == %lld", Int64(connectedPeripheral.num)) - - tryClearExistingChannels() + if !addChannel { + tryClearExistingChannels() + } let decodedString = base64UrlString.base64urlToBase64() if let decodedData = Data(base64Encoded: decodedString) { do { @@ -1318,14 +1319,18 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate var i: Int32 = 0 for cs in channelSet.settings { var chan = Channel() - if i == 0 { + + if i == 0 && !addChannel { chan.role = Channel.Role.primary + } else { chan.role = Channel.Role.secondary } chan.settings = cs - chan.index = i - i += 1 + if !addChannel { + 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 e21b96e9..765969d4 100644 --- a/Meshtastic/MeshtasticApp.swift +++ b/Meshtastic/MeshtasticApp.swift @@ -18,6 +18,7 @@ struct MeshtasticAppleApp: App { @State var saveChannels = false @State var incomingUrl: URL? @State var channelSettings: String? + @State var addChannel = false @StateObject var appState = AppState.shared var body: some Scene { @@ -26,7 +27,7 @@ struct MeshtasticAppleApp: App { .environment(\.managedObjectContext, persistenceController.container.viewContext) .environmentObject(bleManager) .sheet(isPresented: $saveChannels) { - SaveChannelQRCode(channelSetLink: channelSettings ?? "Empty Channel URL", bleManager: bleManager) + SaveChannelQRCode(channelSetLink: channelSettings ?? "Empty Channel URL", addChannel: addChannel, bleManager: bleManager) .presentationDetents([.medium, .large]) .presentationDragIndicator(.visible) } @@ -36,9 +37,13 @@ struct MeshtasticAppleApp: App { self.incomingUrl = userActivity.webpageURL if (self.incomingUrl?.absoluteString.lowercased().contains("meshtastic.org/e/#")) != nil { - if let components = self.incomingUrl?.absoluteString.components(separatedBy: "#") { - self.channelSettings = components.last! + guard let cs = components.last!.components(separatedBy: "?").first else { + return + } + self.channelSettings = cs + self.addChannel = Bool(self.incomingUrl?["add"] ?? "false") ?? false + print("Add Channel \(self.addChannel)") } self.saveChannels = true print("User wants to open a Channel Settings URL: \(self.incomingUrl?.absoluteString ?? "No QR Code Link")") diff --git a/Meshtastic/Views/Settings/Channels.swift b/Meshtastic/Views/Settings/Channels.swift index d2bd8cf5..2581ee15 100644 --- a/Meshtastic/Views/Settings/Channels.swift +++ b/Meshtastic/Views/Settings/Channels.swift @@ -151,6 +151,14 @@ struct Channels: View { channel.settings.uplinkEnabled = uplink channel.settings.downlinkEnabled = downlink channel.settings.moduleSettings.positionPrecision = UInt32(positionPrecision) + + selectedChannel!.role = Int32(channelRole) + selectedChannel!.index = channelIndex + selectedChannel!.name = channelName + selectedChannel!.psk = Data(base64Encoded: channelKey) ?? Data() + selectedChannel!.uplinkEnabled = uplink + selectedChannel!.downlinkEnabled = downlink + selectedChannel!.positionPrecision = Int32(positionPrecision) guard let mutableChannels = node?.myInfo?.channels?.mutableCopy() as? NSMutableOrderedSet else { return @@ -160,7 +168,7 @@ struct Channels: View { } else { mutableChannels.add(selectedChannel as Any) } - node!.myInfo!.channels = mutableChannels.copy() as? NSOrderedSet + node?.myInfo?.channels = mutableChannels.copy() as? NSOrderedSet context.refresh(selectedChannel!, mergeChanges: true) do { try context.save() @@ -171,23 +179,21 @@ struct Channels: View { print("💥 Unresolved Core Data error in the channel editor. Error: \(nsError)") } } else { - if channelIndex <= node!.myInfo!.channels?.count ?? 0 { - guard let channelEntity = node!.myInfo!.channels?[Int(channelIndex)] as? ChannelEntity else { - return - } - let objects = channelEntity.allPrivateMessages - for object in objects { - context.delete(object) - } - context.delete(channelEntity) - do { - try context.save() - print("💾 Deleted Channel: \(channel.settings.name)") - } catch { - context.rollback() - let nsError = error as NSError - print("💥 Unresolved Core Data error in the channel editor. Error: \(nsError)") - } + guard let channelEntity = node?.myInfo?.channels?.first(where: { ($0 as! ChannelEntity).index == channelIndex }) else { + return + } + let objects = (channelEntity as! ChannelEntity).allPrivateMessages + for object in objects { + context.delete(object) + } + context.delete(channelEntity as! ChannelEntity) + do { + try context.save() + print("💾 Deleted Channel: \(channel.settings.name)") + } catch { + context.rollback() + let nsError = error as NSError + print("💥 Unresolved Core Data error in the channel editor. Error: \(nsError)") } } @@ -198,8 +204,6 @@ struct Channels: View { channelName = "" channelRole = 2 hasChanges = false - - _ = bleManager.getChannel(channel: channel, fromUser: node!.user!, toUser: node!.user!) } } label: { Label("save", systemImage: "square.and.arrow.down") diff --git a/Meshtastic/Views/Settings/SaveChannelQRCode.swift b/Meshtastic/Views/Settings/SaveChannelQRCode.swift index 7a825bb5..a44e9e01 100644 --- a/Meshtastic/Views/Settings/SaveChannelQRCode.swift +++ b/Meshtastic/Views/Settings/SaveChannelQRCode.swift @@ -11,6 +11,7 @@ struct SaveChannelQRCode: View { @Environment(\.dismiss) private var dismiss var channelSetLink: String + var addChannel: Bool = false var bleManager: BLEManager @State var connectedToDevice = false @@ -26,7 +27,7 @@ struct SaveChannelQRCode: View { HStack { Button { - let success = bleManager.saveChannelSet(base64UrlString: channelSetLink) + let success = bleManager.saveChannelSet(base64UrlString: channelSetLink, addChannel: addChannel) if success { dismiss() } diff --git a/Meshtastic/Views/Settings/ShareChannels.swift b/Meshtastic/Views/Settings/ShareChannels.swift index 8fa6bf32..0c17e07b 100644 --- a/Meshtastic/Views/Settings/ShareChannels.swift +++ b/Meshtastic/Views/Settings/ShareChannels.swift @@ -272,7 +272,7 @@ struct ShareChannels: View { } } let settingsString = try! channelSet.serializedData().base64EncodedString() - channelsUrl = ("https://meshtastic.org/e/#" + settingsString.base64ToBase64url()) + channelsUrl = ("https://meshtastic.org/e/#" + settingsString.base64ToBase64url())// + "?add=true") } } }