Skip to content

Commit

Permalink
Support MapBuffer in TextInput State
Browse files Browse the repository at this point in the history
Summary:
Support MapBuffer in TextInput State.

Changelog: [Internal]

Reviewed By: NickGerleman

Differential Revision: D38546271

fbshipit-source-id: 93e7fd79d9d8473dd646410f3047fcfafa8516f1
  • Loading branch information
JoshuaGross authored and kelset committed Apr 11, 2023
1 parent 322f721 commit 62364d0
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ public static boolean isRTL(MapBuffer attributedString) {

MapBuffer fragment = fragments.getMapBuffer((short) 0);
MapBuffer textAttributes = fragment.getMapBuffer(FR_KEY_TEXT_ATTRIBUTES);

if (!textAttributes.contains(TextAttributeProps.TA_KEY_LAYOUT_DIRECTION)) {
return false;
}

return TextAttributeProps.getLayoutDirection(
textAttributes.getString(TextAttributeProps.TA_KEY_LAYOUT_DIRECTION))
== LayoutDirection.RTL;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ rn_android_library(
"pfh:ReactNative_CommonInfrastructurePlaceholder",
"supermodule:xplat/default/public.react_native.infra",
],
language = "JAVA",
language = "KOTLIN",
pure_kotlin = False,
required_for_source_only_abi = True,
visibility = [
"PUBLIC",
Expand All @@ -29,7 +30,9 @@ rn_android_library(
react_native_target("java/com/facebook/react/views/imagehelper:imagehelper"),
react_native_target("java/com/facebook/react/views/scroll:scroll"),
react_native_target("java/com/facebook/react/views/text:text"),
react_native_target("java/com/facebook/react/common/mapbuffer:mapbuffer"),
react_native_target("java/com/facebook/react/views/view:view"),
react_native_target("java/com/facebook/react/config:config"),
],
exported_deps = [
react_native_dep("third-party/android/androidx:appcompat"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableNativeMap;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.common.mapbuffer.MapBuffer;
import com.facebook.react.config.ReactFeatureFlags;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.FabricViewStateManager;
Expand All @@ -71,6 +73,7 @@
import com.facebook.react.views.text.TextAttributeProps;
import com.facebook.react.views.text.TextInlineImageSpan;
import com.facebook.react.views.text.TextLayoutManager;
import com.facebook.react.views.text.TextLayoutManagerMapBuffer;
import com.facebook.react.views.text.TextTransform;
import com.facebook.yoga.YogaConstants;
import java.lang.reflect.Field;
Expand All @@ -85,6 +88,12 @@ public class ReactTextInputManager extends BaseViewManager<ReactEditText, Layout
public static final String TAG = ReactTextInputManager.class.getSimpleName();
public static final String REACT_CLASS = "AndroidTextInput";

// See also ReactTextViewManager
private static final short TX_STATE_KEY_ATTRIBUTED_STRING = 0;
private static final short TX_STATE_KEY_PARAGRAPH_ATTRIBUTES = 1;
private static final short TX_STATE_KEY_HASH = 2;
private static final short TX_STATE_KEY_MOST_RECENT_EVENT_COUNT = 3;

private static final int[] SPACING_TYPES = {
Spacing.ALL, Spacing.LEFT, Spacing.RIGHT, Spacing.TOP, Spacing.BOTTOM,
};
Expand Down Expand Up @@ -1305,6 +1314,13 @@ public Object updateState(

stateManager.setStateWrapper(stateWrapper);

if (ReactFeatureFlags.mapBufferSerializationEnabled) {
MapBuffer stateMapBuffer = stateWrapper.getStateDataMapBuffer();
if (stateMapBuffer != null) {
return getReactTextUpdate(view, props, stateMapBuffer);
}
}

ReadableNativeMap state = stateWrapper.getStateData();
if (state == null) {
return null;
Expand Down Expand Up @@ -1337,4 +1353,39 @@ public Object updateState(
TextAttributeProps.getJustificationMode(props),
containsMultipleFragments);
}

public Object getReactTextUpdate(ReactEditText view, ReactStylesDiffMap props, MapBuffer state) {
// If native wants to update the state wrapper but the state data hasn't actually
// changed, the MapBuffer may be empty
if (state.getCount() == 0) {
return null;
}

MapBuffer attributedString = state.getMapBuffer(TX_STATE_KEY_ATTRIBUTED_STRING);
MapBuffer paragraphAttributes = state.getMapBuffer(TX_STATE_KEY_PARAGRAPH_ATTRIBUTES);
if (attributedString == null || paragraphAttributes == null) {
throw new IllegalArgumentException(
"Invalid TextInput State (MapBuffer) was received as a parameters");
}

Spannable spanned =
TextLayoutManagerMapBuffer.getOrCreateSpannableForText(
view.getContext(), attributedString, mReactTextViewManagerCallback);

boolean containsMultipleFragments =
attributedString.getMapBuffer(TextLayoutManagerMapBuffer.AS_KEY_FRAGMENTS).getCount() > 1;

int textBreakStrategy =
TextAttributeProps.getTextBreakStrategy(
paragraphAttributes.getString(TextLayoutManagerMapBuffer.PA_KEY_TEXT_BREAK_STRATEGY));

return ReactTextUpdate.buildReactTextUpdateFromState(
spanned,
state.getInt(TX_STATE_KEY_MOST_RECENT_EVENT_COUNT),
TextAttributeProps.getTextAlignment(
props, TextLayoutManagerMapBuffer.isRTL(attributedString)),
textBreakStrategy,
TextAttributeProps.getJustificationMode(props),
containsMultipleFragments);
}
}
9 changes: 9 additions & 0 deletions ReactCommon/react/renderer/components/text/ParagraphState.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@
namespace facebook {
namespace react {

#ifdef ANDROID
// constants for Text State serialization
constexpr static MapBuffer::Key TX_STATE_KEY_ATTRIBUTED_STRING = 0;
constexpr static MapBuffer::Key TX_STATE_KEY_PARAGRAPH_ATTRIBUTES = 1;
// Used for TextInput only
constexpr static MapBuffer::Key TX_STATE_KEY_HASH = 2;
constexpr static MapBuffer::Key TX_STATE_KEY_MOST_RECENT_EVENT_COUNT = 3;
#endif

/*
* State for <Paragraph> component.
* Represents what to render and how to render.
Expand Down
10 changes: 1 addition & 9 deletions ReactCommon/react/renderer/components/text/conversions.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,13 @@ inline folly::dynamic toDynamic(ParagraphState const &paragraphState) {
return newState;
}

// constants for Text State serialization
constexpr static MapBuffer::Key TX_STATE_KEY_ATTRIBUTED_STRING = 0;
constexpr static MapBuffer::Key TX_STATE_KEY_PARAGRAPH_ATTRIBUTES = 1;
// Used for TextInput
constexpr static MapBuffer::Key TX_STATE_KEY_HASH = 2;
constexpr static MapBuffer::Key TX_STATE_KEY_MOST_RECENT_EVENT_COUNT = 3;

inline MapBuffer toMapBuffer(ParagraphState const &paragraphState) {
auto builder = MapBufferBuilder();
auto attStringMapBuffer = toMapBuffer(paragraphState.attributedString);
builder.putMapBuffer(TX_STATE_KEY_ATTRIBUTED_STRING, attStringMapBuffer);
auto paMapBuffer = toMapBuffer(paragraphState.paragraphAttributes);
builder.putMapBuffer(TX_STATE_KEY_PARAGRAPH_ATTRIBUTES, paMapBuffer);
// TODO: Used for TextInput
builder.putInt(TX_STATE_KEY_HASH, 1234);
builder.putInt(TX_STATE_KEY_HASH, attStringMapBuffer.getInt(AS_KEY_HASH));
return builder.build();
}
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
#include <react/renderer/components/text/conversions.h>
#include <react/renderer/debug/debugStringConvertibleUtils.h>

#ifdef ANDROID
#include <react/renderer/mapbuffer/MapBuffer.h>
#include <react/renderer/mapbuffer/MapBufferBuilder.h>
#endif

#include <utility>

namespace facebook {
Expand Down Expand Up @@ -89,6 +94,23 @@ folly::dynamic AndroidTextInputState::getDynamic() const {
}
return newState;
}

MapBuffer AndroidTextInputState::getMapBuffer() const {
auto builder = MapBufferBuilder();
// See comment in getDynamic block.
if (cachedAttributedStringId == 0) {
builder.putInt(TX_STATE_KEY_MOST_RECENT_EVENT_COUNT, mostRecentEventCount);

auto attStringMapBuffer = toMapBuffer(attributedString);
builder.putMapBuffer(TX_STATE_KEY_ATTRIBUTED_STRING, attStringMapBuffer);
auto paMapBuffer = toMapBuffer(paragraphAttributes);
builder.putMapBuffer(TX_STATE_KEY_PARAGRAPH_ATTRIBUTES, paMapBuffer);

builder.putInt(TX_STATE_KEY_HASH, attStringMapBuffer.getInt(AS_KEY_HASH));
}
return builder.build();
}

#endif

} // namespace react
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,7 @@ class AndroidTextInputState final {
AndroidTextInputState const &previousState,
folly::dynamic const &data);
folly::dynamic getDynamic() const;
MapBuffer getMapBuffer() const {
return MapBufferBuilder::EMPTY();
};
MapBuffer getMapBuffer() const;
};

} // namespace react
Expand Down

0 comments on commit 62364d0

Please sign in to comment.