//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//     C o p y r i g h t   ( c )   2 0 1 9   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  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  UIKit  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//   C o i n c i d e s   w i t h   A n d r o i d ' s   m a x   t e x t   m e s s a g e   l e n g t h  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								let  kMaxMessageBodyCharacterCount  =  2000  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								protocol  AttachmentTextToolbarDelegate :  class  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    func  attachmentTextToolbarDidTapSend ( _  attachmentTextToolbar :  AttachmentTextToolbar ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    func  attachmentTextToolbarDidBeginEditing ( _  attachmentTextToolbar :  AttachmentTextToolbar ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    func  attachmentTextToolbarDidEndEditing ( _  attachmentTextToolbar :  AttachmentTextToolbar ) 
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    func  attachmentTextToolbarDidChange ( _  attachmentTextToolbar :  AttachmentTextToolbar ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//   MARK:   -  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  AttachmentTextToolbar :  UIView ,  UITextViewDelegate  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    weak  var  attachmentTextToolbarDelegate :  AttachmentTextToolbarDelegate ? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    var  messageText :  String ?  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        get  {  return  textView . text  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        set  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            textView . text  =  newValue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            updatePlaceholderTextViewVisibility ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   L a y o u t   C o n s t a n t s 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    let  kMinTextViewHeight :  CGFloat  =  40 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    var  maxTextViewHeight :  CGFloat  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        //   A b o u t   ~ 4   l i n e s   i n   p o r t r a i t   a n d   ~ 3   l i n e s   i n   l a n d s c a p e . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        //   O t h e r w i s e   w e   r i s k   o b s c u r i n g   t o o   m u c h   o f   t h e   c o n t e n t . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  UIDevice . current . orientation . isPortrait  ?  160  :  100 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    var  textViewHeightConstraint :  NSLayoutConstraint ! 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    var  textViewHeight :  CGFloat 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   MARK:   -   I n i t i a l i z e r s 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    init ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . sendButton  =  UIButton ( type :  . system ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . textViewHeight  =  kMinTextViewHeight 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        super . init ( frame :  CGRect . zero ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        //   S p e c i f y i n g   a u t o r s i z i n g   m a s k   a n d   a n   i n t r i n s i c   c o n t e n t   s i z e   a l l o w s   p r o p e r 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        //   s i z i n g   w h e n   u s e d   a s   a n   i n p u t   a c c e s s o r y   v i e w . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . autoresizingMask  =  . flexibleHeight 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . translatesAutoresizingMaskIntoConstraints  =  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . backgroundColor  =  UIColor . clear 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        textView . delegate  =  self 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        let  sendTitle  =  NSLocalizedString ( " ATTACHMENT_APPROVAL_SEND_BUTTON " ,  comment :  " Label for 'send' button in the 'attachment approval' dialog. " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        sendButton . setTitle ( sendTitle ,  for :  . normal ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        sendButton . addTarget ( self ,  action :  #selector ( didTapSend ) ,  for :  . touchUpInside ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								        sendButton . titleLabel ? . font  =  . boldSystemFont ( ofSize :  Values . mediumFontSize ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        sendButton . titleLabel ? . textAlignment  =  . center 
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								        sendButton . tintColor  =  Colors . accent 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        //   I n c r e a s e   h i t   a r e a   o f   s e n d   b u t t o n 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        sendButton . contentEdgeInsets  =  UIEdgeInsets ( top :  6 ,  left :  8 ,  bottom :  6 ,  right :  8 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        let  contentView  =  UIView ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        contentView . addSubview ( sendButton ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        contentView . addSubview ( textContainer ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        contentView . addSubview ( lengthLimitLabel ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        addSubview ( contentView ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        contentView . autoPinEdgesToSuperviewEdges ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        //   L a y o u t 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        let  kToolbarMargin :  CGFloat  =  8 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        //   W e   h a v e   t o   w r a p   t h e   t o o l b a r   i t e m s   i n   a   c o n t e n t   v i e w   b e c a u s e   i O S   ( a t   l e a s t   o n   i O S 1 0 . 3 )   a s s i g n s   t h e   i n p u t A c c e s s o r y V i e w . l a y o u t M a r g i n s 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        //   w h e n   r e s i g n i n g   f i r s t   r e s p o n d e r   ( v e r i f i e d   b y   a u d i t i n g   w i t h   ` l a y o u t M a r g i n s D i d C h a n g e ` ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        //   T h e   e f f e c t   o f   t h i s   i s   t h a t   i f   w e   w e r e   t o   a s s i g n   t h e s e   m a r g i n s   t o   s e l f . l a y o u t M a r g i n s ,   t h e y ' d   b e   b l o w n   a w a y   i f   t h e 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        //   u s e r   d i s m i s s e s   t h e   k e y b o a r d ,   g i v i n g   t h e   i n p u t   a c c e s s o r y   v i e w   a   w o n k y   l a y o u t . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        contentView . layoutMargins  =  UIEdgeInsets ( top :  kToolbarMargin ,  left :  kToolbarMargin ,  bottom :  kToolbarMargin ,  right :  kToolbarMargin ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . textViewHeightConstraint  =  textView . autoSetDimension ( . height ,  toSize :  kMinTextViewHeight ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        //   W e   p i n   a l l   t h r e e   e d g e s   e x p l i c i t l y   r a t h e r   t h a n   d o i n g   s o m e t h i n g   l i k e : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        //     t e x t V i e w . a u t o P i n E d g e s ( t o S u p e r v i e w M a r g i n s E x c l u d i n g E d g e :   . r i g h t ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        //   b e c a u s e   t h a t   m e t h o d   u s e s   ` l e a d i n g `   /   ` t r a i l i n g `   r a t h e r   t h a n   ` l e f t `   v s .   ` r i g h t ` . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        //   S o   i t   d o e s n ' t   w o r k   a s   e x p e c t e d   w i t h   R T L   l a y o u t s   w h e n   w e   e x p l i c i t l y   w a n t   s o m e t h i n g 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        //   t o   b e   o n   t h e   r i g h t   s i d e   f o r   b o t h   R T L   a n d   L T R   l a y o u t s ,   l i k e   w i t h   t h e   s e n d   b u t t o n . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        //   I   b e l i e v e   t h i s   i s   a   b u g   i n   P u r e L a y o u t .   F i l e d   h e r e :   h t t p s : / / g i t h u b . c o m / P u r e L a y o u t / P u r e L a y o u t / i s s u e s / 2 0 9 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        textContainer . autoPinEdge ( toSuperviewMargin :  . top ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        textContainer . autoPinEdge ( toSuperviewMargin :  . bottom ) 
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								        textContainer . autoPinEdge ( toSuperviewMargin :  . left ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        sendButton . autoPinEdge ( . left ,  to :  . right ,  of :  textContainer ,  withOffset :  kToolbarMargin ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        sendButton . autoPinEdge ( . bottom ,  to :  . bottom ,  of :  textContainer ,  withOffset :  - 3 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        sendButton . autoPinEdge ( toSuperviewMargin :  . right ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        sendButton . setContentHuggingHigh ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        sendButton . setCompressionResistanceHigh ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        lengthLimitLabel . autoPinEdge ( toSuperviewMargin :  . left ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        lengthLimitLabel . autoPinEdge ( toSuperviewMargin :  . right ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        lengthLimitLabel . autoPinEdge ( . bottom ,  to :  . top ,  of :  textContainer ,  withOffset :  - 6 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        lengthLimitLabel . setContentHuggingHigh ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        lengthLimitLabel . setCompressionResistanceHigh ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    required  init ? ( coder  aDecoder :  NSCoder )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        notImplemented ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   MARK:   -   U I V i e w   O v e r r i d e s 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    override  var  intrinsicContentSize :  CGSize  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        get  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            //   S i n c e   w e   h a v e   ` s e l f . a u t o r e s i z i n g M a s k   =   U I V i e w A u t o r e s i z i n g F l e x i b l e H e i g h t ` ,   w e   m u s t   s p e c i f y 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            //   a n   i n t r i n s i c C o n t e n t S i z e .   S p e c i f y i n g   C G S i z e . z e r o   c a u s e s   t h e   h e i g h t   t o   b e   d e t e r m i n e d   b y   a u t o l a y o u t . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  CGSize . zero 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   MARK:   -   S u b v i e w s 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    private  let  sendButton :  UIButton 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    private  lazy  var  lengthLimitLabel :  UILabel  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        let  lengthLimitLabel  =  UILabel ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        //   L e n g t h   L i m i t   L a b e l   s h o w n   w h e n   t h e   u s e r   i n p u t s   t o o   l o n g   o f   a   m e s s a g e 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        lengthLimitLabel . textColor  =  . white 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        lengthLimitLabel . text  =  NSLocalizedString ( " ATTACHMENT_APPROVAL_MESSAGE_LENGTH_LIMIT_REACHED " ,  comment :  " One-line label indicating the user can add no more text to the media message field. " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        lengthLimitLabel . textAlignment  =  . center 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        //   A d d   s h a d o w   i n   c a s e   o v e r l a y e d   o n   w h i t e   c o n t e n t 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        lengthLimitLabel . layer . shadowColor  =  UIColor . black . cgColor 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        lengthLimitLabel . layer . shadowOffset  =  . zero 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        lengthLimitLabel . layer . shadowOpacity  =  0.8 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        lengthLimitLabel . layer . shadowRadius  =  2.0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        lengthLimitLabel . isHidden  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  lengthLimitLabel 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    lazy  var  textView :  UITextView  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        let  textView  =  buildTextView ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        textView . returnKeyType  =  . done 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        textView . scrollIndicatorInsets  =  UIEdgeInsets ( top :  5 ,  left :  0 ,  bottom :  5 ,  right :  3 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  textView 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    private  lazy  var  placeholderTextView :  UITextView  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        let  placeholderTextView  =  buildTextView ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								        placeholderTextView . text  =  NSLocalizedString ( " Message " ,  comment :  " " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        placeholderTextView . isEditable  =  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  placeholderTextView 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    private  lazy  var  textContainer :  UIView  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        let  textContainer  =  UIView ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								        textContainer . layer . borderColor  =  UIColor . white . cgColor 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        textContainer . layer . borderWidth  =  Values . separatorThickness 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        textContainer . layer . cornerRadius  =  kMinTextViewHeight  /  2 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        textContainer . clipsToBounds  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        textContainer . addSubview ( placeholderTextView ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        placeholderTextView . autoPinEdgesToSuperviewEdges ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        textContainer . addSubview ( textView ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        textView . autoPinEdgesToSuperviewEdges ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  textContainer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    private  func  buildTextView ( )  ->  UITextView  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        let  textView  =  AttachmentTextView ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								        textView . keyboardAppearance  =  isLightMode  ?  . default  :  . dark 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        textView . backgroundColor  =  . clear 
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								        textView . tintColor  =  . white 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								        textView . font  =  . systemFont ( ofSize :  Values . mediumFontSize ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        textView . textColor  =  . white 
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								        textView . showsVerticalScrollIndicator  =  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        textView . textContainerInset  =  UIEdgeInsets ( top :  10 ,  left :  10 ,  bottom :  10 ,  right :  10 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  textView 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   MARK:   -   A c t i o n s 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    @objc  func  didTapSend ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        attachmentTextToolbarDelegate ? . attachmentTextToolbarDidTapSend ( self ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   MARK:   -   U I T e x t V i e w D e l e g a t e 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  func  textViewDidChange ( _  textView :  UITextView )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        updateHeight ( textView :  textView ) 
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								        attachmentTextToolbarDelegate ? . attachmentTextToolbarDidChange ( self ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  func  textView ( _  textView :  UITextView ,  shouldChangeTextIn  range :  NSRange ,  replacementText  text :  String )  ->  Bool  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ! FeatureFlags . sendingMediaWithOversizeText  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            let  existingText :  String  =  textView . text  ? ?  " " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            let  proposedText :  String  =  ( existingText  as  NSString ) . replacingCharacters ( in :  range ,  with :  text ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            //   D o n ' t   c o m p l i c a t e   t h i n g s   b y   m i x i n g   m e d i a   a t t a c h m e n t s   w i t h   o v e r s i z e   t e x t   a t t a c h m e n t s 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            guard  proposedText . utf8 . count  <  kOversizeTextMessageSizeThreshold  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                Logger . debug ( " long text was truncated " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                self . lengthLimitLabel . isHidden  =  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                //   ` r a n g e `   r e p r e s e n t s   t h e   s e c t i o n   o f   t h e   e x i s t i n g   t e x t   w e   w i l l   r e p l a c e .   W e   c a n   r e - u s e   t h a t   s p a c e . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                //   R a n g e   i s   i n   u n i t s   o f   N S S t r i n g s ' s   s t a n d a r d   U T F - 1 6   c h a r a c t e r s .   S i n c e   s o m e   o f   t h o s e   c h a r s   c o u l d   b e 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                //   r e p r e s e n t e d   a s   s i n g l e   b y t e s   i n   u t f - 8 ,   w h i l e   o t h e r s   m a y   b e   8   o r   m o r e ,   t h e   o n l y   w a y   t o   b e   s u r e   i s 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                //   t o   j u s t   m e a s u r e   t h e   u t f 8   e n c o d e d   b y t e s   o f   t h e   r e p l a c e d   s u b s t r i n g . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                let  bytesAfterDelete :  Int  =  ( existingText  as  NSString ) . replacingCharacters ( in :  range ,  with :  " " ) . utf8 . count 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                //   A c c e p t   a s   m u c h   o f   t h e   i n p u t   a s   w e   c a n 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                let  byteBudget :  Int  =  Int ( kOversizeTextMessageSizeThreshold )  -  bytesAfterDelete 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  byteBudget  >=  0 ,  let  acceptableNewText  =  text . truncated ( toByteCount :  UInt ( byteBudget ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    textView . text  =  ( existingText  as  NSString ) . replacingCharacters ( in :  range ,  with :  acceptableNewText ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . lengthLimitLabel . isHidden  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            //   A f t e r   v e r i f y i n g   t h e   b y t e - l e n g t h   i s   s u f f i c i e n t l y   s m a l l ,   v e r i f y   t h e   c h a r a c t e r   c o u n t   i s   w i t h i n   b o u n d s . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            guard  proposedText . count  <  kMaxMessageBodyCharacterCount  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                Logger . debug ( " hit attachment message body character count limit " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                self . lengthLimitLabel . isHidden  =  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                //   ` r a n g e `   r e p r e s e n t s   t h e   s e c t i o n   o f   t h e   e x i s t i n g   t e x t   w e   w i l l   r e p l a c e .   W e   c a n   r e - u s e   t h a t   s p a c e . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                let  charsAfterDelete :  Int  =  ( existingText  as  NSString ) . replacingCharacters ( in :  range ,  with :  " " ) . count 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                //   A c c e p t   a s   m u c h   o f   t h e   i n p u t   a s   w e   c a n 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                let  charBudget :  Int  =  Int ( kMaxMessageBodyCharacterCount )  -  charsAfterDelete 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  charBudget  >=  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    let  acceptableNewText  =  String ( text . prefix ( charBudget ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    textView . text  =  ( existingText  as  NSString ) . replacingCharacters ( in :  range ,  with :  acceptableNewText ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        //   T h o u g h   w e   c a n   w r a p   t h e   t e x t ,   w e   d o n ' t   w a n t   t o   e n c o u r a g e   m u l t l i n e   c a p t i o n s ,   p l u s   a   " d o n e "   b u t t o n 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        //   a l l o w s   t h e   u s e r   t o   g e t   t h e   k e y b o a r d   o u t   o f   t h e   w a y   w h i l e   i n   t h e   a t t a c h m e n t   a p p r o v a l   v i e w . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  text  = =  " \n "  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            textView . resignFirstResponder ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  func  textViewDidBeginEditing ( _  textView :  UITextView )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        attachmentTextToolbarDelegate ? . attachmentTextToolbarDidBeginEditing ( self ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        updatePlaceholderTextViewVisibility ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  func  textViewDidEndEditing ( _  textView :  UITextView )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        attachmentTextToolbarDelegate ? . attachmentTextToolbarDidEndEditing ( self ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        updatePlaceholderTextViewVisibility ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   MARK:   -   H e l p e r s 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    func  updatePlaceholderTextViewVisibility ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        let  isHidden :  Bool  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            guard  ! self . textView . isFirstResponder  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            guard  let  text  =  self . textView . text  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            guard  text . count  >  0  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        placeholderTextView . isHidden  =  isHidden 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    private  func  updateHeight ( textView :  UITextView )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        //   c o m p u t e   n e w   h e i g h t   a s s u m i n g   w i d t h   i s   u n c h a n g e d 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        let  currentSize  =  textView . frame . size 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        let  newHeight  =  clampedTextViewHeight ( fixedWidth :  currentSize . width ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  newHeight  !=  textViewHeight  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            Logger . debug ( " TextView height changed:  \( textViewHeight )  ->  \( newHeight ) " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            textViewHeight  =  newHeight 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            textViewHeightConstraint ? . constant  =  textViewHeight 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            invalidateIntrinsicContentSize ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    private  func  clampedTextViewHeight ( fixedWidth :  CGFloat )  ->  CGFloat  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        let  contentSize  =  textView . sizeThatFits ( CGSize ( width :  fixedWidth ,  height :  CGFloat . greatestFiniteMagnitude ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  CGFloatClamp ( contentSize . height ,  kMinTextViewHeight ,  maxTextViewHeight ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}