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
}
}