@ -173,59 +173,11 @@ public class AttachmentApprovalViewController: OWSViewController, MessagingToolb
let messagingToolbar = MessagingToolbar ( )
messagingToolbar . messagingToolbarDelegate = self
self . bottomToolbar = messagingToolbar
// / / l e t b o t t o m T o o l b a r : U I T o o l b a r = m a k e C l e a r T o o l b a r ( )
// s e l f . b o t t o m T o o l b a r = b o t t o m T o o l b a r
// s e l f . t e x t V i e w = U I T e x t V i e w ( )
// t e x t V i e w . d e l e g a t e = s e l f
// s e l f . t e x t V i e w . b a c k g r o u n d C o l o r = U I C o l o r . w h i t e
// s e l f . t e x t V i e w . l a y e r . c o r n e r R a d i u s = 4 . 0
//
// l e t t e x t V i e w I t e m = U I B a r B u t t o n I t e m ( c u s t o m V i e w : t e x t V i e w )
// / / t e x t V i e w . a u t o r e s i z i n g M a s k = [ . f l e x i b l e W i d t h , . f l e x i b l e H e i g h t ] ;
// t e x t V i e w . t r a n s l a t e s A u t o r e s i z i n g M a s k I n t o C o n s t r a i n t s = f a l s e
//
// l e t s e n d T i t l e = N S L o c a l i z e d S t r i n g ( " A T T A C H M E N T _ A P P R O V A L _ S E N D _ B U T T O N " , c o m m e n t : " L a b e l f o r ' s e n d ' b u t t o n i n t h e ' a t t a c h m e n t a p p r o v a l ' d i a l o g . " )
// l e t s e n d B u t t o n = U I B a r B u t t o n I t e m ( t i t l e : s e n d T i t l e ,
// s t y l e : . p l a i n ,
// t a r g e t : s e l f ,
// a c t i o n : # s e l e c t o r ( s e n d P r e s s e d ) )
// s e n d B u t t o n . t i n t C o l o r = U I C o l o r . w h i t e
//
// l e t f l e x i b l e S p a c e = U I B a r B u t t o n I t e m ( b a r B u t t o n S y s t e m I t e m : . f l e x i b l e S p a c e , t a r g e t : n i l , a c t i o n : n i l )
// b o t t o m T o o l b a r . i t e m s = [ t e x t V i e w I t e m , s e n d B u t t o n ]
// / / b o t t o m T o o l b a r . i t e m s = [ f l e x i b l e S p a c e , s e n d B u t t o n ]
// b o t t o m T o o l b a r . s e t B a c k g r o u n d I m a g e ( U I I m a g e ( ) , f o r T o o l b a r P o s i t i o n : . a n y , b a r M e t r i c s : . d e f a u l t )
// / / b o t t o m T o o l b a r . b a c k g r o u n d C o l o r = U I C o l o r . c l e a r
// b o t t o m T o o l b a r . b a c k g r o u n d C o l o r = U I C o l o r . y e l l o w
// b o t t o m T o o l b a r . a u t o S e t D i m e n s i o n ( . h e i g h t , t o S i z e : 4 0 , r e l a t i o n : . g r e a t e r T h a n O r E q u a l )
//
// l e t k T o o l b a r M a r g i n : C G F l o a t = 4 . 0
// / / t e x t V i e w . a u t o S e t D i m e n s i o n s ( t o : C G S i z e ( w i d t h : 2 0 0 , h e i g h t : 4 0 ) )
// t e x t V i e w . a u t o P i n E d g e ( t o S u p e r v i e w E d g e : . l e a d i n g , w i t h I n s e t : k T o o l b a r M a r g i n )
// t e x t V i e w . a u t o P i n E d g e ( t o S u p e r v i e w E d g e : . t o p , w i t h I n s e t : k T o o l b a r M a r g i n )
// / / T O D O g e t a c t u a l y o f f s e t b a s e d o n b u t t o n s i z e .
// l e t k T r a i l i n g O f f s e t : C G F l o a t = 8 0
// t e x t V i e w . a u t o P i n E d g e ( t o S u p e r v i e w E d g e : . t r a i l i n g , w i t h I n s e t : k T r a i l i n g O f f s e t )
// t e x t V i e w . a u t o P i n E d g e ( t o S u p e r v i e w E d g e : . b o t t o m , w i t h I n s e t : k T o o l b a r M a r g i n )
//
// s e l f . t e x t V i e w H e i g h t C o n s t r a i n t = t e x t V i e w . a u t o S e t D i m e n s i o n ( . h e i g h t , t o S i z e : k M i n T e x t V i e w H e i g h t )
// s e l f . b o t t o m T o o l b a r = M e s s a g i n g T o o l b a r ( )
// M a k i n g a t o o l b a r t r a n s p a r e n t r e q u i r e s s e t t i n g a n e m p t y u i i m a g e
// s e l f . v i e w . a d d S u b v i e w ( b o t t o m T o o l b a r )
// b o t t o m T o o l b a r . a u t o P i n ( t o B o t t o m L a y o u t G u i d e O f : s e l f , w i t h I n s e t : 0 )
// b o t t o m T o o l b a r . a u t o P i n W i d t h T o S u p e r v i e w ( )
// b o t t o m T o o l b a r . s e t C o m p r e s s i o n R e s i s t a n c e V e r t i c a l H i g h ( )
// b o t t o m T o o l b a r . s e t C o n t e n t H u g g i n g V e r t i c a l H i g h ( )
}
override public var inputAccessoryView : UIView ? {
self . bottomToolbar . layoutIfNeeded ( )
return self . bottomToolbar
// l e t t o o l b a r = U I V i e w ( f r a m e : C G R e c t ( o r i g i n : C G P o i n t . z e r o , s i z e : C G S i z e ( w i d t h : 5 0 , h e i g h t : 1 0 0 ) ) )
// t o o l b a r . b a c k g r o u n d C o l o r = U I C o l o r . p u r p l e
// r e t u r n t o o l b a r
}
override public var canBecomeFirstResponder : Bool {
@ -246,29 +198,6 @@ public class AttachmentApprovalViewController: OWSViewController, MessagingToolb
return toolbar
}
// / / MARK: - U I T e x t V i e w D e l e g a t e
//
// p u b l i c f u n c t e x t V i e w D i d C h a n g e ( _ t e x t V i e w : U I T e x t V i e w ) {
// L o g g e r . d e b u g ( " \ ( s e l f . l o g T a g ) i n \ ( # f u n c t i o n ) " )
// / / C G F l o a t f i x e d W i d t h = t e x t V i e w . f r a m e . s i z e . w i d t h ;
// / / C G S i z e n e w S i z e = [ t e x t V i e w s i z e T h a t F i t s : C G S i z e M a k e ( f i x e d W i d t h , M A X F L O A T ) ] ;
// / / C G R e c t n e w F r a m e = t e x t V i e w . f r a m e ;
// / / n e w F r a m e . s i z e = C G S i z e M a k e ( f m a x f ( n e w S i z e . w i d t h , f i x e d W i d t h ) , n e w S i z e . h e i g h t ) ;
// / / t e x t V i e w . f r a m e = n e w F r a m e ;
// l e t f i x e d W i d t h = t e x t V i e w . f r a m e . s i z e . w i d t h
// l e t n e w S i z e = t e x t V i e w . s i z e T h a t F i t s ( C G S i z e ( w i d t h : f i x e d W i d t h , h e i g h t : C G F l o a t . g r e a t e s t F i n i t e M a g n i t u d e ) )
// / / l e t n e w F r a m e = C G R e c t ( x : t e x t V i e w . f r a m e . o r i g i n . x , y : t e x t V i e w . f r a m e . o r i g i n . y , w i d t h : f i x e d W i d t h , h e i g h t : n e w S i z e . h e i g h t )
// / / L o g g e r . d e b u g ( " \ ( s e l f . l o g T a g ) o l d F r a m e : \ ( t e x t V i e w . f r a m e ) , n e w F r a m e : \ ( n e w F r a m e ) " )
//
// L o g g e r . d e b u g ( " \ ( s e l f . l o g T a g ) o l d H e i g h t : \ ( s e l f . t e x t V i e w H e i g h t C o n s t r a i n t . c o n s t a n t ) , n e w H e i g h t : \ ( n e w S i z e . h e i g h t ) " )
// / / T O D O c l a m p t o a m a x .
// s e l f . t e x t V i e w H e i g h t C o n s t r a i n t . c o n s t a n t = m a x ( k M i n T e x t V i e w H e i g h t , n e w S i z e . h e i g h t )
// s e l f . b o t t o m T o o l b a r . s e t N e e d s L a y o u t ( )
// s e l f . b o t t o m T o o l b a r . l a y o u t I f N e e d e d ( )
// / / t e x t V i e w . f r a m e = n e w F r a m e
// }
// - ( v o i d ) t e x t V i e w D i d C h a n g e : ( U I T e x t V i e w * ) t e x t V i e w
// MARK: - E v e n t H a n d l e r s
@objc
@ -286,6 +215,10 @@ public class AttachmentApprovalViewController: OWSViewController, MessagingToolb
self . sendAttachment ( )
}
func messagingToolbar ( _ messagingToolbar : MessagingToolbar , didChangeHeight newHeight : CGFloat ) {
self . scrollView . contentInset . bottom = newHeight
}
func sendAttachment ( ) {
// d i s a b l e c o n t r o l s a f t e r s e n d w a s t a p p e d .
self . bottomToolbar . isUserInteractionEnabled = false
@ -393,25 +326,28 @@ private class GradientView: UIView {
protocol MessagingToolbarDelegate : class {
func messagingToolbarDidTapSend ( _ messagingToolbar : MessagingToolbar )
func messagingToolbar ( _ messagingToolbar : MessagingToolbar , didChangeHeight newHeight : CGFloat )
}
class MessagingToolbar : UIView , UITextViewDelegate {
// l e t t o o l b a r : U I T o o l b a r
// v a r s e n d B u t t o n : U I B a r B u t t o n I t e m !
private var sendButton : UIButton !
weak var messagingToolbarDelegate : MessagingToolbarDelegate ?
private let sendButton : UIButton
private let textView : UITextView
private let kToolbarMargin : CGFloat = 4
private let kTextViewPadding : CGFloat = 4.0
private var textViewHeightConstraint : NSLayoutConstraint !
// p r i v a t e ( s e t ) v a r h e i g h t C o n s t r a i n t : N S L a y o u t C o n s t r a i n t !
// L a y o u t C o n s t a n t s
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
}
let kMinTextViewHeight : CGFloat = 38
private var kMinTextViewHeight : CGFloat {
// r e t u r n U I F o n t . o w s _ d y n a m i c T y p e B o d y ( ) . l i n e H e i g h t
return 38
var textViewHeight : CGFloat {
didSet {
// T O D O m a g i c n u m b e r s
self . messagingToolbarDelegate ? . messagingToolbar ( self , didChangeHeight : textViewHeight + 2 * 4 )
}
}
required init ? ( coder aDecoder : NSCoder ) {
@ -429,77 +365,35 @@ class MessagingToolbar: UIView, UITextViewDelegate {
}
init ( ) {
let textView = MessageTextView ( )
self . textView = textView
self . textView = MessageTextView ( )
self . sendButton = UIButton ( type : . system )
self . textViewHeight = kMinTextViewHeight
super . init ( frame : CGRect . zero )
let kSendButtonWidth : CGFloat = 100
let kMinToolbarHeight : CGFloat = 40
self . backgroundColor = UIColor . ows_inputToolbarBackground ( )
textView . delegate = self
textView . backgroundColor = UIColor . white
textView . layer . cornerRadius = 4.0
textView . addBorder ( with : UIColor . lightGray )
textView . font = UIFont . ows_dynamicTypeBody ( )
let textViewItem = UIBarButtonItem ( customView : textView )
let sendTitle = NSLocalizedString ( " ATTACHMENT_APPROVAL_SEND_BUTTON " , comment : " Label for 'send' button in the 'attachment approval' dialog. " )
let sendButton = UIButton ( type : . system )
sendButton . setTitle ( sendTitle , for : . normal )
sendButton . addTarget ( self , action : #selector ( didTapSend ) , for : . touchUpInside )
// l e t s e n d B u t t o n = U I B a r B u t t o n I t e m ( t i t l e : s e n d T i t l e ,
// s t y l e : . p l a i n ,
// t a r g e t : s e l f ,
// a c t i o n : # s e l e c t o r ( s e n d P r e s s e d ) )
// s e n d B u t t o n . w i d t h = k S e n d B u t t o n W i d t h
self . sendButton = sendButton
// T O D O
// s e l f . s e n d B u t t o n . t i t l e L a b e l . f o n t = [ U I F o n t o w s _ m e d i u m F o n t W i t h S i z e : 1 6 . f ] ;
// c e n t e r t e x t a l i g n m e n t
sendButton . titleLabel ? . font = UIFont . ows_mediumFont ( withSize : 16 )
sendButton . titleLabel ? . textAlignment = . center
sendButton . tintColor = UIColor . ows_materialBlue ( )
// 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 : 20 , left : 8 , bottom : 4 , right : 8 )
addSubview ( sendButton )
addSubview ( textView )
//
// l e t s e n d B u t t o n I t e m = U I B a r B u t t o n I t e m ( c u s t o m V i e w : s e n d B u t t o n )
//
// / / s e l f . i t e m s = [ t e x t V i e w I t e m , s e n d B u t t o n ]
// s e l f . i t e m s = [ t e x t V i e w I t e m , s e n d B u t t o n I t e m ]
//
// / / t o o l b a r d o e s n ' t r e n d e r w i t h o u t s o m e m i n i m u m h e i g h t s e t .
// / / s e l f . h e i g h t C o n s t r a i n t = s e l f . a u t o S e t D i m e n s i o n ( . h e i g h t ,
// s e l f . a u t o S e t D i m e n s i o n ( . h e i g h t ,
// t o S i z e : k M i n T e x t V i e w H e i g h t + k T o o l b a r M a r g i n * 2 ,
// r e l a t i o n : . g r e a t e r T h a n O r E q u a l )
//
self . autoMatch ( . height , to : . height , of : textView , withMultiplier : 1 , relation : . greaterThanOrEqual )
// A d d i n g t e x t V i e w t o a t o o l b a r i t e m i n s e r t s i t i n t o a " h o s t V i e w "
// T h i s i s n ' t r e a l l y d o c u m e n t d , b u t I ' v e v e r i f i e d i t w o r k s o n i O S 9 a n d i O S 1 0
self . textViewHeightConstraint = textView . autoSetDimension ( . height , toSize : kMinTextViewHeight )
textView . autoPinEdge ( toSuperviewEdge : . leading , withInset : kToolbarMargin )
textView . autoPinEdge ( toSuperviewEdge : . top , withInset : kToolbarMargin )
textView . autoPinEdge ( toSuperviewEdge : . bottom , withInset : kToolbarMargin )
//
// / / l e t k T r a i l i n g O f f s e t : C G F l o a t = k S e n d B u t t o n W i d t h
// / / t e x t V i e w . a u t o P i n E d g e ( t o S u p e r v i e w E d g e : . t r a i l i n g , w i t h I n s e t : k T r a i l i n g O f f s e t )
//
textView . autoPinEdge ( . trailing , to : . leading , of : sendButton , withOffset : - 8 )
sendButton . sizeToFit ( )
sendButton . autoPinEdge ( toSuperviewEdge : . trailing , withInset : kToolbarMargin )
sendButton . autoPinEdge ( toSuperviewEdge : . bottom , withInset : kToolbarMargin )
textView . delegate = self
}
func didTapSend ( ) {
@ -511,60 +405,57 @@ class MessagingToolbar: UIView, UITextViewDelegate {
public func textViewDidChange ( _ textView : UITextView ) {
Logger . debug ( " \( self . logTag ) in \( #function ) " )
// W e d o n ' t w a n t t h e t e x t V i e w t o g r o w i n d e f i n i t e l y
let kMaxTextViewHeight : CGFloat = 160
// 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 )
let fixedWidth = textView . frame . size . width
let newSize = textView . sizeThatFits ( CGSize ( width : fixedWidth , height : CGFloat . greatestFiniteMagnitude ) )
let newHeight = Clamp ( newSize . height , kMinTextViewHeight , kMaxTextViewHeight )
if newHeight != self . textViewHeightConstraint . constant {
Logger . debug ( " \( self . logTag ) oldHeight: \( self . textViewHeightConstraint . constant ) , newHeight: \( newHeight ) " )
self . textViewHeightConstraint . constant = newHeight
self . textView . frame = CGRect ( x : 0 , y : 0 , width : self . textView . frame . size . width , height : newHeight )
// U I V i e w . a n i m a t e ( w i t h D u r a t i o n : 0 . 1 ) {
if newHeight != self . textViewHeight {
Logger . debug ( " \( self . logTag ) TextView height changed: \( self . textViewHeight ) -> \( newHeight ) " )
self . textViewHeight = newHeight
self . setNeedsLayout ( )
self . layoutIfNeeded ( )
self . textView . reloadInputViews ( )
} else {
Logger . debug ( " \( self . logTag ) height unchanged: \( self . textViewHeightConstraint . constant ) " )
}
}
private func clampedTextViewHeight ( fixedWidth : CGFloat ) -> CGFloat {
let contentSize = textView . sizeThatFits ( CGSize ( width : fixedWidth , height : CGFloat . greatestFiniteMagnitude ) )
return Clamp ( contentSize . height , kMinTextViewHeight , maxTextViewHeight )
}
// W e d o p r o g a m m a t i c l a y o u t , e x p l i c i t l y c o m p u t i n g a n d s e t t i n g f r a m e s s i n c e a u t o L a y o u t d o e s
// n o t s e e m t o w o r k w i t h i n p u t A c c e s s o r y v i e w s , e v e n w h e n f o r c i n g a l a y o u t .
override func layoutSubviews ( ) {
super . layoutSubviews ( )
Logger . info ( " \( self . logTag ) in \( #function ) " )
Logger . info ( " textView: \( self . textView . frame ) , sendButton: \( sendButton . frame ) " )
Logger . debug ( " \( self . logTag ) in \( #function ) " )
Logger . debug( " Before layout >>> self: \( self . frame ) textView: \( self . textView . frame ) , sendButton: \( sendButton . frame ) " )
// U p d a t i n g t h e a u t o L a y o u t c o n s t r a i n t s w a s n o t s u f f i c i e n t t o p r o p e r l y s e t t h e f r a m e o f t h e i n p u t A c c e s s o r y V i e w ,
// s o w e m a n u a l l y u p d a t e t h e r e l e v a n t f r a m e s h e r e .
let originalTextViewFrame = self . textView . frame
let newTextViewFrame = CGRect ( x : originalTextViewFrame . origin . x , y : originalTextViewFrame . origin . y , width : originalTextViewFrame . width , height : self . textViewHeightConstraint . constant )
self . textView . frame = newTextViewFrame
let kToolbarMargin : CGFloat = 4
let diffY = newTextViewFrame . height - originalTextViewFrame . height
let originalFrame = self . frame
let newFrame = CGRect ( x : originalFrame . origin . x , y : originalFrame . origin . y - diffY , width : originalFrame . width , height : originalFrame . size . height + diffY )
self . frame = newFrame
let sendButtonWidth = sendButton . frame . size . width
//
// l e t k M a r g i n = 4
// l e t k T e x t V i e w H e i g h t = 4 0
// l e t k T e x t V i e w W i d t h = 2 0 0
//
// l e t k S e n d B u t t o n H e i g h t = 4 0
// l e t k S e n d B u t t o n W i d t h = 1 0 0
//
// s e l f . t e x t V i e w . f r a m e = C G R e c t ( x : k M a r g i n , y : k M a r g i n , w i d t h : k T e x t V i e w W i d t h , h e i g h t : k T e x t V i e w H e i g h t )
// s e l f . s e n d B u t t o n . f r a m e = C G R e c t ( x : k M a r g i n * 2 + k T e x t V i e w W i d t h , y : k M a r g i n , w i d t h : k S e n d B u t t o n W i d t h , h e i g h t : k S e n d B u t t o n H e i g h t )
// s e l f . f r a m e = C G R e c t ( x : 0 , y : 0 , w i d t h : 3 2 0 , h e i g h t : k T e x t V i e w H e i g h t + 2 * k M a r g i n )
// s e l f . b o u n d s = s e l f . f r a m e
//
// / / s e l f . t e x t V i e w . s i z e T o F i t ( )
//
// / / l e t m a x H e i g h t = m a x ( s e l f . s e n d B u t t o n . f r a m e . s i z e . h e i g h t , s e l f . t e x t V i e w . f r a m e . s i z e . h e i g h t )
// / / l e t f i t t e d F r a m e = C G R e c t ( x : f r a m e . o r i g i n . x , y : f r a m e . o r i g i n . y , w i d t h : f r a m e . s i z e . w i d t h , h e i g h t : m a x H e i g h t )
// / / s e l f . f r a m e = f i t t e d F r a m e
// / / s e l f . b o u n d s = f i t t e d F r a m e
let kOriginalToolbarHeight = kMinTextViewHeight + 2 * kToolbarMargin
// A s s u m e s e n d b u t t o n h a s p r o p e r s i z e .
let textViewWidth = frame . size . width - 3 * kToolbarMargin - sendButtonWidth
// d e t e r m i n e h e i g h t g i v e n a f i x e d w i d t h
let textViewHeight = clampedTextViewHeight ( fixedWidth : textViewWidth )
textView . frame = CGRect ( x : kToolbarMargin , y : kToolbarMargin , width : textViewWidth , height : textViewHeight )
assert ( self . textViewHeight = = textViewHeight , " textView.height inconsistent with what was computed in textViewDidChange " )
let newToolbarHeight = textViewHeight + 2 * kToolbarMargin
// f r a m e o r i g i n i s w i t h r e s p e c t t o t h e i n i t i a l h e i g h t o f t h e t o o l b a r , s o w e m u s t o f f s e t t h e t o o l b a r f r a m e
// b y t h e d i f f e r e n c e , e l s e t h e t o o l b a r w i l l e x t e n d i n t o a n d b e h i n d t h e k e y b o a r d .
let toolbarHeightOffset = kOriginalToolbarHeight - newToolbarHeight
self . frame = CGRect ( x : 0 , y : toolbarHeightOffset , width : frame . size . width , height : newToolbarHeight )
// S e n d B u t t o n
// p o s i t i o n i n b o t t o m r i g h t c o r n e r
let sendButtonX = frame . size . width - kToolbarMargin - sendButton . frame . size . width
let sendButtonY = frame . size . height - kToolbarMargin - sendButton . frame . size . height
sendButton . frame = CGRect ( origin : CGPoint ( x : sendButtonX , y : sendButtonY ) , size : sendButton . frame . size )
Logger . debug ( " After layout >>> self: \( self . frame ) textView: \( self . textView . frame ) , sendButton: \( sendButton . frame ) " )
}
}