mirror of
https://github.com/status-im/react-native.git
synced 2025-02-28 09:00:55 +00:00
ReactRawTextShadowNode does not inherit ReactTextShadowNode anymore
Summary: ReactRawTextShadowNode represents "raw" text node (aka textContent), so it cannot have layout or styling, it is just a line of text, a pure string. So, we must not interit it from HUGE ReactTextShadowNode (which represents <Text> node with ReactRawTextShadowNode instance inside). We need this change to make future fancy (and valuable from product perspective) refactoring possible. Stay tuned! Reviewed By: achen1 Differential Revision: D5712961 fbshipit-source-id: 009e48046bdf34ddfd40b93175934969af64b98b
This commit is contained in:
parent
393bf88be6
commit
80027ce6db
@ -9,16 +9,19 @@
|
||||
|
||||
package com.facebook.react.views.text;
|
||||
|
||||
import android.view.View;
|
||||
import com.facebook.react.common.annotations.VisibleForTesting;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
import com.facebook.react.uimanager.ThemedReactContext;
|
||||
import com.facebook.react.uimanager.ViewManager;
|
||||
|
||||
/**
|
||||
* Manages raw text nodes. Since they are used only as a virtual nodes any type of native view
|
||||
* operation will throw an {@link IllegalStateException}
|
||||
* Manages raw text nodes (aka {@code textContent} in terms of DOM).
|
||||
* Since they are used only as a virtual nodes, any type of native view
|
||||
* operation will throw an {@link IllegalStateException}.
|
||||
*/
|
||||
@ReactModule(name = ReactRawTextManager.REACT_CLASS)
|
||||
public class ReactRawTextManager extends ReactTextViewManager {
|
||||
public class ReactRawTextManager extends ViewManager<View, ReactRawTextShadowNode> {
|
||||
|
||||
@VisibleForTesting
|
||||
public static final String REACT_CLASS = "RCTRawText";
|
||||
@ -30,15 +33,19 @@ public class ReactRawTextManager extends ReactTextViewManager {
|
||||
|
||||
@Override
|
||||
public ReactTextView createViewInstance(ThemedReactContext context) {
|
||||
throw new IllegalStateException("RKRawText doesn't map into a native view");
|
||||
throw new IllegalStateException("Attempt to create a native view for RCTRawText");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateExtraData(ReactTextView view, Object extraData) {
|
||||
public void updateExtraData(View view, Object extraData) {}
|
||||
|
||||
@Override
|
||||
public Class<ReactRawTextShadowNode> getShadowNodeClass() {
|
||||
return ReactRawTextShadowNode.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReactTextShadowNode createShadowNodeInstance() {
|
||||
return new ReactVirtualTextShadowNode();
|
||||
public ReactRawTextShadowNode createShadowNodeInstance() {
|
||||
return new ReactRawTextShadowNode();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc. All rights reserved.
|
||||
*
|
||||
* <p>This source code is licensed under the BSD-style license found in the LICENSE file in the root
|
||||
* directory of this source tree. An additional grant of patent rights can be found in the PATENTS
|
||||
* file in the same directory.
|
||||
*/
|
||||
package com.facebook.react.views.text;
|
||||
|
||||
import com.facebook.react.common.annotations.VisibleForTesting;
|
||||
import com.facebook.react.uimanager.ReactShadowNode;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* {@link ReactShadowNode} class for pure raw text node
|
||||
* (aka {@code textContent} in terms of DOM).
|
||||
* Raw text node can only have simple string value without any attributes,
|
||||
* properties or state.
|
||||
*/
|
||||
public class ReactRawTextShadowNode extends ReactShadowNode {
|
||||
|
||||
@VisibleForTesting public static final String PROP_TEXT = "text";
|
||||
|
||||
private @Nullable String mText = null;
|
||||
|
||||
@ReactProp(name = PROP_TEXT)
|
||||
public void setText(@Nullable String text) {
|
||||
mText = text;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
public @Nullable String getText() {
|
||||
return mText;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVirtual() {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -9,11 +9,6 @@
|
||||
|
||||
package com.facebook.react.views.text;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Build;
|
||||
import android.text.BoringLayout;
|
||||
@ -30,27 +25,28 @@ import android.text.style.StrikethroughSpan;
|
||||
import android.text.style.UnderlineSpan;
|
||||
import android.view.Gravity;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.facebook.yoga.YogaDirection;
|
||||
import com.facebook.yoga.YogaConstants;
|
||||
import com.facebook.yoga.YogaMeasureMode;
|
||||
import com.facebook.yoga.YogaMeasureFunction;
|
||||
import com.facebook.yoga.YogaNode;
|
||||
import com.facebook.yoga.YogaMeasureOutput;
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.common.annotations.VisibleForTesting;
|
||||
import com.facebook.react.uimanager.IllegalViewOperationException;
|
||||
import com.facebook.react.uimanager.LayoutShadowNode;
|
||||
import com.facebook.react.uimanager.ReactShadowNode;
|
||||
import com.facebook.react.uimanager.Spacing;
|
||||
import com.facebook.react.uimanager.PixelUtil;
|
||||
import com.facebook.react.uimanager.ReactShadowNode;
|
||||
import com.facebook.react.uimanager.Spacing;
|
||||
import com.facebook.react.uimanager.UIViewOperationQueue;
|
||||
import com.facebook.react.uimanager.ViewDefaults;
|
||||
import com.facebook.react.uimanager.ViewProps;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
import com.facebook.yoga.YogaConstants;
|
||||
import com.facebook.yoga.YogaDirection;
|
||||
import com.facebook.yoga.YogaMeasureFunction;
|
||||
import com.facebook.yoga.YogaMeasureMode;
|
||||
import com.facebook.yoga.YogaMeasureOutput;
|
||||
import com.facebook.yoga.YogaNode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* {@link ReactShadowNode} class for spannable text view.
|
||||
@ -107,13 +103,15 @@ public class ReactTextShadowNode extends LayoutShadowNode {
|
||||
ReactTextShadowNode textShadowNode,
|
||||
SpannableStringBuilder sb,
|
||||
List<SetSpanOperation> ops) {
|
||||
|
||||
int start = sb.length();
|
||||
if (textShadowNode.mText != null) {
|
||||
sb.append(textShadowNode.mText);
|
||||
}
|
||||
|
||||
for (int i = 0, length = textShadowNode.getChildCount(); i < length; i++) {
|
||||
ReactShadowNode child = textShadowNode.getChildAt(i);
|
||||
if (child instanceof ReactTextShadowNode) {
|
||||
|
||||
if (child instanceof ReactRawTextShadowNode) {
|
||||
sb.append(((ReactRawTextShadowNode) child).getText());
|
||||
} else if (child instanceof ReactTextShadowNode) {
|
||||
buildSpannedFromShadowNode((ReactTextShadowNode) child, sb, ops);
|
||||
} else if (child instanceof ReactTextInlineImageShadowNode) {
|
||||
// We make the image take up 1 character in the span and put a corresponding character into
|
||||
@ -182,8 +180,10 @@ public class ReactTextShadowNode extends LayoutShadowNode {
|
||||
}
|
||||
}
|
||||
|
||||
protected static Spannable spannedFromShadowNode(ReactTextShadowNode textShadowNode) {
|
||||
protected static Spannable spannedFromShadowNode(
|
||||
ReactTextShadowNode textShadowNode, String text) {
|
||||
SpannableStringBuilder sb = new SpannableStringBuilder();
|
||||
|
||||
// TODO(5837930): Investigate whether it's worth optimizing this part and do it if so
|
||||
|
||||
// The {@link SpannableStringBuilder} implementation require setSpan operation to be called
|
||||
@ -191,6 +191,11 @@ public class ReactTextShadowNode extends LayoutShadowNode {
|
||||
// a new spannable will be wiped out
|
||||
List<SetSpanOperation> ops = new ArrayList<>();
|
||||
buildSpannedFromShadowNode(textShadowNode, sb, ops);
|
||||
|
||||
if (text != null) {
|
||||
sb.append(text);
|
||||
}
|
||||
|
||||
if (textShadowNode.mFontSize == UNSET) {
|
||||
sb.setSpan(
|
||||
new AbsoluteSizeSpan(textShadowNode.mAllowFontScaling
|
||||
@ -375,7 +380,6 @@ public class ReactTextShadowNode extends LayoutShadowNode {
|
||||
* <Text style={{fontFamily="serif}}>Bold Text</Text>
|
||||
*/
|
||||
private @Nullable String mFontFamily = null;
|
||||
private @Nullable String mText = null;
|
||||
|
||||
private @Nullable Spannable mPreparedSpannableText;
|
||||
|
||||
@ -415,7 +419,7 @@ public class ReactTextShadowNode extends LayoutShadowNode {
|
||||
if (isVirtual()) {
|
||||
return;
|
||||
}
|
||||
mPreparedSpannableText = spannedFromShadowNode(this);
|
||||
mPreparedSpannableText = spannedFromShadowNode(this, null);
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ -428,12 +432,6 @@ public class ReactTextShadowNode extends LayoutShadowNode {
|
||||
}
|
||||
}
|
||||
|
||||
@ReactProp(name = PROP_TEXT)
|
||||
public void setText(@Nullable String text) {
|
||||
mText = text;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = ViewProps.NUMBER_OF_LINES, defaultInt = UNSET)
|
||||
public void setNumberOfLines(int numberOfLines) {
|
||||
mNumberOfLines = numberOfLines == 0 ? UNSET : numberOfLines;
|
||||
|
@ -11,13 +11,14 @@ package com.facebook.react.views.text;
|
||||
|
||||
import com.facebook.react.common.annotations.VisibleForTesting;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
import com.facebook.react.uimanager.ThemedReactContext;
|
||||
|
||||
/**
|
||||
* Manages raw text nodes. Since they are used only as a virtual nodes any type of native view
|
||||
* operation will throw an {@link IllegalStateException}
|
||||
*/
|
||||
@ReactModule(name = ReactVirtualTextViewManager.REACT_CLASS)
|
||||
public class ReactVirtualTextViewManager extends ReactRawTextManager {
|
||||
public class ReactVirtualTextViewManager extends ReactTextViewManager {
|
||||
|
||||
@VisibleForTesting
|
||||
public static final String REACT_CLASS = "RCTVirtualText";
|
||||
@ -26,4 +27,17 @@ public class ReactVirtualTextViewManager extends ReactRawTextManager {
|
||||
public String getName() {
|
||||
return REACT_CLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReactTextView createViewInstance(ThemedReactContext context) {
|
||||
throw new IllegalStateException("Attempt to create a native view for RCTVirtualText");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateExtraData(ReactTextView view, Object extraData) {}
|
||||
|
||||
@Override
|
||||
public ReactTextShadowNode createShadowNodeInstance() {
|
||||
return new ReactVirtualTextShadowNode();
|
||||
}
|
||||
}
|
||||
|
@ -9,21 +9,11 @@
|
||||
|
||||
package com.facebook.react.views.textinput;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.OverridingMethodsMustInvokeSuper;
|
||||
|
||||
import android.os.Build;
|
||||
import android.text.Layout;
|
||||
import android.text.Spannable;
|
||||
import android.util.TypedValue;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
|
||||
import com.facebook.yoga.YogaDirection;
|
||||
import com.facebook.yoga.YogaMeasureMode;
|
||||
import com.facebook.yoga.YogaMeasureFunction;
|
||||
import com.facebook.yoga.YogaNode;
|
||||
import com.facebook.yoga.YogaMeasureOutput;
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
|
||||
import com.facebook.react.common.annotations.VisibleForTesting;
|
||||
@ -32,11 +22,15 @@ import com.facebook.react.uimanager.Spacing;
|
||||
import com.facebook.react.uimanager.ThemedReactContext;
|
||||
import com.facebook.react.uimanager.UIViewOperationQueue;
|
||||
import com.facebook.react.uimanager.ViewDefaults;
|
||||
import com.facebook.react.uimanager.ViewProps;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
import com.facebook.react.views.view.MeasureUtil;
|
||||
import com.facebook.react.views.text.ReactTextShadowNode;
|
||||
import com.facebook.react.views.text.ReactTextUpdate;
|
||||
import com.facebook.react.views.view.MeasureUtil;
|
||||
import com.facebook.yoga.YogaMeasureFunction;
|
||||
import com.facebook.yoga.YogaMeasureMode;
|
||||
import com.facebook.yoga.YogaMeasureOutput;
|
||||
import com.facebook.yoga.YogaNode;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@VisibleForTesting
|
||||
public class ReactTextInputShadowNode extends ReactTextShadowNode implements
|
||||
@ -45,6 +39,10 @@ public class ReactTextInputShadowNode extends ReactTextShadowNode implements
|
||||
private @Nullable EditText mEditText;
|
||||
private int mMostRecentEventCount = UNSET;
|
||||
|
||||
@VisibleForTesting public static final String PROP_TEXT = "text";
|
||||
|
||||
private @Nullable String mText = null;
|
||||
|
||||
public ReactTextInputShadowNode() {
|
||||
mTextBreakStrategy = (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) ?
|
||||
0 : Layout.BREAK_STRATEGY_SIMPLE;
|
||||
@ -114,6 +112,16 @@ public class ReactTextInputShadowNode extends ReactTextShadowNode implements
|
||||
mMostRecentEventCount = mostRecentEventCount;
|
||||
}
|
||||
|
||||
@ReactProp(name = PROP_TEXT)
|
||||
public void setText(@Nullable String text) {
|
||||
mText = text;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
public @Nullable String getText() {
|
||||
return mText;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTextBreakStrategy(@Nullable String textBreakStrategy) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||
@ -136,19 +144,17 @@ public class ReactTextInputShadowNode extends ReactTextShadowNode implements
|
||||
super.onCollectExtraUpdates(uiViewOperationQueue);
|
||||
|
||||
if (mMostRecentEventCount != UNSET) {
|
||||
Spannable preparedSpannableText = spannedFromShadowNode(this);
|
||||
ReactTextUpdate reactTextUpdate =
|
||||
new ReactTextUpdate(
|
||||
preparedSpannableText,
|
||||
mMostRecentEventCount,
|
||||
mContainsImages,
|
||||
getPadding(Spacing.LEFT),
|
||||
getPadding(Spacing.TOP),
|
||||
getPadding(Spacing.RIGHT),
|
||||
getPadding(Spacing.BOTTOM),
|
||||
mTextAlign,
|
||||
mTextBreakStrategy
|
||||
);
|
||||
new ReactTextUpdate(
|
||||
spannedFromShadowNode(this, getText()),
|
||||
mMostRecentEventCount,
|
||||
mContainsImages,
|
||||
getPadding(Spacing.LEFT),
|
||||
getPadding(Spacing.TOP),
|
||||
getPadding(Spacing.RIGHT),
|
||||
getPadding(Spacing.BOTTOM),
|
||||
mTextAlign,
|
||||
mTextBreakStrategy);
|
||||
uiViewOperationQueue.enqueueUpdateExtraData(getReactTag(), reactTextUpdate);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user