2017-02-01 23:49:32 +01:00
//
// C o p y r i g h t ( c ) 2 0 1 7 O p e n W h i s p e r S y s t e m s . A l l r i g h t s r e s e r v e d .
//
import Foundation
/* *
* Creates an outbound call via either Redphone or WebRTC depending on participant preferences .
*/
@objc class OutboundCallInitiator : NSObject {
let TAG = " [OutboundCallInitiator] "
let redphoneManager : PhoneManager
let contactsManager : OWSContactsManager
let contactsUpdater : ContactsUpdater
2017-02-02 18:21:48 +01:00
init ( redphoneManager : PhoneManager , contactsManager : OWSContactsManager , contactsUpdater : ContactsUpdater ) {
2017-02-01 23:49:32 +01:00
self . redphoneManager = redphoneManager
self . contactsManager = contactsManager
self . contactsUpdater = contactsUpdater
}
/* *
* | handle | is a user formatted phone number , e . g . from a system contacts entry
*/
public func initiateCall ( handle : String ) -> Bool {
Logger . info ( " \( TAG ) in \( #function ) with handle: \( handle ) " )
guard let recipientId = PhoneNumber ( fromUserSpecifiedText : handle ) . toE164 ( ) else {
Logger . warn ( " \( TAG ) unable to parse signalId from phone number: \( handle ) " )
return false
}
return initiateCall ( recipientId : recipientId )
}
/* *
* | recipientId | is a e164 formatted phone number .
*/
public func initiateCall ( recipientId : String ) -> Bool {
let localWantsWebRTC = Environment . preferences ( ) . isWebRTCEnabled ( )
if ! localWantsWebRTC {
return self . initiateRedphoneCall ( recipientId : recipientId )
}
// S i n c e u s e r s c a n t o g g l e t h i s s e t t i n g , w h i c h i s o n l y c o m m u n i c a t e d d u r i n g c o n t a c t s y n c , i t ' s e a s y t o i m a g i n e t h e
// p r e f e r e n c e g e t t i n g s t a l e . E s p e c i a l l y a s u s e r s a r e t o g g l i n g t h e f e a t u r e t o t e s t c a l l s . S o h e r e , w e o p t f o r a
// b l o c k i n g n e t w o r k r e q u e s t * e v e r y * t i m e w e p l a c e a c a l l t o m a k e s u r e w e ' v e g o t u p t o d a t e p r e f e r e n c e s .
//
// e . g . T h e f o l l o w i n g w o u l d s u f f i c e i f w e w e r e n ' t w o r r i e d a b o u t s t a l e p r e f e r e n c e s .
// S i g n a l R e c i p i e n t * r e c i p i e n t = [ S i g n a l R e c i p i e n t r e c i p i e n t W i t h T e x t S e c u r e I d e n t i f i e r : s e l f . t h r e a d . c o n t a c t I d e n t i f i e r ] ;
self . contactsUpdater . lookupIdentifier ( recipientId ,
success : { recipient in
let remoteWantsWebRTC = recipient . supportsWebRTC
Logger . debug ( " \( self . TAG ) localWantsWebRTC: \( localWantsWebRTC ) , remoteWantsWebRTC: \( remoteWantsWebRTC ) " )
if localWantsWebRTC , 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 ) " )
2017-02-02 01:22:25 +01:00
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 )
2017-02-01 23:49:32 +01:00
} )
// S i n c e w e ' v e a l r e a d y d i s p a t c h e d a s y n c t o m a k e s u r e w e h a v e f r e s h w e b r t c p r e f e r e n c e d a t a
// w e d o n ' t h a v e a m e a n i n g f u l v a l u e t o r e t u r n h e r e - b u t w e ' r e n o t u s i n g i t a n w a y . = /
return true
}
private func initiateRedphoneCall ( recipientId : String ) -> Bool {
Logger . info ( " \( TAG ) Placing redphone call to: \( recipientId ) " )
let number = PhoneNumber . tryParsePhoneNumber ( fromUserSpecifiedText : recipientId )
let contact = self . contactsManager . latestContact ( for : number )
assert ( number != nil )
assert ( contact != nil )
redphoneManager . initiateOutgoingCall ( to : contact , atRemoteNumber : number )
return true
}
private func initiateWebRTCAudioCall ( recipientId : String ) -> Bool {
2017-02-02 18:21:48 +01:00
// R a t h e r t h a n a n i n i t - a s s i g n e d d e p e n d e n c y p r o p e r t y , w e a c c e s s ` c a l l U I A d a p t e r ` v i a E n v i r o n m e n t
// b e c a u s e i t c a n c h a n g e a f t e r a p p l a u n c h d u e t o u s e r s e t t i n g s
guard let callUIAdapter = Environment . getCurrent ( ) . callUIAdapter else {
assertionFailure ( )
Logger . error ( " \( TAG ) can't initiate call because callUIAdapter is nil " )
return false
}
2017-02-02 01:47:50 +01:00
callUIAdapter . startAndShowOutgoingCall ( recipientId : recipientId )
2017-02-01 23:49:32 +01:00
return true
}
}