Skip to content

Commit

Permalink
Partial Mitigation for Samsung TextInput Hangs (facebook#35967)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: facebook#35967

In facebook#35936 we observed that the presence of AbsoluteSizeSpan may lead to hangs when using the Grammarly keyboard on Samsung.

This mitigation makes it so that we do not emit this span in the most common cases, when it is sufficient to set `android:textSize`. In simple cases, it causes typing into the TextInput to no longer hang.

This does not resolve the issue for TextInputs which meaningfully use layout-effecting spans (or at least font size), such as non-uniform text size within the input. We could potentially do further work to reduce the number of spans emitted in these scenarios, but this may be fighting a losing battle against the platform.

Changelog:
[Android][Fixed] - Partial Mitigation for Samsung TextInput Hangs (Paper)

Reviewed By: cortinico

Differential Revision: D42721684

fbshipit-source-id: 1b6935014c8055c3bd547c7ba5294bb9975479c2
  • Loading branch information
NickGerleman authored and facebook-github-bot committed Jan 26, 2023
1 parent a8166bd commit 3dcd5c8
Showing 1 changed file with 29 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,10 @@ public void maybeSetText(ReactTextUpdate reactTextUpdate) {
new SpannableStringBuilder(reactTextUpdate.getText());

manageSpans(spannableStringBuilder, reactTextUpdate.mContainsMultipleFragments);

// Mitigation for https://github.com/facebook/react-native/issues/35936 (S318090)
stripAbsoluteSizeSpans(spannableStringBuilder);

mContainsImages = reactTextUpdate.containsImages();

// When we update text, we trigger onChangeText code that will
Expand Down Expand Up @@ -658,6 +662,31 @@ private void manageSpans(
}
}

private void stripAbsoluteSizeSpans(SpannableStringBuilder sb) {
// We have already set a font size on the EditText itself. We can safely remove sizing spans
// which are the same as the set font size, and not otherwise overlapped.
final int effectiveFontSize = mTextAttributes.getEffectiveFontSize();
ReactAbsoluteSizeSpan[] spans = sb.getSpans(0, sb.length(), ReactAbsoluteSizeSpan.class);

outer:
for (ReactAbsoluteSizeSpan span : spans) {
if (span.getSize() != effectiveFontSize) {
continue;
}

ReactAbsoluteSizeSpan[] overlappingSpans =
sb.getSpans(sb.getSpanStart(span), sb.getSpanEnd(sb), ReactAbsoluteSizeSpan.class);

for (ReactAbsoluteSizeSpan overlappingSpan : overlappingSpans) {
if (span.getSize() != effectiveFontSize) {
continue outer;
}
}

sb.removeSpan(span);
}
}

private static boolean sameTextForSpan(
final Editable oldText,
final SpannableStringBuilder newText,
Expand Down

0 comments on commit 3dcd5c8

Please sign in to comment.