refactor for voip push notification

pull/560/head
ryanzhao 3 years ago
parent 0ef7bdc9ce
commit 4db87992b2

@ -150,7 +150,6 @@
7BA68909272A27BE00EFC32F /* SessionCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BA68908272A27BE00EFC32F /* SessionCall.swift */; };
7BC01A3E241F40AB00BC7C55 /* NotificationServiceExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC01A3D241F40AB00BC7C55 /* NotificationServiceExtension.swift */; };
7BC01A42241F40AB00BC7C55 /* SessionNotificationServiceExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 7BC01A3B241F40AB00BC7C55 /* SessionNotificationServiceExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
7BC707EA27267973002817AD /* AppDelegate+VoIP.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC707E927267973002817AD /* AppDelegate+VoIP.swift */; };
7BC707F227290ACB002817AD /* SessionCallManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC707F127290ACB002817AD /* SessionCallManager.swift */; };
7BCD116C27016062006330F1 /* WebRTCSession+DataChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BCD116B27016062006330F1 /* WebRTCSession+DataChannel.swift */; };
7BDCFC08242186E700641C39 /* NotificationServiceExtensionContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BDCFC07242186E700641C39 /* NotificationServiceExtensionContext.swift */; };
@ -1137,7 +1136,6 @@
7BC01A3B241F40AB00BC7C55 /* SessionNotificationServiceExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = SessionNotificationServiceExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
7BC01A3D241F40AB00BC7C55 /* NotificationServiceExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationServiceExtension.swift; sourceTree = "<group>"; };
7BC01A3F241F40AB00BC7C55 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
7BC707E927267973002817AD /* AppDelegate+VoIP.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+VoIP.swift"; sourceTree = "<group>"; };
7BC707F127290ACB002817AD /* SessionCallManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionCallManager.swift; sourceTree = "<group>"; };
7BCD116B27016062006330F1 /* WebRTCSession+DataChannel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WebRTCSession+DataChannel.swift"; sourceTree = "<group>"; };
7BDCFC0424206E7300641C39 /* SessionNotificationServiceExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SessionNotificationServiceExtension.entitlements; sourceTree = "<group>"; };
@ -3491,7 +3489,6 @@
76EB03C218170B33006006FC /* AppDelegate.h */,
76EB03C318170B33006006FC /* AppDelegate.m */,
C3AAFFF125AE99710089E6DD /* AppDelegate.swift */,
7BC707E927267973002817AD /* AppDelegate+VoIP.swift */,
34D99CE3217509C1000AFB39 /* AppEnvironment.swift */,
B81D260326158DF5004D1FE1 /* Certificates */,
B8FF8E6025C10D8B004D1F22 /* Countries */,
@ -4956,7 +4953,6 @@
4CA46F4C219CCC630038ABDE /* CaptionView.swift in Sources */,
C328253025CA55370062D0A7 /* ContextMenuWindow.swift in Sources */,
340FC8B7204DAC8D007AEB0F /* OWSConversationSettingsViewController.m in Sources */,
7BC707EA27267973002817AD /* AppDelegate+VoIP.swift in Sources */,
7B1581E4271FC59D00848B49 /* CallModal.swift in Sources */,
34BECE2E1F7ABCE000D7438D /* GifPickerViewController.swift in Sources */,
B84664F5235022F30083A1CD /* MentionUtilities.swift in Sources */,

@ -98,13 +98,16 @@ public final class SessionCall: NSObject {
func reportIncomingCallIfNeeded() {
guard case .offer = mode else { return }
AppEnvironment.shared.callManager.reportIncomingCall(self, callerName: contactName) { error in
if let error = error {
SNLog("[Calls] Failed to report incoming call to CallKit due to error: \(error)")
}
}
}
// MARK: Actions
func startSessionCall(completion: (() -> Void)?) {
guard case .offer = mode else { return }
AppEnvironment.shared.callManager.reportOutgoingCall(self)
Storage.write { transaction in
self.webRTCSession.sendPreOffer(to: self.sessionID, using: transaction).done {
self.webRTCSession.sendOffer(to: self.sessionID, using: transaction).done {
@ -128,5 +131,6 @@ public final class SessionCall: NSObject {
self.webRTCSession.endCall(with: self.sessionID, using: transaction)
}
hasEnded = true
AppEnvironment.shared.callManager.reportCurrentCallEnded()
}
}

@ -45,13 +45,15 @@ public final class SessionCallManager: NSObject, CXProviderDelegate {
public func providerDidReset(_ provider: CXProvider) {
AssertIsOnMainThread()
currentCall?.endSessionCall()
}
public func reportOutgoingCall(_ call: SessionCall, completion: @escaping (Error?) -> Void) {
public func reportOutgoingCall(_ call: SessionCall) {
AssertIsOnMainThread()
self.provider.reportOutgoingCall(with: call.uuid, startedConnectingAt: call.connectingDate)
self.currentCall = call
call.hasStartedConnectingDidChange = {
self.provider.reportOutgoingCall(with: call.uuid, startedConnectingAt: call.connectingDate)
}
call.hasConnectedDidChange = {
self.provider.reportOutgoingCall(with: call.uuid, connectedAt: call.connectedDate)
}
@ -80,6 +82,10 @@ public final class SessionCallManager: NSObject, CXProviderDelegate {
}
}
public func reportCurrentCallEnded() {
self.currentCall = nil
}
// MARK: Util
private func disableUnsupportedFeatures(callUpdate: CXCallUpdate) {
// Call Holding is failing to restart audio when "swapping" calls on the CallKit screen

@ -166,6 +166,8 @@ final class CallVC : UIViewController, WebRTCSessionDelegate, VideoPreviewDelega
self.conversationVC?.showInputAccessoryView()
self.presentingViewController?.dismiss(animated: true, completion: nil)
}
self.modalPresentationStyle = .overFullScreen
self.modalTransitionStyle = .crossDissolve
}
required init(coder: NSCoder) { preconditionFailure("Use init(for:) instead.") }

@ -155,9 +155,8 @@ final class IncomingCallBanner: UIView, UIGestureRecognizerDelegate {
}
@objc private func endCall() {
self.call.endSessionCall{
self.dismiss()
}
self.call.endSessionCall()
self.dismiss()
}
public func showCallVC(answer: Bool) {
@ -165,8 +164,6 @@ final class IncomingCallBanner: UIView, UIGestureRecognizerDelegate {
guard let presentingVC = CurrentAppContext().frontmostViewController() else { preconditionFailure() } // TODO: Handle more gracefully
let callVC = CallVC(for: self.call)
callVC.shouldAnswer = answer
callVC.modalPresentationStyle = .overFullScreen
callVC.modalTransitionStyle = .crossDissolve
if let conversationVC = presentingVC as? ConversationVC {
callVC.conversationVC = conversationVC
conversationVC.inputAccessoryView?.isHidden = true

@ -34,8 +34,6 @@ extension ConversationVC : InputViewDelegate, MessageCellDelegate, ContextMenuAc
let call = SessionCall(for: contactSessionID, uuid: UUID().uuidString, mode: .offer)
let callVC = CallVC(for: call)
callVC.conversationVC = self
callVC.modalPresentationStyle = .overFullScreen
callVC.modalTransitionStyle = .crossDissolve
self.inputAccessoryView?.isHidden = true
self.inputAccessoryView?.alpha = 0
present(callVC, animated: true, completion: nil)

@ -1,21 +0,0 @@
import PushKit
import SessionUtilitiesKit
extension AppDelegate: PKPushRegistryDelegate {
@objc public func registerVoIP() {
let pushRegistry = PKPushRegistry(queue: .main)
pushRegistry.delegate = self
pushRegistry.desiredPushTypes = [.voIP]
}
public func pushRegistry(_ registry: PKPushRegistry, didUpdate pushCredentials: PKPushCredentials, for type: PKPushType) {
let device = NSData(data: pushCredentials.token)
let deviceId = device.description.replacingOccurrences(of:"<", with:"").replacingOccurrences(of:">", with:"").replacingOccurrences(of:" ", with:"")
SNLog(deviceId)
}
public func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
SNLog("Incoming VoIP with payload \(payload)")
}
}

@ -149,8 +149,6 @@ static NSTimeInterval launchStartedAt;
launchStartedAt = CACurrentMediaTime();
[LKAppModeManager configureWithDelegate:self];
[self registerVoIP];
// OWSLinkPreview is now in SessionMessagingKit, so to still be able to deserialize them we
// need to tell NSKeyedUnarchiver about the changes.

@ -15,8 +15,6 @@ extension AppDelegate {
guard let presentingVC = CurrentAppContext().frontmostViewController() else { preconditionFailure() } // TODO: Handle more gracefully
if let conversationVC = presentingVC as? ConversationVC, let contactThread = conversationVC.thread as? TSContactThread, contactThread.contactSessionID() == message.sender! {
let callVC = CallVC(for: call)
callVC.modalPresentationStyle = .overFullScreen
callVC.modalTransitionStyle = .crossDissolve
callVC.conversationVC = conversationVC
conversationVC.inputAccessoryView?.isHidden = true
conversationVC.inputAccessoryView?.alpha = 0

@ -17,7 +17,7 @@ public enum PushRegistrationError: Error {
/**
* Singleton used to integrate with push notification services - registration and routing received remote notifications.
*/
@objc public class PushRegistrationManager: NSObject {
@objc public class PushRegistrationManager: NSObject, PKPushRegistryDelegate {
// MARK: - Dependencies
@ -44,21 +44,25 @@ public enum PushRegistrationError: Error {
private var vanillaTokenResolver: Resolver<Data>?
private var voipRegistry: PKPushRegistry?
private var voipTokenPromise: Promise<Data>?
private var voipTokenResolver: Resolver<Data>?
private var voipTokenPromise: Promise<Data?>?
private var voipTokenResolver: Resolver<Data?>?
// MARK: Public interface
public func requestPushTokens() -> Promise<(pushToken: String, voipToken: String)> {
return firstly {
self.registerUserNotificationSettings()
}.then { () -> Promise<(pushToken: String, voipToken: String)> in
Logger.info("")
return firstly { () -> Promise<Void> in
return self.registerUserNotificationSettings()
}.then { (_) -> Promise<(pushToken: String, voipToken: String)> in
guard !Platform.isSimulator else {
throw PushRegistrationError.pushNotSupported(description: "Push not supported on simulators")
}
return self.registerForVanillaPushToken().map { vanillaPushToken -> (pushToken: String, voipToken: String) in
return (pushToken: vanillaPushToken, voipToken: "")
return self.registerForVanillaPushToken().then { vanillaPushToken -> Promise<(pushToken: String, voipToken: String)> in
self.registerForVoipPushToken().map { voipPushToken in
(pushToken: vanillaPushToken, voipToken: voipPushToken ?? "")
}
}
}
}
@ -168,6 +172,68 @@ public enum PushRegistrationError: Error {
self.vanillaTokenPromise = nil
}
}
private func createVoipRegistryIfNecessary() {
AssertIsOnMainThread()
guard voipRegistry == nil else { return }
let voipRegistry = PKPushRegistry(queue: nil)
self.voipRegistry = voipRegistry
voipRegistry.desiredPushTypes = [.voIP]
voipRegistry.delegate = self
}
private func registerForVoipPushToken() -> Promise<String?> {
AssertIsOnMainThread()
guard self.voipTokenPromise == nil else {
let promise = self.voipTokenPromise!
return promise.map { $0?.hexEncodedString }
}
// No pending voip token yet. Create a new promise
let (promise, resolver) = Promise<Data?>.pending()
self.voipTokenPromise = promise
self.voipTokenResolver = resolver
// We don't create the voip registry in init, because it immediately requests the voip token,
// potentially before we're ready to handle it.
createVoipRegistryIfNecessary()
guard let voipRegistry = self.voipRegistry else {
owsFailDebug("failed to initialize voipRegistry")
resolver.reject(PushRegistrationError.assertionError(description: "failed to initialize voipRegistry"))
return promise.map { _ in
// coerce expected type of returned promise - we don't really care about the value,
// since this promise has been rejected. In practice this shouldn't happen
String()
}
}
// If we've already completed registering for a voip token, resolve it immediately,
// rather than waiting for the delegate method to be called.
if let voipTokenData = voipRegistry.pushToken(for: .voIP) {
Logger.info("using pre-registered voIP token")
resolver.fulfill(voipTokenData)
}
return promise.map { (voipTokenData: Data?) -> String? in
Logger.info("successfully registered for voip push notifications")
return voipTokenData?.hexEncodedString
}.ensure {
self.voipTokenPromise = nil
}
}
// MARK: PKPushRegistryDelegate
public func pushRegistry(_ registry: PKPushRegistry, didUpdate pushCredentials: PKPushCredentials, for type: PKPushType) {
Logger.info("")
owsAssertDebug(type == .voIP)
owsAssertDebug(pushCredentials.type == .voIP)
guard let voipTokenResolver = voipTokenResolver else { return }
voipTokenResolver.fulfill(pushCredentials.token)
}
}
// We transmit pushToken data as hex encoded string to the server

Loading…
Cancel
Save