Skip to content

Commit 70cdf12

Browse files
cortinicofacebook-github-bot
authored andcommitted
Extract inner classes from ReactTextInputManager to separate files (facebook#50657)
Summary: Pull Request resolved: facebook#50657 The ReactTextInputManager file is huge and really hard to migrate to Kotlin. Here I'm extracting 4 private inner classes to separate files and converting them to Kotlin. This will make reviewing the Kotlin migration of ReactTextInputManager a bit easier. Changelog: [Internal] [Changed] - Reviewed By: rshest Differential Revision: D72858396 fbshipit-source-id: 1fcca1b8421c810aa4bf9fdca7656f4e805565d8
1 parent 02aa7e7 commit 70cdf12

File tree

5 files changed

+215
-198
lines changed

5 files changed

+215
-198
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
package com.facebook.react.views.textinput
9+
10+
import com.facebook.react.uimanager.PixelUtil.toDIPFromPixel
11+
import com.facebook.react.uimanager.UIManagerHelper
12+
import com.facebook.react.uimanager.events.EventDispatcher
13+
14+
internal class ReactTextContentSizeWatcher(private val editText: ReactEditText) :
15+
ContentSizeWatcher {
16+
private val eventDispatcher: EventDispatcher?
17+
private val surfaceId: Int
18+
private var previousContentWidth = 0
19+
private var previousContentHeight = 0
20+
21+
init {
22+
val reactContext = UIManagerHelper.getReactContext(editText)
23+
eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, editText.id)
24+
surfaceId = UIManagerHelper.getSurfaceId(reactContext)
25+
}
26+
27+
override fun onLayout() {
28+
var contentWidth = editText.width
29+
var contentHeight = editText.height
30+
31+
// Use instead size of text content within EditText when available
32+
if (editText.layout != null) {
33+
contentWidth =
34+
(editText.compoundPaddingLeft + editText.layout.width + editText.compoundPaddingRight)
35+
contentHeight =
36+
(editText.compoundPaddingTop + editText.layout.height + editText.compoundPaddingBottom)
37+
}
38+
39+
if (contentWidth != previousContentWidth || contentHeight != previousContentHeight) {
40+
previousContentHeight = contentHeight
41+
previousContentWidth = contentWidth
42+
43+
eventDispatcher?.dispatchEvent(
44+
ReactContentSizeChangedEvent(
45+
surfaceId,
46+
editText.id,
47+
toDIPFromPixel(contentWidth.toFloat()),
48+
toDIPFromPixel(contentHeight.toFloat())))
49+
}
50+
}
51+
}

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java

+4-198
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77

88
package com.facebook.react.views.textinput;
99

10-
import static com.facebook.react.uimanager.UIManagerHelper.getReactContext;
11-
1210
import android.content.Context;
1311
import android.content.res.ColorStateList;
1412
import android.graphics.BlendMode;
@@ -17,13 +15,11 @@
1715
import android.graphics.PorterDuff;
1816
import android.graphics.drawable.Drawable;
1917
import android.os.Build;
20-
import android.text.Editable;
2118
import android.text.InputFilter;
2219
import android.text.InputType;
2320
import android.text.Layout;
2421
import android.text.Spannable;
2522
import android.text.SpannableStringBuilder;
26-
import android.text.TextWatcher;
2723
import android.view.Gravity;
2824
import android.view.View;
2925
import android.view.ViewGroup;
@@ -33,14 +29,11 @@
3329
import androidx.autofill.HintConstants;
3430
import androidx.core.content.ContextCompat;
3531
import com.facebook.common.logging.FLog;
36-
import com.facebook.infer.annotation.Assertions;
3732
import com.facebook.react.bridge.Dynamic;
3833
import com.facebook.react.bridge.ReactContext;
3934
import com.facebook.react.bridge.ReactSoftExceptionLogger;
4035
import com.facebook.react.bridge.ReadableArray;
4136
import com.facebook.react.bridge.ReadableType;
42-
import com.facebook.react.bridge.WritableMap;
43-
import com.facebook.react.bridge.WritableNativeMap;
4437
import com.facebook.react.common.MapBuilder;
4538
import com.facebook.react.common.ReactConstants;
4639
import com.facebook.react.common.mapbuffer.MapBuffer;
@@ -50,7 +43,6 @@
5043
import com.facebook.react.uimanager.LayoutShadowNode;
5144
import com.facebook.react.uimanager.LengthPercentage;
5245
import com.facebook.react.uimanager.LengthPercentageType;
53-
import com.facebook.react.uimanager.PixelUtil;
5446
import com.facebook.react.uimanager.ReactStylesDiffMap;
5547
import com.facebook.react.uimanager.Spacing;
5648
import com.facebook.react.uimanager.StateWrapper;
@@ -65,7 +57,6 @@
6557
import com.facebook.react.uimanager.style.BorderStyle;
6658
import com.facebook.react.uimanager.style.LogicalEdge;
6759
import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper;
68-
import com.facebook.react.views.scroll.ScrollEvent;
6960
import com.facebook.react.views.scroll.ScrollEventType;
7061
import com.facebook.react.views.text.DefaultStyleValuesUtil;
7162
import com.facebook.react.views.text.ReactBaseTextShadowNode;
@@ -453,7 +444,7 @@ private void setAutofillHints(ReactEditText view, String... hints) {
453444
@ReactProp(name = "onSelectionChange", defaultBoolean = false)
454445
public void setOnSelectionChange(final ReactEditText view, boolean onSelectionChange) {
455446
if (onSelectionChange) {
456-
view.setSelectionWatcher(new ReactSelectionWatcher(view));
447+
view.setSelectionWatcher(new ReactTextSelectionWatcher(view));
457448
} else {
458449
view.setSelectionWatcher(null);
459450
}
@@ -467,7 +458,7 @@ public void setSubmitBehavior(ReactEditText view, @Nullable String submitBehavio
467458
@ReactProp(name = "onContentSizeChange", defaultBoolean = false)
468459
public void setOnContentSizeChange(final ReactEditText view, boolean onContentSizeChange) {
469460
if (onContentSizeChange) {
470-
view.setContentSizeWatcher(new ReactContentSizeWatcher(view));
461+
view.setContentSizeWatcher(new ReactTextContentSizeWatcher(view));
471462
} else {
472463
view.setContentSizeWatcher(null);
473464
}
@@ -476,7 +467,7 @@ public void setOnContentSizeChange(final ReactEditText view, boolean onContentSi
476467
@ReactProp(name = "onScroll", defaultBoolean = false)
477468
public void setOnScroll(final ReactEditText view, boolean onScroll) {
478469
if (onScroll) {
479-
view.setScrollWatcher(new ReactScrollWatcher(view));
470+
view.setScrollWatcher(new ReactTextScrollWatcher(view));
480471
} else {
481472
view.setScrollWatcher(null);
482473
}
@@ -1051,73 +1042,12 @@ private static void updateStagedInputTypeFlag(
10511042
view.setStagedInputType((view.getStagedInputType() & ~flagsToUnset) | flagsToSet);
10521043
}
10531044

1045+
@Nullable
10541046
private static EventDispatcher getEventDispatcher(
10551047
ReactContext reactContext, ReactEditText editText) {
10561048
return UIManagerHelper.getEventDispatcherForReactTag(reactContext, editText.getId());
10571049
}
10581050

1059-
private final class ReactTextInputTextWatcher implements TextWatcher {
1060-
private final ReactEditText mEditText;
1061-
private final EventDispatcher mEventDispatcher;
1062-
private final int mSurfaceId;
1063-
@Nullable private String mPreviousText;
1064-
1065-
public ReactTextInputTextWatcher(
1066-
final ReactContext reactContext, final ReactEditText editText) {
1067-
mEventDispatcher = getEventDispatcher(reactContext, editText);
1068-
mEditText = editText;
1069-
mPreviousText = null;
1070-
mSurfaceId = UIManagerHelper.getSurfaceId(reactContext);
1071-
}
1072-
1073-
@Override
1074-
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
1075-
// Incoming charSequence gets mutated before onTextChanged() is invoked
1076-
mPreviousText = s.toString();
1077-
}
1078-
1079-
@Override
1080-
public void onTextChanged(CharSequence s, int start, int before, int count) {
1081-
if (mEditText.mDisableTextDiffing) {
1082-
return;
1083-
}
1084-
1085-
// Rearranging the text (i.e. changing between singleline and multiline attributes) can
1086-
// also trigger onTextChanged, call the event in JS only when the text actually changed
1087-
if (count == 0 && before == 0) {
1088-
return;
1089-
}
1090-
1091-
Assertions.assertNotNull(mPreviousText);
1092-
String newText = s.toString().substring(start, start + count);
1093-
String oldText = mPreviousText.substring(start, start + before);
1094-
// Don't send same text changes
1095-
if (count == before && newText.equals(oldText)) {
1096-
return;
1097-
}
1098-
1099-
StateWrapper stateWrapper = mEditText.getStateWrapper();
1100-
1101-
if (stateWrapper != null) {
1102-
WritableMap newStateData = new WritableNativeMap();
1103-
newStateData.putInt("mostRecentEventCount", mEditText.incrementAndGetEventCounter());
1104-
newStateData.putInt("opaqueCacheId", mEditText.getId());
1105-
stateWrapper.updateState(newStateData);
1106-
}
1107-
1108-
// The event that contains the event counter and updates it must be sent first.
1109-
mEventDispatcher.dispatchEvent(
1110-
new ReactTextChangedEvent(
1111-
mSurfaceId,
1112-
mEditText.getId(),
1113-
s.toString(),
1114-
mEditText.incrementAndGetEventCounter()));
1115-
}
1116-
1117-
@Override
1118-
public void afterTextChanged(Editable s) {}
1119-
}
1120-
11211051
@Override
11221052
protected void addEventEmitters(
11231053
final ThemedReactContext reactContext, final ReactEditText editText) {
@@ -1188,130 +1118,6 @@ protected void addEventEmitters(
11881118
});
11891119
}
11901120

1191-
private static class ReactContentSizeWatcher implements ContentSizeWatcher {
1192-
private final ReactEditText mEditText;
1193-
private final EventDispatcher mEventDispatcher;
1194-
private final int mSurfaceId;
1195-
private int mPreviousContentWidth = 0;
1196-
private int mPreviousContentHeight = 0;
1197-
1198-
public ReactContentSizeWatcher(ReactEditText editText) {
1199-
mEditText = editText;
1200-
ReactContext reactContext = getReactContext(editText);
1201-
mEventDispatcher = getEventDispatcher(reactContext, editText);
1202-
mSurfaceId = UIManagerHelper.getSurfaceId(reactContext);
1203-
}
1204-
1205-
@Override
1206-
public void onLayout() {
1207-
if (mEventDispatcher == null) {
1208-
return;
1209-
}
1210-
1211-
int contentWidth = mEditText.getWidth();
1212-
int contentHeight = mEditText.getHeight();
1213-
1214-
// Use instead size of text content within EditText when available
1215-
if (mEditText.getLayout() != null) {
1216-
contentWidth =
1217-
mEditText.getCompoundPaddingLeft()
1218-
+ mEditText.getLayout().getWidth()
1219-
+ mEditText.getCompoundPaddingRight();
1220-
contentHeight =
1221-
mEditText.getCompoundPaddingTop()
1222-
+ mEditText.getLayout().getHeight()
1223-
+ mEditText.getCompoundPaddingBottom();
1224-
}
1225-
1226-
if (contentWidth != mPreviousContentWidth || contentHeight != mPreviousContentHeight) {
1227-
mPreviousContentHeight = contentHeight;
1228-
mPreviousContentWidth = contentWidth;
1229-
1230-
mEventDispatcher.dispatchEvent(
1231-
new ReactContentSizeChangedEvent(
1232-
mSurfaceId,
1233-
mEditText.getId(),
1234-
PixelUtil.toDIPFromPixel(contentWidth),
1235-
PixelUtil.toDIPFromPixel(contentHeight)));
1236-
}
1237-
}
1238-
}
1239-
1240-
private static class ReactSelectionWatcher implements SelectionWatcher {
1241-
private final ReactEditText mReactEditText;
1242-
private final EventDispatcher mEventDispatcher;
1243-
private final int mSurfaceId;
1244-
private int mPreviousSelectionStart;
1245-
private int mPreviousSelectionEnd;
1246-
1247-
public ReactSelectionWatcher(ReactEditText editText) {
1248-
mReactEditText = editText;
1249-
ReactContext reactContext = getReactContext(editText);
1250-
mEventDispatcher = getEventDispatcher(reactContext, editText);
1251-
mSurfaceId = UIManagerHelper.getSurfaceId(reactContext);
1252-
}
1253-
1254-
@Override
1255-
public void onSelectionChanged(int start, int end) {
1256-
// Android will call us back for both the SELECTION_START span and SELECTION_END span in text
1257-
// To prevent double calling back into js we cache the result of the previous call and only
1258-
// forward it on if we have new values
1259-
1260-
// Apparently Android might call this with an end value that is less than the start value
1261-
// Lets normalize them. See https://github.com/facebook/react-native/issues/18579
1262-
int realStart = Math.min(start, end);
1263-
int realEnd = Math.max(start, end);
1264-
1265-
if (mPreviousSelectionStart != realStart || mPreviousSelectionEnd != realEnd) {
1266-
mEventDispatcher.dispatchEvent(
1267-
new ReactTextInputSelectionEvent(
1268-
mSurfaceId, mReactEditText.getId(), realStart, realEnd));
1269-
1270-
mPreviousSelectionStart = realStart;
1271-
mPreviousSelectionEnd = realEnd;
1272-
}
1273-
}
1274-
}
1275-
1276-
private static class ReactScrollWatcher implements ScrollWatcher {
1277-
private final ReactEditText mReactEditText;
1278-
private final EventDispatcher mEventDispatcher;
1279-
private final int mSurfaceId;
1280-
private int mPreviousHorizontal;
1281-
private int mPreviousVert;
1282-
1283-
public ReactScrollWatcher(ReactEditText editText) {
1284-
mReactEditText = editText;
1285-
ReactContext reactContext = getReactContext(editText);
1286-
mEventDispatcher = getEventDispatcher(reactContext, editText);
1287-
mSurfaceId = UIManagerHelper.getSurfaceId(reactContext);
1288-
}
1289-
1290-
@Override
1291-
public void onScrollChanged(int horiz, int vert, int oldHoriz, int oldVert) {
1292-
if (mPreviousHorizontal != horiz || mPreviousVert != vert) {
1293-
ScrollEvent event =
1294-
ScrollEvent.obtain(
1295-
mSurfaceId,
1296-
mReactEditText.getId(),
1297-
ScrollEventType.SCROLL,
1298-
horiz,
1299-
vert,
1300-
0f, // can't get x velocity
1301-
0f, // can't get y velocity
1302-
0, // can't get content width
1303-
0, // can't get content height
1304-
mReactEditText.getWidth(),
1305-
mReactEditText.getHeight());
1306-
1307-
mEventDispatcher.dispatchEvent(event);
1308-
1309-
mPreviousHorizontal = horiz;
1310-
mPreviousVert = vert;
1311-
}
1312-
}
1313-
}
1314-
13151121
@Override
13161122
public @Nullable Map<String, Object> getExportedViewConstants() {
13171123
return MapBuilder.of(

0 commit comments

Comments
 (0)