@ -484,6 +484,7 @@ class CaptioningToolbar: UIView, UITextViewDelegate {
private let sendButton : UIButton
private let textView : UITextView
private let bottomGradient : GradientView
private let lengthLimitLabel : UILabel
// L a y o u t C o n s t a n t s
@ -523,6 +524,7 @@ class CaptioningToolbar: UIView, UITextViewDelegate {
self . bottomGradient = GradientView ( from : UIColor . clear , to : UIColor . black )
self . textView = MessageTextView ( )
self . textViewHeight = kMinTextViewHeight
self . lengthLimitLabel = UILabel ( )
super . init ( frame : CGRect . zero )
@ -560,12 +562,24 @@ class CaptioningToolbar: UIView, UITextViewDelegate {
// 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 )
// 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_CAPTION_LENGTH_LIMIT_REACHED " , comment : " One line label indicating the user can add no more text to the attachment caption. " )
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 = CGSize ( width : 0.0 , height : 0.0 )
lengthLimitLabel . layer . shadowOpacity = 0.8
self . lengthLimitLabel . isHidden = true
let contentView = UIView ( )
addSubview ( contentView )
contentView . autoPinEdgesToSuperviewEdges ( )
contentView . addSubview ( bottomGradient )
contentView . addSubview ( sendButton )
contentView . addSubview ( textView )
contentView . addSubview ( lengthLimitLabel )
// L a y o u t
let kToolbarMargin : CGFloat = 8
@ -597,6 +611,12 @@ class CaptioningToolbar: UIView, UITextViewDelegate {
sendButton . setContentHuggingHigh ( )
sendButton . setCompressionResistanceHigh ( )
lengthLimitLabel . autoPinEdge ( toSuperviewMargin : . left )
lengthLimitLabel . autoPinEdge ( toSuperviewMargin : . right )
lengthLimitLabel . autoPinEdge ( . bottom , to : . top , of : textView , withOffset : - 6 )
lengthLimitLabel . setContentHuggingHigh ( )
lengthLimitLabel . setCompressionResistanceHigh ( )
let bottomGradientHeight = ScaleFromIPhone5 ( 100 )
bottomGradient . autoSetDimension ( . height , toSize : bottomGradientHeight )
bottomGradient . autoPinEdgesToSuperviewEdges ( with : . zero , excludingEdge : . top )
@ -609,19 +629,28 @@ class CaptioningToolbar: UIView, UITextViewDelegate {
// MARK: - U I T e x t V i e w D e l e g a t e
public func textViewDidChange ( _ 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 )
updateHeight ( textView : textView )
}
if newHeight != self . textViewHeight {
Logger . debug ( " \( self . logTag ) TextView height changed: \( self . textViewHeight ) -> \( newHeight ) " )
self . textViewHeight = newHeight
self . textViewHeightConstraint ? . constant = textViewHeight
self . invalidateIntrinsicContentSize ( )
public func textView ( _ textView : UITextView , shouldChangeTextIn range : NSRange , replacementText text : String ) -> Bool {
// L i m i t c a p t i o n c h a r a c t e r c o u n t . W e d o t h i s i n c h a r a c t e r s , n o t b y t e s .
// T h i s c h a r a c t e r l i m i t w i l l b e s a f e l y b e l o w o u r b y t e l i m i t ( 1 6 k ) f o r a l m o s t a l l u s e s .
// B e c a u s e t h e c a p t i o n i n g i n t e r f a c e d o e s n ' t a l l o w n e w l i n e s , i n p r a c t i c e d e s i g n p r e s s u r e s u s e r s t o l e a v e r e l a t i v e l y s h o r t c a p t i o n s .
let maxCharacterCount = 2000
guard textView . text . count + text . count - range . length <= maxCharacterCount else {
self . lengthLimitLabel . isHidden = false
// 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 remainingSpace = maxCharacterCount - textView . text . count
if ( remainingSpace ) > 0 {
let acceptableAddition = text . substring ( to : text . startIndex . advanced ( by : remainingSpace ) )
textView . text = " \( textView . text ? ? " " ) \( acceptableAddition ) "
updateHeight ( textView : textView )
}
return false
}
self . lengthLimitLabel . isHidden = true
public func textView ( _ textView : UITextView , shouldChangeTextIn range : NSRange , replacementText text : String ) -> Bool {
// 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 " {
@ -642,6 +671,19 @@ class CaptioningToolbar: UIView, UITextViewDelegate {
// MARK: - H e l p e r s
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 != self . textViewHeight {
Logger . debug ( " \( self . logTag ) TextView height changed: \( self . textViewHeight ) -> \( newHeight ) " )
self . textViewHeight = newHeight
self . textViewHeightConstraint ? . constant = textViewHeight
self . invalidateIntrinsicContentSize ( )
}
}
private func clampedTextViewHeight ( fixedWidth : CGFloat ) -> CGFloat {
let contentSize = textView . sizeThatFits ( CGSize ( width : fixedWidth , height : CGFloat . greatestFiniteMagnitude ) )
return Clamp ( contentSize . height , kMinTextViewHeight , maxTextViewHeight )