diff --git a/Meshtastic/Helpers/MeshPackets.swift b/Meshtastic/Helpers/MeshPackets.swift index aba02576..dac9aca8 100644 --- a/Meshtastic/Helpers/MeshPackets.swift +++ b/Meshtastic/Helpers/MeshPackets.swift @@ -1308,7 +1308,10 @@ func textMessageAppPacket(packet: MeshPacket, connectedNode: Int64, context: NSM ] manager.schedule() MeshLogger.log("💬 iOS Notification Scheduled for text message from \(newMessage.fromUser?.longName ?? "Unknown")") - } else if newMessage.fromUser != nil && newMessage.toUser == nil { + } else if newMessage.fromUser != nil && newMessage.toUser == nil { + + + // Create an iOS Notification for the received private channel message and schedule it immediately let manager = LocalNotificationManager() manager.notifications = [ diff --git a/Meshtastic/Persistence/ChannelEntityExtension.swift b/Meshtastic/Persistence/ChannelEntityExtension.swift index 4a3bde42..de57a556 100644 --- a/Meshtastic/Persistence/ChannelEntityExtension.swift +++ b/Meshtastic/Persistence/ChannelEntityExtension.swift @@ -10,6 +10,6 @@ extension ChannelEntity { var allPrivateMessages: [MessageEntity] { - self.value(forKey: "allPrivateMessages") as! [MessageEntity] + self.value(forKey: "allPrivateMessages") as? [MessageEntity] ?? [MessageEntity]() } } diff --git a/Meshtastic/Persistence/UpdateCoreData.swift b/Meshtastic/Persistence/UpdateCoreData.swift index 47e9e982..a189e58e 100644 --- a/Meshtastic/Persistence/UpdateCoreData.swift +++ b/Meshtastic/Persistence/UpdateCoreData.swift @@ -61,32 +61,35 @@ public func clearTelemetry(destNum: Int64, metricsType: Int32, context: NSManage } public func deleteChannelMessages(channelIndex: Int32, context: NSManagedObjectContext) { - - let fetchChannelMessagesRequest: NSFetchRequest = NSFetchRequest.init(entityName: "MessageEntity") - fetchChannelMessagesRequest.predicate = NSPredicate(format: "channel == %lld", Int32(channelIndex)) + let fetchChannelMessagesRequest = NSFetchRequest(entityName: "MessageEntity") + fetchChannelMessagesRequest.predicate = NSPredicate(format: "channel == %i AND toUser == nil AND admin == false", Int32(channelIndex)) + fetchChannelMessagesRequest.includesPropertyValues = false do { - let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchChannelMessagesRequest) - try context.executeAndMergeChanges(using: deleteRequest) + let objects = try context.fetch(fetchChannelMessagesRequest) as! [NSManagedObject] + for object in objects { + context.delete(object) + } try context.save() - + context.refreshAllObjects() } catch let error as NSError { print("Error: \(error.localizedDescription)") - abort() } } public func deleteUserMessages(user: UserEntity, context: NSManagedObjectContext) { - let fetchUserMessagesRequest: NSFetchRequest = NSFetchRequest.init(entityName: "MessageEntity") + let fetchUserMessagesRequest = NSFetchRequest(entityName: "MessageEntity") fetchUserMessagesRequest.predicate = NSPredicate(format: "((toUser.num == %lld) OR (fromUser.num == %lld)) AND toUser != nil AND fromUser != nil AND admin == false", Int64(user.num), Int64(user.num)) + fetchUserMessagesRequest.includesPropertyValues = false do { - let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchUserMessagesRequest) - try context.executeAndMergeChanges(using: deleteRequest) + let objects = try context.fetch(fetchUserMessagesRequest) as! [NSManagedObject] + for object in objects { + context.delete(object) + } try context.save() - + context.refresh(user, mergeChanges: true) } catch let error as NSError { print("Error: \(error.localizedDescription)") - abort() } } diff --git a/Meshtastic/Persistence/UserEntityExtension.swift b/Meshtastic/Persistence/UserEntityExtension.swift index 698dbf6d..6b2c2c1a 100644 --- a/Meshtastic/Persistence/UserEntityExtension.swift +++ b/Meshtastic/Persistence/UserEntityExtension.swift @@ -11,11 +11,11 @@ extension UserEntity { var messageList: [MessageEntity] { - self.value(forKey: "allMessages") as! [MessageEntity] + self.value(forKey: "allMessages") as? [MessageEntity] ?? [MessageEntity]() } var adminMessageList: [MessageEntity] { - self.value(forKey: "adminMessages") as! [MessageEntity] + self.value(forKey: "adminMessages") as? [MessageEntity] ?? [MessageEntity]() } } diff --git a/Meshtastic/Views/Messages/Contacts.swift b/Meshtastic/Views/Messages/Contacts.swift index 844be0c0..d22b019e 100644 --- a/Meshtastic/Views/Messages/Contacts.swift +++ b/Meshtastic/Views/Messages/Contacts.swift @@ -32,7 +32,7 @@ struct Contacts: View { // Display Contacts for the rest of the non admin channels if node != nil && node!.myInfo != nil && node!.myInfo!.channels != nil { ForEach(node!.myInfo!.channels!.array as! [ChannelEntity], id: \.self) { (channel: ChannelEntity) in - if channel.name?.lowercased() ?? "" != "admin" && channel.name?.lowercased() ?? "" != "gpio" { + if channel.name?.lowercased() ?? "" != "admin" && channel.name?.lowercased() ?? "" != "gpio" && channel.name?.lowercased() ?? "" != "serial" { VStack { NavigationLink(destination: ChannelMessageList(channel: channel)) { @@ -84,21 +84,23 @@ struct Contacts: View { } .frame(maxWidth: .infinity, maxHeight: 80, alignment: .leading) .contextMenu { - Button { - channel.mute = !channel.mute - - do { - try context.save() - // Would rather not do this but the merge changes on - // A single object is only working on mac GVH - context.refreshAllObjects() - //context.refresh(channel, mergeChanges: true) - } catch { - context.rollback() - print("💥 Save Channel Mute Error") + if false { // Hide mute channel menu item until I can check it in notifications + Button { + channel.mute = !channel.mute + + do { + try context.save() + // Would rather not do this but the merge changes on + // A single object is only working on mac GVH + context.refreshAllObjects() + //context.refresh(channel, mergeChanges: true) + } catch { + context.rollback() + print("💥 Save Channel Mute Error") + } + } label: { + Label(channel.mute ? "Show Alerts" : "Hide Alerts", systemImage: channel.mute ? "bell" : "bell.slash") } - } label: { - Label(channel.mute ? "Show Alerts" : "Hide Alerts", systemImage: channel.mute ? "bell" : "bell.slash") } if channel.allPrivateMessages.count > 0 { Button(role: .destructive) { @@ -116,6 +118,7 @@ struct Contacts: View { Button(role: .destructive) { deleteChannelMessages(channelIndex: channel.index, context: context) + context.refreshAllObjects() } label: { Text("Delete") } @@ -201,6 +204,7 @@ struct Contacts: View { Button(role: .destructive) { deleteUserMessages(user: user, context: context) + } label: { Text("Delete") }