Просмотр исходного кода

Merge pull request #1124 from deltachat/multiple_notifications

multiple notifications
cyBerta 4 лет назад
Родитель
Сommit
382874e1ec

+ 3 - 8
deltachat-ios/AppDelegate.swift

@@ -426,20 +426,15 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
     // MARK: - Handle notification banners
 
     // This method will be called if an incoming message was received while the app was in forground.
-    // On iOS 14+ we show a non-intrusive notification in the notification center, if the notification doesn't belong to a currently opened chat.
-    // On pre iOS 14 this feature isn't available so we're just triggering to show the badge at the launcher icon. This will only have an effect for unread messages > 0
+    // We don't show foreground notifications in the notification center because they don't get grouped properly
     func userNotificationCenter(_: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
         logger.info("forground notification")
-        if #available(iOS 14.0, *) {
-            completionHandler([.list, .badge])
-        } else {
-            completionHandler([.badge])
-        }
+        completionHandler([.badge])
     }
 
     // this method will be called if the user tapped on a notification
     func userNotificationCenter(_: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
-        if response.notification.request.identifier == Constants.notificationIdentifier {
+        if !response.notification.request.identifier.containsExact(subSequence: Constants.notificationIdentifier).isEmpty {
             logger.info("handling notifications")
             let userInfo = response.notification.request.content.userInfo
              if let chatId = userInfo["chat_id"] as? Int,

+ 2 - 0
deltachat-ios/Controller/SettingsController.swift

@@ -323,6 +323,8 @@ internal final class SettingsViewController: UITableViewController, ProgressAler
             if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
                 appDelegate.registerForNotifications()
             }
+        } else {
+            NotificationManager.removeAllNotifications()
         }
         UserDefaults.standard.synchronize()
         NotificationManager.updateApplicationIconBadge(reset: !sender.isOn)

+ 52 - 13
deltachat-ios/Helper/NotificationManager.swift

@@ -8,6 +8,10 @@ public class NotificationManager {
     var incomingMsgObserver: Any?
     var msgsNoticedObserver: Any?
 
+    init() {
+        initIncomingMsgsObserver()
+        initMsgsNoticedObserver()
+    }
 
     public static func updateApplicationIconBadge(reset: Bool) {
         var unreadMessages = 0
@@ -20,9 +24,10 @@ public class NotificationManager {
         }
     }
 
-    init() {
-        initIncomingMsgsObserver()
-        initMsgsNoticedObserver()
+    public static func removeAllNotifications() {
+        let nc = UNUserNotificationCenter.current()
+        nc.removeAllDeliveredNotifications()
+        nc.removeAllPendingNotificationRequests()
     }
 
     private func initIncomingMsgsObserver() {
@@ -35,11 +40,6 @@ public class NotificationManager {
                    let chatId = ui["chat_id"] as? Int,
                    let messageId = ui["message_id"] as? Int,
                    !UserDefaults.standard.bool(forKey: "notifications_disabled") {
-                    
-                    if let lastChatId = AppStateRestorer.shared.restoreLastActiveChatId(),
-                       lastChatId == chatId {
-                        return
-                    }
 
                     NotificationManager.updateApplicationIconBadge(reset: false)
 
@@ -73,10 +73,15 @@ public class NotificationManager {
                         }
                     }
                     let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 0.1, repeats: false)
-
-                    let request = UNNotificationRequest(identifier: Constants.notificationIdentifier, content: content, trigger: trigger)
+                    let accountEmail = DcContact(id: Int(DC_CONTACT_ID_SELF)).email
+                    if #available(iOS 12.0, *) {
+                        content.threadIdentifier = "\(accountEmail)\(chatId)"
+                    }
+                    let request = UNNotificationRequest(identifier: "\(Constants.notificationIdentifier).\(accountEmail).\(chatId).\(msg.messageId)",
+                                                        content: content,
+                                                        trigger: trigger)
                     UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
-                    DcContext.shared.logger?.info("notifications: added \(content.title) \(content.body) \(content.userInfo)")
+                    logger.info("notifications: added \(content.title) \(content.body) \(content.userInfo)")
                 }
             }
         }
@@ -86,14 +91,48 @@ public class NotificationManager {
         msgsNoticedObserver =  NotificationCenter.default.addObserver(
             forName: dcMsgsNoticed,
             object: nil, queue: OperationQueue.main
-        ) { _ in
-            DispatchQueue.global(qos: .background).async {
+        ) { notification in
+            DispatchQueue.global(qos: .background).async { [weak self] in
                 if !UserDefaults.standard.bool(forKey: "notifications_disabled") {
                     NotificationManager.updateApplicationIconBadge(reset: false)
+                    if let ui = notification.userInfo,
+                       let chatId = ui["chat_id"] as? Int {
+                        self?.removePendingNotificationsFor(chatId: chatId)
+                        self?.removeDeliveredNotificationsFor(chatId: chatId)
+                    }
+                }
+            }
+        }
+    }
+
+    private func removeDeliveredNotificationsFor(chatId: Int) {
+        var identifiers = [String]()
+        let nc = UNUserNotificationCenter.current()
+        nc.getDeliveredNotifications { notifications in
+            let accountEmail = DcContact(id: Int(DC_CONTACT_ID_SELF)).email
+            for notification in notifications {
+                if !notification.request.identifier.containsExact(subSequence: "\(Constants.notificationIdentifier).\(accountEmail).\(chatId)").isEmpty {
+                    identifiers.append(notification.request.identifier)
                 }
             }
+            nc.removeDeliveredNotifications(withIdentifiers: identifiers)
         }
     }
+
+    private func removePendingNotificationsFor(chatId: Int) {
+        var identifiers = [String]()
+        let nc = UNUserNotificationCenter.current()
+        nc.getPendingNotificationRequests { notificationRequests in
+            let accountEmail = DcContact(id: Int(DC_CONTACT_ID_SELF)).email
+            for request in notificationRequests {
+                if !request.identifier.containsExact(subSequence: "\(Constants.notificationIdentifier).\(accountEmail).\(chatId)").isEmpty {
+                    identifiers.append(request.identifier)
+                }
+            }
+            nc.removePendingNotificationRequests(withIdentifiers: identifiers)
+        }
+    }
+
     
     deinit {
         NotificationCenter.default.removeObserver(self)