Skip to content

Commit 04c75ba

Browse files
JoshuaGrossfacebook-github-bot
authored andcommitted
Support MapBuffer in TextInput State
Summary: Support MapBuffer in TextInput State. Changelog: [Internal] Reviewed By: NickGerleman Differential Revision: D38546271 fbshipit-source-id: 93e7fd79d9d8473dd646410f3047fcfafa8516f1
1 parent a632048 commit 04c75ba

File tree

7 files changed

+93
-13
lines changed

7 files changed

+93
-13
lines changed

ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,11 @@ public static boolean isRTL(MapBuffer attributedString) {
106106

107107
MapBuffer fragment = fragments.getMapBuffer((short) 0);
108108
MapBuffer textAttributes = fragment.getMapBuffer(FR_KEY_TEXT_ATTRIBUTES);
109+
110+
if (!textAttributes.contains(TextAttributeProps.TA_KEY_LAYOUT_DIRECTION)) {
111+
return false;
112+
}
113+
109114
return TextAttributeProps.getLayoutDirection(
110115
textAttributes.getString(TextAttributeProps.TA_KEY_LAYOUT_DIRECTION))
111116
== LayoutDirection.RTL;

ReactAndroid/src/main/java/com/facebook/react/views/textinput/BUCK

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ rn_android_library(
99
"pfh:ReactNative_CommonInfrastructurePlaceholder",
1010
"supermodule:xplat/default/public.react_native.infra",
1111
],
12-
language = "JAVA",
12+
language = "KOTLIN",
13+
pure_kotlin = False,
1314
required_for_source_only_abi = True,
1415
visibility = [
1516
"PUBLIC",
@@ -29,7 +30,9 @@ rn_android_library(
2930
react_native_target("java/com/facebook/react/views/imagehelper:imagehelper"),
3031
react_native_target("java/com/facebook/react/views/scroll:scroll"),
3132
react_native_target("java/com/facebook/react/views/text:text"),
33+
react_native_target("java/com/facebook/react/common/mapbuffer:mapbuffer"),
3234
react_native_target("java/com/facebook/react/views/view:view"),
35+
react_native_target("java/com/facebook/react/config:config"),
3336
],
3437
exported_deps = [
3538
react_native_dep("third-party/android/androidx:appcompat"),

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

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444
import com.facebook.react.bridge.WritableMap;
4545
import com.facebook.react.bridge.WritableNativeMap;
4646
import com.facebook.react.common.MapBuilder;
47+
import com.facebook.react.common.mapbuffer.MapBuffer;
48+
import com.facebook.react.config.ReactFeatureFlags;
4749
import com.facebook.react.module.annotations.ReactModule;
4850
import com.facebook.react.uimanager.BaseViewManager;
4951
import com.facebook.react.uimanager.FabricViewStateManager;
@@ -69,6 +71,7 @@
6971
import com.facebook.react.views.text.TextAttributeProps;
7072
import com.facebook.react.views.text.TextInlineImageSpan;
7173
import com.facebook.react.views.text.TextLayoutManager;
74+
import com.facebook.react.views.text.TextLayoutManagerMapBuffer;
7275
import com.facebook.react.views.text.TextTransform;
7376
import com.facebook.yoga.YogaConstants;
7477
import java.lang.reflect.Field;
@@ -83,6 +86,12 @@ public class ReactTextInputManager extends BaseViewManager<ReactEditText, Layout
8386
public static final String TAG = ReactTextInputManager.class.getSimpleName();
8487
public static final String REACT_CLASS = "AndroidTextInput";
8588

89+
// See also ReactTextViewManager
90+
private static final short TX_STATE_KEY_ATTRIBUTED_STRING = 0;
91+
private static final short TX_STATE_KEY_PARAGRAPH_ATTRIBUTES = 1;
92+
private static final short TX_STATE_KEY_HASH = 2;
93+
private static final short TX_STATE_KEY_MOST_RECENT_EVENT_COUNT = 3;
94+
8695
private static final int[] SPACING_TYPES = {
8796
Spacing.ALL, Spacing.LEFT, Spacing.RIGHT, Spacing.TOP, Spacing.BOTTOM,
8897
};
@@ -1286,6 +1295,13 @@ public Object updateState(
12861295

12871296
stateManager.setStateWrapper(stateWrapper);
12881297

1298+
if (ReactFeatureFlags.mapBufferSerializationEnabled) {
1299+
MapBuffer stateMapBuffer = stateWrapper.getStateDataMapBuffer();
1300+
if (stateMapBuffer != null) {
1301+
return getReactTextUpdate(view, props, stateMapBuffer);
1302+
}
1303+
}
1304+
12891305
ReadableNativeMap state = stateWrapper.getStateData();
12901306
if (state == null) {
12911307
return null;
@@ -1318,4 +1334,39 @@ public Object updateState(
13181334
TextAttributeProps.getJustificationMode(props),
13191335
containsMultipleFragments);
13201336
}
1337+
1338+
public Object getReactTextUpdate(ReactEditText view, ReactStylesDiffMap props, MapBuffer state) {
1339+
// If native wants to update the state wrapper but the state data hasn't actually
1340+
// changed, the MapBuffer may be empty
1341+
if (state.getCount() == 0) {
1342+
return null;
1343+
}
1344+
1345+
MapBuffer attributedString = state.getMapBuffer(TX_STATE_KEY_ATTRIBUTED_STRING);
1346+
MapBuffer paragraphAttributes = state.getMapBuffer(TX_STATE_KEY_PARAGRAPH_ATTRIBUTES);
1347+
if (attributedString == null || paragraphAttributes == null) {
1348+
throw new IllegalArgumentException(
1349+
"Invalid TextInput State (MapBuffer) was received as a parameters");
1350+
}
1351+
1352+
Spannable spanned =
1353+
TextLayoutManagerMapBuffer.getOrCreateSpannableForText(
1354+
view.getContext(), attributedString, mReactTextViewManagerCallback);
1355+
1356+
boolean containsMultipleFragments =
1357+
attributedString.getMapBuffer(TextLayoutManagerMapBuffer.AS_KEY_FRAGMENTS).getCount() > 1;
1358+
1359+
int textBreakStrategy =
1360+
TextAttributeProps.getTextBreakStrategy(
1361+
paragraphAttributes.getString(TextLayoutManagerMapBuffer.PA_KEY_TEXT_BREAK_STRATEGY));
1362+
1363+
return ReactTextUpdate.buildReactTextUpdateFromState(
1364+
spanned,
1365+
state.getInt(TX_STATE_KEY_MOST_RECENT_EVENT_COUNT),
1366+
TextAttributeProps.getTextAlignment(
1367+
props, TextLayoutManagerMapBuffer.isRTL(attributedString)),
1368+
textBreakStrategy,
1369+
TextAttributeProps.getJustificationMode(props),
1370+
containsMultipleFragments);
1371+
}
13211372
}

ReactCommon/react/renderer/components/text/ParagraphState.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@
2020
namespace facebook {
2121
namespace react {
2222

23+
#ifdef ANDROID
24+
// constants for Text State serialization
25+
constexpr static MapBuffer::Key TX_STATE_KEY_ATTRIBUTED_STRING = 0;
26+
constexpr static MapBuffer::Key TX_STATE_KEY_PARAGRAPH_ATTRIBUTES = 1;
27+
// Used for TextInput only
28+
constexpr static MapBuffer::Key TX_STATE_KEY_HASH = 2;
29+
constexpr static MapBuffer::Key TX_STATE_KEY_MOST_RECENT_EVENT_COUNT = 3;
30+
#endif
31+
2332
/*
2433
* State for <Paragraph> component.
2534
* Represents what to render and how to render.

ReactCommon/react/renderer/components/text/conversions.h

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,13 @@ inline folly::dynamic toDynamic(ParagraphState const &paragraphState) {
2626
return newState;
2727
}
2828

29-
// constants for Text State serialization
30-
constexpr static MapBuffer::Key TX_STATE_KEY_ATTRIBUTED_STRING = 0;
31-
constexpr static MapBuffer::Key TX_STATE_KEY_PARAGRAPH_ATTRIBUTES = 1;
32-
// Used for TextInput
33-
constexpr static MapBuffer::Key TX_STATE_KEY_HASH = 2;
34-
constexpr static MapBuffer::Key TX_STATE_KEY_MOST_RECENT_EVENT_COUNT = 3;
35-
3629
inline MapBuffer toMapBuffer(ParagraphState const &paragraphState) {
3730
auto builder = MapBufferBuilder();
3831
auto attStringMapBuffer = toMapBuffer(paragraphState.attributedString);
3932
builder.putMapBuffer(TX_STATE_KEY_ATTRIBUTED_STRING, attStringMapBuffer);
4033
auto paMapBuffer = toMapBuffer(paragraphState.paragraphAttributes);
4134
builder.putMapBuffer(TX_STATE_KEY_PARAGRAPH_ATTRIBUTES, paMapBuffer);
42-
// TODO: Used for TextInput
43-
builder.putInt(TX_STATE_KEY_HASH, 1234);
35+
builder.putInt(TX_STATE_KEY_HASH, attStringMapBuffer.getInt(AS_KEY_HASH));
4436
return builder.build();
4537
}
4638
#endif

ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputState.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@
1010
#include <react/renderer/components/text/conversions.h>
1111
#include <react/renderer/debug/debugStringConvertibleUtils.h>
1212

13+
#ifdef ANDROID
14+
#include <react/renderer/mapbuffer/MapBuffer.h>
15+
#include <react/renderer/mapbuffer/MapBufferBuilder.h>
16+
#endif
17+
1318
#include <utility>
1419

1520
namespace facebook {
@@ -89,6 +94,23 @@ folly::dynamic AndroidTextInputState::getDynamic() const {
8994
}
9095
return newState;
9196
}
97+
98+
MapBuffer AndroidTextInputState::getMapBuffer() const {
99+
auto builder = MapBufferBuilder();
100+
// See comment in getDynamic block.
101+
if (cachedAttributedStringId == 0) {
102+
builder.putInt(TX_STATE_KEY_MOST_RECENT_EVENT_COUNT, mostRecentEventCount);
103+
104+
auto attStringMapBuffer = toMapBuffer(attributedString);
105+
builder.putMapBuffer(TX_STATE_KEY_ATTRIBUTED_STRING, attStringMapBuffer);
106+
auto paMapBuffer = toMapBuffer(paragraphAttributes);
107+
builder.putMapBuffer(TX_STATE_KEY_PARAGRAPH_ATTRIBUTES, paMapBuffer);
108+
109+
builder.putInt(TX_STATE_KEY_HASH, attStringMapBuffer.getInt(AS_KEY_HASH));
110+
}
111+
return builder.build();
112+
}
113+
92114
#endif
93115

94116
} // namespace react

ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputState.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,7 @@ class AndroidTextInputState final {
9494
AndroidTextInputState const &previousState,
9595
folly::dynamic const &data);
9696
folly::dynamic getDynamic() const;
97-
MapBuffer getMapBuffer() const {
98-
return MapBufferBuilder::EMPTY();
99-
};
97+
MapBuffer getMapBuffer() const;
10098
};
10199

102100
} // namespace react

0 commit comments

Comments
 (0)