mirror of https://github.com/oxen-io/session-ios
Remove legacy notifications adaptee
parent
227d02b8ea
commit
713b781def
@ -1,280 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import PromiseKit
|
|
||||||
|
|
||||||
struct LegacyNotificationConfig {
|
|
||||||
|
|
||||||
static var allNotificationCategories: Set<UIUserNotificationCategory> {
|
|
||||||
let categories = AppNotificationCategory.allCases.map { notificationCategory($0) }
|
|
||||||
return Set(categories)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func notificationActions(for category: AppNotificationCategory) -> [UIUserNotificationAction] {
|
|
||||||
return category.actions.map { notificationAction($0) }
|
|
||||||
}
|
|
||||||
|
|
||||||
static func notificationAction(_ action: AppNotificationAction) -> UIUserNotificationAction {
|
|
||||||
switch action {
|
|
||||||
case .markAsRead:
|
|
||||||
let mutableAction = UIMutableUserNotificationAction()
|
|
||||||
mutableAction.identifier = action.identifier
|
|
||||||
mutableAction.title = MessageStrings.markAsReadNotificationAction
|
|
||||||
mutableAction.activationMode = .background
|
|
||||||
mutableAction.isDestructive = false
|
|
||||||
mutableAction.isAuthenticationRequired = false
|
|
||||||
return mutableAction
|
|
||||||
case .reply:
|
|
||||||
let mutableAction = UIMutableUserNotificationAction()
|
|
||||||
mutableAction.identifier = action.identifier
|
|
||||||
mutableAction.title = MessageStrings.replyNotificationAction
|
|
||||||
mutableAction.activationMode = .background
|
|
||||||
mutableAction.isDestructive = false
|
|
||||||
mutableAction.isAuthenticationRequired = false
|
|
||||||
mutableAction.behavior = .textInput
|
|
||||||
return mutableAction
|
|
||||||
case .showThread:
|
|
||||||
let mutableAction = UIMutableUserNotificationAction()
|
|
||||||
mutableAction.identifier = action.identifier
|
|
||||||
mutableAction.title = CallStrings.showThreadButtonTitle
|
|
||||||
mutableAction.activationMode = .foreground
|
|
||||||
mutableAction.isDestructive = false
|
|
||||||
mutableAction.isAuthenticationRequired = true
|
|
||||||
return mutableAction
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static func action(identifier: String) -> AppNotificationAction? {
|
|
||||||
return AppNotificationAction.allCases.first { notificationAction($0).identifier == identifier }
|
|
||||||
}
|
|
||||||
|
|
||||||
static func notificationActions(category: AppNotificationCategory) -> [UIUserNotificationAction] {
|
|
||||||
return category.actions.map { notificationAction($0) }
|
|
||||||
}
|
|
||||||
|
|
||||||
static func notificationCategory(_ category: AppNotificationCategory) -> UIUserNotificationCategory {
|
|
||||||
let notificationCategory = UIMutableUserNotificationCategory()
|
|
||||||
notificationCategory.identifier = category.identifier
|
|
||||||
|
|
||||||
let actions = notificationActions(category: category)
|
|
||||||
notificationCategory.setActions(actions, for: .minimal)
|
|
||||||
notificationCategory.setActions(actions, for: .default)
|
|
||||||
|
|
||||||
return notificationCategory
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class LegacyNotificationPresenterAdaptee {
|
|
||||||
|
|
||||||
private var notifications: [String: UILocalNotification] = [:]
|
|
||||||
private var userNotificationSettingsPromise: Promise<Void>?
|
|
||||||
private var userNotificationSettingsResolver: Resolver<Void>?
|
|
||||||
|
|
||||||
// Notification registration is confirmed via AppDelegate
|
|
||||||
// Before this occurs, it is not safe to assume push token requests will be acknowledged.
|
|
||||||
//
|
|
||||||
// e.g. in the case that Background Fetch is disabled, token requests will be ignored until
|
|
||||||
// we register user notification settings.
|
|
||||||
@objc
|
|
||||||
public func didRegisterUserNotificationSettings() {
|
|
||||||
AssertIsOnMainThread()
|
|
||||||
guard let userNotificationSettingsResolver = self.userNotificationSettingsResolver else {
|
|
||||||
owsFailDebug("promise completion in \(#function) unexpectedly nil")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
userNotificationSettingsResolver.fulfill(())
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
extension LegacyNotificationPresenterAdaptee: NotificationPresenterAdaptee {
|
|
||||||
|
|
||||||
func registerNotificationSettings() -> Promise<Void> {
|
|
||||||
AssertIsOnMainThread()
|
|
||||||
Logger.debug("")
|
|
||||||
|
|
||||||
guard self.userNotificationSettingsPromise == nil else {
|
|
||||||
let promise = self.userNotificationSettingsPromise!
|
|
||||||
Logger.info("already registered user notification settings")
|
|
||||||
return promise
|
|
||||||
}
|
|
||||||
|
|
||||||
let (promise, resolver) = Promise<Void>.pending()
|
|
||||||
self.userNotificationSettingsPromise = promise
|
|
||||||
self.userNotificationSettingsResolver = resolver
|
|
||||||
|
|
||||||
let settings = UIUserNotificationSettings(types: [.alert, .sound, .badge],
|
|
||||||
categories: LegacyNotificationConfig.allNotificationCategories)
|
|
||||||
UIApplication.shared.registerUserNotificationSettings(settings)
|
|
||||||
|
|
||||||
return promise
|
|
||||||
}
|
|
||||||
|
|
||||||
func notify(category: AppNotificationCategory, title: String?, body: String, userInfo: [AnyHashable: Any], sound: OWSSound?) {
|
|
||||||
AssertIsOnMainThread()
|
|
||||||
notify(category: category, title: title, body: body, userInfo: userInfo, sound: sound, replacingIdentifier: nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func notify(category: AppNotificationCategory, title: String?, body: String, userInfo: [AnyHashable: Any], sound: OWSSound?, replacingIdentifier: String?) {
|
|
||||||
AssertIsOnMainThread()
|
|
||||||
guard UIApplication.shared.applicationState != .active else {
|
|
||||||
if let sound = sound {
|
|
||||||
let soundId = OWSSounds.systemSoundID(for: sound, quiet: true)
|
|
||||||
|
|
||||||
// Vibrate, respect silent switch, respect "Alert" volume, not media volume.
|
|
||||||
AudioServicesPlayAlertSound(soundId)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let alertBody: String
|
|
||||||
if let title = title {
|
|
||||||
// TODO - Make this a format string for better l10n
|
|
||||||
alertBody = title.rtlSafeAppend(":").rtlSafeAppend(" ").rtlSafeAppend(body)
|
|
||||||
} else {
|
|
||||||
alertBody = body
|
|
||||||
}
|
|
||||||
|
|
||||||
let notification = UILocalNotification()
|
|
||||||
notification.category = category.identifier
|
|
||||||
notification.alertBody = alertBody.filterForDisplay
|
|
||||||
notification.userInfo = userInfo
|
|
||||||
notification.soundName = sound?.filename
|
|
||||||
|
|
||||||
var notificationIdentifier: String = UUID().uuidString
|
|
||||||
if let replacingIdentifier = replacingIdentifier {
|
|
||||||
notificationIdentifier = replacingIdentifier
|
|
||||||
Logger.debug("replacing notification with identifier: \(notificationIdentifier)")
|
|
||||||
cancelNotification(identifier: notificationIdentifier)
|
|
||||||
}
|
|
||||||
|
|
||||||
let checkForCancel = category == .incomingMessage
|
|
||||||
if checkForCancel {
|
|
||||||
assert(userInfo[AppNotificationUserInfoKey.threadId] != nil)
|
|
||||||
notification.fireDate = Date(timeIntervalSinceNow: kNotificationDelayForRemoteRead)
|
|
||||||
notification.timeZone = NSTimeZone.local
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.debug("presenting notification with identifier: \(notificationIdentifier)")
|
|
||||||
UIApplication.shared.scheduleLocalNotification(notification)
|
|
||||||
notifications[notificationIdentifier] = notification
|
|
||||||
}
|
|
||||||
|
|
||||||
func cancelNotification(_ notification: UILocalNotification) {
|
|
||||||
AssertIsOnMainThread()
|
|
||||||
UIApplication.shared.cancelLocalNotification(notification)
|
|
||||||
}
|
|
||||||
|
|
||||||
func cancelNotification(identifier: String) {
|
|
||||||
AssertIsOnMainThread()
|
|
||||||
guard let notification = notifications.removeValue(forKey: identifier) else {
|
|
||||||
Logger.debug("no notification to cancel with identifier: \(identifier)")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cancelNotification(notification)
|
|
||||||
}
|
|
||||||
|
|
||||||
func cancelNotifications(threadId: String) {
|
|
||||||
AssertIsOnMainThread()
|
|
||||||
for notification in notifications.values {
|
|
||||||
guard let notificationThreadId = notification.userInfo?[AppNotificationUserInfoKey.threadId] as? String else {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
guard notificationThreadId == threadId else {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
cancelNotification(notification)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func clearAllNotifications() {
|
|
||||||
AssertIsOnMainThread()
|
|
||||||
for (_, notification) in notifications {
|
|
||||||
cancelNotification(notification)
|
|
||||||
}
|
|
||||||
type(of: self).clearExistingNotifications()
|
|
||||||
}
|
|
||||||
|
|
||||||
public class func clearExistingNotifications() {
|
|
||||||
// This will cancel all "scheduled" local notifications that haven't
|
|
||||||
// been presented yet.
|
|
||||||
UIApplication.shared.cancelAllLocalNotifications()
|
|
||||||
// To clear all already presented local notifications, we need to
|
|
||||||
// set the app badge number to zero after setting it to a non-zero value.
|
|
||||||
UIApplication.shared.applicationIconBadgeNumber = 1
|
|
||||||
UIApplication.shared.applicationIconBadgeNumber = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc(OWSLegacyNotificationActionHandler)
|
|
||||||
public class LegacyNotificationActionHandler: NSObject {
|
|
||||||
|
|
||||||
@objc
|
|
||||||
public static let kDefaultActionIdentifier = "LegacyNotificationActionHandler.kDefaultActionIdentifier"
|
|
||||||
|
|
||||||
var actionHandler: NotificationActionHandler {
|
|
||||||
return NotificationActionHandler.shared
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc
|
|
||||||
func handleNotificationResponse(actionIdentifier: String,
|
|
||||||
notification: UILocalNotification,
|
|
||||||
responseInfo: [AnyHashable: Any],
|
|
||||||
completionHandler: @escaping () -> Void) {
|
|
||||||
firstly {
|
|
||||||
try handleNotificationResponse(actionIdentifier: actionIdentifier, notification: notification, responseInfo: responseInfo)
|
|
||||||
}.done {
|
|
||||||
completionHandler()
|
|
||||||
}.catch { error in
|
|
||||||
completionHandler()
|
|
||||||
owsFailDebug("error: \(error)")
|
|
||||||
Logger.error("error: \(error)")
|
|
||||||
}.retainUntilComplete()
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleNotificationResponse(actionIdentifier: String,
|
|
||||||
notification: UILocalNotification,
|
|
||||||
responseInfo: [AnyHashable: Any]) throws -> Promise<Void> {
|
|
||||||
assert(AppReadiness.isAppReady())
|
|
||||||
|
|
||||||
let userInfo = notification.userInfo ?? [:]
|
|
||||||
|
|
||||||
switch actionIdentifier {
|
|
||||||
case type(of: self).kDefaultActionIdentifier:
|
|
||||||
Logger.debug("default action")
|
|
||||||
return try actionHandler.showThread(userInfo: userInfo)
|
|
||||||
default:
|
|
||||||
// proceed
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let action = LegacyNotificationConfig.action(identifier: actionIdentifier) else {
|
|
||||||
throw NotificationError.failDebug("unable to find action for actionIdentifier: \(actionIdentifier)")
|
|
||||||
}
|
|
||||||
|
|
||||||
switch action {
|
|
||||||
case .markAsRead:
|
|
||||||
return try actionHandler.markAsRead(userInfo: userInfo)
|
|
||||||
case .reply:
|
|
||||||
guard let replyText = responseInfo[UIUserNotificationActionResponseTypedTextKey] as? String else {
|
|
||||||
throw NotificationError.failDebug("replyText was unexpectedly nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
return try actionHandler.reply(userInfo: userInfo, replyText: replyText)
|
|
||||||
case .showThread:
|
|
||||||
return try actionHandler.showThread(userInfo: userInfo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension OWSSound {
|
|
||||||
var filename: String? {
|
|
||||||
return OWSSounds.filename(for: self, quiet: false)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue