mirror of
https://github.com/oxen-io/session-ios.git
synced 2023-12-13 21:30:14 +01:00
Merge branch 'charlesmchen/removeRedPhoneCalls'
This commit is contained in:
commit
b0b4771d68
6 changed files with 5 additions and 356 deletions
|
@ -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 = "<group>"; };
|
||||
348A08501E6C73490057E290 /* AttachmentApprovalViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttachmentApprovalViewController.swift; sourceTree = "<group>"; };
|
||||
348A08521E6C75590057E290 /* SignalAttachment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignalAttachment.swift; sourceTree = "<group>"; };
|
||||
348F3A4E1E4A533900750D44 /* CallInterstitialViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallInterstitialViewController.swift; sourceTree = "<group>"; };
|
||||
34FD936E1E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OWSAnyTouchGestureRecognizer.h; path = views/OWSAnyTouchGestureRecognizer.h; sourceTree = "<group>"; };
|
||||
34FD936F1E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OWSAnyTouchGestureRecognizer.m; path = views/OWSAnyTouchGestureRecognizer.m; sourceTree = "<group>"; };
|
||||
450573FC1E78A06D00615BB4 /* OWS103EnableVideoCalling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OWS103EnableVideoCalling.h; path = Migrations/OWS103EnableVideoCalling.h; sourceTree = "<group>"; };
|
||||
|
@ -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 */,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
|
@ -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];
|
||||
}];
|
||||
|
|
Loading…
Reference in a new issue