@ -46,7 +46,10 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
 
		
	
		
			
				
 
		
	
		
			
				    //   MARK:   -   O n g o i n g   C a l l   C o n t r o l s 
 
		
	
		
			
				
 
		
	
		
			
				    var  ongoingCallView :  UIView ! 
 
		
	
		
			
				    var  ongoingCallControls :  UIStackView ! 
 
		
	
		
			
				
 
		
	
		
			
				    var  ongoingAudioCallControls :  UIStackView ! 
 
		
	
		
			
				    var  ongoingVideoCallControls :  UIStackView ! 
 
		
	
		
			
				
 
		
	
		
			
				    var  hangUpButton :  UIButton ! 
 
		
	
		
			
				    var  audioSourceButton :  UIButton ! 
 
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
			
			@ -54,14 +57,11 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
 
		
	
		
			
				    var  audioModeVideoButton :  UIButton ! 
 
		
	
		
			
				    var  videoModeMuteButton :  UIButton ! 
 
		
	
		
			
				    var  videoModeVideoButton :  UIButton ! 
 
		
	
		
			
				    //   TODO:   L a t e r ,   w e ' l l   r e - e n a b l e   t h e   t e x t   m e s s a g e   b u t t o n 
 
		
	
		
			
				    //               s o   u s e r s   c a n   s e n d   a n d   r e a d   m e s s a g e s   d u r i n g   a   
 
		
	
		
			
				    //               c a l l . 
 
		
	
		
			
				//         v a r   t e x t M e s s a g e B u t t o n :   U I B u t t o n !  
		
	
		
			
				    var  videoModeFlipCameraButton :  UIButton ! 
 
		
	
		
			
				
 
		
	
		
			
				    //   MARK:   -   I n c o m i n g   C a l l   C o n t r o l s 
 
		
	
		
			
				
 
		
	
		
			
				    var  incomingCall View:  UI  View! 
 
		
	
		
			
				    var  incomingCall Controls:  UIStack  View! 
 
		
	
		
			
				
 
		
	
		
			
				    var  acceptIncomingButton :  UIButton ! 
 
		
	
		
			
				    var  declineIncomingButton :  UIButton ! 
 
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
			
			@ -182,7 +182,10 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
 
		
	
		
			
				
 
		
	
		
			
				    override  func  loadView ( )  { 
 
		
	
		
			
				        self . view  =  UIView ( ) 
 
		
	
		
			
				
 
		
	
		
			
				        self . view . layoutMargins  =  UIEdgeInsets ( top :  16 ,  left :  20 ,  bottom :  16 ,  right :  20 ) 
 
		
	
		
			
				        createViews ( ) 
 
		
	
		
			
				        createViewConstraints ( ) 
 
		
	
		
			
				    } 
 
		
	
		
			
				
 
		
	
		
			
				    override  func  viewDidLoad ( )  { 
 
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
			
			@ -348,42 +351,60 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
 
		
	
		
			
				
 
		
	
		
			
				//                 t e x t M e s s a g e B u t t o n   =   c r e a t e B u t t o n ( i m a g e N a m e : " m e s s a g e - a c t i v e - w i d e " ,  
		
	
		
			
				//                                                                                                 a c t i o n : # s e l e c t o r ( d i d P r e s s T e x t M e s s a g e ) )  
		
	
		
			
				        audioSourceButton  =  createButton ( image Name:  " audio-call-speaker-inactive " , 
 
		
	
		
			
				        audioSourceButton  =  createButton ( image :  # imageLiteral ( resource :  " audio-call-speaker-inactive " ) , 
 
		
	
		
			
				                                          action :  #selector ( didPressAudioSource ) ) 
 
		
	
		
			
				        audioSourceButton . accessibilityLabel  =  NSLocalizedString ( " CALL_VIEW_AUDIO_SOURCE_LABEL " , 
 
		
	
		
			
				                                                                 comment :  " Accessibility label for selection the audio source " ) 
 
		
	
		
			
				
 
		
	
		
			
				        hangUpButton  =  createButton ( image Name:  " hangup-active-wide " , 
 
		
	
		
			
				        hangUpButton  =  createButton ( image :  # imageLiteral ( resource :  " hangup-active-wide " ) , 
 
		
	
		
			
				                                    action :  #selector ( didPressHangup ) ) 
 
		
	
		
			
				        hangUpButton . accessibilityLabel  =  NSLocalizedString ( " CALL_VIEW_HANGUP_LABEL " , 
 
		
	
		
			
				                                                            comment :  " Accessibility label for hang up call " ) 
 
		
	
		
			
				
 
		
	
		
			
				        audioModeMuteButton  =  createButton ( image Name:  " audio-call-mute-inactive " , 
 
		
	
		
			
				        audioModeMuteButton  =  createButton ( image :  # imageLiteral ( resource :  " audio-call-mute-inactive " ) , 
 
		
	
		
			
				                                           action :  #selector ( didPressMute ) ) 
 
		
	
		
			
				        audioModeMuteButton . setImage ( # imageLiteral ( resourceName :  " audio-call-mute-active " ) ,  for :  . selected ) 
 
		
	
		
			
				
 
		
	
		
			
				        audioModeMuteButton . accessibilityLabel  =  NSLocalizedString ( " CALL_VIEW_MUTE_LABEL " , 
 
		
	
		
			
				                                                                   comment :  " Accessibility label for muting the microphone " ) 
 
		
	
		
			
				
 
		
	
		
			
				        videoModeMuteButton  =  createButton ( imageName :  " video-mute-unselected " , 
 
		
	
		
			
				        audioModeVideoButton  =  createButton ( image :  # imageLiteral ( resourceName :  " audio-call-video-inactive " ) , 
 
		
	
		
			
				                                            action :  #selector ( didPressVideo ) ) 
 
		
	
		
			
				        audioModeVideoButton . setImage ( # imageLiteral ( resourceName :  " audio-call-video-active " ) ,  for :  . selected ) 
 
		
	
		
			
				        audioModeVideoButton . accessibilityLabel  =  NSLocalizedString ( " CALL_VIEW_SWITCH_TO_VIDEO_LABEL " ,  comment :  " Accessibility label to switch to video call " ) 
 
		
	
		
			
				
 
		
	
		
			
				        videoModeMuteButton  =  createButton ( image :  # imageLiteral ( resourceName :  " video-mute-unselected " ) , 
 
		
	
		
			
				                                           action :  #selector ( didPressMute ) ) 
 
		
	
		
			
				        videoModeMuteButton . setImage ( # imageLiteral ( resourceName :  " video-mute-selected " ) ,  for :  . selected ) 
 
		
	
		
			
				        videoModeMuteButton . accessibilityLabel  =  NSLocalizedString ( " CALL_VIEW_MUTE_LABEL " ,  comment :  " Accessibility label for muting the microphone " ) 
 
		
	
		
			
				        videoModeMuteButton . alpha  =  0.9 
 
		
	
		
			
				
 
		
	
		
			
				        audioModeVideoButton  =  createButton ( imageName :  " audio-call-video-inactive " , 
 
		
	
		
			
				                                            action :  #selector ( didPressVideo ) ) 
 
		
	
		
			
				        audioModeVideoButton . accessibilityLabel  =  NSLocalizedString ( " CALL_VIEW_SWITCH_TO_VIDEO_LABEL " ,  comment :  " Accessibility label to switch to video call " ) 
 
		
	
		
			
				        //   T O D O   p r o p e r   a s s e t 
 
		
	
		
			
				        videoModeFlipCameraButton  =  createButton ( image :  # imageLiteral ( resourceName :  " btnRefresh--white " ) , 
 
		
	
		
			
				                                                 action :  #selector ( didPressFlipCamera ) ) 
 
		
	
		
			
				        videoModeFlipCameraButton . setImage ( # imageLiteral ( resourceName :  " btnRefresh--white " ) , 
 
		
	
		
			
				                                           for :  . selected ) 
 
		
	
		
			
				        videoModeFlipCameraButton . accessibilityLabel  =  NSLocalizedString ( " CALL_VIEW_SWITCH_CAMERA_DIRECTION " ,  comment :  " Accessibility label to toggle front vs. rear facing camera " ) 
 
		
	
		
			
				        videoModeFlipCameraButton . alpha  =  0.9 
 
		
	
		
			
				
 
		
	
		
			
				        videoModeVideoButton  =  createButton ( imageName :  " video-video-unselected " , 
 
		
	
		
			
				        videoModeVideoButton  =  createButton ( image :  # imageLiteral ( resource :  " video-video-unselected " ) , 
 
		
	
		
			
				                                            action :  #selector ( didPressVideo ) ) 
 
		
	
		
			
				        videoModeVideoButton . setImage ( # imageLiteral ( resourceName :  " video-video-selected " ) ,  for :  . selected ) 
 
		
	
		
			
				        videoModeVideoButton . accessibilityLabel  =  NSLocalizedString ( " CALL_VIEW_SWITCH_TO_AUDIO_LABEL " ,  comment :  " Accessibility label to switch to audio only " ) 
 
		
	
		
			
				        videoModeVideoButton . alpha  =  0.9 
 
		
	
		
			
				
 
		
	
		
			
				        setButtonSelectedImage( button :  audioModeMuteButton ,  imageName :  " audio-call-mute-active "  ) 
 
		
	
		
			
				        setButtonSelectedImage( button :  videoModeMuteButton ,  imageName :  " video-mute-selected " )  
 
		
	
		
			
				        setButtonSelectedImage( button :  audioModeVideoButton ,  imageName :  " audio-call-video-active " )  
 
		
	
		
			
				        setButtonSelectedImage( button :  videoModeVideoButton ,  imageName :  " video-video-selected "  ) 
 
		
	
		
			
				        ongoingCallControls =  UIStackView ( arrangedSubviews :  [ hangUpButton ]  ) 
 
		
	
		
			
				        ongoingCallControls. axis  =  . vertical  
 
		
	
		
			
				        ongoingCallControls. alignment  =  . center  
 
		
	
		
			
				        view. addSubview ( ongoingCallControls  ) 
 
		
	
		
			
				
 
		
	
		
			
				        ongoingCallView  =  createContainerForCallControls ( controlGroups :  [ 
 
		
	
		
			
				            [ audioModeMuteButton ,  audioSourceButton ,  audioModeVideoButton  ] , 
 
		
	
		
			
				            [ videoModeMuteButton ,  hangUpButton ,  videoModeVideoButton  ] 
 
		
	
		
			
				        ] ) 
 
		
	
		
			
				        ongoingAudioCallControls  =  UIStackView ( arrangedSubviews :  [ audioModeMuteButton ,  audioSourceButton ,  audioModeVideoButton ] ) 
 
		
	
		
			
				        ongoingAudioCallControls . distribution  =  . equalSpacing 
 
		
	
		
			
				        ongoingAudioCallControls . axis  =  . horizontal 
 
		
	
		
			
				
 
		
	
		
			
				        ongoingVideoCallControls  =  UIStackView ( arrangedSubviews :  [ videoModeMuteButton ,  videoModeFlipCameraButton ,  videoModeVideoButton ] ) 
 
		
	
		
			
				        ongoingAudioCallControls . distribution  =  . equalSpacing 
 
		
	
		
			
				        ongoingVideoCallControls . axis  =  . horizontal 
 
		
	
		
			
				    } 
 
		
	
		
			
				
 
		
	
		
			
				    func  presentAudioSourcePicker ( )  { 
 
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
			
			@ -416,59 +437,30 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
 
		
	
		
			
				        self . present ( actionSheetController ,  animated :  true ) 
 
		
	
		
			
				    } 
 
		
	
		
			
				
 
		
	
		
			
				    func  setButtonSelectedImage ( button :  UIButton ,  imageName :  String )  { 
 
		
	
		
			
				        let  image  =  UIImage ( named :  imageName ) 
 
		
	
		
			
				        assert ( image  !=  nil ) 
 
		
	
		
			
				        button . setImage ( image ,  for :  . selected ) 
 
		
	
		
			
				    } 
 
		
	
		
			
				
 
		
	
		
			
				    func  updateAvatarImage ( )  { 
 
		
	
		
			
				        contactAvatarView . image  =  OWSAvatarBuilder . buildImage ( thread :  thread ,  diameter :  400 ,  contactsManager :  contactsManager ) 
 
		
	
		
			
				    } 
 
		
	
		
			
				
 
		
	
		
			
				    func  createIncomingCallControls ( )  { 
 
		
	
		
			
				
 
		
	
		
			
				        acceptIncomingButton  =  createButton ( image Name:  " call-active-wide " , 
 
		
	
		
			
				        acceptIncomingButton  =  createButton ( image :  # imageLiteral ( resource :  " call-active-wide " ) , 
 
		
	
		
			
				                                            action :  #selector ( didPressAnswerCall ) ) 
 
		
	
		
			
				        acceptIncomingButton . accessibilityLabel  =  NSLocalizedString ( " CALL_VIEW_ACCEPT_INCOMING_CALL_LABEL " , 
 
		
	
		
			
				                                                                    comment :  " Accessibility label for accepting incoming calls " ) 
 
		
	
		
			
				        declineIncomingButton  =  createButton ( image Name:  " hangup-active-wide " , 
 
		
	
		
			
				        declineIncomingButton  =  createButton ( image :  # imageLiteral ( resource :  " hangup-active-wide " ) , 
 
		
	
		
			
				                                             action :  #selector ( didPressDeclineCall ) ) 
 
		
	
		
			
				        declineIncomingButton . accessibilityLabel  =  NSLocalizedString ( " CALL_VIEW_DECLINE_INCOMING_CALL_LABEL " , 
 
		
	
		
			
				                                                                     comment :  " Accessibility label for declining incoming calls " ) 
 
		
	
		
			
				
 
		
	
		
			
				        incomingCallView  =  createContainerForCallControls ( controlGroups :  [ 
 
		
	
		
			
				            [ acceptIncomingButton ,  declineIncomingButton  ] 
 
		
	
		
			
				            ] ) 
 
		
	
		
			
				    } 
 
		
	
		
			
				
 
		
	
		
			
				    func  createContainerForCallControls ( controlGroups :  [ [ UIView ] ] )  ->  UIView  { 
 
		
	
		
			
				        let  containerView  =  UIView ( ) 
 
		
	
		
			
				        self . view . addSubview ( containerView ) 
 
		
	
		
			
				        var  rows :  [ UIView ]  =  [ ] 
 
		
	
		
			
				        for  controlGroup  in  controlGroups  { 
 
		
	
		
			
				            rows . append ( rowWithSubviews ( subviews :  controlGroup ) ) 
 
		
	
		
			
				        } 
 
		
	
		
			
				        let  rowspacing  =  ScaleFromIPhone5To7Plus ( 6 ,  7 ) 
 
		
	
		
			
				        var  prevRow :  UIView ? 
 
		
	
		
			
				        for  row  in  rows  { 
 
		
	
		
			
				            containerView . addSubview ( row ) 
 
		
	
		
			
				            row . autoHCenterInSuperview ( ) 
 
		
	
		
			
				            if  prevRow  !=  nil  { 
 
		
	
		
			
				                row . autoPinEdge ( . top ,  to :  . bottom ,  of :  prevRow ! ,  withOffset :  rowspacing ) 
 
		
	
		
			
				            } 
 
		
	
		
			
				            prevRow  =  row 
 
		
	
		
			
				        } 
 
		
	
		
			
				        incomingCallControls  =  UIStackView ( arrangedSubviews :  [ acceptIncomingButton ,  declineIncomingButton ] ) 
 
		
	
		
			
				        incomingCallControls . axis  =  . horizontal 
 
		
	
		
			
				        incomingCallControls . alignment  =  . center 
 
		
	
		
			
				        incomingCallControls . distribution  =  . equalSpacing 
 
		
	
		
			
				
 
		
	
		
			
				        containerView . setContentHuggingVerticalHigh ( ) 
 
		
	
		
			
				        rows . first ! . autoPinEdge ( toSuperviewEdge :  . top ) 
 
		
	
		
			
				        rows . last ! . autoPinEdge ( toSuperviewEdge :  . bottom ) 
 
		
	
		
			
				        return  containerView 
 
		
	
		
			
				        view . addSubview ( incomingCallControls ) 
 
		
	
		
			
				    } 
 
		
	
		
			
				
 
		
	
		
			
				    func  createButton ( imageName :  String ,  action :  Selector )  ->  UIButton  { 
 
		
	
		
			
				        let  image  =  UIImage ( named :  imageName ) 
 
		
	
		
			
				        assert ( image  !=  nil ) 
 
		
	
		
			
				    func  createButton ( image :  UIImage ,  action :  Selector )  ->  UIButton  { 
 
		
	
		
			
				        let  button  =  UIButton ( ) 
 
		
	
		
			
				        button . setImage ( image ,  for :  . normal ) 
 
		
	
		
			
				        button . imageEdgeInsets  =  UIEdgeInsets ( top :  buttonInset ( ) , 
 
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
			
			@ -481,134 +473,81 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
 
		
	
		
			
				        return  button 
 
		
	
		
			
				    } 
 
		
	
		
			
				
 
		
	
		
			
				    //   C r e a t e s   a   r o w   c o n t a i n i n g   a   g i v e n   s e t   o f   s u b v i e w s . 
 
		
	
		
			
				    func  rowWithSubviews ( subviews :  [ UIView ] )  ->  UIView  { 
 
		
	
		
			
				        let  row  =  UIView ( ) 
 
		
	
		
			
				        row . setContentHuggingVerticalHigh ( ) 
 
		
	
		
			
				        row . autoSetDimension ( . height ,  toSize :  buttonSize ( ) ) 
 
		
	
		
			
				
 
		
	
		
			
				        if  subviews . count  >  1  { 
 
		
	
		
			
				            //   I f   t h e r e ' s   m o r e   t h a n   o n e   s u b v i e w   i n   t h e   r o w , 
 
		
	
		
			
				            //   s p a c e   t h e m   e v e n l y   w i t h i n   t h e   r o w . 
 
		
	
		
			
				            var  lastSubview :  UIView ? 
 
		
	
		
			
				            for  subview  in  subviews  { 
 
		
	
		
			
				                row . addSubview ( subview ) 
 
		
	
		
			
				                subview . setContentHuggingHorizontalHigh ( ) 
 
		
	
		
			
				                subview . autoVCenterInSuperview ( ) 
 
		
	
		
			
				
 
		
	
		
			
				                if  lastSubview  !=  nil  { 
 
		
	
		
			
				                    let  spacer  =  UIView ( ) 
 
		
	
		
			
				                    spacer . isHidden  =  true 
 
		
	
		
			
				                    row . addSubview ( spacer ) 
 
		
	
		
			
				                    spacer . autoPinEdge ( . left ,  to :  . right ,  of :  lastSubview ! ) 
 
		
	
		
			
				                    spacer . autoPinEdge ( . right ,  to :  . left ,  of :  subview ) 
 
		
	
		
			
				                    spacer . setContentHuggingHorizontalLow ( ) 
 
		
	
		
			
				                    spacer . autoVCenterInSuperview ( ) 
 
		
	
		
			
				
 
		
	
		
			
				                    if  subviews . count  = =  2  { 
 
		
	
		
			
				                        //   s p e c i a l   c a s e   t o   h a r d c o d e   t h e   s p a c e r ' s   s i z e   w h e n   t h e r e   i s   o n l y   1   s p a c e r . 
 
		
	
		
			
				                        spacer . autoSetDimension ( . width ,  toSize :  ScaleFromIPhone5To7Plus ( 46 ,  60 ) ) 
 
		
	
		
			
				                    }  else  { 
 
		
	
		
			
				                        spacer . autoSetDimension ( . width ,  toSize :  ScaleFromIPhone5To7Plus ( 3 ,  5 ) ) 
 
		
	
		
			
				                    } 
 
		
	
		
			
				                } 
 
		
	
		
			
				
 
		
	
		
			
				                lastSubview  =  subview 
 
		
	
		
			
				            } 
 
		
	
		
			
				            subviews . first ! . autoPinEdge ( toSuperviewEdge :  . left ) 
 
		
	
		
			
				            subviews . last ! . autoPinEdge ( toSuperviewEdge :  . right ) 
 
		
	
		
			
				        }  else  if  subviews . count  = =  1  { 
 
		
	
		
			
				            //   I f   t h e r e ' s   o n l y   o n e   s u b v i e w   i n   t h i s   r o w ,   c e n t e r   i t . 
 
		
	
		
			
				            let  subview  =  subviews . first ! 
 
		
	
		
			
				            row . addSubview ( subview ) 
 
		
	
		
			
				            subview . autoVCenterInSuperview ( ) 
 
		
	
		
			
				            subview . autoPinWidthToSuperview ( ) 
 
		
	
		
			
				        } 
 
		
	
		
			
				
 
		
	
		
			
				        return  row 
 
		
	
		
			
				    } 
 
		
	
		
			
				
 
		
	
		
			
				    //   MARK:   -   L a y o u t 
 
		
	
		
			
				
 
		
	
		
			
				    override  func  updateViewConstraints ( )  { 
 
		
	
		
			
				        if  ! hasConstraints  { 
 
		
	
		
			
				            //   W e   o n l y   w a n t   t o   c r e a t e   o u r   c o n s t r a i n t s   o n c e . 
 
		
	
		
			
				            // 
 
		
	
		
			
				            //   N o t e   t h a t   c o n s t r a i n t s   a r e   a l s o   c r e a t e d   e l s e w h e r e . 
 
		
	
		
			
				            //   T h i s   o n l y   c r e a t e s   t h e   c o n s t r a i n t s   f o r   t h e   t o p - l e v e l   c o n t e n t s   o f   t h e   v i e w . 
 
		
	
		
			
				            hasConstraints  =  true 
 
		
	
		
			
				
 
		
	
		
			
				            let  topMargin  =  CGFloat ( 40 ) 
 
		
	
		
			
				            let  contactHMargin  =  CGFloat ( 5 ) 
 
		
	
		
			
				            let  contactVSpacing  =  CGFloat ( 3 ) 
 
		
	
		
			
				            let  ongoingHMargin  =  ScaleFromIPhone5To7Plus ( 46 ,  72 ) 
 
		
	
		
			
				            let  incomingHMargin  =  ScaleFromIPhone5To7Plus ( 46 ,  72 ) 
 
		
	
		
			
				            let  settingsNagHMargin  =  CGFloat ( 30 ) 
 
		
	
		
			
				            let  ongoingBottomMargin  =  ScaleFromIPhone5To7Plus ( 23 ,  41 ) 
 
		
	
		
			
				            let  incomingBottomMargin  =  CGFloat ( 41 ) 
 
		
	
		
			
				            let  settingsNagBottomMargin  =  CGFloat ( 41 ) 
 
		
	
		
			
				            let  avatarTopSpacing  =  ScaleFromIPhone5To7Plus ( 25 ,  50 ) 
 
		
	
		
			
				            //   T h e   b u t t o n s   h a v e   b u i l t - i n   1 0 %   m a r g i n s ,   s o   t o   a p p e a r   c e n t e r e d 
 
		
	
		
			
				            //   t h e   a v a t a r ' s   b o t t o m   s p a c i n g   s h o u l d   b e   a   b i t   l e s s . 
 
		
	
		
			
				            let  avatarBottomSpacing  =  ScaleFromIPhone5To7Plus ( 18 ,  41 ) 
 
		
	
		
			
				            //   L a y o u t   o f   t h e   l o c a l   v i d e o   v i e w   i s   a   b i t   u n u s u a l   b e c a u s e   
 
		
	
		
			
				            //   a l t h o u g h   t h e   v i e w   i s   s q u a r e ,   i t   w i l l   b e   u s e d 
 
		
	
		
			
				            let  videoPreviewHMargin  =  CGFloat ( 0 ) 
 
		
	
		
			
				
 
		
	
		
			
				            //   D a r k   b l u r r e d   b a c k g r o u n d . 
 
		
	
		
			
				            blurView . autoPinEdgesToSuperviewEdges ( ) 
 
		
	
		
			
				
 
		
	
		
			
				            localVideoView . autoPinTrailingToSuperviewMargin ( withInset :  videoPreviewHMargin ) 
 
		
	
		
			
				            localVideoView . autoPinEdge ( toSuperviewEdge :  . top ,  withInset :  topMargin ) 
 
		
	
		
			
				            let  localVideoSize  =  ScaleFromIPhone5To7Plus ( 80 ,  100 ) 
 
		
	
		
			
				            localVideoView . autoSetDimension ( . width ,  toSize :  localVideoSize ) 
 
		
	
		
			
				            localVideoView . autoSetDimension ( . height ,  toSize :  localVideoSize ) 
 
		
	
		
			
				
 
		
	
		
			
				            remoteVideoView . autoPinEdgesToSuperviewEdges ( ) 
 
		
	
		
			
				
 
		
	
		
			
				            contactNameLabel . autoPinEdge ( toSuperviewEdge :  . top ,  withInset :  topMargin ) 
 
		
	
		
			
				            contactNameLabel . autoPinLeadingToSuperviewMargin ( withInset :  contactHMargin ) 
 
		
	
		
			
				            contactNameLabel . setContentHuggingVerticalHigh ( ) 
 
		
	
		
			
				            contactNameLabel . setCompressionResistanceHigh ( ) 
 
		
	
		
			
				
 
		
	
		
			
				            callStatusLabel . autoPinEdge ( . top ,  to :  . bottom ,  of :  contactNameLabel ,  withOffset :  contactVSpacing ) 
 
		
	
		
			
				            callStatusLabel . autoPinLeadingToSuperviewMargin ( withInset :  contactHMargin ) 
 
		
	
		
			
				            callStatusLabel . setContentHuggingVerticalHigh ( ) 
 
		
	
		
			
				            callStatusLabel . setCompressionResistanceHigh ( ) 
 
		
	
		
			
				
 
		
	
		
			
				            contactAvatarContainerView . autoPinEdge ( . top ,  to :  . bottom ,  of :  callStatusLabel ,  withOffset :  + avatarTopSpacing ) 
 
		
	
		
			
				            contactAvatarContainerView . autoPinEdge ( . bottom ,  to :  . top ,  of :  ongoingCallView ,  withOffset :  - avatarBottomSpacing ) 
 
		
	
		
			
				            contactAvatarContainerView . autoPinWidthToSuperview ( withMargin :  avatarTopSpacing ) 
 
		
	
		
			
				
 
		
	
		
			
				            contactAvatarView . autoCenterInSuperview ( ) 
 
		
	
		
			
				
 
		
	
		
			
				            //   E n s u r e   C o n t a c A v a t a r V i e w   g e t s   a s   c l o s e   a s   p o s s i b l e   t o   i t ' s   s u p e r v i e w   e d g e s   w h i l e   m a i n t a i n i n g 
 
		
	
		
			
				            //   a s p e c t   r a t i o . 
 
		
	
		
			
				            contactAvatarView . autoPinToSquareAspectRatio ( ) 
 
		
	
		
			
				            contactAvatarView . autoPinEdge ( toSuperviewEdge :  . top ,  withInset :  0 ,  relation :  . greaterThanOrEqual ) 
 
		
	
		
			
				            contactAvatarView . autoPinEdge ( toSuperviewEdge :  . right ,  withInset :  0 ,  relation :  . greaterThanOrEqual ) 
 
		
	
		
			
				            contactAvatarView . autoPinEdge ( toSuperviewEdge :  . bottom ,  withInset :  0 ,  relation :  . greaterThanOrEqual ) 
 
		
	
		
			
				            contactAvatarView . autoPinEdge ( toSuperviewEdge :  . left ,  withInset :  0 ,  relation :  . greaterThanOrEqual ) 
 
		
	
		
			
				            NSLayoutConstraint . autoSetPriority ( UILayoutPriorityDefaultLow )  { 
 
		
	
		
			
				                contactAvatarView . autoPinEdgesToSuperviewMargins ( ) 
 
		
	
		
			
				            } 
 
		
	
		
			
				    func  createViewConstraints ( )  { 
 
		
	
		
			
				        let  topMargin  =  CGFloat ( 40 ) 
 
		
	
		
			
				        let  contactVSpacing  =  CGFloat ( 3 ) 
 
		
	
		
			
				        let  settingsNagHMargin  =  CGFloat ( 30 ) 
 
		
	
		
			
				        let  ongoingBottomMargin  =  ScaleFromIPhone5To7Plus ( 23 ,  41 ) 
 
		
	
		
			
				        let  incomingHMargin  =  ScaleFromIPhone5To7Plus ( 30 ,  56 ) 
 
		
	
		
			
				        let  incomingBottomMargin  =  CGFloat ( 41 ) 
 
		
	
		
			
				        let  settingsNagBottomMargin  =  CGFloat ( 41 ) 
 
		
	
		
			
				        let  avatarTopSpacing  =  ScaleFromIPhone5To7Plus ( 25 ,  50 ) 
 
		
	
		
			
				        //   T h e   b u t t o n s   h a v e   b u i l t - i n   1 0 %   m a r g i n s ,   s o   t o   a p p e a r   c e n t e r e d 
 
		
	
		
			
				        //   t h e   a v a t a r ' s   b o t t o m   s p a c i n g   s h o u l d   b e   a   b i t   l e s s . 
 
		
	
		
			
				        let  avatarBottomSpacing  =  ScaleFromIPhone5To7Plus ( 18 ,  41 ) 
 
		
	
		
			
				        //   L a y o u t   o f   t h e   l o c a l   v i d e o   v i e w   i s   a   b i t   u n u s u a l   b e c a u s e 
 
		
	
		
			
				        //   a l t h o u g h   t h e   v i e w   i s   s q u a r e ,   i t   w i l l   b e   u s e d 
 
		
	
		
			
				        let  videoPreviewHMargin  =  CGFloat ( 0 ) 
 
		
	
		
			
				
 
		
	
		
			
				            //   O n g o i n g   c a l l   c o n t r o l s 
 
		
	
		
			
				            ongoingCallView . autoPinEdge ( toSuperviewEdge :  . bottom ,  withInset :  ongoingBottomMargin ) 
 
		
	
		
			
				            ongoingCallView . autoPinWidthToSuperview ( withMargin :  ongoingHMargin ) 
 
		
	
		
			
				            ongoingCallView . setContentHuggingVerticalHigh ( ) 
 
		
	
		
			
				        //   D a r k   b l u r r e d   b a c k g r o u n d . 
 
		
	
		
			
				        blurView . autoPinEdgesToSuperviewEdges ( ) 
 
		
	
		
			
				
 
		
	
		
			
				        localVideoView . autoPinTrailingToSuperviewMargin ( withInset :  videoPreviewHMargin ) 
 
		
	
		
			
				        localVideoView . autoPinEdge ( toSuperviewEdge :  . top ,  withInset :  topMargin ) 
 
		
	
		
			
				        let  localVideoSize  =  ScaleFromIPhone5To7Plus ( 80 ,  100 ) 
 
		
	
		
			
				        localVideoView . autoSetDimension ( . width ,  toSize :  localVideoSize ) 
 
		
	
		
			
				        localVideoView . autoSetDimension ( . height ,  toSize :  localVideoSize ) 
 
		
	
		
			
				
 
		
	
		
			
				        remoteVideoView . autoPinEdgesToSuperviewEdges ( ) 
 
		
	
		
			
				
 
		
	
		
			
				        contactNameLabel . autoPinEdge ( toSuperviewEdge :  . top ,  withInset :  topMargin ) 
 
		
	
		
			
				        contactNameLabel . autoPinLeadingToSuperviewMargin ( ) 
 
		
	
		
			
				        contactNameLabel . setContentHuggingVerticalHigh ( ) 
 
		
	
		
			
				        contactNameLabel . setCompressionResistanceHigh ( ) 
 
		
	
		
			
				
 
		
	
		
			
				        callStatusLabel . autoPinEdge ( . top ,  to :  . bottom ,  of :  contactNameLabel ,  withOffset :  contactVSpacing ) 
 
		
	
		
			
				        callStatusLabel . autoPinLeadingToSuperviewMargin ( ) 
 
		
	
		
			
				        callStatusLabel . setContentHuggingVerticalHigh ( ) 
 
		
	
		
			
				        callStatusLabel . setCompressionResistanceHigh ( ) 
 
		
	
		
			
				
 
		
	
		
			
				        contactAvatarContainerView . autoPinEdge ( . top ,  to :  . bottom ,  of :  callStatusLabel ,  withOffset :  + avatarTopSpacing ) 
 
		
	
		
			
				        contactAvatarContainerView . autoPinEdge ( . bottom ,  to :  . top ,  of :  ongoingCallControls ,  withOffset :  - avatarBottomSpacing ) 
 
		
	
		
			
				        contactAvatarContainerView . autoPinWidthToSuperview ( withMargin :  avatarTopSpacing ) 
 
		
	
		
			
				
 
		
	
		
			
				        contactAvatarView . autoCenterInSuperview ( ) 
 
		
	
		
			
				
 
		
	
		
			
				        //   E n s u r e   C o n t a c A v a t a r V i e w   g e t s   a s   c l o s e   a s   p o s s i b l e   t o   i t ' s   s u p e r v i e w   e d g e s   w h i l e   m a i n t a i n i n g 
 
		
	
		
			
				        //   a s p e c t   r a t i o . 
 
		
	
		
			
				        contactAvatarView . autoPinToSquareAspectRatio ( ) 
 
		
	
		
			
				        contactAvatarView . autoPinEdge ( toSuperviewEdge :  . top ,  withInset :  0 ,  relation :  . greaterThanOrEqual ) 
 
		
	
		
			
				        contactAvatarView . autoPinEdge ( toSuperviewEdge :  . right ,  withInset :  0 ,  relation :  . greaterThanOrEqual ) 
 
		
	
		
			
				        contactAvatarView . autoPinEdge ( toSuperviewEdge :  . bottom ,  withInset :  0 ,  relation :  . greaterThanOrEqual ) 
 
		
	
		
			
				        contactAvatarView . autoPinEdge ( toSuperviewEdge :  . left ,  withInset :  0 ,  relation :  . greaterThanOrEqual ) 
 
		
	
		
			
				        NSLayoutConstraint . autoSetPriority ( UILayoutPriorityDefaultLow )  { 
 
		
	
		
			
				            contactAvatarView . autoPinEdgesToSuperviewMargins ( ) 
 
		
	
		
			
				        } 
 
		
	
		
			
				
 
		
	
		
			
				            //   I n c o m i n g   c a l l   c o n t r o l s 
 
		
	
		
			
				            incomingCallView . autoPinEdge ( toSuperviewEdge :  . bottom ,  withInset :  incomingBottomMargin ) 
 
		
	
		
			
				            incomingCallView . autoPinWidthToSuperview ( withMargin :  incomingHMargin ) 
 
		
	
		
			
				            incomingCallView . setContentHuggingVerticalHigh ( ) 
 
		
	
		
			
				        //   O n g o i n g   c a l l   c o n t r o l s 
 
		
	
		
			
				        ongoingCallControls . autoPinEdge ( toSuperviewEdge :  . bottom ,  withInset :  ongoingBottomMargin ) 
 
		
	
		
			
				        ongoingCallControls . autoPinLeadingToSuperviewMargin ( ) 
 
		
	
		
			
				        ongoingCallControls . autoPinTrailingToSuperviewMargin ( ) 
 
		
	
		
			
				        ongoingCallControls . setContentHuggingVerticalHigh ( ) 
 
		
	
		
			
				
 
		
	
		
			
				            //   S e t t i n g s   n a g   v i e w s 
 
		
	
		
			
				            settingsNagView . autoPinEdge ( toSuperviewEdge :  . bottom ,  withInset :  settingsNagBottomMargin ) 
 
		
	
		
			
				            settingsNagView . autoPinWidthToSuperview ( withMargin :  settingsNagHMargin ) 
 
		
	
		
			
				            settingsNagView . autoPinEdge ( . top ,  to :  . bottom ,  of :  callStatusLabel ) 
 
		
	
		
			
				        } 
 
		
	
		
			
				        //   I n c o m i n g   c a l l   c o n t r o l s 
 
		
	
		
			
				        incomingCallControls . autoPinEdge ( toSuperviewEdge :  . bottom ,  withInset :  incomingBottomMargin ) 
 
		
	
		
			
				        incomingCallControls . autoPinLeadingToSuperviewMargin ( withInset :  incomin ) 
 
		
	
		
			
				        incomingCallControls . autoPinTrailingToSuperviewMargin ( withInset :  incomingHMargin ) 
 
		
	
		
			
				        incomingCallControls . setContentHuggingVerticalHigh ( ) 
 
		
	
		
			
				
 
		
	
		
			
				        //   S e t t i n g s   n a g   v i e w s 
 
		
	
		
			
				        settingsNagView . autoPinEdge ( toSuperviewEdge :  . bottom ,  withInset :  settingsNagBottomMargin ) 
 
		
	
		
			
				        settingsNagView . autoPinWidthToSuperview ( withMargin :  settingsNagHMargin ) 
 
		
	
		
			
				        settingsNagView . autoPinEdge ( . top ,  to :  . bottom ,  of :  callStatusLabel ) 
 
		
	
		
			
				    } 
 
		
	
		
			
				
 
		
	
		
			
				    override  func  updateViewConstraints ( )  { 
 
		
	
		
			
				        updateRemoteVideoLayout ( ) 
 
		
	
		
			
				        updateLocalVideoLayout ( ) 
 
		
	
		
			
				
 
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
			
			@ -738,7 +677,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
 
		
	
		
			
				        if  isShowingSettingsNag  { 
 
		
	
		
			
				            settingsNagView . isHidden  =  false 
 
		
	
		
			
				            contactAvatarView . isHidden  =  true 
 
		
	
		
			
				            ongoingCall View . isHidden  =  true 
 
		
	
		
			
				            ongoingCall Controls . isHidden  =  true 
 
		
	
		
			
				            return 
 
		
	
		
			
				        } 
 
		
	
		
			
				
 
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
			
			@ -752,10 +691,10 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
 
		
	
		
			
				
 
		
	
		
			
				        //   S h o w   I n c o m i n g   v s .   O n g o i n g   c a l l   c o n t r o l s 
 
		
	
		
			
				        let  isRinging  =  callState  = =  . localRinging 
 
		
	
		
			
				        incomingCall View . isHidden  =  ! isRinging 
 
		
	
		
			
				        incomingCall View . isUserInteractionEnabled  =  isRinging 
 
		
	
		
			
				        ongoingCall View . isHidden  =  isRinging 
 
		
	
		
			
				        ongoingCall View . isUserInteractionEnabled  =  ! isRinging 
 
		
	
		
			
				        incomingCall Controls . isHidden  =  ! isRinging 
 
		
	
		
			
				        incomingCall Controls . isUserInteractionEnabled  =  isRinging 
 
		
	
		
			
				        ongoingCall Controls . isHidden  =  isRinging 
 
		
	
		
			
				        ongoingCall Controls . isUserInteractionEnabled  =  ! isRinging 
 
		
	
		
			
				
 
		
	
		
			
				        //   R e w o r k   c o n t r o l   s t a t e   i f   r e m o t e   v i d e o   i s   a v a i l a b l e . 
 
		
	
		
			
				        let  hasRemoteVideo  =  ! remoteVideoView . isHidden 
 
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
			
			@ -764,18 +703,19 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
 
		
	
		
			
				        //   R e w o r k   c o n t r o l   s t a t e   i f   l o c a l   v i d e o   i s   a v a i l a b l e . 
 
		
	
		
			
				        let  hasLocalVideo  =  ! localVideoView . isHidden 
 
		
	
		
			
				
 
		
	
		
			
				        for  subview  in  [ audioModeMuteButton ,  audioModeVideoButton ]  { 
 
		
	
		
			
				            subview ? . isHidden  =  hasLocalVideo 
 
		
	
		
			
				        } 
 
		
	
		
			
				        for  subview  in  [ videoModeMuteButton ,  videoModeVideoButton ]  { 
 
		
	
		
			
				            subview ? . isHidden  =  ! hasLocalVideo 
 
		
	
		
			
				        if  hasLocalVideo  { 
 
		
	
		
			
				            ongoingAudioCallControls . removeFromSuperview ( ) 
 
		
	
		
			
				            ongoingCallControls . insertArrangedSubview ( ongoingVideoCallControls ,  at :  0 ) 
 
		
	
		
			
				        }  else  { 
 
		
	
		
			
				            ongoingVideoCallControls . removeFromSuperview ( ) 
 
		
	
		
			
				            ongoingCallControls . insertArrangedSubview ( ongoingAudioCallControls ,  at :  0 ) 
 
		
	
		
			
				        } 
 
		
	
		
			
				
 
		
	
		
			
				        //   A l s o   h i d e   o t h e r   c o n t r o l s   i f   u s e r   h a s   t a p p e d   t o   h i d e   t h e m . 
 
		
	
		
			
				        if  shouldRemoteVideoControlsBeHidden  &&  ! remoteVideoView . isHidden  { 
 
		
	
		
			
				            contactNameLabel . isHidden  =  true 
 
		
	
		
			
				            callStatusLabel . isHidden  =  true 
 
		
	
		
			
				            ongoingCall View . isHidden  =  true 
 
		
	
		
			
				            ongoingCall Controls . isHidden  =  true 
 
		
	
		
			
				        }  else  { 
 
		
	
		
			
				            contactNameLabel . isHidden  =  false 
 
		
	
		
			
				            callStatusLabel . isHidden  =  false 
 
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
			
			@ -915,6 +855,16 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
 
		
	
		
			
				        callUIAdapter . setHasLocalVideo ( call :  call ,  hasLocalVideo :  hasLocalVideo ) 
 
		
	
		
			
				    } 
 
		
	
		
			
				
 
		
	
		
			
				    func  didPressFlipCamera ( sender :  UIButton )  { 
 
		
	
		
			
				        //   t o g g l e   v a l u e 
 
		
	
		
			
				        sender . isSelected  =  ! sender . isSelected 
 
		
	
		
			
				
 
		
	
		
			
				        let  useBackCamera  =  sender . isSelected 
 
		
	
		
			
				        Logger . info ( " \( TAG )  in  \( #function )  with useBackCamera:  \( useBackCamera ) " ) 
 
		
	
		
			
				
 
		
	
		
			
				        callUIAdapter . setCameraSource ( call :  call ,  useBackCamera :  useBackCamera ) 
 
		
	
		
			
				    } 
 
		
	
		
			
				
 
		
	
		
			
				    /* * 
 
		
	
		
			
				     *  Denies  an  incoming  not - yet - connected  call ,  Do  not  confuse  with  ` didPressHangup ` . 
 
		
	
		
			
				     */