Skip to content

Commit fea0215

Browse files
IOS-838: ConversationInputTextView cursor adjustments don't behave properly
At the moment, when trying to drag the input/selection cursor(s) in the ConverationInputTextView, as soon as you reach the top or bottom edge of a draft with >4 lines, you'll immediately scroll to the very top or the very bottom. This is because we're currently overriding the default implementation of setContentOffset:animated: to always perform the adjustment without animation. We do this because we don't want the animated content offset adjustment to interfere with the growing the bounds of the text view. This can cause the text to overshoot the updated bounds pre-iOS 13. But we only grow the text view in response to the text changing. So instead of disabling all content offset animations, we can get away with just disabling content offset animations while the text is changing. So this commit: - Sets a flag between -textViewShouldChange... and -textViewDidChange: - On iOS 13 and later, we'll always respect the animate argument of setContentOffset:animated: - Pre-iOS 13, we'll ignore the animate parameter if the flag is set
1 parent bdf03e6 commit fea0215

File tree

2 files changed

+23
-6
lines changed

2 files changed

+23
-6
lines changed

Signal/src/ViewControllers/ConversationView/ConversationInputTextView.swift

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class ConversationInputTextView: MentionTextView {
2727

2828
var trimmedText: String { text.ows_stripped() }
2929
var untrimmedText: String { text }
30+
private var textIsChanging = false
3031

3132
required init() {
3233
super.init()
@@ -114,10 +115,22 @@ class ConversationInputTextView: MentionTextView {
114115

115116
override func setContentOffset(_ contentOffset: CGPoint, animated: Bool) {
116117
// When creating new lines, contentOffset is animated, but because because
117-
// we are simultaneously resizing the text view, this can cause the
118-
// text in the textview to be "too high" in the text view.
119-
// Solution is to disable animation for setting content offset.
120-
super.setContentOffset(contentOffset, animated: false)
118+
// we are simultaneously resizing the text view, on pre-iOS 13 this can
119+
// cause the text in the textview to be "too high" in the text view.
120+
// Solution is to disable animation for setting content offset between
121+
// -textViewShouldChange... and -textViewDidChange.
122+
//
123+
// We can't unilaterally disable *all* animated scrolling because that breaks
124+
// manipulation of the cursor in scrollable text. Animation is required to
125+
// slow the text view scrolling down to human scale when the cursor reaches
126+
// the top or bottom edge.
127+
let shouldAnimate: Bool
128+
if #available(iOS 13, *) {
129+
shouldAnimate = animated
130+
} else {
131+
shouldAnimate = animated && !textIsChanging
132+
}
133+
super.setContentOffset(contentOffset, animated: shouldAnimate)
121134
}
122135

123136
override var contentInset: UIEdgeInsets {
@@ -169,8 +182,14 @@ class ConversationInputTextView: MentionTextView {
169182

170183
// MARK: - UITextViewDelegate
171184

185+
override func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
186+
textIsChanging = true
187+
return true
188+
}
189+
172190
override func textViewDidChange(_ textView: UITextView) {
173191
super.textViewDidChange(textView)
192+
textIsChanging = false
174193

175194
updatePlaceholderVisibility()
176195
updateTextContainerInset()

Signal/src/ViewControllers/ConversationView/ConversationInputToolbar.m

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ typedef NS_CLOSED_ENUM(NSUInteger, VoiceMemoRecordingState){
2727

2828
typedef NS_CLOSED_ENUM(NSUInteger, KeyboardType) { KeyboardType_System, KeyboardType_Sticker, KeyboardType_Attachment };
2929

30-
static void *kConversationInputTextViewObservingContext = &kConversationInputTextViewObservingContext;
31-
3230
const CGFloat kMinTextViewHeight = 36;
3331
const CGFloat kMinToolbarItemHeight = 44;
3432
const CGFloat kMaxTextViewHeight = 98;

0 commit comments

Comments
 (0)