diff --git a/Meshtastic/Helpers/LocalNotificationManager.swift b/Meshtastic/Helpers/LocalNotificationManager.swift index 47f64bce..064021e1 100644 --- a/Meshtastic/Helpers/LocalNotificationManager.swift +++ b/Meshtastic/Helpers/LocalNotificationManager.swift @@ -4,36 +4,36 @@ import OSLog class LocalNotificationManager { - var notifications = [Notification]() + var notifications = [Notification]() let thumbsUpAction = UNNotificationAction(identifier: "messageNotification.thumbsUpAction", title: "👍 \(Tapbacks.thumbsUp.description)", options: []) let thumbsDownAction = UNNotificationAction(identifier: "messageNotification.thumbsDownAction", title: "👎 \(Tapbacks.thumbsDown.description)", options: []) let replyInputAction = UNTextInputNotificationAction(identifier: "messageNotification.replyInputAction", title: "reply".localized, options: []) - // Step 1 Request Permissions for notifications - private func requestAuthorization() { - UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in + // Step 1 Request Permissions for notifications + private func requestAuthorization() { + UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in - if granted == true && error == nil { + if granted == true && error == nil { self.scheduleNotifications() - } - } - } + } + } + } func schedule() { - UNUserNotificationCenter.current().getNotificationSettings { settings in - switch settings.authorizationStatus { - case .notDetermined: + UNUserNotificationCenter.current().getNotificationSettings { settings in + switch settings.authorizationStatus { + case .notDetermined: self.requestAuthorization() - case .authorized, .provisional: - self.scheduleNotifications() - default: - break // Do nothing - } - } - } + case .authorized, .provisional: + self.scheduleNotifications() + default: + break // Do nothing + } + } + } - // This function iterates over the Notification objects in the notifications array and schedules them for delivery in the future - private func scheduleNotifications() { + // This function iterates over the Notification objects in the notifications array and schedules them for delivery in the future + private func scheduleNotifications() { let messageNotificationCategory = UNNotificationCategory( identifier: "messageNotificationCategory", actions: [thumbsUpAction, thumbsDownAction, replyInputAction], @@ -43,13 +43,15 @@ class LocalNotificationManager { UNUserNotificationCenter.current().setNotificationCategories([messageNotificationCategory]) - for notification in notifications { - let content = UNMutableNotificationContent() - content.subtitle = notification.subtitle - content.title = notification.title - content.body = notification.content - content.sound = .default - content.interruptionLevel = .timeSensitive + for notification in notifications { + let content = UNMutableNotificationContent() + if let subtitle = notification.subtitle { + content.subtitle = subtitle + } + content.title = notification.title + content.body = notification.content + content.sound = .default + content.interruptionLevel = .timeSensitive if notification.target != nil { content.userInfo["target"] = notification.target @@ -68,34 +70,33 @@ class LocalNotificationManager { content.userInfo["userNum"] = notification.userNum } - let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false) - let request = UNNotificationRequest(identifier: notification.id, content: content, trigger: trigger) + let request = UNNotificationRequest(identifier: notification.id, content: content, trigger: nil) - UNUserNotificationCenter.current().add(request) { error in + UNUserNotificationCenter.current().add(request) { error in if let error { Logger.services.error("Error Scheduling Notification: \(error.localizedDescription)") } - } - } - } + } + } + } - // Check and debug what local notifications have been scheduled - func listScheduledNotifications() { - UNUserNotificationCenter.current().getPendingNotificationRequests { notifications in + // Check and debug what local notifications have been scheduled + func listScheduledNotifications() { + UNUserNotificationCenter.current().getPendingNotificationRequests { notifications in - for notification in notifications { + for notification in notifications { Logger.services.debug("\(notification, privacy: .public)") - } - } - } + } + } + } } struct Notification { - var id: String - var title: String - var subtitle: String - var content: String + var id: String + var title: String + var subtitle: String? + var content: String var target: String? var path: String? var messageId: Int64? diff --git a/Meshtastic/Helpers/MeshPackets.swift b/Meshtastic/Helpers/MeshPackets.swift index a5cfa7ba..4247f326 100644 --- a/Meshtastic/Helpers/MeshPackets.swift +++ b/Meshtastic/Helpers/MeshPackets.swift @@ -948,44 +948,61 @@ func textMessageAppPacket( manager.schedule() Logger.services.debug("iOS Notification Scheduled for text message from \(newMessage.fromUser?.longName ?? "unknown".localized)") } - } else if newMessage.fromUser != nil && newMessage.toUser == nil { + } else if newMessage.toUser == nil { let fetchMyInfoRequest = MyInfoEntity.fetchRequest() - fetchMyInfoRequest.predicate = NSPredicate(format: "myNodeNum == %lld", Int64(connectedNode)) - - do { - let fetchedMyInfo = try context.fetch(fetchMyInfoRequest) - if !fetchedMyInfo.isEmpty { - appState.unreadChannelMessages = fetchedMyInfo[0].unreadMessages - - for channel in (fetchedMyInfo[0].channels?.array ?? []) as? [ChannelEntity] ?? [] { - if channel.index == newMessage.channel { - context.refresh(channel, mergeChanges: true) - } - if channel.index == newMessage.channel && !channel.mute && UserDefaults.channelMessageNotifications { - // Create an iOS Notification for the received private channel message and schedule it immediately - let manager = LocalNotificationManager() - manager.notifications = [ - Notification( - id: ("notification.id.\(newMessage.messageId)"), - title: "\(newMessage.fromUser?.longName ?? "unknown".localized)", - subtitle: "AKA \(newMessage.fromUser?.shortName ?? "?")", - content: messageText!, - target: "messages", - path: "meshtastic:///messages?channelId=\(newMessage.channel)&messageId=\(newMessage.messageId)", - messageId: newMessage.messageId, - channel: newMessage.channel, - userNum: Int64(newMessage.fromUser?.userId ?? "0") - ) - ] - manager.schedule() - Logger.services.debug("iOS Notification Scheduled for text message from \(newMessage.fromUser?.longName ?? "unknown".localized)") - } - } - } - } catch { - // Handle error - } - } + fetchMyInfoRequest.predicate = NSPredicate(format: "myNodeNum == %lld", Int64(connectedNode)) + + do { + let fetchedMyInfo = try context.fetch(fetchMyInfoRequest) + if !fetchedMyInfo.isEmpty { + appState.unreadChannelMessages = fetchedMyInfo[0].unreadMessages + + for channel in (fetchedMyInfo[0].channels?.array ?? []) as? [ChannelEntity] ?? [] { + if channel.index == newMessage.channel { + context.refresh(channel, mergeChanges: true) + } + if channel.index == newMessage.channel && !channel.mute && UserDefaults.channelMessageNotifications { + // Create an iOS Notification for the received private channel message and schedule it immediately + let manager = LocalNotificationManager() + + if newMessage.fromUser != nil { + manager.notifications = [ + Notification( + id: ("notification.id.\(newMessage.messageId)"), + title: "\(newMessage.fromUser?.longName ?? "unknown".localized)", + subtitle: "AKA \(newMessage.fromUser?.shortName ?? "?")", + content: messageText!, + target: "messages", + path: "meshtastic:///messages?channelId=\(newMessage.channel)&messageId=\(newMessage.messageId)", + messageId: newMessage.messageId, + channel: newMessage.channel, + userNum: Int64(newMessage.fromUser?.userId ?? "0") + ) + ] + } else { + manager.notifications = [ + Notification( + id: ("notification.id.\(newMessage.messageId)"), + title: "unknown".localized, + content: messageText!, + target: "messages", + path: "meshtastic:///messages?channelId=\(newMessage.channel)&messageId=\(newMessage.messageId)", + messageId: newMessage.messageId, + channel: newMessage.channel, + userNum: 0 + ) + ] + } + + manager.schedule() + Logger.services.debug("iOS Notification Scheduled for text message from \(newMessage.fromUser?.longName ?? "unknown".localized)") + } + } + } + } catch { + // Handle error + } + } } } catch { context.rollback() @@ -998,6 +1015,7 @@ func textMessageAppPacket( } } + func waypointPacket (packet: MeshPacket, context: NSManagedObjectContext) { let logString = String.localizedStringWithFormat("mesh.log.waypoint.received %@".localized, String(packet.from))