Skip to content

Commit

Permalink
Possible fix for 18890 (facebook#19687)
Browse files Browse the repository at this point in the history
Summary:
Potential fixes for 18890. The issue was that when the setAttributedText method in RCTBaseTextInputView.m is called it does two main things:

Check that the attributed text that it receives is equal to the existing attributed text in the underlying backed up view ( backedTextInputView)
If not set the attributed text of the backed up view to the value passed into the method. This kills the dictation as it is effectively the equivalent of typing in the backed up text view.
    self.backedTextInputView.attributedText = attributedText;
is the problem. It kills the dictation. It may have other effects as well.

In all cases I have seen the underlying text of the attributed string that is passed in the same as the text in the backedTextInputView, what was said to the dictation; however the attributes are different, which causes the isEqualToAttributedString: check to fail and thus the update happens, and the keyboard is killed.

Fix is to test for the underlying string equality not the attributed string equality when the input mode is dictation.

By necessity this had to be an integration test on an existing application. To test I enabled the keyboard and started the dictation. It worked with this fixes and not without. Will upload videos later.

This might break attributes on dictation, as it is happening. However anything set on the existing underlying text view should hold.

[IOS] [BUG] [Textinput] fixed an issue where the keyboard dictation ended abruptly.
Closes facebook#19687

Differential Revision: D8450590

Pulled By: hramos

fbshipit-source-id: f97084131f98e9e0ed1f32111afc0f9f510f3b3b
  • Loading branch information
eoinnorris authored and Fanghao committed Sep 6, 2018
1 parent bf39b3f commit 9c5f99a
Showing 1 changed file with 21 additions and 7 deletions.
28 changes: 21 additions & 7 deletions Libraries/Text/TextInput/RCTBaseTextInputView.m
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,22 @@ - (NSAttributedString *)attributedText
return self.backedTextInputView.attributedText;
}

- (BOOL)textOf:(NSAttributedString*)newText equals:(NSAttributedString*)oldText{
UITextInputMode *currentInputMode = self.backedTextInputView.textInputMode;
if ([currentInputMode.primaryLanguage isEqualToString:@"dictation"]) {
// When the dictation is running we can't update the attibuted text on the backed up text view
// because setting the attributed string will kill the dictation. This means that we can't impose
// the settings on a dictation.
return ([newText.string isEqualToString:oldText.string]);
} else {
return ([newText isEqualToAttributedString:oldText]);
}
}

- (void)setAttributedText:(NSAttributedString *)attributedText
{
NSInteger eventLag = _nativeEventCount - _mostRecentEventCount;

BOOL textNeedsUpdate = NO;
// Remove tag attribute to ensure correct attributed string comparison.
NSMutableAttributedString *const backedTextInputViewTextCopy = [self.backedTextInputView.attributedText mutableCopy];
NSMutableAttributedString *const attributedTextCopy = [attributedText mutableCopy];
Expand All @@ -111,8 +123,10 @@ - (void)setAttributedText:(NSAttributedString *)attributedText

[attributedTextCopy removeAttribute:RCTTextAttributesTagAttributeName
range:NSMakeRange(0, attributedTextCopy.length)];

if (eventLag == 0 && ![attributedTextCopy isEqualToAttributedString:backedTextInputViewTextCopy]) {

textNeedsUpdate = ([self textOf:attributedTextCopy equals:backedTextInputViewTextCopy] == NO);

if (eventLag == 0 && textNeedsUpdate) {
UITextRange *selection = self.backedTextInputView.selectedTextRange;
NSInteger oldTextLength = self.backedTextInputView.attributedText.string.length;

Expand All @@ -121,13 +135,13 @@ - (void)setAttributedText:(NSAttributedString *)attributedText
if (selection.empty) {
// Maintaining a cursor position relative to the end of the old text.
NSInteger offsetStart =
[self.backedTextInputView offsetFromPosition:self.backedTextInputView.beginningOfDocument
toPosition:selection.start];
[self.backedTextInputView offsetFromPosition:self.backedTextInputView.beginningOfDocument
toPosition:selection.start];
NSInteger offsetFromEnd = oldTextLength - offsetStart;
NSInteger newOffset = attributedText.string.length - offsetFromEnd;
UITextPosition *position =
[self.backedTextInputView positionFromPosition:self.backedTextInputView.beginningOfDocument
offset:newOffset];
[self.backedTextInputView positionFromPosition:self.backedTextInputView.beginningOfDocument
offset:newOffset];
[self.backedTextInputView setSelectedTextRange:[self.backedTextInputView textRangeFromPosition:position toPosition:position]
notifyDelegate:YES];
}
Expand Down

0 comments on commit 9c5f99a

Please sign in to comment.