diff --git a/CHANGELOG.md b/CHANGELOG.md index e70bd700..d1d5d577 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,9 +19,14 @@ The changelog for `MessageKit`. Also see the [releases](https://github.com/Messa [#162](https://github.com/MessageKit/MessageKit/pull/162) by [@SD10](https://github.com/SD10). ### Fixed + +- `MessageInputBar` now correctly sizes itself when breaking its max height or pasting in large amounts of text +[#173](https://github.com/MessageKit/MessageKit/pull/173) by [@nathantannar4](https://github.com/nathantannar4). + - `MessageInputBar` faced a rendering issue on subsequent presentations of a `MessageViewController`. This was originally patched by adding a copy to the view during `viewDidAppear(animated:)` however that led to other issues [#116](https://github.com/MessageKit/MessageKit/issues/116). A correct patch has now been applied. [#178](https://github.com/MessageKit/MessageKit/pull/178) by [@nathantannar4](https://github.com/nathantannar4). + ### Changed - **Breaking Change** `snapshotOptionsForLocation` method is now part of `LocationMessageDisplayDelegate`. [#150](https://github.com/MessageKit/MessageKit/pull/150) by [@etoledom](https://github.com/etoledom). @@ -34,7 +39,10 @@ The changelog for `MessageKit`. Also see the [releases](https://github.com/Messa - **Breaking Change** `messageLabelInsets` now defaults to a `left` inset of 18 for incoming messages and a `right` inset of 18 for outgoing messages. -[#162](https://github.com/MessageKit/MessageKit/pull/162) by [@SD10](https://github.com/SD10). +[#162](https://github.com/MessageKit/MessageKit/pull/162) by [@SD10](https://github.com/SD10). + +- **Breaking Change** `InputTextView`'s `UITextViewDelegate` is now set to `self` +[#173](https://github.com/MessageKit/MessageKit/pull/173) by [@nathantannar4](https://github.com/nathantannar4). ### Removed - **Breaking Change** `cellTopLabelInsets` and `cellBottomLabelInsets` from `MessagesCollectionViewFlowLayout`. diff --git a/Sources/InputTextView.swift b/Sources/InputTextView.swift index 4c793537..aa5242c9 100644 --- a/Sources/InputTextView.swift +++ b/Sources/InputTextView.swift @@ -24,7 +24,7 @@ import UIKit -open class InputTextView: UITextView { +open class InputTextView: UITextView, UITextViewDelegate { // MARK: - Properties @@ -118,6 +118,7 @@ open class InputTextView: UITextView { layer.cornerRadius = 5.0 layer.borderWidth = 1.25 layer.borderColor = UIColor.lightGray.cgColor + delegate = self addSubviews() addConstraints() @@ -145,5 +146,20 @@ open class InputTextView: UITextView { placeholderLabelConstraintSet?.left?.constant = placeholderLabelInsets.left placeholderLabelConstraintSet?.right?.constant = -placeholderLabelInsets.bottom } - + + // MARK: - UITextViewDelegate + + public func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { + + // When isScrollEnabled gets changed in MessageInputBar when it becomes more than the maxHeight there is a bug the incorrectly sets the contentSize. This fixes it by inserting the text via `replacingCharacters` + if text == UIPasteboard.general.string { + if let messageInputBar = messageInputBar { + if !messageInputBar.isOverMaxHeight { + textView.text = (textView.text as NSString).replacingCharacters(in: range, with: text) + return false + } + } + } + return true + } } diff --git a/Sources/MessageInputBar.swift b/Sources/MessageInputBar.swift index dfb7591b..eac5c988 100644 --- a/Sources/MessageInputBar.swift +++ b/Sources/MessageInputBar.swift @@ -131,12 +131,20 @@ open class MessageInputBar: UIView { var heightToFit = sizeToFit.height.rounded() + padding.top + padding.bottom if heightToFit >= maxHeight { - inputTextView.isScrollEnabled = true + if !isOverMaxHeight { + textViewHeightAnchor?.isActive = true + inputTextView.isScrollEnabled = true + isOverMaxHeight = true + } heightToFit = maxHeight } else { - inputTextView.isScrollEnabled = false - inputTextView.invalidateIntrinsicContentSize() + if isOverMaxHeight { + textViewHeightAnchor?.isActive = false + inputTextView.isScrollEnabled = false + isOverMaxHeight = false + } } + inputTextView.invalidateIntrinsicContentSize() let size = CGSize(width: bounds.width, height: heightToFit) @@ -148,9 +156,12 @@ open class MessageInputBar: UIView { return size } + private(set) var isOverMaxHeight = false + /// The maximum intrinsicContentSize height. When reached the delegate 'didChangeIntrinsicContentTo' will be called. open var maxHeight: CGFloat = UIScreen.main.bounds.height / 3 { didSet { + textViewHeightAnchor?.constant = maxHeight invalidateIntrinsicContentSize() } } @@ -189,6 +200,7 @@ open class MessageInputBar: UIView { // MARK: - Auto-Layout Management private var textViewLayoutSet: NSLayoutConstraintSet? + private var textViewHeightAnchor: NSLayoutConstraint? private var leftStackViewLayoutSet: NSLayoutConstraintSet? private var rightStackViewLayoutSet: NSLayoutConstraintSet? private var bottomStackViewLayoutSet: NSLayoutConstraintSet? @@ -247,6 +259,7 @@ open class MessageInputBar: UIView { left: inputTextView.leftAnchor.constraint(equalTo: leftStackView.rightAnchor, constant: textViewPadding.left), right: inputTextView.rightAnchor.constraint(equalTo: rightStackView.leftAnchor, constant: -textViewPadding.right) ).activate() + textViewHeightAnchor = inputTextView.heightAnchor.constraint(equalToConstant: maxHeight) leftStackViewLayoutSet = NSLayoutConstraintSet( top: inputTextView.topAnchor.constraint(equalTo: topAnchor, constant: padding.top), @@ -419,11 +432,11 @@ open class MessageInputBar: UIView { // MARK: - Notifications/Hooks - @objc open func orientationDidChange() { + @objc open func orientationDidChange() { invalidateIntrinsicContentSize() } - @objc open func textViewDidChange() { + @objc open func textViewDidChange() { let trimmedText = inputTextView.text.trimmingCharacters(in: .whitespacesAndNewlines) sendButton.isEnabled = !trimmedText.isEmpty @@ -435,11 +448,11 @@ open class MessageInputBar: UIView { invalidateIntrinsicContentSize() } - @objc open func textViewDidBeginEditing() { + @objc open func textViewDidBeginEditing() { self.items.forEach { $0.keyboardEditingBeginsAction() } } - @objc open func textViewDidEndEditing() { + @objc open func textViewDidEndEditing() { self.items.forEach { $0.keyboardEditingEndsAction() } }