diff --git a/Meshtastic Client.xcodeproj/project.pbxproj b/Meshtastic Client.xcodeproj/project.pbxproj index 6243313b..374d17e4 100644 --- a/Meshtastic Client.xcodeproj/project.pbxproj +++ b/Meshtastic Client.xcodeproj/project.pbxproj @@ -41,6 +41,7 @@ DDAF8C6926ED0D070058C060 /* deviceonly.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF8C6826ED0D070058C060 /* deviceonly.pb.swift */; }; DDAF8C6B26ED0DD80058C060 /* environmental_measurement.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF8C6A26ED0DD80058C060 /* environmental_measurement.pb.swift */; }; DDAF8C6E26ED19040058C060 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF8C6D26ED19040058C060 /* Extensions.swift */; }; + DDB020A0272B0C6B00F8DBAE /* PersistanceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB0209F272B0C6B00F8DBAE /* PersistanceController.swift */; }; DDC2E15826CE248E0042C5E4 /* MeshtasticClientApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC2E15726CE248E0042C5E4 /* MeshtasticClientApp.swift */; }; DDC2E15C26CE248F0042C5E4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DDC2E15B26CE248F0042C5E4 /* Assets.xcassets */; }; DDC2E15F26CE248F0042C5E4 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DDC2E15E26CE248F0042C5E4 /* Preview Assets.xcassets */; }; @@ -104,6 +105,7 @@ DDAF8C6826ED0D070058C060 /* deviceonly.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = deviceonly.pb.swift; sourceTree = ""; }; DDAF8C6A26ED0DD80058C060 /* environmental_measurement.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = environmental_measurement.pb.swift; sourceTree = ""; }; DDAF8C6D26ED19040058C060 /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = ""; }; + DDB0209F272B0C6B00F8DBAE /* PersistanceController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersistanceController.swift; sourceTree = ""; }; DDC2E15426CE248E0042C5E4 /* MeshtasticClient.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MeshtasticClient.app; sourceTree = BUILT_PRODUCTS_DIR; }; DDC2E15726CE248E0042C5E4 /* MeshtasticClientApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshtasticClientApp.swift; sourceTree = ""; }; DDC2E15B26CE248F0042C5E4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; @@ -200,6 +202,14 @@ path = Protobufs; sourceTree = ""; }; + DDB0209E272B0C5700F8DBAE /* Data */ = { + isa = PBXGroup; + children = ( + DDB0209F272B0C6B00F8DBAE /* PersistanceController.swift */, + ); + path = Data; + sourceTree = ""; + }; DDC2E14B26CE248E0042C5E4 = { isa = PBXGroup; children = ( @@ -281,6 +291,7 @@ DDC2E18826CE24EE0042C5E4 /* Model */ = { isa = PBXGroup; children = ( + DDB0209E272B0C5700F8DBAE /* Data */, DD47E3DE26F39D9F00029299 /* MyInfoModel.swift */, DDF924C526FA2375009FE055 /* MessageModel.swift */, DD836AEC26F858F900ABCC23 /* MeshData.swift */, @@ -471,6 +482,7 @@ DD47E3CC26F0E51D00029299 /* NodeDetail.swift in Sources */, DD836AEF26F85D8D00ABCC23 /* NodeInfoModel.swift in Sources */, DDC2E1A726CEB3400042C5E4 /* LocationHelper.swift in Sources */, + DDB020A0272B0C6B00F8DBAE /* PersistanceController.swift in Sources */, DD47E3D226F1210600029299 /* HelperFunctions.swift in Sources */, DDAF8C5F26ED09B50058C060 /* radioconfig.pb.swift in Sources */, DD913639270DFF4C00D7ACF3 /* LocalNotificationManager.swift in Sources */, diff --git a/MeshtasticClient/Helpers/BLEManager.swift b/MeshtasticClient/Helpers/BLEManager.swift index b5e59994..215023cc 100644 --- a/MeshtasticClient/Helpers/BLEManager.swift +++ b/MeshtasticClient/Helpers/BLEManager.swift @@ -110,7 +110,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph @objc func timeoutTimerFired(timer: Timer) { guard let context = timer.userInfo as? [String: String] else { return } - let name = context["name", default: "Unknown"] + let name : String = context["name", default: "Unknown"] self.timeoutTimerCount += 1 @@ -124,8 +124,9 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph if meshLoggingEnabled { Logger.log("BLE Connecting Timeout Timer disconnected orphaned radio: \(name) in state: \(connectedPeripheral.peripheral.state.rawValue)") } } - print("BLE Connecting 2 Second Timeout Timer Fired \(timeoutTimerCount) Time(s): \(name)") - if meshLoggingEnabled { Logger.log("BLE Connecting 2 Second Timeout Timer Fired \(timeoutTimerCount) Time(s): \(name)") } + self.lastConnectionError = "Timeout while connecting to \(name)." + print("BLE Connecting 2 Second Timeout Timer Fired \(timeoutTimerCount) Times and failed: \(name)") + if meshLoggingEnabled { Logger.log("BLE Connecting 2 Second Timeout Timer Fired \(timeoutTimerCount) Times and failed: \(name)") } self.timeoutTimer?.invalidate() self.timeoutTimerCount = 0 @@ -211,9 +212,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph peripheral.discoverServices([meshtasticServiceCBUUID]) if meshLoggingEnabled { Logger.log("BLE Connected: \(peripheral.name ?? "Unknown")") } print("BLE Connected: \(peripheral.name ?? "Unknown")") - - // Clear the "Available Radios" list - //peripherals.removeAll() + } // Disconnect Peripheral Event diff --git a/MeshtasticClient/MeshtasticClientApp.swift b/MeshtasticClient/MeshtasticClientApp.swift index 0209ca6e..881d8097 100644 --- a/MeshtasticClient/MeshtasticClientApp.swift +++ b/MeshtasticClient/MeshtasticClientApp.swift @@ -5,12 +5,28 @@ struct MeshtasticClientApp: App { @ObservedObject private var bleManager: BLEManager = BLEManager() @ObservedObject private var userSettings: UserSettings = UserSettings() + //let persistenceController = PersistenceController.shared + //@Environment(\.scenePhase) var scenePhase var body: some Scene { WindowGroup { ContentView() .environmentObject(bleManager) .environmentObject(userSettings) + //.environment(\.managedObjectContext, persistenceController.container.viewContext) } + //.onChange(of: scenePhase) { (newScenePhase) in + // switch newScenePhase { + // case .background: + // print("Scene is in the background") + // persistenceController.save() + // case .inactive: + // print("Scene is inactive") + // case .active: + // print("Scene is active") + // @unknown default: + // print("Apple must have changed something") + // } + //} } } diff --git a/MeshtasticClient/Model/Data/PersistanceController.swift b/MeshtasticClient/Model/Data/PersistanceController.swift new file mode 100644 index 00000000..91dfbe15 --- /dev/null +++ b/MeshtasticClient/Model/Data/PersistanceController.swift @@ -0,0 +1,36 @@ +import CoreData + +struct PersistenceController { + + static let shared = PersistenceController() + + let container: NSPersistentContainer + + init() { + container = NSPersistentContainer(name: "Mesh") + container.loadPersistentStores { (description, error ) in + if let error = error { + fatalError("Error: \(error.localizedDescription)") + } + } + } + + func save(completion: @escaping (Error?) -> () = {_ in}) { + let context = container.viewContext + if context.hasChanges { + do { + try context.save() + completion(nil) + } catch { + completion(error) + } + } + } + + func delete(_ object: NSManagedObject, completion: @escaping (Error?) -> () = { _ + in }) { + let context = container.viewContext + context.delete(object) + save(completion: completion) + } +} diff --git a/MeshtasticClient/Views/Messages/Channels.swift b/MeshtasticClient/Views/Messages/Channels.swift index ca3e0b97..7f6f9775 100644 --- a/MeshtasticClient/Views/Messages/Channels.swift +++ b/MeshtasticClient/Views/Messages/Channels.swift @@ -3,9 +3,14 @@ import SwiftUI import CoreBluetooth struct Channels: View { + + @EnvironmentObject var bleManager: BLEManager + @EnvironmentObject var userSettings: UserSettings @State private var isShowingDetailView = true var body: some View { + + NavigationView { GeometryReader { bounds in diff --git a/MeshtasticClient/Views/Messages/Messages.swift b/MeshtasticClient/Views/Messages/Messages.swift index b7771fe6..82579ce7 100644 --- a/MeshtasticClient/Views/Messages/Messages.swift +++ b/MeshtasticClient/Views/Messages/Messages.swift @@ -20,7 +20,6 @@ struct Messages: View { @State private var deleteMessageId : UInt32 = 0 // Message Data and Bluetooth - // @EnvironmentObject var messageData: MessageData @EnvironmentObject var bleManager: BLEManager public var broadcastNodeId: UInt32 = 4294967295 @@ -101,7 +100,7 @@ struct Messages: View { Text("Hidden Bottom Anchor").hidden().frame(height: 0).id(bottomId) } .onReceive(timer) { input in - bleManager.messageData.load() + // bleManager.messageData.load() if messageCount < bleManager.messageData.messages.count { scrollView.scrollTo(bottomId) messageCount = bleManager.messageData.messages.count @@ -191,7 +190,6 @@ struct Messages: View { }) .onAppear { - bleManager.messageData.load() messageCount = bleManager.messageData.messages.count } }