From dd8e4b85ecccfa16fc966677b1eeca1dcdb7f245 Mon Sep 17 00:00:00 2001 From: Pavel Anokhov Date: Fri, 9 Mar 2018 23:49:11 +0300 Subject: [PATCH] app icon badge fixed repeating notifications --- Adamant/AppDelegate.swift | 34 +++++++++++++++++-- .../DataProviders/ChatsProvider.swift | 2 ++ .../NotificationsService.swift | 29 ++++++++++++---- .../Services/AdamantNotificationService.swift | 16 ++++++--- 4 files changed, 68 insertions(+), 13 deletions(-) diff --git a/Adamant/AppDelegate.swift b/Adamant/AppDelegate.swift index 32bbd7eef..33d13a689 100644 --- a/Adamant/AppDelegate.swift +++ b/Adamant/AppDelegate.swift @@ -15,6 +15,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? var repeater: RepeaterService! + + weak var accountService: AccountService? + weak var notificationService: NotificationsService? // MARK: - Lifecycle @@ -28,6 +31,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate { container.registerAdamantChatsStory() container.registerAdamantSettingsStory() + accountService = container.resolve(AccountService.self) + notificationService = container.resolve(NotificationsService.self) + // MARK: 2. Prepare UI self.window = UIWindow(frame: UIScreen.main.bounds) @@ -109,6 +115,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func applicationDidBecomeActive(_ application: UIApplication) { repeater.resumeAll() + + if accountService?.account != nil { + notificationService?.removeAllDeliveredNotifications() + } } // MARK: Background fetch @@ -131,18 +141,38 @@ class AppDelegate: UIResponder, UIApplicationDelegate { return } - let lastHeight: Int64? + var lastHeight: Int64? if let raw = securedStore.get(StoreKey.chatProvider.receivedLastHeight) { lastHeight = Int64(raw) } else { lastHeight = nil } + var notifiedCount = 0 + if let raw = securedStore.get(StoreKey.chatProvider.notifiedLastHeight), let notifiedHeight = Int64(raw), let h = lastHeight { + if h < notifiedHeight { + lastHeight = notifiedHeight + + if let raw = securedStore.get(StoreKey.chatProvider.notifiedMessagesCount), let count = Int(raw) { + notifiedCount = count + } + } + } + + apiService.getChatTransactions(address: address, height: lastHeight, offset: nil) { result in switch result { case .success(let transactions): if transactions.count > 0 { - notificationsService.showNotification(title: String.adamantLocalized.notifications.newMessageTitle, body: String.localizedStringWithFormat(String.adamantLocalized.notifications.newMessageBody, transactions.count), type: .newMessages) + let total = transactions.count + notifiedCount + securedStore.set(String(total), for: StoreKey.chatProvider.notifiedMessagesCount) + + if let newLastHeight = transactions.map({$0.height}).sorted().last { + securedStore.set(String(newLastHeight), for: StoreKey.chatProvider.notifiedLastHeight) + } + + + notificationsService.showNotification(title: String.adamantLocalized.notifications.newMessageTitle, body: String.localizedStringWithFormat(String.adamantLocalized.notifications.newMessageBody, total), type: .newMessages(count: total)) completionHandler(.newData) } else { completionHandler(.noData) diff --git a/Adamant/ServiceProtocols/DataProviders/ChatsProvider.swift b/Adamant/ServiceProtocols/DataProviders/ChatsProvider.swift index 42ce03cc7..514f0991e 100644 --- a/Adamant/ServiceProtocols/DataProviders/ChatsProvider.swift +++ b/Adamant/ServiceProtocols/DataProviders/ChatsProvider.swift @@ -72,6 +72,8 @@ extension StoreKey { static let address = "chatProvider.address" static let receivedLastHeight = "chatProvider.receivedLastHeight" static let readedLastHeight = "chatProvider.readedLastHeight" + static let notifiedLastHeight = "chatProvider.notifiedLastHeight" + static let notifiedMessagesCount = "chatProvider.notifiedCount" } } diff --git a/Adamant/ServiceProtocols/NotificationsService.swift b/Adamant/ServiceProtocols/NotificationsService.swift index 5d0bf4008..ccac67091 100644 --- a/Adamant/ServiceProtocols/NotificationsService.swift +++ b/Adamant/ServiceProtocols/NotificationsService.swift @@ -33,9 +33,9 @@ extension StoreKey { /// - transaction: token transaction /// - custom: other enum AdamantNotificationType { - case newMessages - case newTransactions - case custom(identifier: String) + case newMessages(count: Int) + case newTransactions(count: Int) + case custom(identifier: String, badge: NSNumber?) var identifier: String { switch self { @@ -45,10 +45,23 @@ enum AdamantNotificationType { case .newTransactions: return "newTransactions" - case .custom(let identifier): + case .custom(let identifier, _): return identifier } } + + var badge: NSNumber? { + switch self { + case .newMessages(let count): + return NSNumber(integerLiteral: count) + + case .newTransactions(let count): + return NSNumber(integerLiteral: count) + + case .custom(_, let badge): + return badge + } + } } // MARK: - Notifications @@ -64,13 +77,15 @@ enum NotificationsServiceResult { case denied(error: Error?) } -protocol NotificationsService { +protocol NotificationsService: class { var notificationsEnabled: Bool { get } func setNotificationsEnabled(_ enabled: Bool, completion: @escaping (NotificationsServiceResult) -> Void) func showNotification(title: String, body: String, type: AdamantNotificationType) - func removeAllPendingNotificationRequests(ofType type: AdamantNotificationType) - func removeAllDeliveredNotifications(ofType type: AdamantNotificationType) + func removeAllPendingNotificationRequests() + func removeAllDeliveredNotifications() +// func removeAllPendingNotificationRequests(ofType type: AdamantNotificationType) +// func removeAllDeliveredNotifications(ofType type: AdamantNotificationType) } diff --git a/Adamant/Services/AdamantNotificationService.swift b/Adamant/Services/AdamantNotificationService.swift index 20acbfdab..5289f0c0d 100644 --- a/Adamant/Services/AdamantNotificationService.swift +++ b/Adamant/Services/AdamantNotificationService.swift @@ -7,6 +7,7 @@ // import Foundation +import UIKit import UserNotifications class AdamantNotificationsService: NotificationsService { @@ -43,6 +44,11 @@ class AdamantNotificationsService: NotificationsService { // MARK: Lifecycle init() { + NotificationCenter.default.addObserver(forName: Notification.Name.adamantUserLoggedIn, object: nil, queue: OperationQueue.main) { _ in + UNUserNotificationCenter.current().removeAllDeliveredNotifications() + UIApplication.shared.applicationIconBadgeNumber = 0 + } + NotificationCenter.default.addObserver(forName: Notification.Name.adamantUserLoggedOut, object: nil, queue: nil) { [weak self] _ in self?.notificationsEnabled = false self?.securedStore.remove(StoreKey.notificationsService.notificationsEnabled) @@ -99,6 +105,7 @@ class AdamantNotificationsService: NotificationsService { content.title = title content.body = body content.sound = UNNotificationSound.default() + content.badge = type.badge let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false) let request = UNNotificationRequest(identifier: type.identifier, content: content, trigger: trigger) @@ -110,11 +117,12 @@ class AdamantNotificationsService: NotificationsService { } } - func removeAllPendingNotificationRequests(ofType type: AdamantNotificationType) { - UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: [type.identifier]) + func removeAllPendingNotificationRequests() { + UNUserNotificationCenter.current().removeAllPendingNotificationRequests() } - func removeAllDeliveredNotifications(ofType type: AdamantNotificationType) { - UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: [type.identifier]) + func removeAllDeliveredNotifications() { + UNUserNotificationCenter.current().removeAllDeliveredNotifications() + UIApplication.shared.applicationIconBadgeNumber = 0 } }