diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index b3769f063..22d850f7c 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -20,7 +20,6 @@ 348A08441E6A1D2C0057E290 /* OWSMessagesToolbarContentView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 348A08431E6A1D2C0057E290 /* OWSMessagesToolbarContentView.xib */; }; 348A08511E6C73490057E290 /* AttachmentApprovalViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 348A08501E6C73490057E290 /* AttachmentApprovalViewController.swift */; }; 348A08531E6C75590057E290 /* SignalAttachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 348A08521E6C75590057E290 /* SignalAttachment.swift */; }; - 348F3A4F1E4A533900750D44 /* CallInterstitialViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 348F3A4E1E4A533900750D44 /* CallInterstitialViewController.swift */; }; 34FD93701E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 34FD936F1E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.m */; }; 450573FE1E78A06D00615BB4 /* OWS103EnableVideoCalling.m in Sources */ = {isa = PBXBuildFile; fileRef = 450573FD1E78A06D00615BB4 /* OWS103EnableVideoCalling.m */; }; 4505C2BF1E648EA300CEBF41 /* ExperienceUpgrade.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4505C2BE1E648EA300CEBF41 /* ExperienceUpgrade.swift */; }; @@ -645,7 +644,6 @@ 348A08431E6A1D2C0057E290 /* OWSMessagesToolbarContentView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = OWSMessagesToolbarContentView.xib; sourceTree = ""; }; 348A08501E6C73490057E290 /* AttachmentApprovalViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttachmentApprovalViewController.swift; sourceTree = ""; }; 348A08521E6C75590057E290 /* SignalAttachment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignalAttachment.swift; sourceTree = ""; }; - 348F3A4E1E4A533900750D44 /* CallInterstitialViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallInterstitialViewController.swift; sourceTree = ""; }; 34FD936E1E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OWSAnyTouchGestureRecognizer.h; path = views/OWSAnyTouchGestureRecognizer.h; sourceTree = ""; }; 34FD936F1E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OWSAnyTouchGestureRecognizer.m; path = views/OWSAnyTouchGestureRecognizer.m; sourceTree = ""; }; 450573FC1E78A06D00615BB4 /* OWS103EnableVideoCalling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OWS103EnableVideoCalling.h; path = Migrations/OWS103EnableVideoCalling.h; sourceTree = ""; }; @@ -2696,7 +2694,6 @@ isa = PBXGroup; children = ( 348A08501E6C73490057E290 /* AttachmentApprovalViewController.swift */, - 348F3A4E1E4A533900750D44 /* CallInterstitialViewController.swift */, 4509E79B1DD6545B0025A59F /* CallViewController.swift */, FC31962B1A06A2190094C78E /* FingerprintViewController.h */, FC31962C1A06A2190094C78E /* FingerprintViewController.m */, @@ -3191,7 +3188,6 @@ E197B61818BBEC1A00F073E5 /* RemoteIOAudio.m in Sources */, B67ADDC41989FF8700E1A773 /* RPServerRequestsManager.m in Sources */, 348A08511E6C73490057E290 /* AttachmentApprovalViewController.swift in Sources */, - 348F3A4F1E4A533900750D44 /* CallInterstitialViewController.swift in Sources */, EF764C351DB67CC5000D9A87 /* UIViewController+CameraPermissions.m in Sources */, 453201251E71100C00F20761 /* DisplayableTextFilter.swift in Sources */, 76EB059418170B33006006FC /* HttpManager.m in Sources */, diff --git a/Signal/src/call/CallService.swift b/Signal/src/call/CallService.swift index 22da2e6dd..7d3e8a080 100644 --- a/Signal/src/call/CallService.swift +++ b/Signal/src/call/CallService.swift @@ -253,18 +253,6 @@ protocol CallServiceObserver: class { return "CallServiceActiveCallNotification" } - class func presentCallInterstitialNotificationName() -> String { - return "CallServicePresentCallInterstitialNotification" - } - - class func dismissCallInterstitialNotificationName() -> String { - return "CallServiceDismissCallInterstitialNotification" - } - - class func callWasCancelledByInterstitialNotificationName() -> String { - return "CallServiceCallWasCancelledByInterstitialNotification" - } - // MARK: - Service Actions /** @@ -396,7 +384,7 @@ protocol CallServiceObserver: class { // Insert missed call record if let callRecord = call.callRecord { - if (callRecord.callType == RPRecentCallTypeIncoming) { + if callRecord.callType == RPRecentCallTypeIncoming { callRecord.updateCallType(RPRecentCallTypeMissed) } } else { diff --git a/Signal/src/call/OutboundCallInitiator.swift b/Signal/src/call/OutboundCallInitiator.swift index 133d65ca4..dfa30fac9 100644 --- a/Signal/src/call/OutboundCallInitiator.swift +++ b/Signal/src/call/OutboundCallInitiator.swift @@ -10,41 +10,14 @@ import Foundation @objc class OutboundCallInitiator: NSObject { let TAG = "[OutboundCallInitiator]" - let redphoneManager: PhoneManager let contactsManager: OWSContactsManager let contactsUpdater: ContactsUpdater - var cancelledCallTokens: [String] = [] - - init(redphoneManager: PhoneManager, contactsManager: OWSContactsManager, contactsUpdater: ContactsUpdater) { - self.redphoneManager = redphoneManager - + init(contactsManager: OWSContactsManager, contactsUpdater: ContactsUpdater) { self.contactsManager = contactsManager self.contactsUpdater = contactsUpdater super.init() - - NotificationCenter.default.addObserver(self, - selector:#selector(callWasCancelledByInterstitial), - name:Notification.Name(rawValue: CallService.callWasCancelledByInterstitialNotificationName()), - object:nil) - } - - deinit { - NotificationCenter.default.removeObserver(self) - } - - func callWasCancelledByInterstitial(notification: NSNotification) { - AssertIsOnMainThread() - - let callToken = notification.object as! String - cancelCallToken(callToken:callToken) - } - - func cancelCallToken(callToken: String) { - AssertIsOnMainThread() - - cancelledCallTokens.append(callToken) } /** @@ -65,76 +38,7 @@ import Foundation * |recipientId| is a e164 formatted phone number. */ public func initiateCall(recipientId: String) -> Bool { - - // A temporary unique id used to identify this call during the - let callToken = NSUUID().uuidString - presentCallInterstitial(callToken:callToken) - - // Since users can toggle this setting, which is only communicated during contact sync, it's easy to imagine the - // preference getting stale. Especially as users are toggling the feature to test calls. So here, we opt for a - // blocking network request *every* time we place a call to make sure we've got up to date preferences. - // - // e.g. The following would suffice if we weren't worried about stale preferences. - // SignalRecipient *recipient = [SignalRecipient recipientWithTextSecureIdentifier:self.thread.contactIdentifier]; - self.contactsUpdater.lookupIdentifier(recipientId, - success: { recipient in - guard !self.cancelledCallTokens.contains(callToken) else { - Logger.info("\(self.TAG) OutboundCallInitiator aborting due to cancelled call.") - return - } - - guard !Environment.getCurrent().phoneManager.hasOngoingRedphoneCall() else { - Logger.error("\(self.TAG) OutboundCallInitiator aborting due to ongoing RedPhone call.") - return - } - guard Environment.getCurrent().callService.call == nil else { - Logger.error("\(self.TAG) OutboundCallInitiator aborting due to ongoing WebRTC call.") - return - } - - let remoteWantsWebRTC = recipient.supportsWebRTC - Logger.debug("\(self.TAG) remoteWantsWebRTC: \(remoteWantsWebRTC)") - - if remoteWantsWebRTC { - _ = self.initiateWebRTCAudioCall(recipientId: recipientId) - } else { - _ = self.initiateRedphoneCall(recipientId: recipientId) - } - }, - failure: { error in - Logger.warn("\(self.TAG) looking up recipientId: \(recipientId) failed with error \(error)") - - self.cancelCallToken(callToken:callToken) - self.dismissCallInterstitial(callToken:callToken) - - let alertTitle = NSLocalizedString("UNABLE_TO_PLACE_CALL", comment:"Alert Title") - let alertController = UIAlertController(title: alertTitle, message: error.localizedDescription, preferredStyle: .alert) - - let dismissAction = UIAlertAction(title: NSLocalizedString("DISMISS_BUTTON_TEXT", comment: "Generic short text for button to dismiss a dialog"), style: .default) - alertController.addAction(dismissAction) - UIApplication.shared.keyWindow?.rootViewController?.present(alertController, animated: true, completion: nil) - }) - - // Since we've already dispatched async to make sure we have fresh webrtc preference data - // we don't have a meaningful value to return here - but we're not using it anway. =/ - return true - } - - private func initiateRedphoneCall(recipientId: String) -> Bool { - Logger.info("\(TAG) Placing redphone call to: \(recipientId)") - - let number = PhoneNumber.tryParsePhoneNumber(fromUserSpecifiedText: recipientId) - assert(number != nil) - - let contact: Contact? = self.contactsManager.latestContact(for: number) - - redphoneManager.initiateOutgoingCall(to: contact, atRemoteNumber: number) - - return true - } - - private func initiateWebRTCAudioCall(recipientId: String) -> Bool { - // Rather than an init-assigned dependency property, we access `callUIAdapter` via Environment + // Rather than an init-assigned dependency property, we access `callUIAdapter` via Environment // because it can change after app launch due to user settings guard let callUIAdapter = Environment.getCurrent().callUIAdapter else { assertionFailure() @@ -145,18 +49,4 @@ import Foundation callUIAdapter.startAndShowOutgoingCall(recipientId: recipientId) return true } - - private func presentCallInterstitial(callToken: String) { - AssertIsOnMainThread() - - let notificationName = CallService.presentCallInterstitialNotificationName() - NotificationCenter.default.post(name: NSNotification.Name(rawValue: notificationName), object: callToken) - } - - private func dismissCallInterstitial(callToken: String) { - AssertIsOnMainThread() - - let notificationName = CallService.dismissCallInterstitialNotificationName() - NotificationCenter.default.post(name: NSNotification.Name(rawValue: notificationName), object: callToken) - } } diff --git a/Signal/src/environment/Environment.m b/Signal/src/environment/Environment.m index 1649ecf00..82eaa5f5c 100644 --- a/Signal/src/environment/Environment.m +++ b/Signal/src/environment/Environment.m @@ -184,8 +184,7 @@ static Environment *environment = nil; OWSAssert(self.phoneManager); OWSAssert(self.contactsManager); OWSAssert(self.contactsUpdater); - _outboundCallInitiator = [[OutboundCallInitiator alloc] initWithRedphoneManager:self.phoneManager - contactsManager:self.contactsManager + _outboundCallInitiator = [[OutboundCallInitiator alloc] initWithContactsManager:self.contactsManager contactsUpdater:self.contactsUpdater]; } } diff --git a/Signal/src/view controllers/CallInterstitialViewController.swift b/Signal/src/view controllers/CallInterstitialViewController.swift deleted file mode 100644 index 3b07dab79..000000000 --- a/Signal/src/view controllers/CallInterstitialViewController.swift +++ /dev/null @@ -1,171 +0,0 @@ -// -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. -// - -import Foundation - -@objc(OWSCallInterstitialViewController) -class CallInterstitialViewController: UIViewController { - - let TAG = "[CallInterstitialViewController]" - - var wasCallCancelled = false - let callToken: String! - - // MARK: Views - - var hasConstraints = false - var blurView: UIVisualEffectView! - var contentView: UIView! - - // MARK: Initializers - - @available(*, unavailable, message:"init is unavailable, use initWithCallToken") - required init?(coder aDecoder: NSCoder) { - assert(false) - self.callToken = "" - super.init(coder: aDecoder) - } - - required init(callToken: String) { - self.callToken = callToken - super.init(nibName: nil, bundle: nil) - observeNotifications() - } - - func observeNotifications() { - NotificationCenter.default.addObserver(self, - selector:#selector(willResignActive), - name:NSNotification.Name.UIApplicationWillResignActive, - object:nil) - } - - deinit { - NotificationCenter.default.removeObserver(self) - } - - func willResignActive() { - cancelCall() - } - - // MARK: View Lifecycle - - override func viewDidLoad() { - super.viewDidLoad() - - createViews() - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - - blurView.layer.opacity = 0 - contentView.layer.opacity = 0 - } - - override func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) - - UIView.animate(withDuration: 0.3, - delay: 1.0, - options: UIViewAnimationOptions.curveLinear, - animations: { - self.blurView.layer.opacity = 1 - self.contentView.layer.opacity = 1 - }, - completion: nil) - } - - override func viewWillDisappear(_ animated: Bool) { - super.viewWillDisappear(animated) - - blurView.layer.removeAllAnimations() - contentView.layer.removeAllAnimations() - } - - // MARK: - Create Views - - func createViews() { - assert(self.view != nil) - - // Dark blurred background. - let blurEffect = UIBlurEffect(style: .dark) - blurView = UIVisualEffectView(effect: blurEffect) - blurView.isUserInteractionEnabled = false - self.view.addSubview(blurView) - - contentView = UIView() - self.view.addSubview(contentView) - - let dialingLabel = UILabel() - dialingLabel.text = NSLocalizedString("CALL_INTERSTITIAL_CALLING_LABEL", comment: "Title for call interstitial view") - dialingLabel.textColor = UIColor.white - dialingLabel.font = UIFont.ows_lightFont(withSize:ScaleFromIPhone5To7Plus(32, 40)) - dialingLabel.textAlignment = .center - contentView.addSubview(dialingLabel) - - let cancelCallButton = UIButton() - cancelCallButton.setTitle(NSLocalizedString("TXT_CANCEL_TITLE", comment: "nil"), - for:.normal) - cancelCallButton.setTitleColor(UIColor.white, for:.normal) - cancelCallButton.titleLabel?.font = UIFont.ows_lightFont(withSize:ScaleFromIPhone5To7Plus(26, 32)) - let buttonInset = ScaleFromIPhone5To7Plus(7, 9) - cancelCallButton.titleEdgeInsets = UIEdgeInsets(top: buttonInset, - left: buttonInset, - bottom: buttonInset, - right: buttonInset) - cancelCallButton.addTarget(self, action:#selector(cancelCallButtonPressed), for:.touchUpInside) - contentView.addSubview(cancelCallButton) - - dialingLabel.autoPinWidthToSuperview() - dialingLabel.autoVCenterInSuperview() - - cancelCallButton.autoSetDimension(.height, toSize:ScaleFromIPhone5To7Plus(50, 60)) - cancelCallButton.autoPinWidthToSuperview() - cancelCallButton.autoPinEdge(toSuperviewEdge:.bottom, withInset:ScaleFromIPhone5To7Plus(23, 41)) - } - - // MARK: - Layout - - override func updateViewConstraints() { - if !hasConstraints { - // We only want to create our constraints once. - // - // Note that constraints are also created elsewhere. - // This only creates the constraints for the top-level contents of the view. - hasConstraints = true - - // Force creation of the view. - let view = self.view - assert(view != nil) - - // Dark blurred background. - blurView.autoPinEdgesToSuperviewEdges() - - contentView.autoPinEdgesToSuperviewEdges() - } - - super.updateViewConstraints() - } - - // MARK: - Methods - - func cancelCall() { - guard !wasCallCancelled else { - return - } - wasCallCancelled = true - - assert(callToken != nil) - let notificationName = CallService.callWasCancelledByInterstitialNotificationName() - NotificationCenter.default.post(name: NSNotification.Name(rawValue: notificationName), object: callToken) - - self.dismiss(animated: false) - } - - // MARK: - Events - - func cancelCallButtonPressed(sender button: UIButton) { - cancelCall() - } -} diff --git a/Signal/src/view controllers/SignalsViewController.m b/Signal/src/view controllers/SignalsViewController.m index 4fbacad5c..5c1c23b2b 100644 --- a/Signal/src/view controllers/SignalsViewController.m +++ b/Signal/src/view controllers/SignalsViewController.m @@ -137,14 +137,6 @@ NSString *const SignalsViewControllerSegueShowIncomingCall = @"ShowIncomingCallS selector:@selector(handleActiveCallNotification:) name:[CallService callServiceActiveCallNotificationName] object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(handlePresentCallInterstitialNotification:) - name:[CallService presentCallInterstitialNotificationName] - object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(handleDismissCallInterstitialNotification:) - name:[CallService dismissCallInterstitialNotificationName] - object:nil]; [self updateBarButtonItems]; } @@ -203,50 +195,6 @@ NSString *const SignalsViewControllerSegueShowIncomingCall = @"ShowIncomingCallS } } -- (void)handlePresentCallInterstitialNotification:(NSNotification *)notification -{ - AssertIsOnMainThread(); - - NSString *callToken = notification.object; - OWSAssert(callToken != nil); - - OWSCallInterstitialViewController *viewController = [[OWSCallInterstitialViewController alloc] initWithCallToken:callToken]; - - void(^presentInterstitial)() = ^{ - viewController.modalPresentationStyle = UIModalPresentationOverFullScreen; - [self presentViewController:viewController - animated:NO - completion:nil]; - }; - - // Dismiss any other modals so we can present call modal. - if (self.presentedViewController) { - [self dismissViewControllerAnimated:YES completion:presentInterstitial]; - } else { - presentInterstitial(); - } -} - -- (void)handleDismissCallInterstitialNotification:(NSNotification *)notification -{ - AssertIsOnMainThread(); - - NSString *callToken = notification.object; - OWSAssert(callToken != nil); - - if (!self.presentedViewController || - ![self.presentedViewController isKindOfClass:[OWSCallInterstitialViewController class]]) { - return; - } - - - OWSCallInterstitialViewController *viewController = (OWSCallInterstitialViewController *)self.presentedViewController; - if (![viewController.callToken isEqualToString:callToken]) { - return; - } - [self dismissViewControllerAnimated:YES completion:nil]; -} - - (void)handleActiveCallNotification:(NSNotification *)notification { AssertIsOnMainThread(); @@ -262,8 +210,7 @@ NSString *const SignalsViewControllerSegueShowIncomingCall = @"ShowIncomingCallS // Dismiss any other modals so we can present call modal. if (self.presentedViewController) { - BOOL shouldAnimate = ![self.presentedViewController isKindOfClass:[OWSCallInterstitialViewController class]]; - [self dismissViewControllerAnimated:shouldAnimate + [self dismissViewControllerAnimated:YES completion:^{ [self performSegueWithIdentifier:SignalsViewControllerSegueShowIncomingCall sender:call]; }];