Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion packages/react-native/ReactAndroid/api/ReactAndroid.api
Original file line number Diff line number Diff line change
Expand Up @@ -6110,7 +6110,7 @@ public class com/facebook/react/views/text/ReactTextView : androidx/appcompat/wi
public fun updateView ()V
}

public final class com/facebook/react/views/text/ReactTextViewManager : com/facebook/react/uimanager/BaseViewManager, com/facebook/react/uimanager/IViewManagerWithChildren, com/facebook/react/views/text/ReactTextViewManagerCallback {
public class com/facebook/react/views/text/ReactTextViewManager : com/facebook/react/uimanager/BaseViewManager, com/facebook/react/uimanager/IViewManagerWithChildren, com/facebook/react/views/text/ReactTextViewManagerCallback {
public static final field Companion Lcom/facebook/react/views/text/ReactTextViewManager$Companion;
public static final field REACT_CLASS Ljava/lang/String;
public fun <init> ()V
Expand All @@ -6123,11 +6123,14 @@ public final class com/facebook/react/views/text/ReactTextViewManager : com/face
public fun createViewInstance (Lcom/facebook/react/uimanager/ThemedReactContext;)Lcom/facebook/react/views/text/ReactTextView;
public fun getExportedCustomDirectEventTypeConstants ()Ljava/util/Map;
public fun getName ()Ljava/lang/String;
protected final fun getReactTextViewManagerCallback ()Lcom/facebook/react/views/text/ReactTextViewManagerCallback;
public fun getShadowNodeClass ()Ljava/lang/Class;
public fun needsCustomLayoutForChildren ()Z
public synthetic fun onAfterUpdateTransaction (Landroid/view/View;)V
protected fun onAfterUpdateTransaction (Lcom/facebook/react/views/text/ReactTextView;)V
public fun onPostProcessSpannable (Landroid/text/Spannable;)V
public synthetic fun prepareToRecycleView (Lcom/facebook/react/uimanager/ThemedReactContext;Landroid/view/View;)Landroid/view/View;
protected fun prepareToRecycleView (Lcom/facebook/react/uimanager/ThemedReactContext;Lcom/facebook/react/views/text/ReactTextView;)Lcom/facebook/react/views/text/ReactTextView;
public final fun setAccessible (Lcom/facebook/react/views/text/ReactTextView;Z)V
public final fun setAdjustFontSizeToFit (Lcom/facebook/react/views/text/ReactTextView;Z)V
public final fun setAndroidHyphenationFrequency (Lcom/facebook/react/views/text/ReactTextView;Ljava/lang/String;)V
Expand All @@ -6145,6 +6148,7 @@ public final class com/facebook/react/views/text/ReactTextViewManager : com/face
public final fun setOverflow (Lcom/facebook/react/views/text/ReactTextView;Ljava/lang/String;)V
public synthetic fun setPadding (Landroid/view/View;IIII)V
public fun setPadding (Lcom/facebook/react/views/text/ReactTextView;IIII)V
protected final fun setReactTextViewManagerCallback (Lcom/facebook/react/views/text/ReactTextViewManagerCallback;)V
public final fun setSelectable (Lcom/facebook/react/views/text/ReactTextView;Z)V
public final fun setSelectionColor (Lcom/facebook/react/views/text/ReactTextView;Ljava/lang/Integer;)V
public final fun setTextAlignVertical (Lcom/facebook/react/views/text/ReactTextView;Ljava/lang/String;)V
Expand All @@ -6153,6 +6157,7 @@ public final class com/facebook/react/views/text/ReactTextViewManager : com/face
public synthetic fun updateState (Landroid/view/View;Lcom/facebook/react/uimanager/ReactStylesDiffMap;Lcom/facebook/react/uimanager/StateWrapper;)Ljava/lang/Object;
public fun updateState (Lcom/facebook/react/views/text/ReactTextView;Lcom/facebook/react/uimanager/ReactStylesDiffMap;Lcom/facebook/react/uimanager/StateWrapper;)Ljava/lang/Object;
public synthetic fun updateViewAccessibility (Landroid/view/View;)V
protected fun updateViewAccessibility (Lcom/facebook/react/views/text/ReactTextView;)V
}

public final class com/facebook/react/views/text/ReactTextViewManager$Companion {
Expand All @@ -6170,6 +6175,9 @@ public final class com/facebook/react/views/text/ReactTypefaceUtils {
public static final fun parseFontWeight (Ljava/lang/String;)I
}

public final class com/facebook/react/views/text/SelectableTextViewManager$Companion {
}

public final class com/facebook/react/views/text/TextAttributeProps {
public static final field Companion Lcom/facebook/react/views/text/TextAttributeProps$Companion;
public static final field TA_KEY_ACCESSIBILITY_ROLE I
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -687,7 +687,9 @@ public PreparedLayout reusePreparedLayoutWithNewReactTags(
preparedLayout.getLayout(),
preparedLayout.getMaximumNumberOfLines(),
preparedLayout.getVerticalOffset(),
reactTags);
reactTags,
preparedLayout.getTextBreakStrategy(),
preparedLayout.getJustificationMode());
}

@AnyThread
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ internal object FabricNameComponentMapping {
"Slider" to "RCTSlider",
"ModalHostView" to "RCTModalHostView",
"Paragraph" to "RCTText",
"SelectableParagraph" to "RCTSelectableText",
"Text" to "RCTText",
"RawText" to "RCTRawText",
"ActivityIndicatorView" to "AndroidProgressBar",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ internal class PreparedLayout(
val maximumNumberOfLines: Int,
val verticalOffset: Float,
val reactTags: IntArray,
val textBreakStrategy: Int,
val justificationMode: Int,
)
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ package com.facebook.react.views.text
import android.os.Build
import android.text.Layout
import android.text.Spannable
import android.text.SpannableString
import android.text.Spanned
import android.text.TextUtils
import android.text.util.Linkify
Expand All @@ -31,6 +32,7 @@ import com.facebook.react.uimanager.LayoutShadowNode
import com.facebook.react.uimanager.LengthPercentage
import com.facebook.react.uimanager.LengthPercentageType
import com.facebook.react.uimanager.ReactStylesDiffMap
import com.facebook.react.uimanager.ReferenceStateWrapper
import com.facebook.react.uimanager.StateWrapper
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.ViewDefaults
Expand All @@ -46,7 +48,7 @@ import java.util.HashMap
/** View manager for `<Text>` nodes. */
@ReactModule(name = ReactTextViewManager.REACT_CLASS)
@OptIn(UnstableReactNativeAPI::class)
public class ReactTextViewManager
public open class ReactTextViewManager
@JvmOverloads
public constructor(
protected var reactTextViewManagerCallback: ReactTextViewManagerCallback? = null
Expand Down Expand Up @@ -131,6 +133,11 @@ public constructor(
stateWrapper: StateWrapper,
): Any? {
SystraceSection("ReactTextViewManager.updateState").use { s ->
val refState = (stateWrapper as? ReferenceStateWrapper)?.stateDataReference
if (refState is PreparedLayout) {
return getReactTextUpdateFromPreparedLayout(view, refState)
}

val stateMapBuffer = stateWrapper.stateDataMapBuffer
return if (stateMapBuffer != null) {
getReactTextUpdate(view, props, stateMapBuffer)
Expand Down Expand Up @@ -176,6 +183,34 @@ public constructor(
)
}

/**
* Constructs a [ReactTextUpdate] from a [PreparedLayout] received via [ReferenceStateWrapper].
*/
private fun getReactTextUpdateFromPreparedLayout(
view: ReactTextView,
preparedLayout: PreparedLayout,
): ReactTextUpdate {
val layout = preparedLayout.layout
val text = layout.text
val spanned = if (text is Spannable) text else SpannableString(text)
view.setSpanned(spanned)

val textAlign =
when (layout.alignment) {
Layout.Alignment.ALIGN_CENTER -> Gravity.CENTER_HORIZONTAL
Layout.Alignment.ALIGN_OPPOSITE -> Gravity.END
else -> Gravity.START
}

return ReactTextUpdate(
spanned,
-1,
textAlign,
preparedLayout.textBreakStrategy,
preparedLayout.justificationMode,
)
}

override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any>? {
val baseEventTypeConstants = super.getExportedCustomDirectEventTypeConstants()
val eventTypeConstants = baseEventTypeConstants ?: HashMap()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* 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.
*/

package com.facebook.react.views.text

import com.facebook.react.common.annotations.UnstableReactNativeAPI

/**
* A [ReactTextViewManager] registered under the name "RCTSelectableText". Used to route selectable
* text through [ReactTextView] (a real [android.widget.TextView]) instead of
* [PreparedLayoutTextView] when enablePreparedTextLayout is on, since [PreparedLayoutTextView] does
* not support native text selection.
*/
@UnstableReactNativeAPI
public class SelectableTextViewManager
@JvmOverloads
public constructor(reactTextViewManagerCallback: ReactTextViewManagerCallback? = null) :
ReactTextViewManager(reactTextViewManagerCallback) {

override fun getName(): String = REACT_CLASS

public companion object {
public const val REACT_CLASS: String = "RCTSelectableText"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -821,15 +821,16 @@ internal object TextLayoutManager {
}

return createLayout(
text,
paint,
attributedString,
paragraphAttributes,
width,
widthYogaMeasureMode,
height,
heightYogaMeasureMode,
)
text,
paint,
attributedString,
paragraphAttributes,
width,
widthYogaMeasureMode,
height,
heightYogaMeasureMode,
)
.layout
}

private fun createLayout(
Expand All @@ -841,7 +842,7 @@ internal object TextLayoutManager {
widthYogaMeasureMode: YogaMeasureMode,
height: Float,
heightYogaMeasureMode: YogaMeasureMode,
): Layout {
): CreateLayoutResult {
val boring = isBoring(text, paint)

val textBreakStrategy =
Expand Down Expand Up @@ -899,19 +900,23 @@ internal object TextLayoutManager {
)
}

return createLayout(
text,
boring,
width,
widthYogaMeasureMode,
includeFontPadding,
return CreateLayoutResult(
createLayout(
text,
boring,
width,
widthYogaMeasureMode,
includeFontPadding,
textBreakStrategy,
hyphenationFrequency,
alignment,
justificationMode,
ellipsizeMode,
maximumNumberOfLines,
paint,
),
textBreakStrategy,
hyphenationFrequency,
alignment,
justificationMode,
ellipsizeMode,
maximumNumberOfLines,
paint,
)
}

Expand All @@ -937,7 +942,7 @@ internal object TextLayoutManager {
)
val baseTextAttributes =
TextAttributeProps.fromMapBuffer(attributedString.getMapBuffer(AS_KEY_BASE_ATTRIBUTES))
val layout =
val result =
createLayout(
text,
newPaintWithAttributes(baseTextAttributes, context),
Expand All @@ -956,14 +961,21 @@ internal object TextLayoutManager {

val verticalOffset =
getVerticalOffset(
layout,
result.layout,
paragraphAttributes,
height,
heightYogaMeasureMode,
maximumNumberOfLines,
)

return PreparedLayout(layout, maximumNumberOfLines, verticalOffset, reactTags)
return PreparedLayout(
result.layout,
maximumNumberOfLines,
verticalOffset,
reactTags,
result.textBreakStrategy,
result.justificationMode,
)
}

@JvmStatic
Expand Down Expand Up @@ -1373,6 +1385,12 @@ internal object TextLayoutManager {
BoringLayout.isBoring(text, paint, TextDirectionHeuristics.FIRSTSTRONG_LTR, true, null)
}

private class CreateLayoutResult(
val layout: Layout,
val textBreakStrategy: Int,
val justificationMode: Int,
)

private class AttachmentMetrics {
var wasFound: Boolean = false
var top: Float = 0f
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <react/renderer/components/scrollview/ScrollViewComponentDescriptor.h>
#include <react/renderer/components/text/ParagraphComponentDescriptor.h>
#include <react/renderer/components/text/RawTextComponentDescriptor.h>
#include <react/renderer/components/text/SelectableParagraphComponentDescriptor.h>
#include <react/renderer/components/text/TextComponentDescriptor.h>
#include <react/renderer/components/view/LayoutConformanceComponentDescriptor.h>
#include <react/renderer/components/view/ViewComponentDescriptor.h>
Expand Down Expand Up @@ -71,6 +72,9 @@ void addCoreComponents(
AndroidHorizontalScrollContentViewComponentDescriptor>());
providerRegistry->add(
concreteComponentDescriptorProvider<ParagraphComponentDescriptor>());
providerRegistry->add(
concreteComponentDescriptorProvider<
SelectableParagraphComponentDescriptor>());
providerRegistry->add(
concreteComponentDescriptorProvider<
AndroidDrawerLayoutComponentDescriptor>());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ std::string componentNameByReactViewName(std::string viewName) {
if (viewName == "Text") {
return "Paragraph";
}
if (viewName == "SelectableText") {
return "SelectableParagraph";
}

if (viewName == "VirtualText") {
return "Text";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* 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.
*/

#pragma once

#include <react/renderer/core/ConcreteComponentDescriptor.h>
#include <react/renderer/textlayoutmanager/TextLayoutManager.h>
#include <react/utils/ContextContainer.h>

namespace facebook::react {

constexpr const char *const TextLayoutManagerKey = "TextLayoutManager";

template <typename ShadowNodeT>
class BaseParagraphComponentDescriptor : public ConcreteComponentDescriptor<ShadowNodeT> {
public:
explicit BaseParagraphComponentDescriptor(const ComponentDescriptorParameters &parameters)
: ConcreteComponentDescriptor<ShadowNodeT>(parameters),
textLayoutManager_(getManagerByName<TextLayoutManager>(this->contextContainer_, TextLayoutManagerKey))
{
}

ComponentName getComponentName() const override
{
return ShadowNodeT::Name();
}

protected:
void adopt(ShadowNode &shadowNode) const override
{
ConcreteComponentDescriptor<ShadowNodeT>::adopt(shadowNode);

auto &paragraphShadowNode = static_cast<ShadowNodeT &>(shadowNode);

// `ParagraphShadowNode` uses `TextLayoutManager` to measure text content
// and communicate text rendering metrics to mounting layer.
paragraphShadowNode.setTextLayoutManager(textLayoutManager_);
}

private:
// Every `ParagraphShadowNode` has a reference to a shared `TextLayoutManager`
const std::shared_ptr<const TextLayoutManager> textLayoutManager_;
};

} // namespace facebook::react

This file was deleted.

Loading
Loading