session-ios/Signal/src/UserInterface/Notifications/UserNotificationsAdaptee.swift

163 lines
6.7 KiB
Swift
Raw Normal View History

2017-02-02 23:42:06 +01:00
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
/**
* TODO This is currently unused code. I started implenting new notifications as UserNotifications rather than the deprecated
* LocalNotifications before I realized we can't mix and match. Registering notifications for one clobbers the other.
* So, for now iOS10 continues to use LocalNotifications until we can port all the NotificationsManager stuff here.
*/
import Foundation
import UserNotifications
@available(iOS 10.0, *)
struct AppNotifications {
enum Category {
case missedCall,
rejectedCallFromUnseenIdentity
// Don't forget to update this! We use it to register categories.
static let allValues = [ missedCall, rejectedCallFromUnseenIdentity ]
}
enum Action {
case callBack,
showThread,
confirmIdentityAndCallBack
}
static var allCategories: Set<UNNotificationCategory> {
let categories = Category.allValues.map { category($0) }
return Set(categories)
}
static func category(_ type: Category) -> UNNotificationCategory {
switch type {
case .missedCall:
return UNNotificationCategory(identifier: "org.whispersystems.signal.AppNotifications.Category.missedCall",
actions: [ action(.callBack) ],
intentIdentifiers: [],
options: [])
case .rejectedCallFromUnseenIdentity:
return UNNotificationCategory(identifier: "org.whispersystems.signal.AppNotifications.Category.rejectedCallFromUnseenIdentity",
actions: [ action(.confirmIdentityAndCallBack), action(.showThread) ],
intentIdentifiers: [],
options: [])
}
}
static func action(_ type: Action) -> UNNotificationAction {
switch type {
case .callBack:
return UNNotificationAction(identifier: "org.whispersystems.signal.AppNotifications.Action.callBack",
2017-02-02 23:42:06 +01:00
title: CallStrings.callBackButtonTitle,
options: .authenticationRequired)
case .showThread:
return UNNotificationAction(identifier: "org.whispersystems.signal.AppNotifications.Action.showThread",
title: CallStrings.showThreadButtonTitle,
options: .authenticationRequired)
case .confirmIdentityAndCallBack:
return UNNotificationAction(identifier: "org.whispersystems.signal.AppNotifications.Action.confirmIdentityAndCallBack",
title: CallStrings.confirmIdentityAndCallBackButtonTitle,
options: .authenticationRequired)
}
}
}
@available(iOS 10.0, *)
class UserNotificationsAdaptee: NSObject, OWSCallNotificationsAdaptee, UNUserNotificationCenterDelegate {
let TAG = "[UserNotificationsAdaptee]"
private let center: UNUserNotificationCenter
var previewType: NotificationType {
return Environment.getCurrent().preferences.notificationPreviewType()
}
override init() {
self.center = UNUserNotificationCenter.current()
super.init()
center.delegate = self
// FIXME TODO only do this after user has registered.
// maybe the PushManager needs a reference to the NotificationsAdapter.
requestAuthorization()
center.setNotificationCategories(AppNotifications.allCategories)
}
func requestAuthorization() {
center.requestAuthorization(options: [.badge, .sound, .alert]) { (granted, error) in
if granted {
Logger.debug("\(self.TAG) \(#function) succeeded.")
} else if error != nil {
Logger.error("\(self.TAG) \(#function) failed with error: \(error!)")
} else {
Logger.error("\(self.TAG) \(#function) failed without error.")
}
}
}
// MARK: - OWSCallNotificationsAdaptee
public func presentIncomingCall(_ call: SignalCall, callerName: String) {
Logger.debug("\(TAG) \(#function) is no-op, because it's handled with callkit.")
// TODO since CallKit doesn't currently work on the simulator,
// we could implement UNNotifications for simulator testing, or if people have opted out of callkit.
}
public func presentMissedCall(_ call: SignalCall, callerName: String) {
Logger.debug("\(TAG) \(#function)")
let content = UNMutableNotificationContent()
// TODO group by thread identifier
// content.threadIdentifier = threadId
let notificationBody = { () -> String in
switch previewType {
case .noNameNoPreview:
2017-02-02 23:42:06 +01:00
return CallStrings.missedCallNotificationBody
case .nameNoPreview, .namePreview:
return (Environment.getCurrent().preferences.isCallKitPrivacyEnabled()
? CallStrings.missedCallNotificationBodyWithoutCallerName
: String(format: CallStrings.missedCallNotificationBodyWithCallerName, callerName))
}}()
content.body = notificationBody
content.sound = UNNotificationSound.default()
content.categoryIdentifier = AppNotifications.category(.missedCall).identifier
let request = UNNotificationRequest.init(identifier: call.localId.uuidString, content: content, trigger: nil)
center.add(request)
}
func presentRejectedCallWithIdentityChange(_ call: SignalCall, callerName: String) {
Logger.debug("\(TAG) \(#function)")
let content = UNMutableNotificationContent()
// TODO group by thread identifier
// content.threadIdentifier = threadId
let notificationBody = { () -> String in
switch previewType {
case .noNameNoPreview:
return CallStrings.rejectedCallWithIdentityChangeNotificationBody
case .nameNoPreview, .namePreview:
return (Environment.getCurrent().preferences.isCallKitPrivacyEnabled()
? CallStrings.rejectedCallWithIdentityChangeNotificationBodyWithoutCallerName
: String(format: CallStrings.rejectedCallWithIdentityChangeNotificationBodyWithCallerName, callerName))
}}()
content.body = notificationBody
content.sound = UNNotificationSound.default()
content.categoryIdentifier = AppNotifications.category(.rejectedCallFromUnseenIdentity).identifier
let request = UNNotificationRequest.init(identifier: call.localId.uuidString, content: content, trigger: nil)
center.add(request)
}
}