From c9e11d5a2017a9d515c93bf2936b0c015bafdf7e Mon Sep 17 00:00:00 2001 From: Szymon Date: Wed, 8 Mar 2023 10:33:25 +0100 Subject: [PATCH 01/22] android part --- Libraries/Text/Text.js | 9 +++-- Libraries/Text/TextNativeComponent.js | 2 +- .../react/uimanager/ViewDefaults.java | 3 +- .../facebook/react/uimanager/ViewProps.java | 1 + .../views/text/ReactBaseTextShadowNode.java | 7 ++++ .../text/ReactTextAnchorViewManager.java | 6 +++ .../react/views/text/ReactTextShadowNode.java | 6 +-- .../react/views/text/TextLayoutManager.java | 38 ++++++++++++++++++ .../text/TextLayoutManagerMapBuffer.java | 39 ++++++++++++++++++- .../react/views/textinput/ReactEditText.java | 6 +++ .../textinput/ReactTextInputLocalData.java | 2 +- .../textinput/ReactTextInputManager.java | 7 ++++ .../textinput/ReactTextInputShadowNode.java | 4 ++ .../attributedstring/ParagraphAttributes.cpp | 3 ++ .../attributedstring/ParagraphAttributes.h | 6 +++ .../renderer/attributedstring/conversions.h | 16 ++++++-- .../AndroidTextInputProps.cpp | 12 ++++++ .../androidtextinput/AndroidTextInputProps.h | 1 + 18 files changed, 154 insertions(+), 14 deletions(-) diff --git a/Libraries/Text/Text.js b/Libraries/Text/Text.js index df548af47dab81..7f1dc712d5bf0b 100644 --- a/Libraries/Text/Text.js +++ b/Libraries/Text/Text.js @@ -59,6 +59,7 @@ const Text: React.AbstractComponent< pressRetentionOffset, role, suppressHighlighting, + numberOfLines, ...restProps } = props; @@ -192,12 +193,12 @@ const Text: React.AbstractComponent< } } - let numberOfLines = restProps.numberOfLines; + let numberOfLinesValue = numberOfLines; if (numberOfLines != null && !(numberOfLines >= 0)) { console.error( `'numberOfLines' in must be a non-negative number, received: ${numberOfLines}. The value will be set to 0.`, ); - numberOfLines = 0; + numberOfLinesValue = 0; } const hasTextAncestor = useContext(TextAncestor); @@ -241,7 +242,7 @@ const Text: React.AbstractComponent< isHighlighted={isHighlighted} isPressable={isPressable} nativeID={id ?? nativeID} - numberOfLines={numberOfLines} + maximumNumberOfLines={numberOfLinesValue} ref={forwardedRef} selectable={_selectable} selectionColor={selectionColor} @@ -267,7 +268,7 @@ const Text: React.AbstractComponent< ellipsizeMode={ellipsizeMode ?? 'tail'} isHighlighted={isHighlighted} nativeID={id ?? nativeID} - numberOfLines={numberOfLines} + maximumNumberOfLines={numberOfLinesValue} ref={forwardedRef} selectable={_selectable} selectionColor={selectionColor} diff --git a/Libraries/Text/TextNativeComponent.js b/Libraries/Text/TextNativeComponent.js index 0d5990455b5be0..f49970e1b40255 100644 --- a/Libraries/Text/TextNativeComponent.js +++ b/Libraries/Text/TextNativeComponent.js @@ -31,7 +31,7 @@ const textViewConfig = { validAttributes: { isHighlighted: true, isPressable: true, - numberOfLines: true, + maximumNumberOfLines: true, ellipsizeMode: true, allowFontScaling: true, dynamicTypeRamp: true, diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewDefaults.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewDefaults.java index 8cab4071bda2ef..ad5fa969d38db4 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewDefaults.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewDefaults.java @@ -12,5 +12,6 @@ public class ViewDefaults { public static final float FONT_SIZE_SP = 14.0f; public static final int LINE_HEIGHT = 0; - public static final int NUMBER_OF_LINES = Integer.MAX_VALUE; + public static final int NUMBER_OF_LINES = -1; + public static final int MAXIMUM_NUMBER_OF_LINES = Integer.MAX_VALUE; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java index 3f76fa7dd3d9b1..7a5d0966eba4aa 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java @@ -96,6 +96,7 @@ public class ViewProps { public static final String LETTER_SPACING = "letterSpacing"; public static final String NEEDS_OFFSCREEN_ALPHA_COMPOSITING = "needsOffscreenAlphaCompositing"; public static final String NUMBER_OF_LINES = "numberOfLines"; + public static final String MAXIMUM_NUMBER_OF_LINES = "maximumNumberOfLines"; public static final String ELLIPSIZE_MODE = "ellipsizeMode"; public static final String ADJUSTS_FONT_SIZE_TO_FIT = "adjustsFontSizeToFit"; public static final String MINIMUM_FONT_SCALE = "minimumFontScale"; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java index 12c1c5e05728a9..06185bde230d79 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java @@ -328,6 +328,7 @@ protected Spannable spannedFromShadowNode( protected boolean mIsAccessibilityLink = false; protected int mNumberOfLines = UNSET; + protected int mMaxNumberOfLines = UNSET; protected int mTextAlign = Gravity.NO_GRAVITY; protected int mTextBreakStrategy = (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) ? 0 : Layout.BREAK_STRATEGY_HIGH_QUALITY; @@ -412,6 +413,12 @@ public void setNumberOfLines(int numberOfLines) { markUpdated(); } + @ReactProp(name = ViewProps.MAXIMUM_NUMBER_OF_LINES, defaultInt = UNSET) + public void setMaxNumberOfLines(int numberOfLines) { + mMaxNumberOfLines = numberOfLines == 0 ? UNSET : numberOfLines; + markUpdated(); + } + @ReactProp(name = ViewProps.LINE_HEIGHT, defaultFloat = Float.NaN) public void setLineHeight(float lineHeight) { mTextAttributes.setLineHeight(lineHeight); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java index 7b5d0c1dd32eaf..735e7aebd985e0 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java @@ -54,6 +54,12 @@ public void setNumberOfLines(ReactTextView view, int numberOfLines) { view.setNumberOfLines(numberOfLines); } + // maxLines can only be set in master view (block), doesn't really make sense to set in a span + @ReactProp(name = ViewProps.MAXIMUM_NUMBER_OF_LINES, defaultInt = ViewDefaults.NUMBER_OF_LINES) + public void setMaxNumberOfLines(ReactTextView view, int numberOfLines) { + view.setNumberOfLines(numberOfLines); + } + @ReactProp(name = ViewProps.ELLIPSIZE_MODE) public void setEllipsizeMode(ReactTextView view, @Nullable String ellipsizeMode) { if (ellipsizeMode == null || ellipsizeMode.equals("tail")) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java index 2e237f01970fb5..419eadb7450a4b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java @@ -82,7 +82,7 @@ public long measure( int minimumFontSize = (int) Math.max(mMinimumFontScale * initialFontSize, PixelUtil.toPixelFromDIP(4)); while (currentFontSize > minimumFontSize - && (mNumberOfLines != UNSET && layout.getLineCount() > mNumberOfLines + && (mMaxNumberOfLines != UNSET && layout.getLineCount() > mMaxNumberOfLines || heightMode != YogaMeasureMode.UNDEFINED && layout.getHeight() > height)) { // TODO: We could probably use a smarter algorithm here. This will require 0(n) // measurements @@ -124,9 +124,9 @@ public long measure( } final int lineCount = - mNumberOfLines == UNSET + mMaxNumberOfLines == UNSET ? layout.getLineCount() - : Math.min(mNumberOfLines, layout.getLineCount()); + : Math.min(mMaxNumberOfLines, layout.getLineCount()); // Instead of using `layout.getWidth()` (which may yield a significantly larger width for // text that is wrapping), compute width using the longest line. diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java index 870545bc5f451d..316fab68ad759e 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java @@ -18,6 +18,7 @@ import android.text.Spanned; import android.text.StaticLayout; import android.text.TextPaint; +import android.text.TextUtils; import android.util.LayoutDirection; import android.util.LruCache; import android.view.View; @@ -65,6 +66,7 @@ public class TextLayoutManager { private static final String TEXT_BREAK_STRATEGY_KEY = "textBreakStrategy"; private static final String HYPHENATION_FREQUENCY_KEY = "android_hyphenationFrequency"; private static final String MAXIMUM_NUMBER_OF_LINES_KEY = "maximumNumberOfLines"; + private static final String NUMBER_OF_LINES_KEY = "numberOfLines"; private static final LruCache sSpannableCache = new LruCache<>(spannableCacheSize); private static final ConcurrentHashMap sTagToSpannableCache = @@ -385,6 +387,42 @@ public static long measureText( ? paragraphAttributes.getInt(MAXIMUM_NUMBER_OF_LINES_KEY) : UNSET; + int numberOfLines = + paragraphAttributes.hasKey(NUMBER_OF_LINES_KEY) + ? paragraphAttributes.getInt(NUMBER_OF_LINES_KEY) + : UNSET; + + int lines = layout.getLineCount(); + if (numberOfLines != UNSET && numberOfLines != 0 && numberOfLines > lines && text.length() > 0) { + int numberOfEmptyLines = numberOfLines - lines; + SpannableStringBuilder ssb = new SpannableStringBuilder(); + + for (int i = 0; i < numberOfEmptyLines; ++i) { + ssb.append("\n"); + } + + Object[] spans = text.getSpans(0, 0, Object.class); + for (Object span : spans) { // It's possible we need to set exl-exl + ssb.setSpan(span, 0, ssb.length(), text.getSpanFlags(span)); + }; + + text = new SpannableStringBuilder(TextUtils.concat(text, ssb)); + boring = null; + layout = createLayout( + text, + boring, + width, + widthYogaMeasureMode, + includeFontPadding, + textBreakStrategy, + hyphenationFrequency); + } + + + if (numberOfLines != UNSET && numberOfLines != 0 && numberOfLines <= lines) { + maximumNumberOfLines = numberOfLines; + } + int calculatedLineCount = maximumNumberOfLines == UNSET || maximumNumberOfLines == 0 ? layout.getLineCount() diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java index 9ff17c4359fbe1..f86923275c7bc6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java @@ -18,6 +18,7 @@ import android.text.Spanned; import android.text.StaticLayout; import android.text.TextPaint; +import android.text.TextUtils; import android.util.LayoutDirection; import android.util.LruCache; import android.view.View; @@ -61,6 +62,7 @@ public class TextLayoutManagerMapBuffer { public static final short PA_KEY_ADJUST_FONT_SIZE_TO_FIT = 3; public static final short PA_KEY_INCLUDE_FONT_PADDING = 4; public static final short PA_KEY_HYPHENATION_FREQUENCY = 5; + public static final short PA_KEY_NUMBER_OF_LINES = 6; private static final boolean ENABLE_MEASURE_LOGGING = ReactBuildConfig.DEBUG && false; @@ -405,10 +407,45 @@ public static long measureText( ? paragraphAttributes.getInt(PA_KEY_MAX_NUMBER_OF_LINES) : UNSET; + int numberOfLines = + paragraphAttributes.contains(PA_KEY_NUMBER_OF_LINES) + ? paragraphAttributes.getInt(PA_KEY_NUMBER_OF_LINES) + : UNSET; + + int lines = layout.getLineCount(); + if (numberOfLines != UNSET && numberOfLines != 0 && numberOfLines > lines && text.length() > 0) { + int numberOfEmptyLines = numberOfLines - lines; + SpannableStringBuilder ssb = new SpannableStringBuilder(); + + for (int i = 0; i < numberOfEmptyLines; ++i) { + ssb.append("\n"); + } + + Object[] spans = text.getSpans(0, 0, Object.class); + for (Object span : spans) { // It's possible we need to set exl-exl + ssb.setSpan(span, 0, ssb.length(), text.getSpanFlags(span)); + }; + + text = new SpannableStringBuilder(TextUtils.concat(text, ssb)); + boring = null; + layout = createLayout( + text, + boring, + width, + widthYogaMeasureMode, + includeFontPadding, + textBreakStrategy, + hyphenationFrequency); + } + + if (numberOfLines != UNSET && numberOfLines != 0 && numberOfLines <= lines) { + maximumNumberOfLines = numberOfLines; + } + int calculatedLineCount = maximumNumberOfLines == UNSET || maximumNumberOfLines == 0 ? layout.getLineCount() - : Math.min(maximumNumberOfLines, layout.getLineCount()); + : Math.min(maximumNumberOfLines, layout.getLineCount()); // Instead of using `layout.getWidth()` (which may yield a significantly larger width for // text that is wrapping), compute width using the longest line. diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java index 6e2e24cc29eaa1..61ded0765e449d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java @@ -477,7 +477,13 @@ public void setInputType(int type) { * href='https://android.googlesource.com/platform/frameworks/base/+/jb-release/core/java/android/widget/TextView.java'>TextView.java} */ if (isMultiline()) { + // we save max lines as setSingleLines overwrites it + // https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/widget/TextView.java#10671 + int maxLines = getMaxLines(); setSingleLine(false); + if (maxLines != -1) { + setMaxLines(maxLines); + } } // We override the KeyListener so that all keys on the soft input keyboard as well as hardware diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputLocalData.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputLocalData.java index a85051068d2974..c59be1de38e761 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputLocalData.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputLocalData.java @@ -41,9 +41,9 @@ public ReactTextInputLocalData(EditText editText) { public void apply(EditText editText) { editText.setText(mText); editText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize); + editText.setInputType(mInputType); editText.setMinLines(mMinLines); editText.setMaxLines(mMaxLines); - editText.setInputType(mInputType); editText.setHint(mPlaceholder); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { editText.setBreakStrategy(mBreakStrategy); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java index 7059ca3ed48846..7451bab2842fbe 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java @@ -732,9 +732,16 @@ public void setEditable(ReactEditText view, boolean editable) { @ReactProp(name = ViewProps.NUMBER_OF_LINES, defaultInt = 1) public void setNumLines(ReactEditText view, int numLines) { + view.setInputType(view.getInputType() | InputType.TYPE_TEXT_FLAG_MULTI_LINE); view.setLines(numLines); } + @ReactProp(name = ViewProps.MAXIMUM_NUMBER_OF_LINES, defaultInt = 1) + public void setMaxNumLines(ReactEditText view, int numLines) { + view.setInputType(view.getInputType() | InputType.TYPE_TEXT_FLAG_MULTI_LINE); + view.setMaxLines(numLines); + } + @ReactProp(name = "maxLength") public void setMaxLength(ReactEditText view, @Nullable Integer maxLength) { InputFilter[] currentFilters = view.getFilters(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputShadowNode.java index d53a7f9083aa60..26ecd718ca4f54 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputShadowNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputShadowNode.java @@ -118,6 +118,10 @@ public long measure( if (mNumberOfLines != UNSET) { editText.setLines(mNumberOfLines); + } else { + if (mMaxNumberOfLines != UNSET) { + editText.setMaxLines(mMaxNumberOfLines); + } } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M diff --git a/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp b/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp index 2994acac6122a0..fff0d5ebb10adc 100644 --- a/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp +++ b/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp @@ -16,6 +16,7 @@ namespace facebook::react { bool ParagraphAttributes::operator==(const ParagraphAttributes &rhs) const { return std::tie( + numberOfLines, maximumNumberOfLines, ellipsizeMode, textBreakStrategy, @@ -23,6 +24,7 @@ bool ParagraphAttributes::operator==(const ParagraphAttributes &rhs) const { includeFontPadding, android_hyphenationFrequency) == std::tie( + rhs.numberOfLines, rhs.maximumNumberOfLines, rhs.ellipsizeMode, rhs.textBreakStrategy, @@ -42,6 +44,7 @@ bool ParagraphAttributes::operator!=(const ParagraphAttributes &rhs) const { #if RN_DEBUG_STRING_CONVERTIBLE SharedDebugStringConvertibleList ParagraphAttributes::getDebugProps() const { return { + debugStringConvertibleItem("numberOfLines", numberOfLines), debugStringConvertibleItem("maximumNumberOfLines", maximumNumberOfLines), debugStringConvertibleItem("ellipsizeMode", ellipsizeMode), debugStringConvertibleItem("textBreakStrategy", textBreakStrategy), diff --git a/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h b/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h index f5f87c6cf52050..b7d1e90c9d7e9d 100644 --- a/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h +++ b/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h @@ -30,6 +30,11 @@ class ParagraphAttributes : public DebugStringConvertible { public: #pragma mark - Fields + /* + * Number of lines which paragraph takes. + */ + int numberOfLines{}; + /* * Maximum number of lines which paragraph can take. * Zero value represents "no limit". @@ -92,6 +97,7 @@ struct hash { const facebook::react::ParagraphAttributes &attributes) const { return folly::hash::hash_combine( 0, + attributes.numberOfLines, attributes.maximumNumberOfLines, attributes.ellipsizeMode, attributes.textBreakStrategy, diff --git a/ReactCommon/react/renderer/attributedstring/conversions.h b/ReactCommon/react/renderer/attributedstring/conversions.h index 8687b892204da2..26379f41e98b9b 100644 --- a/ReactCommon/react/renderer/attributedstring/conversions.h +++ b/ReactCommon/react/renderer/attributedstring/conversions.h @@ -835,12 +835,18 @@ inline ParagraphAttributes convertRawProp( ParagraphAttributes const &defaultParagraphAttributes) { auto paragraphAttributes = ParagraphAttributes{}; - paragraphAttributes.maximumNumberOfLines = convertRawProp( + paragraphAttributes.numberOfLines = convertRawProp( context, rawProps, "numberOfLines", - sourceParagraphAttributes.maximumNumberOfLines, - defaultParagraphAttributes.maximumNumberOfLines); + sourceParagraphAttributes.numberOfLines, + defaultParagraphAttributes.numberOfLines); + paragraphAttributes.maximumNumberOfLines = convertRawProp( + context, + rawProps, + "maximumNumberOfLines", + sourceParagraphAttributes.maximumNumberOfLines, + defaultParagraphAttributes.maximumNumberOfLines); paragraphAttributes.ellipsizeMode = convertRawProp( context, rawProps, @@ -913,6 +919,7 @@ inline std::string toString(AttributedString::Range const &range) { inline folly::dynamic toDynamic( const ParagraphAttributes ¶graphAttributes) { auto values = folly::dynamic::object(); + values("numberOfLines", paragraphAttributes.numberOfLines); values("maximumNumberOfLines", paragraphAttributes.maximumNumberOfLines); values("ellipsizeMode", toString(paragraphAttributes.ellipsizeMode)); values("textBreakStrategy", toString(paragraphAttributes.textBreakStrategy)); @@ -1118,6 +1125,7 @@ constexpr static MapBuffer::Key PA_KEY_TEXT_BREAK_STRATEGY = 2; constexpr static MapBuffer::Key PA_KEY_ADJUST_FONT_SIZE_TO_FIT = 3; constexpr static MapBuffer::Key PA_KEY_INCLUDE_FONT_PADDING = 4; constexpr static MapBuffer::Key PA_KEY_HYPHENATION_FREQUENCY = 5; +constexpr static MapBuffer::Key PA_KEY_NUMBER_OF_LINES = 6; inline MapBuffer toMapBuffer(const ParagraphAttributes ¶graphAttributes) { auto builder = MapBufferBuilder(); @@ -1135,6 +1143,8 @@ inline MapBuffer toMapBuffer(const ParagraphAttributes ¶graphAttributes) { builder.putString( PA_KEY_HYPHENATION_FREQUENCY, toString(paragraphAttributes.android_hyphenationFrequency)); + builder.putInt( + PA_KEY_NUMBER_OF_LINES, paragraphAttributes.numberOfLines); return builder.build(); } diff --git a/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp b/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp index 19cb290a3323f2..ca8215d9ccc68e 100644 --- a/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp +++ b/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp @@ -56,6 +56,10 @@ AndroidTextInputProps::AndroidTextInputProps( "numberOfLines", sourceProps.numberOfLines, {0})), + maximumNumberOfLines(CoreFeatures::enablePropIteratorSetter? sourceProps.maximumNumberOfLines : convertRawProp(context, rawProps, + "maximumNumberOfLines", + sourceProps.maximumNumberOfLines, + {0})), disableFullscreenUI(CoreFeatures::enablePropIteratorSetter? sourceProps.disableFullscreenUI : convertRawProp(context, rawProps, "disableFullscreenUI", sourceProps.disableFullscreenUI, @@ -283,6 +287,12 @@ void AndroidTextInputProps::setProp( value, paragraphAttributes, maximumNumberOfLines, + "maximumNumberOfLines"); + REBUILD_FIELD_SWITCH_CASE( + paDefaults, + value, + paragraphAttributes, + numberOfLines, "numberOfLines"); REBUILD_FIELD_SWITCH_CASE( paDefaults, value, paragraphAttributes, ellipsizeMode, "ellipsizeMode"); @@ -325,6 +335,7 @@ void AndroidTextInputProps::setProp( } switch (hash) { + RAW_SET_PROP_SWITCH_CASE_BASIC(maximumNumberOfLines); RAW_SET_PROP_SWITCH_CASE_BASIC(autoComplete); RAW_SET_PROP_SWITCH_CASE_BASIC(returnKeyLabel); RAW_SET_PROP_SWITCH_CASE_BASIC(numberOfLines); @@ -425,6 +436,7 @@ void AndroidTextInputProps::setProp( // TODO T53300085: support this in codegen; this was hand-written folly::dynamic AndroidTextInputProps::getDynamic() const { folly::dynamic props = folly::dynamic::object(); + props["maximumNumberOfLines"] = maximumNumberOfLines; props["autoComplete"] = autoComplete; props["returnKeyLabel"] = returnKeyLabel; props["numberOfLines"] = numberOfLines; diff --git a/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h b/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h index 7652984ce15e86..a24b68f0d036a6 100644 --- a/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h +++ b/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h @@ -117,6 +117,7 @@ class AndroidTextInputProps final : public ViewProps, public BaseTextProps { std::string autoComplete{}; std::string returnKeyLabel{}; int numberOfLines{0}; + int maximumNumberOfLines{0}; bool disableFullscreenUI{false}; std::string textBreakStrategy{}; SharedColor underlineColorAndroid{}; From e55eed861b39c99d75cd57efd9b58056a62c3ac3 Mon Sep 17 00:00:00 2001 From: Szymon Date: Wed, 8 Mar 2023 10:55:08 +0100 Subject: [PATCH 02/22] ios changes --- .../TextInput/RCTTextInputViewConfig.js | 2 + Libraries/Components/TextInput/TextInput.js | 10 +++- Libraries/Text/Text/RCTTextViewManager.m | 2 +- .../RCTMultilineTextInputViewManager.m | 15 ++++++ .../TextInput/RCTBaseTextInputShadowView.h | 1 + .../TextInput/RCTBaseTextInputShadowView.m | 17 ++++++- .../RCTSinglelineTextInputViewManager.m | 1 + .../textlayoutmanager/RCTTextLayoutManager.mm | 46 ++++++++++++++----- 8 files changed, 79 insertions(+), 15 deletions(-) diff --git a/Libraries/Components/TextInput/RCTTextInputViewConfig.js b/Libraries/Components/TextInput/RCTTextInputViewConfig.js index 6f693295320eb4..d531bee9a5cd6a 100644 --- a/Libraries/Components/TextInput/RCTTextInputViewConfig.js +++ b/Libraries/Components/TextInput/RCTTextInputViewConfig.js @@ -144,6 +144,8 @@ const RCTTextInputViewConfig = { placeholder: true, autoCorrect: true, multiline: true, + numberOfLines: true, + maximumNumberOfLines: true, textContentType: true, maxLength: true, autoCapitalize: true, diff --git a/Libraries/Components/TextInput/TextInput.js b/Libraries/Components/TextInput/TextInput.js index ec337de164ef8a..898a513e935a99 100644 --- a/Libraries/Components/TextInput/TextInput.js +++ b/Libraries/Components/TextInput/TextInput.js @@ -519,7 +519,6 @@ type AndroidProps = $ReadOnly<{| /** * Sets the number of lines for a `TextInput`. Use it with multiline set to * `true` to be able to fill the lines. - * @platform android */ numberOfLines?: ?number, @@ -532,10 +531,14 @@ type AndroidProps = $ReadOnly<{| /** * Sets the number of rows for a `TextInput`. Use it with multiline set to * `true` to be able to fill the lines. - * @platform android */ rows?: ?number, + /** + * Sets the maximum number of lines the TextInput can have. + */ + maximumNumberOfLines?: ?number, + /** * When `false`, it will prevent the soft keyboard from showing when the field is focused. * Defaults to `true`. @@ -1077,6 +1080,8 @@ function InternalTextInput(props: Props): React.Node { accessibilityState, id, tabIndex, + rows, + numberOfLines, ...otherProps } = props; @@ -1447,6 +1452,7 @@ function InternalTextInput(props: Props): React.Node { focusable={tabIndex !== undefined ? !tabIndex : focusable} mostRecentEventCount={mostRecentEventCount} nativeID={id ?? props.nativeID} + numberOfLines={props.rows ?? props.numberOfLines} onBlur={_onBlur} onKeyPressSync={props.unstable_onKeyPressSync} onChange={_onChange} diff --git a/Libraries/Text/Text/RCTTextViewManager.m b/Libraries/Text/Text/RCTTextViewManager.m index 7fec0b7b58b010..7b53c80d557acc 100644 --- a/Libraries/Text/Text/RCTTextViewManager.m +++ b/Libraries/Text/Text/RCTTextViewManager.m @@ -26,7 +26,7 @@ @implementation RCTTextViewManager { RCT_EXPORT_MODULE(RCTText) -RCT_REMAP_SHADOW_PROPERTY(numberOfLines, maximumNumberOfLines, NSInteger) +RCT_EXPORT_SHADOW_PROPERTY(maximumNumberOfLines, NSInteger) RCT_REMAP_SHADOW_PROPERTY(ellipsizeMode, lineBreakMode, NSLineBreakMode) RCT_REMAP_SHADOW_PROPERTY(adjustsFontSizeToFit, adjustsFontSizeToFit, BOOL) RCT_REMAP_SHADOW_PROPERTY(minimumFontScale, minimumFontScale, CGFloat) diff --git a/Libraries/Text/TextInput/Multiline/RCTMultilineTextInputViewManager.m b/Libraries/Text/TextInput/Multiline/RCTMultilineTextInputViewManager.m index e729bb7a222a78..7d019df9b50778 100644 --- a/Libraries/Text/TextInput/Multiline/RCTMultilineTextInputViewManager.m +++ b/Libraries/Text/TextInput/Multiline/RCTMultilineTextInputViewManager.m @@ -7,6 +7,8 @@ #import #import +#import +#import @implementation RCTMultilineTextInputViewManager @@ -17,8 +19,21 @@ - (UIView *)view return [[RCTMultilineTextInputView alloc] initWithBridge:self.bridge]; } +- (RCTShadowView *)shadowView +{ + RCTBaseTextInputShadowView *shadowView = (RCTBaseTextInputShadowView *)[super shadowView]; + + shadowView.maximumNumberOfLines = 0; + shadowView.exactNumberOfLines = 0; + + return shadowView; +} + #pragma mark - Multiline (aka TextView) specific properties RCT_REMAP_VIEW_PROPERTY(dataDetectorTypes, backedTextInputView.dataDetectorTypes, UIDataDetectorTypes) +RCT_EXPORT_SHADOW_PROPERTY(maximumNumberOfLines, NSInteger) +RCT_REMAP_SHADOW_PROPERTY(numberOfLines, exactNumberOfLines, NSInteger) + @end diff --git a/Libraries/Text/TextInput/RCTBaseTextInputShadowView.h b/Libraries/Text/TextInput/RCTBaseTextInputShadowView.h index 8f4cf7eb1b5f47..6238ebc600927f 100644 --- a/Libraries/Text/TextInput/RCTBaseTextInputShadowView.h +++ b/Libraries/Text/TextInput/RCTBaseTextInputShadowView.h @@ -16,6 +16,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, copy, nullable) NSString *text; @property (nonatomic, copy, nullable) NSString *placeholder; @property (nonatomic, assign) NSInteger maximumNumberOfLines; +@property (nonatomic, assign) NSInteger exactNumberOfLines; @property (nonatomic, copy, nullable) RCTDirectEventBlock onContentSizeChange; - (void)uiManagerWillPerformMounting; diff --git a/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m b/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m index 04d2446f86d9b3..2b1affe16880dc 100644 --- a/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m +++ b/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m @@ -218,7 +218,22 @@ - (NSAttributedString *)measurableAttributedText - (CGSize)sizeThatFitsMinimumSize:(CGSize)minimumSize maximumSize:(CGSize)maximumSize { - NSAttributedString *attributedText = [self measurableAttributedText]; + NSMutableAttributedString *attributedText = [[self measurableAttributedText] mutableCopy]; + + /* + * The block below is responsible for setting the exact height of the view in lines + * Unfortunatelly, iOS doesn't export any easy way to do it. So we set maximumNumberOfLines + * prop and then add random lines at the front. However, they are only used for layout + * so they are not visible on the screen. + */ + if (self.exactNumberOfLines) { + NSMutableString *newLines = [NSMutableString stringWithCapacity: self.exactNumberOfLines]; + for (NSUInteger i = 0UL; i < self.exactNumberOfLines; ++i) { + [newLines appendString:@"\n"]; + } + [attributedText insertAttributedString:[[NSAttributedString alloc] initWithString:newLines attributes:self.textAttributes.effectiveTextAttributes] atIndex:0]; + _maximumNumberOfLines = self.exactNumberOfLines; + } if (!_textStorage) { _textContainer = [NSTextContainer new]; diff --git a/Libraries/Text/TextInput/Singleline/RCTSinglelineTextInputViewManager.m b/Libraries/Text/TextInput/Singleline/RCTSinglelineTextInputViewManager.m index 413ac42238783a..56d039ce2518f9 100644 --- a/Libraries/Text/TextInput/Singleline/RCTSinglelineTextInputViewManager.m +++ b/Libraries/Text/TextInput/Singleline/RCTSinglelineTextInputViewManager.m @@ -19,6 +19,7 @@ - (RCTShadowView *)shadowView RCTBaseTextInputShadowView *shadowView = (RCTBaseTextInputShadowView *)[super shadowView]; shadowView.maximumNumberOfLines = 1; + shadowView.exactNumberOfLines = 0; return shadowView; } diff --git a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm index c877e0a1e7824e..8e11f4571c8c97 100644 --- a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm +++ b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm @@ -178,26 +178,50 @@ - (LinesMeasurements)getLinesForAttributedString:(AttributedString)attributedStr return paragraphLines; } -- (NSTextStorage *)_textStorageForNSAttributesString:(NSAttributedString *)attributedString +- (NSTextStorage *)_textStorageForNSAttributesString:(NSAttributedString *)inputAttributedString paragraphAttributes:(ParagraphAttributes)paragraphAttributes size:(CGSize)size { - NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:size]; - - textContainer.lineFragmentPadding = 0.0; // Note, the default value is 5. - textContainer.lineBreakMode = paragraphAttributes.maximumNumberOfLines > 0 - ? RCTNSLineBreakModeFromEllipsizeMode(paragraphAttributes.ellipsizeMode) - : NSLineBreakByClipping; - textContainer.maximumNumberOfLines = paragraphAttributes.maximumNumberOfLines; + NSMutableAttributedString *attributedString = [ inputAttributedString mutableCopy]; + + /* + * The block below is responsible for setting the exact height of the view in lines + * Unfortunatelly, iOS doesn't export any easy way to do it. So we set maximumNumberOfLines + * prop and then add random lines at the front. However, they are only used for layout + * so they are not visible on the screen. This method is used for drawing only for Paragraph component + * but we set exact height in lines only on TextInput that doesn't use it. + */ + if (paragraphAttributes.numberOfLines) { + paragraphAttributes.maximumNumberOfLines = paragraphAttributes.numberOfLines; + NSMutableString *newLines = [NSMutableString stringWithCapacity: paragraphAttributes.numberOfLines]; + for (NSUInteger i = 0UL; i < paragraphAttributes.numberOfLines; ++i) { + // K is added on purpose. New line seems to be not enough for NTtextContainer + [newLines appendString:@"K\n"]; + } + NSDictionary * attributesOfFirstCharacter = [inputAttributedString attributesAtIndex:0 effectiveRange:NULL]; + + + [attributedString insertAttributedString:[[NSAttributedString alloc] initWithString:newLines attributes:attributesOfFirstCharacter] atIndex:0]; + } + + NSTextContainer *textContainer = [NSTextContainer new]; + NSLayoutManager *layoutManager = [NSLayoutManager new]; layoutManager.usesFontLeading = NO; [layoutManager addTextContainer:textContainer]; - - NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:attributedString]; - + NSTextStorage *textStorage = [NSTextStorage new]; [textStorage addLayoutManager:layoutManager]; + textContainer.lineFragmentPadding = 0.0; // Note, the default value is 5. + textContainer.lineBreakMode = paragraphAttributes.maximumNumberOfLines > 0 + ? RCTNSLineBreakModeFromEllipsizeMode(paragraphAttributes.ellipsizeMode) + : NSLineBreakByClipping; + textContainer.size = size; + textContainer.maximumNumberOfLines = paragraphAttributes.maximumNumberOfLines; + + [textStorage replaceCharactersInRange:(NSRange){0, textStorage.length} withAttributedString:attributedString]; + if (paragraphAttributes.adjustsFontSizeToFit) { CGFloat minimumFontSize = !isnan(paragraphAttributes.minimumFontSize) ? paragraphAttributes.minimumFontSize : 4.0; CGFloat maximumFontSize = !isnan(paragraphAttributes.maximumFontSize) ? paragraphAttributes.maximumFontSize : 96.0; From cd78e0d7114425305456281f7162918a490f4f75 Mon Sep 17 00:00:00 2001 From: Szymon Date: Wed, 8 Mar 2023 11:24:57 +0100 Subject: [PATCH 03/22] update types, configs --- .../AndroidTextInputNativeComponent.js | 7 ++++ Libraries/Components/TextInput/TextInput.d.ts | 24 ++++++++++---- .../Components/TextInput/TextInput.flow.js | 32 +++++++++++-------- 3 files changed, 43 insertions(+), 20 deletions(-) diff --git a/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js b/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js index e7c28912a0779e..de487e09a704eb 100644 --- a/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js +++ b/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js @@ -179,6 +179,13 @@ export type NativeProps = $ReadOnly<{| */ numberOfLines?: ?Int32, + /** + * Sets the maximum number of lines for a `TextInput`. Use it with multiline set to + * `true` to be able to fill the lines. + * @platform android + */ + maximumNumberOfLines?: ?Int32, + /** * When `false`, if there is a small amount of space available around a text input * (e.g. landscape orientation on a phone), the OS may choose to have the user edit diff --git a/Libraries/Components/TextInput/TextInput.d.ts b/Libraries/Components/TextInput/TextInput.d.ts index 637807aafd3864..30a1511ae9d2b6 100644 --- a/Libraries/Components/TextInput/TextInput.d.ts +++ b/Libraries/Components/TextInput/TextInput.d.ts @@ -414,12 +414,6 @@ export interface TextInputAndroidProps { */ inlineImagePadding?: number | undefined; - /** - * Sets the number of lines for a TextInput. - * Use it with multiline set to true to be able to fill the lines. - */ - numberOfLines?: number | undefined; - /** * Sets the return key to the label. Use it instead of `returnKeyType`. * @platform android @@ -609,11 +603,29 @@ export interface TextInputProps */ maxLength?: number | undefined; + /** + * Sets the maximum number of lines for a TextInput. + * Use it with multiline set to true to be able to fill the lines. + */ + maximumNumberOfLines?: number | undefined; + /** * If true, the text input can be multiple lines. The default value is false. */ multiline?: boolean | undefined; + /** + * Sets the number of lines for a TextInput. + * Use it with multiline set to true to be able to fill the lines. + */ + numberOfLines?: number | undefined; + + /** + * Sets the number of rows for a TextInput. + * Use it with multiline set to true to be able to fill the lines. + */ + rows?: number | undefined; + /** * Callback that is called when the text input is blurred */ diff --git a/Libraries/Components/TextInput/TextInput.flow.js b/Libraries/Components/TextInput/TextInput.flow.js index 57259190f1a449..bf9e2a24c526a2 100644 --- a/Libraries/Components/TextInput/TextInput.flow.js +++ b/Libraries/Components/TextInput/TextInput.flow.js @@ -478,26 +478,12 @@ type AndroidProps = $ReadOnly<{| */ inlineImagePadding?: ?number, - /** - * Sets the number of lines for a `TextInput`. Use it with multiline set to - * `true` to be able to fill the lines. - * @platform android - */ - numberOfLines?: ?number, - /** * Sets the return key to the label. Use it instead of `returnKeyType`. * @platform android */ returnKeyLabel?: ?string, - /** - * Sets the number of rows for a `TextInput`. Use it with multiline set to - * `true` to be able to fill the lines. - * @platform android - */ - rows?: ?number, - /** * When `false`, it will prevent the soft keyboard from showing when the field is focused. * Defaults to `true`. @@ -646,6 +632,12 @@ export type Props = $ReadOnly<{| */ keyboardType?: ?KeyboardType, + /** + * Sets the maximum number of lines for a `TextInput`. Use it with multiline set to + * `true` to be able to fill the lines. + */ + maximumNumberOfLines?: ?number, + /** * Specifies largest possible scale a font can reach when `allowFontScaling` is enabled. * Possible values: @@ -667,6 +659,12 @@ export type Props = $ReadOnly<{| */ multiline?: ?boolean, + /** + * Sets the number of lines for a `TextInput`. Use it with multiline set to + * `true` to be able to fill the lines. + */ + numberOfLines?: ?number, + /** * Callback that is called when the text input is blurred. */ @@ -828,6 +826,12 @@ export type Props = $ReadOnly<{| */ returnKeyType?: ?ReturnKeyType, + /** + * Sets the number of rows for a `TextInput`. Use it with multiline set to + * `true` to be able to fill the lines. + */ + rows?: ?number, + /** * If `true`, the text input obscures the text entered so that sensitive text * like passwords stay secure. The default value is `false`. Does not work with 'multiline={true}'. From 34acc74d2fdb98b5c054b950ddc678ec3edf744a Mon Sep 17 00:00:00 2001 From: Szymon Date: Wed, 8 Mar 2023 11:32:02 +0100 Subject: [PATCH 04/22] fix NativeTextComponent Props --- Libraries/Text/TextNativeComponent.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Libraries/Text/TextNativeComponent.js b/Libraries/Text/TextNativeComponent.js index f49970e1b40255..812f334806eb73 100644 --- a/Libraries/Text/TextNativeComponent.js +++ b/Libraries/Text/TextNativeComponent.js @@ -18,6 +18,7 @@ import {type TextProps} from './TextProps'; type NativeTextProps = $ReadOnly<{ ...TextProps, + maximumNumberOfLines?: ?number, isHighlighted?: ?boolean, selectionColor?: ?ProcessedColorValue, onClick?: ?(event: PressEvent) => mixed, From 22d718940233fa4c38b79c48485aa47295a3ac45 Mon Sep 17 00:00:00 2001 From: Szymon Date: Fri, 10 Mar 2023 10:21:48 +0100 Subject: [PATCH 05/22] fix fabric issue with newlines --- .../facebook/react/views/text/TextLayoutManager.java | 11 ++++++++--- .../react/views/text/TextLayoutManagerMapBuffer.java | 9 +++++++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java index 316fab68ad759e..5f2abfef45ae6d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java @@ -393,12 +393,17 @@ public static long measureText( : UNSET; int lines = layout.getLineCount(); - if (numberOfLines != UNSET && numberOfLines != 0 && numberOfLines > lines && text.length() > 0) { + if (numberOfLines != UNSET && numberOfLines != 0 && numberOfLines >= lines && text.length() > 0) { int numberOfEmptyLines = numberOfLines - lines; SpannableStringBuilder ssb = new SpannableStringBuilder(); + // for some reason a newline on end causes issues with computing height so we add a character + if (text.toString().endsWith("\n")) { + ssb.append("A"); + } + for (int i = 0; i < numberOfEmptyLines; ++i) { - ssb.append("\n"); + ssb.append("\nA"); } Object[] spans = text.getSpans(0, 0, Object.class); @@ -419,7 +424,7 @@ public static long measureText( } - if (numberOfLines != UNSET && numberOfLines != 0 && numberOfLines <= lines) { + if (numberOfLines != UNSET && numberOfLines != 0) { maximumNumberOfLines = numberOfLines; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java index f86923275c7bc6..981b78e5a0f570 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java @@ -417,8 +417,13 @@ public static long measureText( int numberOfEmptyLines = numberOfLines - lines; SpannableStringBuilder ssb = new SpannableStringBuilder(); + // for some reason a newline on end causes issues with computing height so we add a character + if (text.toString().endsWith("\n")) { + ssb.append("A"); + } + for (int i = 0; i < numberOfEmptyLines; ++i) { - ssb.append("\n"); + ssb.append("\nA"); } Object[] spans = text.getSpans(0, 0, Object.class); @@ -438,7 +443,7 @@ public static long measureText( hyphenationFrequency); } - if (numberOfLines != UNSET && numberOfLines != 0 && numberOfLines <= lines) { + if (numberOfLines != UNSET && numberOfLines != 0) { maximumNumberOfLines = numberOfLines; } From e5388e180467a76fc4983c7f04b8f878cb86bfc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szymon=20Kapa=C5=82a?= Date: Wed, 15 Mar 2023 09:40:26 +0100 Subject: [PATCH 06/22] Apply suggestions from code review Co-authored-by: Janic Duplessis --- Libraries/Text/TextInput/RCTBaseTextInputShadowView.m | 2 +- .../facebook/react/views/text/TextLayoutManagerMapBuffer.java | 4 ++-- .../react/renderer/textlayoutmanager/RCTTextLayoutManager.mm | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m b/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m index 2b1affe16880dc..9d777436763f24 100644 --- a/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m +++ b/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m @@ -227,7 +227,7 @@ - (CGSize)sizeThatFitsMinimumSize:(CGSize)minimumSize maximumSize:(CGSize)maximu * so they are not visible on the screen. */ if (self.exactNumberOfLines) { - NSMutableString *newLines = [NSMutableString stringWithCapacity: self.exactNumberOfLines]; + NSMutableString *newLines = [NSMutableString stringWithCapacity:self.exactNumberOfLines]; for (NSUInteger i = 0UL; i < self.exactNumberOfLines; ++i) { [newLines appendString:@"\n"]; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java index 981b78e5a0f570..72a1e4466507b0 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java @@ -407,7 +407,7 @@ public static long measureText( ? paragraphAttributes.getInt(PA_KEY_MAX_NUMBER_OF_LINES) : UNSET; - int numberOfLines = + int numberOfLines = paragraphAttributes.contains(PA_KEY_NUMBER_OF_LINES) ? paragraphAttributes.getInt(PA_KEY_NUMBER_OF_LINES) : UNSET; @@ -450,7 +450,7 @@ public static long measureText( int calculatedLineCount = maximumNumberOfLines == UNSET || maximumNumberOfLines == 0 ? layout.getLineCount() - : Math.min(maximumNumberOfLines, layout.getLineCount()); + : Math.min(maximumNumberOfLines, layout.getLineCount()); // Instead of using `layout.getWidth()` (which may yield a significantly larger width for // text that is wrapping), compute width using the longest line. diff --git a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm index 8e11f4571c8c97..7a1646318a0df4 100644 --- a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm +++ b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm @@ -199,7 +199,7 @@ - (NSTextStorage *)_textStorageForNSAttributesString:(NSAttributedString *)input // K is added on purpose. New line seems to be not enough for NTtextContainer [newLines appendString:@"K\n"]; } - NSDictionary * attributesOfFirstCharacter = [inputAttributedString attributesAtIndex:0 effectiveRange:NULL]; + NSDictionary * attributesOfFirstCharacter = [inputAttributedString attributesAtIndex:0 effectiveRange:NULL]; [attributedString insertAttributedString:[[NSAttributedString alloc] initWithString:newLines attributes:attributesOfFirstCharacter] atIndex:0]; From 448a5ebe58e22892d4bf34dd122db872abd3f359 Mon Sep 17 00:00:00 2001 From: Szymon Date: Wed, 15 Mar 2023 11:01:19 +0100 Subject: [PATCH 07/22] add example to rntester --- .../TextInput/TextInputExample.android.js | 30 ----------- .../TextInput/TextInputSharedExamples.js | 52 +++++++++++++++++++ 2 files changed, 52 insertions(+), 30 deletions(-) diff --git a/packages/rn-tester/js/examples/TextInput/TextInputExample.android.js b/packages/rn-tester/js/examples/TextInput/TextInputExample.android.js index 45e9f8623c7bd3..2f4f9ef590f49f 100644 --- a/packages/rn-tester/js/examples/TextInput/TextInputExample.android.js +++ b/packages/rn-tester/js/examples/TextInput/TextInputExample.android.js @@ -377,36 +377,6 @@ exports.examples = ([ ); }, }, - { - title: 'Fixed number of lines', - platform: 'android', - render: function (): React.Node { - return ( - - - - - - - ); - }, - }, { title: 'Auto-expanding', render: function (): React.Node { diff --git a/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js b/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js index 353379409ffe6a..a99807cb665b8f 100644 --- a/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js +++ b/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js @@ -91,6 +91,12 @@ const styles = StyleSheet.create({ right: -5, bottom: -5, }, + textInputLines: { + borderWidth: 1, + borderColor: 'black', + padding: 0, + textAlignVertical: Platform.OS === 'android' ? 'top' : undefined, + }, }); class WithLabel extends React.Component<$FlowFixMeProps> { @@ -1116,4 +1122,50 @@ module.exports = ([ name: 'textStyles', render: () => , }, + { + title: 'Height in rows/lines', + name: 'rows', + render: function (): React.Node { + return ( + + + + + + + + + ); + }, + }, ]: Array); From b58d91490f0b23798e38cd29c807d04c6a7e6fc9 Mon Sep 17 00:00:00 2001 From: Szymon Date: Sat, 22 Apr 2023 10:34:48 +0200 Subject: [PATCH 08/22] fix text component on android - (is was stipping off natest views) --- packages/react-native/ReactAndroid/build.gradle | 3 +++ .../react/views/text/ReactTextAnchorViewManager.java | 8 +------- .../java/com/facebook/react/views/text/ReactTextView.java | 6 +++--- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/packages/react-native/ReactAndroid/build.gradle b/packages/react-native/ReactAndroid/build.gradle index 6f5cff2885209a..c86ee38e2649e3 100644 --- a/packages/react-native/ReactAndroid/build.gradle +++ b/packages/react-native/ReactAndroid/build.gradle @@ -709,6 +709,9 @@ dependencies { androidTestImplementation("androidx.test:rules:${ANDROIDX_TEST_VERSION}") androidTestImplementation("org.mockito:mockito-core:${MOCKITO_CORE_VERSION}") + api('com.parse.bolts:bolts-tasks:1.4.0') + api('com.parse.bolts:bolts-applinks:1.4.0') + // This compileOnly dependency is needed to be able to update the offline // mirror from a non-linux machine, while still executing inside a Linux CI // as we declare a dependency on aap2 @linux so we're sure the linux artifact diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java index 735e7aebd985e0..c3032eb7674732 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java @@ -49,13 +49,7 @@ public void setAccessible(ReactTextView view, boolean accessible) { } // maxLines can only be set in master view (block), doesn't really make sense to set in a span - @ReactProp(name = ViewProps.NUMBER_OF_LINES, defaultInt = ViewDefaults.NUMBER_OF_LINES) - public void setNumberOfLines(ReactTextView view, int numberOfLines) { - view.setNumberOfLines(numberOfLines); - } - - // maxLines can only be set in master view (block), doesn't really make sense to set in a span - @ReactProp(name = ViewProps.MAXIMUM_NUMBER_OF_LINES, defaultInt = ViewDefaults.NUMBER_OF_LINES) + @ReactProp(name = ViewProps.MAXIMUM_NUMBER_OF_LINES, defaultInt = ViewDefaults.MAXIMUM_NUMBER_OF_LINES) public void setMaxNumberOfLines(ReactTextView view, int numberOfLines) { view.setNumberOfLines(numberOfLines); } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java index 6e742793eafe49..f87285c76eb0b2 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java @@ -87,7 +87,7 @@ private void initView() { mReactBackgroundManager = new ReactViewBackgroundManager(this); - mNumberOfLines = ViewDefaults.NUMBER_OF_LINES; + mNumberOfLines = ViewDefaults.MAXIMUM_NUMBER_OF_LINES; mAdjustsFontSizeToFit = false; mLinkifyMaskType = 0; mNotifyOnInlineViewLayout = false; @@ -573,7 +573,7 @@ public boolean hasOverlappingRendering() { } public void setNumberOfLines(int numberOfLines) { - mNumberOfLines = numberOfLines == 0 ? ViewDefaults.NUMBER_OF_LINES : numberOfLines; + mNumberOfLines = numberOfLines == 0 ? ViewDefaults.MAXIMUM_NUMBER_OF_LINES : numberOfLines; setSingleLine(mNumberOfLines == 1); setMaxLines(mNumberOfLines); } @@ -593,7 +593,7 @@ public void setNotifyOnInlineViewLayout(boolean notifyOnInlineViewLayout) { public void updateView() { @Nullable TextUtils.TruncateAt ellipsizeLocation = - mNumberOfLines == ViewDefaults.NUMBER_OF_LINES || mAdjustsFontSizeToFit + mNumberOfLines == ViewDefaults.MAXIMUM_NUMBER_OF_LINES || mAdjustsFontSizeToFit ? null : mEllipsizeLocation; setEllipsize(ellipsizeLocation); From b29648d0b7a7ac1b1797498327c3a80d9a242bfe Mon Sep 17 00:00:00 2001 From: Szymon Date: Tue, 16 May 2023 09:17:19 +0200 Subject: [PATCH 09/22] apply suggestions --- .eslintignore | 3 --- .../Libraries/Components/TextInput/TextInput.d.ts | 2 +- .../Libraries/Components/TextInput/TextInput.flow.js | 2 +- .../react-native/Libraries/Components/TextInput/TextInput.js | 5 ++++- packages/react-native/Libraries/Text/Text.js | 1 - packages/react-native/ReactAndroid/build.gradle | 3 --- 6 files changed, 6 insertions(+), 10 deletions(-) diff --git a/.eslintignore b/.eslintignore index 49c1ac6eac737a..1c6bf1db313db8 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,9 +1,6 @@ **/main.js **/staticBundle.js docs/generatedComponentApiDocs.js -flow/ -Libraries/Renderer/* -Libraries/vendor/**/* node_modules/ packages/*/node_modules packages/react-native-codegen/lib diff --git a/packages/react-native/Libraries/Components/TextInput/TextInput.d.ts b/packages/react-native/Libraries/Components/TextInput/TextInput.d.ts index 806b874529c9c1..0835135ff6b49d 100644 --- a/packages/react-native/Libraries/Components/TextInput/TextInput.d.ts +++ b/packages/react-native/Libraries/Components/TextInput/TextInput.d.ts @@ -652,7 +652,7 @@ export interface TextInputProps * Sets the maximum number of lines for a TextInput. * Use it with multiline set to true to be able to fill the lines. */ - maximumNumberOfLines?: number | undefined; + maxNumberOfLines?: number | undefined; /** * If true, the text input can be multiple lines. The default value is false. diff --git a/packages/react-native/Libraries/Components/TextInput/TextInput.flow.js b/packages/react-native/Libraries/Components/TextInput/TextInput.flow.js index 924e7d09d65ac1..b1d994e3301e71 100644 --- a/packages/react-native/Libraries/Components/TextInput/TextInput.flow.js +++ b/packages/react-native/Libraries/Components/TextInput/TextInput.flow.js @@ -622,7 +622,7 @@ export type Props = $ReadOnly<{| * Sets the maximum number of lines for a `TextInput`. Use it with multiline set to * `true` to be able to fill the lines. */ - maximumNumberOfLines?: ?number, + maxNumberOfLines?: ?number, /** * Specifies largest possible scale a font can reach when `allowFontScaling` is enabled. diff --git a/packages/react-native/Libraries/Components/TextInput/TextInput.js b/packages/react-native/Libraries/Components/TextInput/TextInput.js index c9dd391953a78d..77979b1b2157ed 100644 --- a/packages/react-native/Libraries/Components/TextInput/TextInput.js +++ b/packages/react-native/Libraries/Components/TextInput/TextInput.js @@ -405,7 +405,7 @@ type AndroidProps = $ReadOnly<{| /** * Sets the maximum number of lines the TextInput can have. */ - maximumNumberOfLines?: ?number, + maxNumberOfLines?: ?number, /** * When `false`, it will prevent the soft keyboard from showing when the field is focused. @@ -1071,6 +1071,7 @@ function InternalTextInput(props: Props): React.Node { tabIndex, rows, numberOfLines, + maxNumberOfLines, ...otherProps } = props; @@ -1442,6 +1443,7 @@ function InternalTextInput(props: Props): React.Node { mostRecentEventCount={mostRecentEventCount} nativeID={id ?? props.nativeID} numberOfLines={props.rows ?? props.numberOfLines} + maximumNumberOfLines={maxNumberOfLines} onBlur={_onBlur} onKeyPressSync={props.unstable_onKeyPressSync} onChange={_onChange} @@ -1497,6 +1499,7 @@ function InternalTextInput(props: Props): React.Node { mostRecentEventCount={mostRecentEventCount} nativeID={id ?? props.nativeID} numberOfLines={props.rows ?? props.numberOfLines} + maximumNumberOfLines={maxNumberOfLines} onBlur={_onBlur} onChange={_onChange} onFocus={_onFocus} diff --git a/packages/react-native/Libraries/Text/Text.js b/packages/react-native/Libraries/Text/Text.js index 7f1dc712d5bf0b..61c2f638d1e0d1 100644 --- a/packages/react-native/Libraries/Text/Text.js +++ b/packages/react-native/Libraries/Text/Text.js @@ -242,7 +242,6 @@ const Text: React.AbstractComponent< isHighlighted={isHighlighted} isPressable={isPressable} nativeID={id ?? nativeID} - maximumNumberOfLines={numberOfLinesValue} ref={forwardedRef} selectable={_selectable} selectionColor={selectionColor} diff --git a/packages/react-native/ReactAndroid/build.gradle b/packages/react-native/ReactAndroid/build.gradle index c86ee38e2649e3..6f5cff2885209a 100644 --- a/packages/react-native/ReactAndroid/build.gradle +++ b/packages/react-native/ReactAndroid/build.gradle @@ -709,9 +709,6 @@ dependencies { androidTestImplementation("androidx.test:rules:${ANDROIDX_TEST_VERSION}") androidTestImplementation("org.mockito:mockito-core:${MOCKITO_CORE_VERSION}") - api('com.parse.bolts:bolts-tasks:1.4.0') - api('com.parse.bolts:bolts-applinks:1.4.0') - // This compileOnly dependency is needed to be able to update the offline // mirror from a non-linux machine, while still executing inside a Linux CI // as we declare a dependency on aap2 @linux so we're sure the linux artifact From 24614c6e6e25da81a9540e3d96d99ea86a09e324 Mon Sep 17 00:00:00 2001 From: Szymon Date: Tue, 16 May 2023 09:48:39 +0200 Subject: [PATCH 10/22] update rntester examples --- .../js/examples/TextInput/TextInputSharedExamples.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js b/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js index 6892565735e8d1..1c88d35d9f11d4 100644 --- a/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js +++ b/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js @@ -1153,13 +1153,13 @@ module.exports = ([ placeholder="Five line input using rows prop" /> Date: Mon, 29 May 2023 06:52:31 -0700 Subject: [PATCH 11/22] Move LayoutMetrics and LayoutPrimitives from core to graphics folder (#37609) Summary: Pull Request resolved: /~https://github.com/facebook/react-native/pull/37609 changelog: [internal] Moving LayoutMetrics and LayoutPrimitives from core to graphics module. This is to enable different implementation for different platforms. Reviewed By: rubennorte Differential Revision: D45904748 fbshipit-source-id: a4e666d7c7390e87abdb09235f96655b63f451f9 --- .../Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h | 2 +- .../React/Fabric/Mounting/RCTComponentViewProtocol.h | 2 +- packages/react-native/React/Fabric/RCTConversions.h | 2 +- .../renderer/animations/LayoutAnimationKeyFrameManager.cpp | 2 +- .../react/renderer/attributedstring/TextAttributes.h | 2 +- .../renderer/components/scrollview/ScrollViewShadowNode.cpp | 2 +- .../react/renderer/components/view/TouchEventEmitter.h | 2 +- .../react/renderer/components/view/ViewEventEmitter.h | 2 +- .../ReactCommon/react/renderer/components/view/ViewProps.h | 2 +- .../ReactCommon/react/renderer/components/view/conversions.h | 2 +- .../ReactCommon/react/renderer/core/LayoutConstraints.h | 2 +- .../ReactCommon/react/renderer/core/LayoutableShadowNode.cpp | 2 +- .../ReactCommon/react/renderer/core/LayoutableShadowNode.h | 2 +- .../react-native/ReactCommon/react/renderer/core/conversions.h | 2 +- .../react/renderer/{core => graphics}/LayoutMetrics.cpp | 0 .../react/renderer/{core => graphics}/LayoutMetrics.h | 2 +- .../react/renderer/{core => graphics}/LayoutPrimitives.h | 0 .../ReactCommon/react/renderer/mounting/ShadowTree.cpp | 1 - .../ReactCommon/react/renderer/mounting/ShadowView.cpp | 2 +- .../ReactCommon/react/renderer/mounting/ShadowView.h | 2 +- .../react-native/ReactCommon/react/renderer/mounting/StubView.h | 2 +- .../ReactCommon/react/renderer/timeline/TimelineFrame.h | 2 +- .../ReactCommon/react/renderer/timeline/TimelineHandler.h | 1 - 23 files changed, 19 insertions(+), 21 deletions(-) rename packages/react-native/ReactCommon/react/renderer/{core => graphics}/LayoutMetrics.cpp (100%) rename packages/react-native/ReactCommon/react/renderer/{core => graphics}/LayoutMetrics.h (98%) rename packages/react-native/ReactCommon/react/renderer/{core => graphics}/LayoutPrimitives.h (100%) diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h index f2aff61c92c38f..010f3ecf9f4509 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h @@ -14,8 +14,8 @@ #import #import #import -#import #import +#import NS_ASSUME_NONNULL_BEGIN diff --git a/packages/react-native/React/Fabric/Mounting/RCTComponentViewProtocol.h b/packages/react-native/React/Fabric/Mounting/RCTComponentViewProtocol.h index 50d7d434f560ff..38215a22900733 100644 --- a/packages/react-native/React/Fabric/Mounting/RCTComponentViewProtocol.h +++ b/packages/react-native/React/Fabric/Mounting/RCTComponentViewProtocol.h @@ -9,9 +9,9 @@ #import #import -#import #import #import +#import NS_ASSUME_NONNULL_BEGIN diff --git a/packages/react-native/React/Fabric/RCTConversions.h b/packages/react-native/React/Fabric/RCTConversions.h index ca5cd623f46f44..f0b847ec09756a 100644 --- a/packages/react-native/React/Fabric/RCTConversions.h +++ b/packages/react-native/React/Fabric/RCTConversions.h @@ -9,8 +9,8 @@ #import #import -#import #import +#import #import NS_ASSUME_NONNULL_BEGIN diff --git a/packages/react-native/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp b/packages/react-native/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp index 34aed3a676046f..957f6e3850a8f2 100644 --- a/packages/react-native/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp +++ b/packages/react-native/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp @@ -20,10 +20,10 @@ #include #include #include -#include #include #include #include +#include #include #include #include diff --git a/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.h b/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.h index a681e9b4837145..5ba43ae62f7cb7 100644 --- a/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.h +++ b/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.h @@ -14,11 +14,11 @@ #include #include #include -#include #include #include #include #include +#include #include namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewShadowNode.cpp index 7fe5a502133b0b..57b1be60aad49e 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewShadowNode.cpp @@ -8,7 +8,7 @@ #include "ScrollViewShadowNode.h" #include -#include +#include namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/TouchEventEmitter.h b/packages/react-native/ReactCommon/react/renderer/components/view/TouchEventEmitter.h index ad42dfa7674eac..75f09d612d11a4 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/TouchEventEmitter.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/TouchEventEmitter.h @@ -10,9 +10,9 @@ #include #include #include -#include #include #include +#include namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/ViewEventEmitter.h b/packages/react-native/ReactCommon/react/renderer/components/view/ViewEventEmitter.h index 2267fac1ed08eb..ad43403b5ee72b 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/ViewEventEmitter.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/ViewEventEmitter.h @@ -10,8 +10,8 @@ #include #include -#include #include +#include #include "TouchEventEmitter.h" diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/ViewProps.h b/packages/react-native/ReactCommon/react/renderer/components/view/ViewProps.h index 8b6a8445fe82d8..9851ec65c1c088 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/ViewProps.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/ViewProps.h @@ -10,10 +10,10 @@ #include #include #include -#include #include #include #include +#include #include #include diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h b/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h index 85191d843731df..2f2747e22cdf81 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h @@ -13,8 +13,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/packages/react-native/ReactCommon/react/renderer/core/LayoutConstraints.h b/packages/react-native/ReactCommon/react/renderer/core/LayoutConstraints.h index 96089757f189bf..0456686b802906 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/LayoutConstraints.h +++ b/packages/react-native/ReactCommon/react/renderer/core/LayoutConstraints.h @@ -10,7 +10,7 @@ #include #include -#include +#include #include namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.cpp index 41b31772b18cd1..9393ae8c984c1c 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.cpp @@ -9,11 +9,11 @@ #include #include -#include #include #include #include #include +#include namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.h b/packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.h index ed0dc70088697b..5e53b90271f6a0 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.h +++ b/packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.h @@ -14,10 +14,10 @@ #include #include -#include #include #include #include +#include #include namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/renderer/core/conversions.h b/packages/react-native/ReactCommon/react/renderer/core/conversions.h index 8723d5e23d1c9f..22cb3c3d050bba 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/conversions.h +++ b/packages/react-native/ReactCommon/react/renderer/core/conversions.h @@ -7,7 +7,7 @@ #pragma once -#include +#include namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/renderer/core/LayoutMetrics.cpp b/packages/react-native/ReactCommon/react/renderer/graphics/LayoutMetrics.cpp similarity index 100% rename from packages/react-native/ReactCommon/react/renderer/core/LayoutMetrics.cpp rename to packages/react-native/ReactCommon/react/renderer/graphics/LayoutMetrics.cpp diff --git a/packages/react-native/ReactCommon/react/renderer/core/LayoutMetrics.h b/packages/react-native/ReactCommon/react/renderer/graphics/LayoutMetrics.h similarity index 98% rename from packages/react-native/ReactCommon/react/renderer/core/LayoutMetrics.h rename to packages/react-native/ReactCommon/react/renderer/graphics/LayoutMetrics.h index 16faa8bc78c6e2..a225835366e412 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/LayoutMetrics.h +++ b/packages/react-native/ReactCommon/react/renderer/graphics/LayoutMetrics.h @@ -8,9 +8,9 @@ #pragma once #include -#include #include #include +#include #include #include diff --git a/packages/react-native/ReactCommon/react/renderer/core/LayoutPrimitives.h b/packages/react-native/ReactCommon/react/renderer/graphics/LayoutPrimitives.h similarity index 100% rename from packages/react-native/ReactCommon/react/renderer/core/LayoutPrimitives.h rename to packages/react-native/ReactCommon/react/renderer/graphics/LayoutPrimitives.h diff --git a/packages/react-native/ReactCommon/react/renderer/mounting/ShadowTree.cpp b/packages/react-native/ReactCommon/react/renderer/mounting/ShadowTree.cpp index 0b9106bbb5d2b0..0d4ba5e6228a7e 100644 --- a/packages/react-native/ReactCommon/react/renderer/mounting/ShadowTree.cpp +++ b/packages/react-native/ReactCommon/react/renderer/mounting/ShadowTree.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/packages/react-native/ReactCommon/react/renderer/mounting/ShadowView.cpp b/packages/react-native/ReactCommon/react/renderer/mounting/ShadowView.cpp index 68a48d8e429325..21621ede498498 100644 --- a/packages/react-native/ReactCommon/react/renderer/mounting/ShadowView.cpp +++ b/packages/react-native/ReactCommon/react/renderer/mounting/ShadowView.cpp @@ -7,9 +7,9 @@ #include "ShadowView.h" -#include #include #include +#include namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/renderer/mounting/ShadowView.h b/packages/react-native/ReactCommon/react/renderer/mounting/ShadowView.h index b963d81e61c3a6..fddc1a153822b6 100644 --- a/packages/react-native/ReactCommon/react/renderer/mounting/ShadowView.h +++ b/packages/react-native/ReactCommon/react/renderer/mounting/ShadowView.h @@ -10,11 +10,11 @@ #include #include #include -#include #include #include #include #include +#include namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/renderer/mounting/StubView.h b/packages/react-native/ReactCommon/react/renderer/mounting/StubView.h index 472e6c0d100241..4d5e7ea8a3a1b7 100644 --- a/packages/react-native/ReactCommon/react/renderer/mounting/StubView.h +++ b/packages/react-native/ReactCommon/react/renderer/mounting/StubView.h @@ -10,9 +10,9 @@ #include #include -#include #include #include +#include #include namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/renderer/timeline/TimelineFrame.h b/packages/react-native/ReactCommon/react/renderer/timeline/TimelineFrame.h index c732948356c9e5..e676ec10c10738 100644 --- a/packages/react-native/ReactCommon/react/renderer/timeline/TimelineFrame.h +++ b/packages/react-native/ReactCommon/react/renderer/timeline/TimelineFrame.h @@ -7,7 +7,7 @@ #pragma once -#include +#include #include #include diff --git a/packages/react-native/ReactCommon/react/renderer/timeline/TimelineHandler.h b/packages/react-native/ReactCommon/react/renderer/timeline/TimelineHandler.h index 2be8f825801e36..f37e5773cfb806 100644 --- a/packages/react-native/ReactCommon/react/renderer/timeline/TimelineHandler.h +++ b/packages/react-native/ReactCommon/react/renderer/timeline/TimelineHandler.h @@ -7,7 +7,6 @@ #pragma once -#include #include #include From f77567d554c8af61d7240489ac24a55b60455218 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Mon, 29 May 2023 07:27:36 -0700 Subject: [PATCH 12/22] Revert D45904748: Move LayoutMetrics and LayoutPrimitives from core to graphics folder Differential Revision: D45904748 Original commit changeset: a4e666d7c739 Original Phabricator Diff: D45904748 fbshipit-source-id: c2da28836cb51966854c81d4e380a2abeb742cda --- .../Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h | 2 +- .../React/Fabric/Mounting/RCTComponentViewProtocol.h | 2 +- packages/react-native/React/Fabric/RCTConversions.h | 2 +- .../renderer/animations/LayoutAnimationKeyFrameManager.cpp | 2 +- .../react/renderer/attributedstring/TextAttributes.h | 2 +- .../renderer/components/scrollview/ScrollViewShadowNode.cpp | 2 +- .../react/renderer/components/view/TouchEventEmitter.h | 2 +- .../react/renderer/components/view/ViewEventEmitter.h | 2 +- .../ReactCommon/react/renderer/components/view/ViewProps.h | 2 +- .../ReactCommon/react/renderer/components/view/conversions.h | 2 +- .../ReactCommon/react/renderer/core/LayoutConstraints.h | 2 +- .../react/renderer/{graphics => core}/LayoutMetrics.cpp | 0 .../react/renderer/{graphics => core}/LayoutMetrics.h | 2 +- .../react/renderer/{graphics => core}/LayoutPrimitives.h | 0 .../ReactCommon/react/renderer/core/LayoutableShadowNode.cpp | 2 +- .../ReactCommon/react/renderer/core/LayoutableShadowNode.h | 2 +- .../react-native/ReactCommon/react/renderer/core/conversions.h | 2 +- .../ReactCommon/react/renderer/mounting/ShadowTree.cpp | 1 + .../ReactCommon/react/renderer/mounting/ShadowView.cpp | 2 +- .../ReactCommon/react/renderer/mounting/ShadowView.h | 2 +- .../react-native/ReactCommon/react/renderer/mounting/StubView.h | 2 +- .../ReactCommon/react/renderer/timeline/TimelineFrame.h | 2 +- .../ReactCommon/react/renderer/timeline/TimelineHandler.h | 1 + 23 files changed, 21 insertions(+), 19 deletions(-) rename packages/react-native/ReactCommon/react/renderer/{graphics => core}/LayoutMetrics.cpp (100%) rename packages/react-native/ReactCommon/react/renderer/{graphics => core}/LayoutMetrics.h (98%) rename packages/react-native/ReactCommon/react/renderer/{graphics => core}/LayoutPrimitives.h (100%) diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h index 010f3ecf9f4509..f2aff61c92c38f 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h @@ -14,8 +14,8 @@ #import #import #import +#import #import -#import NS_ASSUME_NONNULL_BEGIN diff --git a/packages/react-native/React/Fabric/Mounting/RCTComponentViewProtocol.h b/packages/react-native/React/Fabric/Mounting/RCTComponentViewProtocol.h index 38215a22900733..50d7d434f560ff 100644 --- a/packages/react-native/React/Fabric/Mounting/RCTComponentViewProtocol.h +++ b/packages/react-native/React/Fabric/Mounting/RCTComponentViewProtocol.h @@ -9,9 +9,9 @@ #import #import +#import #import #import -#import NS_ASSUME_NONNULL_BEGIN diff --git a/packages/react-native/React/Fabric/RCTConversions.h b/packages/react-native/React/Fabric/RCTConversions.h index f0b847ec09756a..ca5cd623f46f44 100644 --- a/packages/react-native/React/Fabric/RCTConversions.h +++ b/packages/react-native/React/Fabric/RCTConversions.h @@ -9,8 +9,8 @@ #import #import +#import #import -#import #import NS_ASSUME_NONNULL_BEGIN diff --git a/packages/react-native/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp b/packages/react-native/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp index 957f6e3850a8f2..34aed3a676046f 100644 --- a/packages/react-native/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp +++ b/packages/react-native/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp @@ -20,10 +20,10 @@ #include #include #include +#include #include #include #include -#include #include #include #include diff --git a/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.h b/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.h index 5ba43ae62f7cb7..a681e9b4837145 100644 --- a/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.h +++ b/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.h @@ -14,11 +14,11 @@ #include #include #include +#include #include #include #include #include -#include #include namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewShadowNode.cpp index 57b1be60aad49e..7fe5a502133b0b 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewShadowNode.cpp @@ -8,7 +8,7 @@ #include "ScrollViewShadowNode.h" #include -#include +#include namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/TouchEventEmitter.h b/packages/react-native/ReactCommon/react/renderer/components/view/TouchEventEmitter.h index 75f09d612d11a4..ad42dfa7674eac 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/TouchEventEmitter.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/TouchEventEmitter.h @@ -10,9 +10,9 @@ #include #include #include +#include #include #include -#include namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/ViewEventEmitter.h b/packages/react-native/ReactCommon/react/renderer/components/view/ViewEventEmitter.h index ad43403b5ee72b..2267fac1ed08eb 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/ViewEventEmitter.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/ViewEventEmitter.h @@ -10,8 +10,8 @@ #include #include +#include #include -#include #include "TouchEventEmitter.h" diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/ViewProps.h b/packages/react-native/ReactCommon/react/renderer/components/view/ViewProps.h index 9851ec65c1c088..8b6a8445fe82d8 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/ViewProps.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/ViewProps.h @@ -10,10 +10,10 @@ #include #include #include +#include #include #include #include -#include #include #include diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h b/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h index 2f2747e22cdf81..85191d843731df 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h @@ -13,8 +13,8 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/packages/react-native/ReactCommon/react/renderer/core/LayoutConstraints.h b/packages/react-native/ReactCommon/react/renderer/core/LayoutConstraints.h index 0456686b802906..96089757f189bf 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/LayoutConstraints.h +++ b/packages/react-native/ReactCommon/react/renderer/core/LayoutConstraints.h @@ -10,7 +10,7 @@ #include #include -#include +#include #include namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/LayoutMetrics.cpp b/packages/react-native/ReactCommon/react/renderer/core/LayoutMetrics.cpp similarity index 100% rename from packages/react-native/ReactCommon/react/renderer/graphics/LayoutMetrics.cpp rename to packages/react-native/ReactCommon/react/renderer/core/LayoutMetrics.cpp diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/LayoutMetrics.h b/packages/react-native/ReactCommon/react/renderer/core/LayoutMetrics.h similarity index 98% rename from packages/react-native/ReactCommon/react/renderer/graphics/LayoutMetrics.h rename to packages/react-native/ReactCommon/react/renderer/core/LayoutMetrics.h index a225835366e412..16faa8bc78c6e2 100644 --- a/packages/react-native/ReactCommon/react/renderer/graphics/LayoutMetrics.h +++ b/packages/react-native/ReactCommon/react/renderer/core/LayoutMetrics.h @@ -8,9 +8,9 @@ #pragma once #include +#include #include #include -#include #include #include diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/LayoutPrimitives.h b/packages/react-native/ReactCommon/react/renderer/core/LayoutPrimitives.h similarity index 100% rename from packages/react-native/ReactCommon/react/renderer/graphics/LayoutPrimitives.h rename to packages/react-native/ReactCommon/react/renderer/core/LayoutPrimitives.h diff --git a/packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.cpp index 9393ae8c984c1c..41b31772b18cd1 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.cpp @@ -9,11 +9,11 @@ #include #include +#include #include #include #include #include -#include namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.h b/packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.h index 5e53b90271f6a0..ed0dc70088697b 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.h +++ b/packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.h @@ -14,10 +14,10 @@ #include #include +#include #include #include #include -#include #include namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/renderer/core/conversions.h b/packages/react-native/ReactCommon/react/renderer/core/conversions.h index 22cb3c3d050bba..8723d5e23d1c9f 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/conversions.h +++ b/packages/react-native/ReactCommon/react/renderer/core/conversions.h @@ -7,7 +7,7 @@ #pragma once -#include +#include namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/renderer/mounting/ShadowTree.cpp b/packages/react-native/ReactCommon/react/renderer/mounting/ShadowTree.cpp index 0d4ba5e6228a7e..0b9106bbb5d2b0 100644 --- a/packages/react-native/ReactCommon/react/renderer/mounting/ShadowTree.cpp +++ b/packages/react-native/ReactCommon/react/renderer/mounting/ShadowTree.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include diff --git a/packages/react-native/ReactCommon/react/renderer/mounting/ShadowView.cpp b/packages/react-native/ReactCommon/react/renderer/mounting/ShadowView.cpp index 21621ede498498..68a48d8e429325 100644 --- a/packages/react-native/ReactCommon/react/renderer/mounting/ShadowView.cpp +++ b/packages/react-native/ReactCommon/react/renderer/mounting/ShadowView.cpp @@ -7,9 +7,9 @@ #include "ShadowView.h" +#include #include #include -#include namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/renderer/mounting/ShadowView.h b/packages/react-native/ReactCommon/react/renderer/mounting/ShadowView.h index fddc1a153822b6..b963d81e61c3a6 100644 --- a/packages/react-native/ReactCommon/react/renderer/mounting/ShadowView.h +++ b/packages/react-native/ReactCommon/react/renderer/mounting/ShadowView.h @@ -10,11 +10,11 @@ #include #include #include +#include #include #include #include #include -#include namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/renderer/mounting/StubView.h b/packages/react-native/ReactCommon/react/renderer/mounting/StubView.h index 4d5e7ea8a3a1b7..472e6c0d100241 100644 --- a/packages/react-native/ReactCommon/react/renderer/mounting/StubView.h +++ b/packages/react-native/ReactCommon/react/renderer/mounting/StubView.h @@ -10,9 +10,9 @@ #include #include +#include #include #include -#include #include namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/renderer/timeline/TimelineFrame.h b/packages/react-native/ReactCommon/react/renderer/timeline/TimelineFrame.h index e676ec10c10738..c732948356c9e5 100644 --- a/packages/react-native/ReactCommon/react/renderer/timeline/TimelineFrame.h +++ b/packages/react-native/ReactCommon/react/renderer/timeline/TimelineFrame.h @@ -7,7 +7,7 @@ #pragma once -#include +#include #include #include diff --git a/packages/react-native/ReactCommon/react/renderer/timeline/TimelineHandler.h b/packages/react-native/ReactCommon/react/renderer/timeline/TimelineHandler.h index f37e5773cfb806..2be8f825801e36 100644 --- a/packages/react-native/ReactCommon/react/renderer/timeline/TimelineHandler.h +++ b/packages/react-native/ReactCommon/react/renderer/timeline/TimelineHandler.h @@ -7,6 +7,7 @@ #pragma once +#include #include #include From 4bfc7be8bac6d04595145a01e09207e10a9c153f Mon Sep 17 00:00:00 2001 From: Intl Scheduler <> Date: Mon, 29 May 2023 21:34:22 -0700 Subject: [PATCH 13/22] translation auto-update for i18n/fb4a.config.json on master Summary: Chronos Job Instance ID: 1125907889493757 Sandcastle Job Instance ID: 36028797978627335 allow-large-files ignore-conflict-markers opt-out-review Differential Revision: D46270525 fbshipit-source-id: 26beec108aa03c970338fdc4561af24798813acf --- .../ReactAndroid/src/main/res/devsupport/values-sq/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-sq/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-sq/strings.xml index 96e5af862b88ab..3f0f8caa0523c7 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values-sq/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values-sq/strings.xml @@ -4,4 +4,5 @@ Menyja e zhvilluesit e React Native (%1$s) + Duke ekzekutuar %1$s From bac869c25d93707f1d5814ee5884273b7d2fec94 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Tue, 30 May 2023 04:10:17 -0700 Subject: [PATCH 14/22] Make RNTester use RCTAppDelegate (#37572) Summary: Pull Request resolved: /~https://github.com/facebook/react-native/pull/37572 Currently, RNTester was using a completely custom AppDelegate and not leveraging the RCTAppDelegate we use in the OSS. This resulted in a misalignment between the two setups and duplicated work to test stuff internally furst and then in the OSS, with some more time needed to understand why one setup was working and the other wasn't. With this change, we are aligning the two, bringing RNTester closer to the OSS setup. There are still small differences, but we can iterate over those. ## Changelog: [iOS][Changed] - Make RNTester use RCTAppDelegate Reviewed By: cortinico Differential Revision: D46182888 fbshipit-source-id: 7c55b06de1a317b1f2d4ad0d18a390dc4d3356a4 --- .../AppDelegate/RCTLegacyInteropComponents.mm | 3 +- packages/rn-tester/RNTester/AppDelegate.h | 8 +- packages/rn-tester/RNTester/AppDelegate.mm | 271 ++---------------- .../RNTester/RNTesterTurboModuleProvider.h | 26 -- .../RNTester/RNTesterTurboModuleProvider.mm | 43 --- .../RNTesterPods.xcodeproj/project.pbxproj | 6 - packages/rn-tester/react-native.config.js | 1 + 7 files changed, 21 insertions(+), 337 deletions(-) delete mode 100644 packages/rn-tester/RNTester/RNTesterTurboModuleProvider.h delete mode 100644 packages/rn-tester/RNTester/RNTesterTurboModuleProvider.mm diff --git a/packages/react-native/Libraries/AppDelegate/RCTLegacyInteropComponents.mm b/packages/react-native/Libraries/AppDelegate/RCTLegacyInteropComponents.mm index d1d68376b08493..549e41a9b91b5f 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTLegacyInteropComponents.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTLegacyInteropComponents.mm @@ -1,3 +1,4 @@ + /* * Copyright (c) Meta Platforms, Inc. and affiliates. * @@ -11,7 +12,7 @@ @implementation RCTLegacyInteropComponents + (NSArray *)legacyInteropComponents { - return @[]; + return @[ @"RNTMyLegacyNativeView" ]; } @end diff --git a/packages/rn-tester/RNTester/AppDelegate.h b/packages/rn-tester/RNTester/AppDelegate.h index 55625d8693c2a8..d172167ee1d627 100644 --- a/packages/rn-tester/RNTester/AppDelegate.h +++ b/packages/rn-tester/RNTester/AppDelegate.h @@ -5,13 +5,9 @@ * LICENSE file in the root directory of this source tree. */ +#import #import -@class RCTBridge; - -@interface AppDelegate : UIResponder - -@property (nonatomic, strong) UIWindow *window; -@property (nonatomic, readonly) RCTBridge *bridge; +@interface AppDelegate : RCTAppDelegate @end diff --git a/packages/rn-tester/RNTester/AppDelegate.mm b/packages/rn-tester/RNTester/AppDelegate.mm index a04050d75f9127..f4e8d4006c5416 100644 --- a/packages/rn-tester/RNTester/AppDelegate.mm +++ b/packages/rn-tester/RNTester/AppDelegate.mm @@ -7,161 +7,30 @@ #import "AppDelegate.h" -#ifndef RCT_USE_HERMES -#if __has_include() -#define RCT_USE_HERMES 1 -#else -#define RCT_USE_HERMES 0 -#endif -#endif - -#ifdef RCT_NEW_ARCH_ENABLED -#ifndef RN_FABRIC_ENABLED -#define RN_FABRIC_ENABLED -#endif -#endif - -#if RCT_USE_HERMES -#import -#else -#import -#endif - -#import #import -#import -#import -#import -#import -#import -#import -#import -#import #import -#import -#import -#import -#import -#import -#import -#import - -#import +#import +#import #if !TARGET_OS_TV && !TARGET_OS_UIKITFORMAC #import #endif -#ifdef RN_FABRIC_ENABLED -#import -#import -#import -#import - -#import -#import -#import -#endif - #if RCT_NEW_ARCH_ENABLED +#import #import #endif -#if DEBUG -#ifdef FB_SONARKIT_ENABLED -#import -#import -#import -#import -#import -#import -#import -#endif -#endif - -#import -#import "RNTesterTurboModuleProvider.h" - -@interface RCTBridge () -- (std::shared_ptr)jsMessageThread; -- (void)invokeAsync:(std::function &&)func; -@end - -using namespace facebook::react; - -@interface AppDelegate () { - std::shared_ptr _runtimeScheduler; -#ifdef RN_FABRIC_ENABLED - RCTSurfacePresenterBridgeAdapter *_bridgeAdapter; - std::shared_ptr _reactNativeConfig; - facebook::react::ContextContainer::Shared _contextContainer; -#endif -} -@end - -#if RCT_NEW_ARCH_ENABLED -/// Declare conformance to `RCTComponentViewFactoryComponentProvider` -@interface AppDelegate () -@end -#endif - -static NSString *const kRNConcurrentRoot = @"concurrentRoot"; - @implementation AppDelegate -#ifdef RN_FABRIC_ENABLED -- (instancetype)init +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - if (self = [super init]) { - _contextContainer = std::make_shared(); - _reactNativeConfig = std::make_shared(); - _contextContainer->insert("ReactNativeConfig", _reactNativeConfig); - } - return self; -} -#endif - -- (BOOL)application:(__unused UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions -{ - RCTEnableTurboModule(YES); - - _bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; - - // Appetizer.io params check - NSDictionary *initProps = [self prepareInitialProps]; - -#if RCT_NEW_ARCH_ENABLED - [RCTComponentViewFactory currentComponentViewFactory].thirdPartyFabricComponentsProvider = self; -#endif - -#ifdef RN_FABRIC_ENABLED - _bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:_bridge contextContainer:_contextContainer]; - - _bridge.surfacePresenter = _bridgeAdapter.surfacePresenter; - - UIView *rootView = [[RCTFabricSurfaceHostingProxyRootView alloc] initWithBridge:_bridge - moduleName:@"RNTesterApp" - initialProperties:initProps]; + self.moduleName = @"RNTesterApp"; + // You can add your custom initial props in the dictionary below. + // They will be passed down to the ViewController used by React Native. + self.initialProps = [self prepareInitialProps]; - [self registerPaperComponents:@[ @"RNTMyLegacyNativeView" ]]; -#else - UIView *rootView = [[RCTRootView alloc] initWithBridge:_bridge moduleName:@"RNTesterApp" initialProperties:initProps]; -#endif - - self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; - UIViewController *rootViewController = [UIViewController new]; - rootViewController.view = rootView; - self.window.rootViewController = rootViewController; - [self.window makeKeyAndVisible]; - [self initializeFlipper:application]; - - return YES; -} - -- (BOOL)concurrentRootEnabled -{ - // Switch this bool to turn on and off the concurrent root - return true; + return [super application:application didFinishLaunchingWithOptions:launchOptions]; } - (NSDictionary *)prepareInitialProps @@ -173,34 +42,14 @@ - (NSDictionary *)prepareInitialProps initProps[@"exampleFromAppetizeParams"] = [NSString stringWithFormat:@"rntester://example/%@Example", _routeUri]; } -#ifdef RN_FABRIC_ENABLED - initProps[kRNConcurrentRoot] = @([self concurrentRootEnabled]); -#endif - return initProps; } -- (NSURL *)sourceURLForBridge:(__unused RCTBridge *)bridge +- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"js/RNTesterApp.ios"]; } -- (void)initializeFlipper:(UIApplication *)application -{ -#if DEBUG -#ifdef FB_SONARKIT_ENABLED - FlipperClient *client = [FlipperClient sharedClient]; - SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults]; - [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application - withDescriptorMapper:layoutDescriptorMapper]]; - [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]]; - [client addPlugin:[FlipperKitReactPlugin new]]; - [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]]; - [client start]; -#endif -#endif -} - - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options @@ -215,108 +64,20 @@ - (void)loadSourceForBridge:(RCTBridge *)bridge [RCTJavaScriptLoader loadBundleAtURL:[self sourceURLForBridge:bridge] onProgress:onProgress onComplete:loadCallback]; } -#pragma mark - RCTCxxBridgeDelegate - -// This function is called during -// `[[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];` -- (std::unique_ptr)jsExecutorFactoryForBridge:(RCTBridge *)bridge -{ - std::shared_ptr callInvoker = bridge.jsCallInvoker; - _runtimeScheduler = std::make_shared(RCTRuntimeExecutorFromBridge(bridge)); - -#ifdef RN_FABRIC_ENABLED - _contextContainer->erase("RuntimeScheduler"); - _contextContainer->insert("RuntimeScheduler", _runtimeScheduler); - callInvoker = std::make_shared(_runtimeScheduler); -#endif - - RCTTurboModuleManager *turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge - delegate:self - jsInvoker:callInvoker]; - [bridge setRCTTurboModuleRegistry:turboModuleManager]; - -#if RCT_DEV - /** - * Eagerly initialize RCTDevMenu so CMD + d, CMD + i, and CMD + r work. - * This is a stop gap until we have a system to eagerly init Turbo Modules. - */ - [turboModuleManager moduleForName:"RCTDevMenu"]; -#endif - - __weak __typeof(self) weakSelf = self; - -#if RCT_USE_HERMES - return std::make_unique( -#else - return std::make_unique( -#endif - facebook::react::RCTJSIExecutorRuntimeInstaller([weakSelf, bridge, turboModuleManager]( - facebook::jsi::Runtime &runtime) { - if (!bridge) { - return; - } - - __typeof(self) strongSelf = weakSelf; - if (strongSelf && strongSelf->_runtimeScheduler) { - facebook::react::RuntimeSchedulerBinding::createAndInstallIfNeeded(runtime, strongSelf->_runtimeScheduler); - } - - facebook::react::RuntimeExecutor syncRuntimeExecutor = - [&](std::function &&callback) { callback(runtime); }; - [turboModuleManager installJSBindingWithRuntimeExecutor:syncRuntimeExecutor]; - })); -} - -#pragma mark - RCTTurboModuleManagerDelegate - -- (Class)getModuleClassFromName:(const char *)name -{ - return facebook::react::RNTesterTurboModuleClassProvider(name); -} - - (std::shared_ptr)getTurboModule:(const std::string &)name jsInvoker:(std::shared_ptr)jsInvoker { - return facebook::react::RNTesterTurboModuleProvider(name, jsInvoker); -} - -- (id)getModuleInstanceFromClass:(Class)moduleClass -{ - // Set up the default RCTImageLoader and RCTNetworking modules. - if (moduleClass == RCTImageLoader.class) { - return [[moduleClass alloc] initWithRedirectDelegate:nil - loadersProvider:^NSArray> *(RCTModuleRegistry *) { - return @[ [RCTLocalAssetImageLoader new] ]; - } - decodersProvider:^NSArray> *(RCTModuleRegistry *) { - return @[ [RCTGIFImageDecoder new] ]; - }]; - } else if (moduleClass == RCTNetworking.class) { - return [[moduleClass alloc] initWithHandlersProvider:^NSArray> *(RCTModuleRegistry *) { - return @[ - [RCTHTTPRequestHandler new], - [RCTDataRequestHandler new], - [RCTFileRequestHandler new], - ]; - }]; + if (name == std::string([@"SampleTurboCxxModule" UTF8String])) { + return std::make_shared(jsInvoker); } - // No custom initializer here. - return [moduleClass new]; -} - -#pragma mark - Interop layer - -- (void)registerPaperComponents:(NSArray *)components -{ -#if RCT_NEW_ARCH_ENABLED - for (NSString *component in components) { - [RCTLegacyViewManagerInteropComponentView supportLegacyViewManagerWithName:component]; +#ifdef RCT_NEW_ARCH_ENABLED + if (name == std::string([@"NativeCxxModuleExampleCxx" UTF8String])) { + return std::make_shared(jsInvoker); } #endif + return nullptr; } -#pragma mark - Push Notifications - #if !TARGET_OS_TV && !TARGET_OS_UIKITFORMAC // Required to register for notifications diff --git a/packages/rn-tester/RNTester/RNTesterTurboModuleProvider.h b/packages/rn-tester/RNTester/RNTesterTurboModuleProvider.h deleted file mode 100644 index 3ca84512719340..00000000000000 --- a/packages/rn-tester/RNTester/RNTesterTurboModuleProvider.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import - -namespace facebook { -namespace react { - -/** - * Provide the TurboModule class for the given name. - */ -Class RNTesterTurboModuleClassProvider(const char *name); - -/** - * Provide a pure C++ instance of a TurboModule, specific to this app. - */ -std::shared_ptr RNTesterTurboModuleProvider( - const std::string &name, - std::shared_ptr jsInvoker); - -} // namespace react -} // namespace facebook diff --git a/packages/rn-tester/RNTester/RNTesterTurboModuleProvider.mm b/packages/rn-tester/RNTester/RNTesterTurboModuleProvider.mm deleted file mode 100644 index 32e5c3418013a9..00000000000000 --- a/packages/rn-tester/RNTester/RNTesterTurboModuleProvider.mm +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import "RNTesterTurboModuleProvider.h" - -#ifdef RCT_NEW_ARCH_ENABLED -#import -#endif -#import -#import -#import - -// NOTE: This entire file should be codegen'ed. - -namespace facebook { -namespace react { - -Class RNTesterTurboModuleClassProvider(const char *name) -{ - return RCTCoreModulesClassProvider(name); -} - -std::shared_ptr RNTesterTurboModuleProvider( - const std::string &name, - std::shared_ptr jsInvoker) -{ - if (name == "SampleTurboCxxModule") { - return std::make_shared(jsInvoker); - } -#ifdef RCT_NEW_ARCH_ENABLED - if (name == "NativeCxxModuleExampleCxx") { - return std::make_shared(jsInvoker); - } -#endif - return nullptr; -} - -} // namespace react -} // namespace facebook diff --git a/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj b/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj index 4e5505f231fb69..01af6ae1065c2d 100644 --- a/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj +++ b/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj @@ -15,7 +15,6 @@ 383889DA23A7398900D06C3E /* RCTConvert_UIColorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 383889D923A7398900D06C3E /* RCTConvert_UIColorTests.m */; }; 3D2AFAF51D646CF80089D1A3 /* legacy_image@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3D2AFAF41D646CF80089D1A3 /* legacy_image@2x.png */; }; 5C60EB1C226440DB0018C04F /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C60EB1B226440DB0018C04F /* AppDelegate.mm */; }; - 5CB07C9B226467E60039471C /* RNTesterTurboModuleProvider.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5CB07C99226467E60039471C /* RNTesterTurboModuleProvider.mm */; }; 8145AE06241172D900A3F8DA /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8145AE05241172D900A3F8DA /* LaunchScreen.storyboard */; }; 953D44E0A849F5064163EA24 /* libPods-RNTesterIntegrationTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4F4A7C4C85AB0198A25D51E4 /* libPods-RNTesterIntegrationTests.a */; }; BE3BEE3556275C62F33864C8 /* libPods-RNTesterUnitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6144DEEE56C6C17B301A90E4 /* libPods-RNTesterUnitTests.a */; }; @@ -96,8 +95,6 @@ 3D2AFAF41D646CF80089D1A3 /* legacy_image@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "legacy_image@2x.png"; path = "RNTester/legacy_image@2x.png"; sourceTree = ""; }; 4F4A7C4C85AB0198A25D51E4 /* libPods-RNTesterIntegrationTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTesterIntegrationTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 5C60EB1B226440DB0018C04F /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = RNTester/AppDelegate.mm; sourceTree = ""; }; - 5CB07C99226467E60039471C /* RNTesterTurboModuleProvider.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = RNTesterTurboModuleProvider.mm; path = RNTester/RNTesterTurboModuleProvider.mm; sourceTree = ""; }; - 5CB07C9A226467E60039471C /* RNTesterTurboModuleProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNTesterTurboModuleProvider.h; path = RNTester/RNTesterTurboModuleProvider.h; sourceTree = ""; }; 6144DEEE56C6C17B301A90E4 /* libPods-RNTesterUnitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTesterUnitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 7FC437025B5EE3899315628B /* Pods-RNTester.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTester.release.xcconfig"; path = "Target Support Files/Pods-RNTester/Pods-RNTester.release.xcconfig"; sourceTree = ""; }; 8145AE05241172D900A3F8DA /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = RNTester/LaunchScreen.storyboard; sourceTree = ""; }; @@ -230,8 +227,6 @@ E771AEEA22B44E3100EA1189 /* Info.plist */, 13B07FAF1A68108700A75B9A /* AppDelegate.h */, 5C60EB1B226440DB0018C04F /* AppDelegate.mm */, - 5CB07C9A226467E60039471C /* RNTesterTurboModuleProvider.h */, - 5CB07C99226467E60039471C /* RNTesterTurboModuleProvider.mm */, 13B07FB71A68108700A75B9A /* main.m */, 2DDEF00F1F84BF7B00DBDF73 /* Images.xcassets */, 8145AE05241172D900A3F8DA /* LaunchScreen.storyboard */, @@ -762,7 +757,6 @@ buildActionMask = 2147483647; files = ( 272E6B3F1BEA849E001FCF37 /* UpdatePropertiesExampleView.m in Sources */, - 5CB07C9B226467E60039471C /* RNTesterTurboModuleProvider.mm in Sources */, 27F441EC1BEBE5030039B79C /* FlexibleSizeExampleView.m in Sources */, 5C60EB1C226440DB0018C04F /* AppDelegate.mm in Sources */, 13B07FC11A68108700A75B9A /* main.m in Sources */, diff --git a/packages/rn-tester/react-native.config.js b/packages/rn-tester/react-native.config.js index 099000c501058d..b3ad6adb66f61b 100644 --- a/packages/rn-tester/react-native.config.js +++ b/packages/rn-tester/react-native.config.js @@ -28,6 +28,7 @@ module.exports = { project: { ios: { sourceDir: '.', + unstable_reactLegacyComponentNames: ['RNTMyLegacyNativeView'], }, android: { sourceDir: '../../', From cfb57015f51bd74fa2bedaad7da2f02b98e59292 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Tue, 30 May 2023 04:10:17 -0700 Subject: [PATCH 15/22] Backporting a fix for hermesc on linux (#37596) Summary: Pull Request resolved: /~https://github.com/facebook/react-native/pull/37596 This commit is a backport of this [commit](/~https://github.com/facebook/react-native/commit/32327cc17779659bc441580d44784a60a74ede32) so that we build the right version of hermes in CI. This also bumps the hermes keys to make sure that we are building it properly from now on. ## Changelog: [Internal] - Fix Hermes versioning and bump hermes workspace keys Reviewed By: cortinico Differential Revision: D46225179 fbshipit-source-id: f00c9d20d37f3bd5689e0742063f98e3bfe373c2 --- .circleci/config.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6ce5e972848378..8babd32c1d91da 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -59,7 +59,7 @@ references: checkout_cache_key: &checkout_cache_key v1-checkout gems_cache_key: &gems_cache_key v1-gems-{{ checksum "Gemfile.lock" }} gradle_cache_key: &gradle_cache_key v1-gradle-{{ checksum "gradle/wrapper/gradle-wrapper.properties" }}-{{ checksum "packages/react-native/ReactAndroid/gradle.properties" }} - hermes_workspace_cache_key: &hermes_workspace_cache_key v4-hermes-{{ .Environment.CIRCLE_JOB }}-{{ checksum "/tmp/hermes/hermesversion" }} + hermes_workspace_cache_key: &hermes_workspace_cache_key v5-hermes-{{ .Environment.CIRCLE_JOB }}-{{ checksum "/tmp/hermes/hermesversion" }} hermes_workspace_debug_cache_key: &hermes_workspace_debug_cache_key v2-hermes-{{ .Environment.CIRCLE_JOB }}-debug-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }} hermes_workspace_release_cache_key: &hermes_workspace_release_cache_key v2-hermes-{{ .Environment.CIRCLE_JOB }}-release-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }} hermes_linux_cache_key: &hermes_linux_cache_key v1-hermes-{{ .Environment.CIRCLE_JOB }}-linux-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }} @@ -1109,7 +1109,7 @@ jobs: - image: debian:11 environment: - HERMES_WS_DIR: *hermes_workspace_root - - HERMES_VERSION_FILE: "sdks/.hermesversion" + - HERMES_VERSION_FILE: "packages/react-native/sdks/.hermesversion" - BUILD_FROM_SOURCE: true steps: - run: @@ -1128,8 +1128,11 @@ jobs: mkdir -p "/tmp/hermes" "/tmp/hermes/download" "/tmp/hermes/hermes" if [ -f "$HERMES_VERSION_FILE" ]; then + echo "Hermes Version file found! Using this version for the build:" cat $HERMES_VERSION_FILE > /tmp/hermes/hermesversion else + echo "Hermes Version file not found!!!" + echo "Using the last commit from main for the build:" HERMES_TAG_SHA=$(git ls-remote /~https://github.com/facebook/hermes main | cut -f 1 | tr -d '[:space:]') echo $HERMES_TAG_SHA > /tmp/hermes/hermesversion fi From d5dfc99bca83f17a428531f4c709297a832cf1e8 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Tue, 30 May 2023 04:12:38 -0700 Subject: [PATCH 16/22] Attempt at fixing crash when blurring image on iOS (#37614) Summary: Pull Request resolved: /~https://github.com/facebook/react-native/pull/37614 changelog: [internal] We do not control what `vImageBoxConvolve_ARGB8888` returns, it may return 0. If it does return 0, we will allocate memory chunk of size 0. Yes, malloc will let you do that. Well, it depends on the implementation, but according to the spec it is legal. The only requirement is to by able to call free on that without crash. If `vImageBoxConvolve_ARGB8888` does return 0 and we allocate memory of size 0. Call to `vImageBoxConvolve_ARGB8888` with tempBuffer of size 0 will lead to a crash. [The documentation](https://developer.apple.com/documentation/accelerate/1515945-vimageboxconvolve_argb8888#discussion) for `vImageBoxConvolve_ARGB8888` and tempBuffer states: > To determine the minimum size for the temporary buffer, the first time you call this function pass the kvImageGetTempBufferSize flag. Pass the same values for all other parameters that you intend to use in for the second call. The function returns the required minimum size, which **should be a positive value**. (A negative returned value indicates an error.) The kvImageGetTempBufferSize flag prevents the function from performing any processing other than to determine the minimum buffer size. I think the keyword word there is "should be a positive value". 0 is not a positive value. Reviewed By: javache, yungsters Differential Revision: D46263204 fbshipit-source-id: baa8fac5b3be6fb5bed02800cd725cc4cf43485a --- packages/react-native/Libraries/Image/RCTImageBlurUtils.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-native/Libraries/Image/RCTImageBlurUtils.m b/packages/react-native/Libraries/Image/RCTImageBlurUtils.m index 7214a87d4c860a..e5a17309473b12 100644 --- a/packages/react-native/Libraries/Image/RCTImageBlurUtils.m +++ b/packages/react-native/Libraries/Image/RCTImageBlurUtils.m @@ -54,7 +54,7 @@ // create temp buffer vImage_Error tempBufferSize = vImageBoxConvolve_ARGB8888( &buffer1, &buffer2, NULL, 0, 0, boxSize, boxSize, NULL, kvImageGetTempBufferSize | kvImageEdgeExtend); - if (tempBufferSize < 0) { + if (tempBufferSize <= 0) { free(buffer1.data); free(buffer2.data); return inputImage; From f7d9693cf0d4e1328b821bd2c0af368c89da4e94 Mon Sep 17 00:00:00 2001 From: Douglas Lowder Date: Tue, 30 May 2023 06:44:49 -0700 Subject: [PATCH 17/22] Fix Fabric issue with React-Core pod when Xcode project has multiple targets (#37581) Summary: In Xcode projects with multiple targets, and in particular when targets are for different platforms (e.g. iOS and macOS), Cocoapods may add a suffix to a Pod name like `React-Core`. When this happens, the code in `new_architecture.rb` (which was looking for a pod with exact name `React-Core`) would not add the preprocessor definitions for Fabric as expected. This change fixes this issue. Fixes /~https://github.com/facebook/react-native/issues/37102 . ## Changelog: [iOS] [Fixed] - Fix Fabric issue with React-Core pod when Xcode project has multiple targets Pull Request resolved: /~https://github.com/facebook/react-native/pull/37581 Test Plan: Tested that this change fixes this issue which occurs 100% of the time in React Native TV projects. Reviewed By: dmytrorykun Differential Revision: D46264704 Pulled By: cipolleschi fbshipit-source-id: 8dfc8e342b5a110ef1f028636e01e5c5f2b6e2f0 --- packages/react-native/scripts/cocoapods/new_architecture.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/react-native/scripts/cocoapods/new_architecture.rb b/packages/react-native/scripts/cocoapods/new_architecture.rb index 1b66a14684cec6..192d2702645a9f 100644 --- a/packages/react-native/scripts/cocoapods/new_architecture.rb +++ b/packages/react-native/scripts/cocoapods/new_architecture.rb @@ -16,7 +16,8 @@ def self.set_clang_cxx_language_standard_if_needed(installer) language_standard = nil installer.pods_project.targets.each do |target| - if target.name == 'React-Core' + # The React-Core pod may have a suffix added by Cocoapods, so we test whether 'React-Core' is a substring, and do not require exact match + if target.name.include? 'React-Core' language_standard = target.resolved_build_setting("CLANG_CXX_LANGUAGE_STANDARD", resolve_against_xcconfig: true).values[0] end end @@ -61,7 +62,8 @@ def self.modify_flags_for_new_architecture(installer, is_new_arch_enabled) # Add RCT_NEW_ARCH_ENABLED to generated pod target projects installer.target_installation_results.pod_target_installation_results.each do |pod_name, target_installation_result| - if pod_name == 'React-Core' + # The React-Core pod may have a suffix added by Cocoapods, so we test whether 'React-Core' is a substring, and do not require exact match + if pod_name.include? 'React-Core' target_installation_result.native_target.build_configurations.each do |config| config.build_settings['OTHER_CPLUSPLUSFLAGS'] = @@new_arch_cpp_flags end From ef6fc1cef27f34d983886b0e0f7332e1a42ad5ff Mon Sep 17 00:00:00 2001 From: Pranav Yadav Date: Tue, 30 May 2023 07:14:25 -0700 Subject: [PATCH 18/22] Remove `greet.yml` action (#37587) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: This (`greet.yml`) action requires some _changes_ to "repo" settings which are _out of maintainers' controls_. So, instead of wasting compute; let's just delete this action :( 🤗🌏 ## Changelog: [GENERAL] [REMOVED] - [Actions] Remove `greet.yml` action Pull Request resolved: /~https://github.com/facebook/react-native/pull/37587 Test Plan: - Not needed. Reviewed By: cortinico Differential Revision: D46275607 Pulled By: cipolleschi fbshipit-source-id: 80880568cbae1158006445e078e638e4e375cb73 --- .github/workflows/greet.yml | 50 ------------------------------------- 1 file changed, 50 deletions(-) delete mode 100644 .github/workflows/greet.yml diff --git a/.github/workflows/greet.yml b/.github/workflows/greet.yml deleted file mode 100644 index 7828f08ed188f8..00000000000000 --- a/.github/workflows/greet.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: 🎉 Greet First Time Contributors 🎉 -# This workflow is triggered on pull requests. - -on: - pull_request: - types: [opened] - -permissions: - contents: read - -jobs: - check_for_first_contribution: - name: '🎉 Greet First Time Contributors' - permissions: - contents: read - pull-requests: write # for actions/first-interaction to comment on PR - runs-on: ubuntu-latest - steps: - - uses: actions/first-interaction@v1.1.1 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - pr-message: | - "### Hi there, :wave: - - ### Congratulations :tada: on your **_'First Pull Request'_** to [React Native](/~https://github.com/facebook/react-native)! :partying_face: - - Thank you, :pray: for taking the time to contribute to this project and share your ideas. - - Someone from the team will review your PR and get back to you _as soon as possible_ with feedback if any. :blush: Post review, and if all tests are passing, your PR will be _imported_ to internal FB phabricator and should be merged if it also passes all internal tests. :partying_face: - -
- P.S.: In the meantime, you should go through below checklist: (click to expand) - - - 1. Make sure you have _signed_ the [CLA](https://code.facebook.com/cla) :balance_scale:, - 2. There are _no_ typos :sweat_smile:, - 3. There are _no_ warnings reported by the **Danger** workflow :robot:, - 4. You ran `yarn prettier` and `yarn lint` :nail_care:, - 5. All tests :test_tube: are _passing_. i.e. The CI checks should be green :green_circle:, and - 6. You have _added_ necessary tests for your code, if it's a refactor or a new functionality. :test_tube: - -
- - --- - - - - [Contributing Guidelines](https://reactnative.dev/contributing/overview) | [React Native Website](https://reactnative.dev/) | [Framework discussions, proposals and RFCs](/~https://github.com/react-native-community/discussions-and-proposals/discussions) - - " From 39709bbe4a34862741bd3a08b1f80511cbf7f8d2 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Tue, 30 May 2023 07:15:02 -0700 Subject: [PATCH 19/22] Add tests in CI not to break Hermes-Xcode integration (#37616) Summary: Pull Request resolved: /~https://github.com/facebook/react-native/pull/37616 Add tests in CircleCI to avoid that changes in Hermes can break the Xcode integration. ## Changelog: [Internal] - Add CI tests to avoid to break the Hermes-Xcode integration Reviewed By: cortinico Differential Revision: D46265656 fbshipit-source-id: 176f1a33fe6944a68fb14b62e5c626fe30d296cc --- .circleci/config.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8babd32c1d91da..8a7d38a0b3f1df 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -922,6 +922,32 @@ jobs: # ------------------------- # JOBS: Test iOS RNTester # ------------------------- + # This job builds configures Xcode so that Hermes is built from source + # (but only the iphonesimulator slice) and integrated with the Xcode + # build toolchain. The `test_ios_rntester` job, instead, takes the + # same prebuilt for Hermes that we are going to use in the Release. + test_ios_rntester_hermes_xcode_integration: + executor: reactnativeios + steps: + - checkout_code_with_cache + - run_yarn + - brew_install: + package: cmake + - run: + name: Pod install + command: | + cd packages/rn-tester + rm -rf Pods Podfile.lock + bundle install + RCT_NEW_ARCH_ENABLED=1 bundle exec pod install + - run: + name: Build RNTester + command: | + xcodebuild build \ + -workspace packages/rn-tester/RNTesterPods.xcworkspace \ + -scheme RNTester \ + -sdk iphonesimulator + test_ios_rntester: executor: reactnativeios parameters: @@ -1600,6 +1626,7 @@ workflows: - equal: [ false, << pipeline.parameters.run_nightly_workflow >> ] jobs: - prepare_hermes_workspace + - test_ios_rntester_hermes_xcode_integration - build_hermesc_linux: requires: - prepare_hermes_workspace From c3e1c41918bf71dc2056c9780b674d6f2c1e1916 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Tue, 30 May 2023 07:20:25 -0700 Subject: [PATCH 20/22] Use SurfaceRegistry globals whenever available (#37410) Summary: Pull Request resolved: /~https://github.com/facebook/react-native/pull/37410 Incremental adoption of new bridgeless API's, where they are semantically equivalent to the old one. Changelog: [Internal] Reviewed By: christophpurrer Differential Revision: D45736529 fbshipit-source-id: e41f6840e7c329f6051530e53773fae760584842 --- .../uimanager/SurfaceRegistryBinding.cpp | 120 +++++++----------- 1 file changed, 47 insertions(+), 73 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/SurfaceRegistryBinding.cpp b/packages/react-native/ReactCommon/react/renderer/uimanager/SurfaceRegistryBinding.cpp index 14cb0235ed3317..91125c1f9a595d 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/SurfaceRegistryBinding.cpp +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/SurfaceRegistryBinding.cpp @@ -13,6 +13,22 @@ namespace facebook::react { +namespace { + +void throwIfBridgeless( + jsi::Runtime &runtime, + jsi::Object &global, + const char *methodName) { + auto isBridgeless = global.getProperty(runtime, "RN$Bridgeless"); + if (isBridgeless.isBool() && isBridgeless.asBool()) { + throw std::runtime_error( + "SurfaceRegistryBinding::" + std::string(methodName) + + " failed. Global was not installed."); + } +} + +} // namespace + void SurfaceRegistryBinding::startSurface( jsi::Runtime &runtime, SurfaceId surfaceId, @@ -26,43 +42,24 @@ void SurfaceRegistryBinding::startSurface( parameters["fabric"] = true; auto global = runtime.global(); - auto isBridgeless = global.hasProperty(runtime, "RN$Bridgeless") && - global.getProperty(runtime, "RN$Bridgeless").asBool(); - - if (isBridgeless) { - if (!global.hasProperty(runtime, "RN$SurfaceRegistry")) { - throw std::runtime_error( - "SurfaceRegistryBinding::startSurface: Failed to start Surface \"" + - moduleName + "\". global.RN$SurfaceRegistry was not installed."); - } - - auto registry = global.getPropertyAsObject(runtime, "RN$SurfaceRegistry"); - auto method = registry.getPropertyAsFunction(runtime, "renderSurface"); + auto registry = global.getProperty(runtime, "RN$AppRegistry"); + if (registry.isObject()) { + auto method = std::move(registry).asObject(runtime).getPropertyAsFunction( + runtime, "runApplication"); method.call( runtime, {jsi::String::createFromUtf8(runtime, moduleName), jsi::valueFromDynamic(runtime, parameters), jsi::Value(runtime, displayModeToInt(displayMode))}); } else { - if (moduleName != "LogBox" && - global.hasProperty(runtime, "RN$SurfaceRegistry")) { - auto registry = global.getPropertyAsObject(runtime, "RN$SurfaceRegistry"); - auto method = registry.getPropertyAsFunction(runtime, "renderSurface"); - - method.call( - runtime, - {jsi::String::createFromUtf8(runtime, moduleName), - jsi::valueFromDynamic(runtime, parameters), - jsi::Value(runtime, displayModeToInt(displayMode))}); - } else { - callMethodOfModule( - runtime, - "AppRegistry", - "runApplication", - {jsi::String::createFromUtf8(runtime, moduleName), - jsi::valueFromDynamic(runtime, parameters), - jsi::Value(runtime, displayModeToInt(displayMode))}); - } + throwIfBridgeless(runtime, global, "startSurface"); + callMethodOfModule( + runtime, + "AppRegistry", + "runApplication", + {jsi::String::createFromUtf8(runtime, moduleName), + jsi::valueFromDynamic(runtime, parameters), + jsi::Value(runtime, displayModeToInt(displayMode))}); } } @@ -79,44 +76,24 @@ void SurfaceRegistryBinding::setSurfaceProps( parameters["fabric"] = true; auto global = runtime.global(); - auto isBridgeless = global.hasProperty(runtime, "RN$Bridgeless") && - global.getProperty(runtime, "RN$Bridgeless").asBool(); - - if (isBridgeless) { - if (!global.hasProperty(runtime, "RN$SurfaceRegistry")) { - throw std::runtime_error( - "SurfaceRegistryBinding::setSurfaceProps: Failed to set Surface props for \"" + - moduleName + "\". global.RN$SurfaceRegistry was not installed."); - } - - auto registry = global.getPropertyAsObject(runtime, "RN$SurfaceRegistry"); - auto method = registry.getPropertyAsFunction(runtime, "setSurfaceProps"); - + auto registry = global.getProperty(runtime, "RN$AppRegistry"); + if (registry.isObject()) { + auto method = std::move(registry).asObject(runtime).getPropertyAsFunction( + runtime, "setSurfaceProps"); method.call( runtime, {jsi::String::createFromUtf8(runtime, moduleName), jsi::valueFromDynamic(runtime, parameters), jsi::Value(runtime, displayModeToInt(displayMode))}); } else { - if (moduleName != "LogBox" && - global.hasProperty(runtime, "RN$SurfaceRegistry")) { - auto registry = global.getPropertyAsObject(runtime, "RN$SurfaceRegistry"); - auto method = registry.getPropertyAsFunction(runtime, "setSurfaceProps"); - - method.call( - runtime, - {jsi::String::createFromUtf8(runtime, moduleName), - jsi::valueFromDynamic(runtime, parameters), - jsi::Value(runtime, displayModeToInt(displayMode))}); - } else { - callMethodOfModule( - runtime, - "AppRegistry", - "setSurfaceProps", - {jsi::String::createFromUtf8(runtime, moduleName), - jsi::valueFromDynamic(runtime, parameters), - jsi::Value(runtime, displayModeToInt(displayMode))}); - } + throwIfBridgeless(runtime, global, "setSurfaceProps"); + callMethodOfModule( + runtime, + "AppRegistry", + "setSurfaceProps", + {jsi::String::createFromUtf8(runtime, moduleName), + jsi::valueFromDynamic(runtime, parameters), + jsi::Value(runtime, displayModeToInt(displayMode))}); } } @@ -124,18 +101,15 @@ void SurfaceRegistryBinding::stopSurface( jsi::Runtime &runtime, SurfaceId surfaceId) { auto global = runtime.global(); - auto isBridgeless = global.hasProperty(runtime, "RN$Bridgeless") && - global.getProperty(runtime, "RN$Bridgeless").asBool(); - - if (isBridgeless) { - if (!global.hasProperty(runtime, "RN$stopSurface")) { - // ReactFabric module has not been loaded yet; there's no surface to stop. - return; - } - // Bridgeless mode uses a custom JSI binding instead of callable module. - global.getPropertyAsFunction(runtime, "RN$stopSurface") + auto stopFunction = global.getProperty(runtime, "RN$stopSurface"); + if (stopFunction.isObject() && + stopFunction.asObject(runtime).isFunction(runtime)) { + std::move(stopFunction) + .asObject(runtime) + .asFunction(runtime) .call(runtime, {jsi::Value{surfaceId}}); } else { + throwIfBridgeless(runtime, global, "stopSurface"); callMethodOfModule( runtime, "ReactFabric", From 908eecae0e0dd9479dc1785bef2a2fe5226392e6 Mon Sep 17 00:00:00 2001 From: Szymon Date: Thu, 15 Jun 2023 09:11:23 +0200 Subject: [PATCH 21/22] choose proper numberOfLines prop name based on native config --- packages/react-native/Libraries/Text/Text.js | 12 ++++++++++-- .../Libraries/Text/TextNativeComponent.js | 5 +++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/react-native/Libraries/Text/Text.js b/packages/react-native/Libraries/Text/Text.js index 61c2f638d1e0d1..ecdca4bdb5f20b 100644 --- a/packages/react-native/Libraries/Text/Text.js +++ b/packages/react-native/Libraries/Text/Text.js @@ -18,7 +18,7 @@ import processColor from '../StyleSheet/processColor'; import {getAccessibilityRoleFromRole} from '../Utilities/AcessibilityMapping'; import Platform from '../Utilities/Platform'; import TextAncestor from './TextAncestor'; -import {NativeText, NativeVirtualText} from './TextNativeComponent'; +import {NativeText, NativeVirtualText, CONTAINS_MAX_NUMBER_OF_LINES_RENAME} from './TextNativeComponent'; import * as React from 'react'; import {useContext, useMemo, useState} from 'react'; @@ -201,6 +201,14 @@ const Text: React.AbstractComponent< numberOfLinesValue = 0; } + const numberOfLinesProps = useMemo(() => { + return { + [CONTAINS_MAX_NUMBER_OF_LINES_RENAME + ? 'maximumNumberOfLines' + : 'numberOfLines']: numberOfLinesValue, + }; + }, [numberOfLinesValue]); + const hasTextAncestor = useContext(TextAncestor); const _accessible = Platform.select({ @@ -252,6 +260,7 @@ const Text: React.AbstractComponent< = createViewConfig(textViewConfig), ): any); +export const CONTAINS_MAX_NUMBER_OF_LINES_RENAME = + getNativeComponentAttributes('RCTText')?.NativeProps?.maximumNumberOfLines === + 'number'; + export const NativeVirtualText: HostComponent = !global.RN$Bridgeless && !UIManager.hasViewManagerConfig('RCTVirtualText') ? NativeText From bcb467d0d0ed98383566ecf011ca763a70c8c253 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szymon=20Kapa=C5=82a?= Date: Mon, 10 Jul 2023 18:04:07 +0200 Subject: [PATCH 22/22] Update packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java Co-authored-by: Jakub Piasecki --- .../facebook/react/views/textinput/ReactTextInputManager.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java index 21eb41d6f89b37..c6a2d63b1d49f0 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java @@ -743,7 +743,9 @@ public void setNumLines(ReactEditText view, int numLines) { @ReactProp(name = ViewProps.MAXIMUM_NUMBER_OF_LINES, defaultInt = 1) public void setMaxNumLines(ReactEditText view, int numLines) { - view.setInputType(view.getInputType() | InputType.TYPE_TEXT_FLAG_MULTI_LINE); + if ((view.getInputType() & InputType.TYPE_TEXT_FLAG_MULTI_LINE) == 0) { + view.setInputType(view.getInputType() | InputType.TYPE_TEXT_FLAG_MULTI_LINE); + } view.setMaxLines(numLines); }