react-native 0.72.0-rc.0 → 0.72.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Libraries/Core/ReactNativeVersion.js +1 -1
- package/Libraries/Core/ReactNativeVersionCheck.js +5 -1
- package/Libraries/ReactNative/UIManager.js +27 -1
- package/Libraries/Renderer/implementations/ReactFabric-dev.js +26 -3
- package/Libraries/Renderer/implementations/ReactFabric-prod.js +13 -1
- package/Libraries/Renderer/implementations/ReactFabric-profiling.js +13 -1
- package/React/Base/RCTVersion.m +1 -1
- package/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropCoordinatorAdapter.mm +1 -1
- package/ReactAndroid/gradle.properties +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java +40 -1
- package/ReactAndroid/src/main/java/com/facebook/react/ReactFragment.java +22 -7
- package/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java +3 -0
- package/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactActivityDelegate.kt +4 -0
- package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/CustomLetterSpacingSpan.java +4 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/CustomStyleSpan.java +4 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextUpdate.java +1 -5
- package/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java +190 -134
- package/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java +23 -10
- package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundManager.java +5 -0
- package/ReactAndroid/src/main/jni/react/fabric/Binding.cpp +3 -0
- package/ReactCommon/React-rncore.podspec +12 -4
- package/ReactCommon/cxxreact/ReactNativeVersion.h +1 -1
- package/ReactCommon/react/config/ReactNativeConfig.cpp +3 -0
- package/ReactCommon/react/renderer/components/legacyviewmanagerinterop/RCTLegacyViewManagerInteropCoordinator.h +4 -1
- package/ReactCommon/react/renderer/components/legacyviewmanagerinterop/RCTLegacyViewManagerInteropCoordinator.mm +49 -2
- package/ReactCommon/react/renderer/components/text/ParagraphLayoutManager.cpp +30 -5
- package/ReactCommon/react/renderer/components/text/ParagraphLayoutManager.h +12 -0
- package/ReactCommon/react/renderer/core/CoreFeatures.cpp +1 -0
- package/ReactCommon/react/renderer/core/CoreFeatures.h +5 -0
- package/ReactCommon/react/renderer/textlayoutmanager/platform/android/react/renderer/textlayoutmanager/TextLayoutManager.cpp +5 -1
- package/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm +112 -83
- package/build.gradle.kts +17 -0
- package/gradle.properties +1 -0
- package/package.json +7 -7
- package/scripts/cocoapods/__tests__/codegen_utils-test.rb +9 -1
- package/scripts/cocoapods/codegen_utils.rb +1 -1
- package/sdks/hermesc/osx-bin/hermesc +0 -0
- package/sdks/hermesc/win64-bin/hermesc.exe +0 -0
- package/settings.gradle.kts +30 -0
- package/template/metro.config.js +7 -13
- package/template/package.json +4 -2
|
@@ -11,6 +11,8 @@ import static com.facebook.react.uimanager.UIManagerHelper.getReactContext;
|
|
|
11
11
|
import static com.facebook.react.views.text.TextAttributeProps.UNSET;
|
|
12
12
|
|
|
13
13
|
import android.content.Context;
|
|
14
|
+
import android.graphics.Color;
|
|
15
|
+
import android.graphics.Paint;
|
|
14
16
|
import android.graphics.Rect;
|
|
15
17
|
import android.graphics.Typeface;
|
|
16
18
|
import android.graphics.drawable.Drawable;
|
|
@@ -50,15 +52,19 @@ import com.facebook.react.views.text.CustomLetterSpacingSpan;
|
|
|
50
52
|
import com.facebook.react.views.text.CustomLineHeightSpan;
|
|
51
53
|
import com.facebook.react.views.text.CustomStyleSpan;
|
|
52
54
|
import com.facebook.react.views.text.ReactAbsoluteSizeSpan;
|
|
55
|
+
import com.facebook.react.views.text.ReactBackgroundColorSpan;
|
|
56
|
+
import com.facebook.react.views.text.ReactForegroundColorSpan;
|
|
53
57
|
import com.facebook.react.views.text.ReactSpan;
|
|
58
|
+
import com.facebook.react.views.text.ReactStrikethroughSpan;
|
|
54
59
|
import com.facebook.react.views.text.ReactTextUpdate;
|
|
55
60
|
import com.facebook.react.views.text.ReactTypefaceUtils;
|
|
61
|
+
import com.facebook.react.views.text.ReactUnderlineSpan;
|
|
56
62
|
import com.facebook.react.views.text.TextAttributes;
|
|
57
63
|
import com.facebook.react.views.text.TextInlineImageSpan;
|
|
58
64
|
import com.facebook.react.views.text.TextLayoutManager;
|
|
59
65
|
import com.facebook.react.views.view.ReactViewBackgroundManager;
|
|
60
66
|
import java.util.ArrayList;
|
|
61
|
-
import java.util.
|
|
67
|
+
import java.util.Objects;
|
|
62
68
|
|
|
63
69
|
/**
|
|
64
70
|
* A wrapper around the EditText that lets us better control what happens when an EditText gets
|
|
@@ -82,7 +88,6 @@ public class ReactEditText extends AppCompatEditText
|
|
|
82
88
|
// *TextChanged events should be triggered. This is less expensive than removing the text
|
|
83
89
|
// listeners and adding them back again after the text change is completed.
|
|
84
90
|
protected boolean mIsSettingTextFromJS;
|
|
85
|
-
protected boolean mIsSettingTextFromCacheUpdate = false;
|
|
86
91
|
private int mDefaultGravityHorizontal;
|
|
87
92
|
private int mDefaultGravityVertical;
|
|
88
93
|
|
|
@@ -362,7 +367,7 @@ public class ReactEditText extends AppCompatEditText
|
|
|
362
367
|
}
|
|
363
368
|
|
|
364
369
|
super.onSelectionChanged(selStart, selEnd);
|
|
365
|
-
if (
|
|
370
|
+
if (mSelectionWatcher != null && hasFocus()) {
|
|
366
371
|
mSelectionWatcher.onSelectionChanged(selStart, selEnd);
|
|
367
372
|
}
|
|
368
373
|
}
|
|
@@ -512,6 +517,14 @@ public class ReactEditText extends AppCompatEditText
|
|
|
512
517
|
}
|
|
513
518
|
}
|
|
514
519
|
|
|
520
|
+
@Override
|
|
521
|
+
public void setFontFeatureSettings(String fontFeatureSettings) {
|
|
522
|
+
if (!Objects.equals(fontFeatureSettings, getFontFeatureSettings())) {
|
|
523
|
+
super.setFontFeatureSettings(fontFeatureSettings);
|
|
524
|
+
mTypefaceDirty = true;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
515
528
|
public void maybeUpdateTypeface() {
|
|
516
529
|
if (!mTypefaceDirty) {
|
|
517
530
|
return;
|
|
@@ -523,6 +536,17 @@ public class ReactEditText extends AppCompatEditText
|
|
|
523
536
|
ReactTypefaceUtils.applyStyles(
|
|
524
537
|
getTypeface(), mFontStyle, mFontWeight, mFontFamily, getContext().getAssets());
|
|
525
538
|
setTypeface(newTypeface);
|
|
539
|
+
|
|
540
|
+
// Match behavior of CustomStyleSpan and enable SUBPIXEL_TEXT_FLAG when setting anything
|
|
541
|
+
// nonstandard
|
|
542
|
+
if (mFontStyle != UNSET
|
|
543
|
+
|| mFontWeight != UNSET
|
|
544
|
+
|| mFontFamily != null
|
|
545
|
+
|| getFontFeatureSettings() != null) {
|
|
546
|
+
setPaintFlags(getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG);
|
|
547
|
+
} else {
|
|
548
|
+
setPaintFlags(getPaintFlags() & (~Paint.SUBPIXEL_TEXT_FLAG));
|
|
549
|
+
}
|
|
526
550
|
}
|
|
527
551
|
|
|
528
552
|
// VisibleForTesting from {@link TextInputEventsTestCase}.
|
|
@@ -584,10 +608,8 @@ public class ReactEditText extends AppCompatEditText
|
|
|
584
608
|
SpannableStringBuilder spannableStringBuilder =
|
|
585
609
|
new SpannableStringBuilder(reactTextUpdate.getText());
|
|
586
610
|
|
|
587
|
-
manageSpans(spannableStringBuilder
|
|
588
|
-
|
|
589
|
-
// Mitigation for https://github.com/facebook/react-native/issues/35936 (S318090)
|
|
590
|
-
stripAttributeEquivalentSpans(spannableStringBuilder);
|
|
611
|
+
manageSpans(spannableStringBuilder);
|
|
612
|
+
stripStyleEquivalentSpans(spannableStringBuilder);
|
|
591
613
|
|
|
592
614
|
mContainsImages = reactTextUpdate.containsImages();
|
|
593
615
|
|
|
@@ -615,7 +637,7 @@ public class ReactEditText extends AppCompatEditText
|
|
|
615
637
|
}
|
|
616
638
|
|
|
617
639
|
// Update cached spans (in Fabric only).
|
|
618
|
-
updateCachedSpannable(
|
|
640
|
+
updateCachedSpannable();
|
|
619
641
|
}
|
|
620
642
|
|
|
621
643
|
/**
|
|
@@ -624,8 +646,7 @@ public class ReactEditText extends AppCompatEditText
|
|
|
624
646
|
* will adapt to the new text, hence why {@link SpannableStringBuilder#replace} never removes
|
|
625
647
|
* them.
|
|
626
648
|
*/
|
|
627
|
-
private void manageSpans(
|
|
628
|
-
SpannableStringBuilder spannableStringBuilder, boolean skipAddSpansForMeasurements) {
|
|
649
|
+
private void manageSpans(SpannableStringBuilder spannableStringBuilder) {
|
|
629
650
|
Object[] spans = getText().getSpans(0, length(), Object.class);
|
|
630
651
|
for (int spanIdx = 0; spanIdx < spans.length; spanIdx++) {
|
|
631
652
|
Object span = spans[spanIdx];
|
|
@@ -653,58 +674,170 @@ public class ReactEditText extends AppCompatEditText
|
|
|
653
674
|
spannableStringBuilder.setSpan(span, spanStart, spanEnd, spanFlags);
|
|
654
675
|
}
|
|
655
676
|
}
|
|
677
|
+
}
|
|
656
678
|
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
if (!skipAddSpansForMeasurements) {
|
|
661
|
-
addSpansForMeasurement(getText());
|
|
662
|
-
}
|
|
679
|
+
// TODO: Replace with Predicate<T> and lambdas once Java 8 builds in OSS
|
|
680
|
+
interface SpanPredicate<T> {
|
|
681
|
+
boolean test(T span);
|
|
663
682
|
}
|
|
664
683
|
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
684
|
+
/**
|
|
685
|
+
* Remove spans from the SpannableStringBuilder which can be represented by TextAppearance
|
|
686
|
+
* attributes on the underlying EditText. This works around instability on Samsung devices with
|
|
687
|
+
* the presence of spans https://github.com/facebook/react-native/issues/35936 (S318090)
|
|
688
|
+
*/
|
|
689
|
+
private void stripStyleEquivalentSpans(SpannableStringBuilder sb) {
|
|
690
|
+
stripSpansOfKind(
|
|
691
|
+
sb,
|
|
692
|
+
ReactAbsoluteSizeSpan.class,
|
|
693
|
+
new SpanPredicate<ReactAbsoluteSizeSpan>() {
|
|
694
|
+
@Override
|
|
695
|
+
public boolean test(ReactAbsoluteSizeSpan span) {
|
|
696
|
+
return span.getSize() == mTextAttributes.getEffectiveFontSize();
|
|
697
|
+
}
|
|
698
|
+
});
|
|
670
699
|
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
700
|
+
stripSpansOfKind(
|
|
701
|
+
sb,
|
|
702
|
+
ReactBackgroundColorSpan.class,
|
|
703
|
+
new SpanPredicate<ReactBackgroundColorSpan>() {
|
|
704
|
+
@Override
|
|
705
|
+
public boolean test(ReactBackgroundColorSpan span) {
|
|
706
|
+
return span.getBackgroundColor() == mReactBackgroundManager.getBackgroundColor();
|
|
707
|
+
}
|
|
708
|
+
});
|
|
675
709
|
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
710
|
+
stripSpansOfKind(
|
|
711
|
+
sb,
|
|
712
|
+
ReactForegroundColorSpan.class,
|
|
713
|
+
new SpanPredicate<ReactForegroundColorSpan>() {
|
|
714
|
+
@Override
|
|
715
|
+
public boolean test(ReactForegroundColorSpan span) {
|
|
716
|
+
return span.getForegroundColor() == getCurrentTextColor();
|
|
717
|
+
}
|
|
718
|
+
});
|
|
719
|
+
|
|
720
|
+
stripSpansOfKind(
|
|
721
|
+
sb,
|
|
722
|
+
ReactStrikethroughSpan.class,
|
|
723
|
+
new SpanPredicate<ReactStrikethroughSpan>() {
|
|
724
|
+
@Override
|
|
725
|
+
public boolean test(ReactStrikethroughSpan span) {
|
|
726
|
+
return (getPaintFlags() & Paint.STRIKE_THRU_TEXT_FLAG) != 0;
|
|
727
|
+
}
|
|
728
|
+
});
|
|
681
729
|
|
|
682
|
-
|
|
730
|
+
stripSpansOfKind(
|
|
731
|
+
sb,
|
|
732
|
+
ReactUnderlineSpan.class,
|
|
733
|
+
new SpanPredicate<ReactUnderlineSpan>() {
|
|
734
|
+
@Override
|
|
735
|
+
public boolean test(ReactUnderlineSpan span) {
|
|
736
|
+
return (getPaintFlags() & Paint.UNDERLINE_TEXT_FLAG) != 0;
|
|
737
|
+
}
|
|
738
|
+
});
|
|
739
|
+
|
|
740
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
741
|
+
stripSpansOfKind(
|
|
742
|
+
sb,
|
|
743
|
+
CustomLetterSpacingSpan.class,
|
|
744
|
+
new SpanPredicate<CustomLetterSpacingSpan>() {
|
|
745
|
+
@Override
|
|
746
|
+
public boolean test(CustomLetterSpacingSpan span) {
|
|
747
|
+
return span.getSpacing() == mTextAttributes.getEffectiveLetterSpacing();
|
|
748
|
+
}
|
|
749
|
+
});
|
|
683
750
|
}
|
|
751
|
+
|
|
752
|
+
stripSpansOfKind(
|
|
753
|
+
sb,
|
|
754
|
+
CustomStyleSpan.class,
|
|
755
|
+
new SpanPredicate<CustomStyleSpan>() {
|
|
756
|
+
@Override
|
|
757
|
+
public boolean test(CustomStyleSpan span) {
|
|
758
|
+
return span.getStyle() == mFontStyle
|
|
759
|
+
&& Objects.equals(span.getFontFamily(), mFontFamily)
|
|
760
|
+
&& span.getWeight() == mFontWeight
|
|
761
|
+
&& Objects.equals(span.getFontFeatureSettings(), getFontFeatureSettings());
|
|
762
|
+
}
|
|
763
|
+
});
|
|
684
764
|
}
|
|
685
765
|
|
|
686
|
-
private void
|
|
687
|
-
SpannableStringBuilder
|
|
688
|
-
|
|
689
|
-
// existing spans. Remove all spans, add the attributes, then re-add the spans over
|
|
690
|
-
workingText.append(originalText);
|
|
766
|
+
private <T> void stripSpansOfKind(
|
|
767
|
+
SpannableStringBuilder sb, Class<T> clazz, SpanPredicate<T> shouldStrip) {
|
|
768
|
+
T[] spans = sb.getSpans(0, sb.length(), clazz);
|
|
691
769
|
|
|
692
|
-
for (
|
|
693
|
-
|
|
770
|
+
for (T span : spans) {
|
|
771
|
+
if (shouldStrip.test(span)) {
|
|
772
|
+
sb.removeSpan(span);
|
|
773
|
+
}
|
|
694
774
|
}
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
/**
|
|
778
|
+
* Copy styles represented as attributes to the underlying span, for later measurement or other
|
|
779
|
+
* usage outside the ReactEditText.
|
|
780
|
+
*/
|
|
781
|
+
private void addSpansFromStyleAttributes(SpannableStringBuilder workingText) {
|
|
782
|
+
int spanFlags = Spannable.SPAN_INCLUSIVE_INCLUSIVE;
|
|
783
|
+
|
|
784
|
+
// Set all bits for SPAN_PRIORITY so that this span has the highest possible priority
|
|
785
|
+
// (least precedence). This ensures the span is behind any overlapping spans.
|
|
786
|
+
spanFlags |= Spannable.SPAN_PRIORITY;
|
|
695
787
|
|
|
696
788
|
workingText.setSpan(
|
|
697
789
|
new ReactAbsoluteSizeSpan(mTextAttributes.getEffectiveFontSize()),
|
|
698
790
|
0,
|
|
699
791
|
workingText.length(),
|
|
700
|
-
|
|
792
|
+
spanFlags);
|
|
793
|
+
|
|
794
|
+
workingText.setSpan(
|
|
795
|
+
new ReactForegroundColorSpan(getCurrentTextColor()), 0, workingText.length(), spanFlags);
|
|
701
796
|
|
|
702
|
-
|
|
797
|
+
int backgroundColor = mReactBackgroundManager.getBackgroundColor();
|
|
798
|
+
if (backgroundColor != Color.TRANSPARENT) {
|
|
703
799
|
workingText.setSpan(
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
800
|
+
new ReactBackgroundColorSpan(backgroundColor), 0, workingText.length(), spanFlags);
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
if ((getPaintFlags() & Paint.STRIKE_THRU_TEXT_FLAG) != 0) {
|
|
804
|
+
workingText.setSpan(new ReactStrikethroughSpan(), 0, workingText.length(), spanFlags);
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
if ((getPaintFlags() & Paint.UNDERLINE_TEXT_FLAG) != 0) {
|
|
808
|
+
workingText.setSpan(new ReactUnderlineSpan(), 0, workingText.length(), spanFlags);
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
812
|
+
float effectiveLetterSpacing = mTextAttributes.getEffectiveLetterSpacing();
|
|
813
|
+
if (!Float.isNaN(effectiveLetterSpacing)) {
|
|
814
|
+
workingText.setSpan(
|
|
815
|
+
new CustomLetterSpacingSpan(effectiveLetterSpacing),
|
|
816
|
+
0,
|
|
817
|
+
workingText.length(),
|
|
818
|
+
spanFlags);
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
if (mFontStyle != UNSET
|
|
823
|
+
|| mFontWeight != UNSET
|
|
824
|
+
|| mFontFamily != null
|
|
825
|
+
|| getFontFeatureSettings() != null) {
|
|
826
|
+
workingText.setSpan(
|
|
827
|
+
new CustomStyleSpan(
|
|
828
|
+
mFontStyle,
|
|
829
|
+
mFontWeight,
|
|
830
|
+
getFontFeatureSettings(),
|
|
831
|
+
mFontFamily,
|
|
832
|
+
getContext().getAssets()),
|
|
833
|
+
0,
|
|
834
|
+
workingText.length(),
|
|
835
|
+
spanFlags);
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
float lineHeight = mTextAttributes.getEffectiveLineHeight();
|
|
839
|
+
if (!Float.isNaN(lineHeight)) {
|
|
840
|
+
workingText.setSpan(new CustomLineHeightSpan(lineHeight), 0, workingText.length(), spanFlags);
|
|
708
841
|
}
|
|
709
842
|
}
|
|
710
843
|
|
|
@@ -724,73 +857,6 @@ public class ReactEditText extends AppCompatEditText
|
|
|
724
857
|
return true;
|
|
725
858
|
}
|
|
726
859
|
|
|
727
|
-
// This is hacked in for Fabric. When we delete non-Fabric code, we might be able to simplify or
|
|
728
|
-
// clean this up a bit.
|
|
729
|
-
private void addSpansForMeasurement(Spannable spannable) {
|
|
730
|
-
if (!mFabricViewStateManager.hasStateWrapper()) {
|
|
731
|
-
return;
|
|
732
|
-
}
|
|
733
|
-
|
|
734
|
-
boolean originalDisableTextDiffing = mDisableTextDiffing;
|
|
735
|
-
mDisableTextDiffing = true;
|
|
736
|
-
|
|
737
|
-
int start = 0;
|
|
738
|
-
int end = spannable.length();
|
|
739
|
-
|
|
740
|
-
// Remove duplicate spans we might add here
|
|
741
|
-
Object[] spans = spannable.getSpans(0, length(), Object.class);
|
|
742
|
-
for (Object span : spans) {
|
|
743
|
-
int spanFlags = spannable.getSpanFlags(span);
|
|
744
|
-
boolean isInclusive =
|
|
745
|
-
(spanFlags & Spanned.SPAN_INCLUSIVE_INCLUSIVE) == Spanned.SPAN_INCLUSIVE_INCLUSIVE
|
|
746
|
-
|| (spanFlags & Spanned.SPAN_INCLUSIVE_EXCLUSIVE) == Spanned.SPAN_INCLUSIVE_EXCLUSIVE;
|
|
747
|
-
if (isInclusive
|
|
748
|
-
&& span instanceof ReactSpan
|
|
749
|
-
&& spannable.getSpanStart(span) == start
|
|
750
|
-
&& spannable.getSpanEnd(span) == end) {
|
|
751
|
-
spannable.removeSpan(span);
|
|
752
|
-
}
|
|
753
|
-
}
|
|
754
|
-
|
|
755
|
-
List<TextLayoutManager.SetSpanOperation> ops = new ArrayList<>();
|
|
756
|
-
|
|
757
|
-
if (!Float.isNaN(mTextAttributes.getLetterSpacing())) {
|
|
758
|
-
ops.add(
|
|
759
|
-
new TextLayoutManager.SetSpanOperation(
|
|
760
|
-
start, end, new CustomLetterSpacingSpan(mTextAttributes.getLetterSpacing())));
|
|
761
|
-
}
|
|
762
|
-
ops.add(
|
|
763
|
-
new TextLayoutManager.SetSpanOperation(
|
|
764
|
-
start, end, new ReactAbsoluteSizeSpan((int) mTextAttributes.getEffectiveFontSize())));
|
|
765
|
-
if (mFontStyle != UNSET || mFontWeight != UNSET || mFontFamily != null) {
|
|
766
|
-
ops.add(
|
|
767
|
-
new TextLayoutManager.SetSpanOperation(
|
|
768
|
-
start,
|
|
769
|
-
end,
|
|
770
|
-
new CustomStyleSpan(
|
|
771
|
-
mFontStyle,
|
|
772
|
-
mFontWeight,
|
|
773
|
-
null, // TODO: do we need to support FontFeatureSettings / fontVariant?
|
|
774
|
-
mFontFamily,
|
|
775
|
-
getReactContext(ReactEditText.this).getAssets())));
|
|
776
|
-
}
|
|
777
|
-
if (!Float.isNaN(mTextAttributes.getEffectiveLineHeight())) {
|
|
778
|
-
ops.add(
|
|
779
|
-
new TextLayoutManager.SetSpanOperation(
|
|
780
|
-
start, end, new CustomLineHeightSpan(mTextAttributes.getEffectiveLineHeight())));
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
int priority = 0;
|
|
784
|
-
for (TextLayoutManager.SetSpanOperation op : ops) {
|
|
785
|
-
// Actual order of calling {@code execute} does NOT matter,
|
|
786
|
-
// but the {@code priority} DOES matter.
|
|
787
|
-
op.execute(spannable, priority);
|
|
788
|
-
priority++;
|
|
789
|
-
}
|
|
790
|
-
|
|
791
|
-
mDisableTextDiffing = originalDisableTextDiffing;
|
|
792
|
-
}
|
|
793
|
-
|
|
794
860
|
protected boolean showSoftKeyboard() {
|
|
795
861
|
return mInputMethodManager.showSoftInput(this, 0);
|
|
796
862
|
}
|
|
@@ -1060,7 +1126,9 @@ public class ReactEditText extends AppCompatEditText
|
|
|
1060
1126
|
|
|
1061
1127
|
float effectiveLetterSpacing = mTextAttributes.getEffectiveLetterSpacing();
|
|
1062
1128
|
if (!Float.isNaN(effectiveLetterSpacing)) {
|
|
1063
|
-
|
|
1129
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
1130
|
+
setLetterSpacing(effectiveLetterSpacing);
|
|
1131
|
+
}
|
|
1064
1132
|
}
|
|
1065
1133
|
}
|
|
1066
1134
|
|
|
@@ -1075,7 +1143,7 @@ public class ReactEditText extends AppCompatEditText
|
|
|
1075
1143
|
* TextLayoutManager.java with some very minor modifications. There's some duplication between
|
|
1076
1144
|
* here and TextLayoutManager, so there might be an opportunity for refactor.
|
|
1077
1145
|
*/
|
|
1078
|
-
private void updateCachedSpannable(
|
|
1146
|
+
private void updateCachedSpannable() {
|
|
1079
1147
|
// Noops in non-Fabric
|
|
1080
1148
|
if (mFabricViewStateManager == null || !mFabricViewStateManager.hasStateWrapper()) {
|
|
1081
1149
|
return;
|
|
@@ -1085,12 +1153,6 @@ public class ReactEditText extends AppCompatEditText
|
|
|
1085
1153
|
return;
|
|
1086
1154
|
}
|
|
1087
1155
|
|
|
1088
|
-
if (resetStyles) {
|
|
1089
|
-
mIsSettingTextFromCacheUpdate = true;
|
|
1090
|
-
addSpansForMeasurement(getText());
|
|
1091
|
-
mIsSettingTextFromCacheUpdate = false;
|
|
1092
|
-
}
|
|
1093
|
-
|
|
1094
1156
|
Editable currentText = getText();
|
|
1095
1157
|
boolean haveText = currentText != null && currentText.length() > 0;
|
|
1096
1158
|
|
|
@@ -1132,8 +1194,7 @@ public class ReactEditText extends AppCompatEditText
|
|
|
1132
1194
|
// ...
|
|
1133
1195
|
// - android.app.Activity.dispatchKeyEvent (Activity.java:3447)
|
|
1134
1196
|
try {
|
|
1135
|
-
|
|
1136
|
-
unstripAttributeEquivalentSpans(sb, text);
|
|
1197
|
+
sb.append(currentText.subSequence(0, currentText.length()));
|
|
1137
1198
|
} catch (IndexOutOfBoundsException e) {
|
|
1138
1199
|
ReactSoftExceptionLogger.logSoftException(TAG, e);
|
|
1139
1200
|
}
|
|
@@ -1149,11 +1210,9 @@ public class ReactEditText extends AppCompatEditText
|
|
|
1149
1210
|
// Measure something so we have correct height, even if there's no string.
|
|
1150
1211
|
sb.append("I");
|
|
1151
1212
|
}
|
|
1152
|
-
|
|
1153
|
-
// Make sure that all text styles are applied when we're measurable the hint or "blank" text
|
|
1154
|
-
addSpansForMeasurement(sb);
|
|
1155
1213
|
}
|
|
1156
1214
|
|
|
1215
|
+
addSpansFromStyleAttributes(sb);
|
|
1157
1216
|
TextLayoutManager.setCachedSpannabledForTag(getId(), sb);
|
|
1158
1217
|
}
|
|
1159
1218
|
|
|
@@ -1168,7 +1227,7 @@ public class ReactEditText extends AppCompatEditText
|
|
|
1168
1227
|
private class TextWatcherDelegator implements TextWatcher {
|
|
1169
1228
|
@Override
|
|
1170
1229
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
|
1171
|
-
if (!
|
|
1230
|
+
if (!mIsSettingTextFromJS && mListeners != null) {
|
|
1172
1231
|
for (TextWatcher listener : mListeners) {
|
|
1173
1232
|
listener.beforeTextChanged(s, start, count, after);
|
|
1174
1233
|
}
|
|
@@ -1182,23 +1241,20 @@ public class ReactEditText extends AppCompatEditText
|
|
|
1182
1241
|
TAG, "onTextChanged[" + getId() + "]: " + s + " " + start + " " + before + " " + count);
|
|
1183
1242
|
}
|
|
1184
1243
|
|
|
1185
|
-
if (!
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
listener.onTextChanged(s, start, before, count);
|
|
1189
|
-
}
|
|
1244
|
+
if (!mIsSettingTextFromJS && mListeners != null) {
|
|
1245
|
+
for (TextWatcher listener : mListeners) {
|
|
1246
|
+
listener.onTextChanged(s, start, before, count);
|
|
1190
1247
|
}
|
|
1191
|
-
|
|
1192
|
-
updateCachedSpannable(
|
|
1193
|
-
!mIsSettingTextFromJS && !mIsSettingTextFromState && start == 0 && before == 0);
|
|
1194
1248
|
}
|
|
1195
1249
|
|
|
1250
|
+
updateCachedSpannable();
|
|
1251
|
+
|
|
1196
1252
|
onContentSizeChange();
|
|
1197
1253
|
}
|
|
1198
1254
|
|
|
1199
1255
|
@Override
|
|
1200
1256
|
public void afterTextChanged(Editable s) {
|
|
1201
|
-
if (!
|
|
1257
|
+
if (!mIsSettingTextFromJS && mListeners != null) {
|
|
1202
1258
|
for (TextWatcher listener : mListeners) {
|
|
1203
1259
|
listener.afterTextChanged(s);
|
|
1204
1260
|
}
|
package/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java
CHANGED
|
@@ -13,6 +13,7 @@ import android.content.Context;
|
|
|
13
13
|
import android.content.res.ColorStateList;
|
|
14
14
|
import android.graphics.BlendMode;
|
|
15
15
|
import android.graphics.BlendModeColorFilter;
|
|
16
|
+
import android.graphics.Paint;
|
|
16
17
|
import android.graphics.PorterDuff;
|
|
17
18
|
import android.graphics.drawable.Drawable;
|
|
18
19
|
import android.os.Build;
|
|
@@ -68,6 +69,7 @@ import com.facebook.react.views.text.DefaultStyleValuesUtil;
|
|
|
68
69
|
import com.facebook.react.views.text.ReactBaseTextShadowNode;
|
|
69
70
|
import com.facebook.react.views.text.ReactTextUpdate;
|
|
70
71
|
import com.facebook.react.views.text.ReactTextViewManagerCallback;
|
|
72
|
+
import com.facebook.react.views.text.ReactTypefaceUtils;
|
|
71
73
|
import com.facebook.react.views.text.TextAttributeProps;
|
|
72
74
|
import com.facebook.react.views.text.TextInlineImageSpan;
|
|
73
75
|
import com.facebook.react.views.text.TextLayoutManager;
|
|
@@ -412,6 +414,11 @@ public class ReactTextInputManager extends BaseViewManager<ReactEditText, Layout
|
|
|
412
414
|
view.setFontStyle(fontStyle);
|
|
413
415
|
}
|
|
414
416
|
|
|
417
|
+
@ReactProp(name = ViewProps.FONT_VARIANT)
|
|
418
|
+
public void setFontVariant(ReactEditText view, @Nullable ReadableArray fontVariant) {
|
|
419
|
+
view.setFontFeatureSettings(ReactTypefaceUtils.parseFontVariant(fontVariant));
|
|
420
|
+
}
|
|
421
|
+
|
|
415
422
|
@ReactProp(name = ViewProps.INCLUDE_FONT_PADDING, defaultBoolean = true)
|
|
416
423
|
public void setIncludeFontPadding(ReactEditText view, boolean includepad) {
|
|
417
424
|
view.setIncludeFontPadding(includepad);
|
|
@@ -935,6 +942,20 @@ public class ReactTextInputManager extends BaseViewManager<ReactEditText, Layout
|
|
|
935
942
|
view.setAutoFocus(autoFocus);
|
|
936
943
|
}
|
|
937
944
|
|
|
945
|
+
@ReactProp(name = ViewProps.TEXT_DECORATION_LINE)
|
|
946
|
+
public void setTextDecorationLine(ReactEditText view, @Nullable String textDecorationLineString) {
|
|
947
|
+
view.setPaintFlags(
|
|
948
|
+
view.getPaintFlags() & ~(Paint.STRIKE_THRU_TEXT_FLAG | Paint.UNDERLINE_TEXT_FLAG));
|
|
949
|
+
|
|
950
|
+
for (String token : textDecorationLineString.split(" ")) {
|
|
951
|
+
if (token.equals("underline")) {
|
|
952
|
+
view.setPaintFlags(view.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
|
|
953
|
+
} else if (token.equals("line-through")) {
|
|
954
|
+
view.setPaintFlags(view.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
|
|
938
959
|
@ReactPropGroup(
|
|
939
960
|
names = {
|
|
940
961
|
ViewProps.BORDER_WIDTH,
|
|
@@ -1329,9 +1350,6 @@ public class ReactTextInputManager extends BaseViewManager<ReactEditText, Layout
|
|
|
1329
1350
|
TextLayoutManager.getOrCreateSpannableForText(
|
|
1330
1351
|
view.getContext(), attributedString, mReactTextViewManagerCallback);
|
|
1331
1352
|
|
|
1332
|
-
boolean containsMultipleFragments =
|
|
1333
|
-
attributedString.getArray("fragments").toArrayList().size() > 1;
|
|
1334
|
-
|
|
1335
1353
|
int textBreakStrategy =
|
|
1336
1354
|
TextAttributeProps.getTextBreakStrategy(
|
|
1337
1355
|
paragraphAttributes.getString(ViewProps.TEXT_BREAK_STRATEGY));
|
|
@@ -1344,8 +1362,7 @@ public class ReactTextInputManager extends BaseViewManager<ReactEditText, Layout
|
|
|
1344
1362
|
TextAttributeProps.getTextAlignment(
|
|
1345
1363
|
props, TextLayoutManager.isRTL(attributedString), view.getGravityHorizontal()),
|
|
1346
1364
|
textBreakStrategy,
|
|
1347
|
-
TextAttributeProps.getJustificationMode(props, currentJustificationMode)
|
|
1348
|
-
containsMultipleFragments);
|
|
1365
|
+
TextAttributeProps.getJustificationMode(props, currentJustificationMode));
|
|
1349
1366
|
}
|
|
1350
1367
|
|
|
1351
1368
|
public Object getReactTextUpdate(ReactEditText view, ReactStylesDiffMap props, MapBuffer state) {
|
|
@@ -1366,9 +1383,6 @@ public class ReactTextInputManager extends BaseViewManager<ReactEditText, Layout
|
|
|
1366
1383
|
TextLayoutManagerMapBuffer.getOrCreateSpannableForText(
|
|
1367
1384
|
view.getContext(), attributedString, mReactTextViewManagerCallback);
|
|
1368
1385
|
|
|
1369
|
-
boolean containsMultipleFragments =
|
|
1370
|
-
attributedString.getMapBuffer(TextLayoutManagerMapBuffer.AS_KEY_FRAGMENTS).getCount() > 1;
|
|
1371
|
-
|
|
1372
1386
|
int textBreakStrategy =
|
|
1373
1387
|
TextAttributeProps.getTextBreakStrategy(
|
|
1374
1388
|
paragraphAttributes.getString(TextLayoutManagerMapBuffer.PA_KEY_TEXT_BREAK_STRATEGY));
|
|
@@ -1381,7 +1395,6 @@ public class ReactTextInputManager extends BaseViewManager<ReactEditText, Layout
|
|
|
1381
1395
|
TextAttributeProps.getTextAlignment(
|
|
1382
1396
|
props, TextLayoutManagerMapBuffer.isRTL(attributedString), view.getGravityHorizontal()),
|
|
1383
1397
|
textBreakStrategy,
|
|
1384
|
-
TextAttributeProps.getJustificationMode(props, currentJustificationMode)
|
|
1385
|
-
containsMultipleFragments);
|
|
1398
|
+
TextAttributeProps.getJustificationMode(props, currentJustificationMode));
|
|
1386
1399
|
}
|
|
1387
1400
|
}
|
package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundManager.java
CHANGED
|
@@ -19,6 +19,7 @@ public class ReactViewBackgroundManager {
|
|
|
19
19
|
|
|
20
20
|
private @Nullable ReactViewBackgroundDrawable mReactBackgroundDrawable;
|
|
21
21
|
private View mView;
|
|
22
|
+
private int mColor = Color.TRANSPARENT;
|
|
22
23
|
|
|
23
24
|
public ReactViewBackgroundManager(View view) {
|
|
24
25
|
this.mView = view;
|
|
@@ -56,6 +57,10 @@ public class ReactViewBackgroundManager {
|
|
|
56
57
|
}
|
|
57
58
|
}
|
|
58
59
|
|
|
60
|
+
public int getBackgroundColor() {
|
|
61
|
+
return mColor;
|
|
62
|
+
}
|
|
63
|
+
|
|
59
64
|
public void setBorderWidth(int position, float width) {
|
|
60
65
|
getOrCreateReactViewBackground().setBorderWidth(position, width);
|
|
61
66
|
}
|
|
@@ -429,6 +429,9 @@ void Binding::installFabricUIManager(
|
|
|
429
429
|
"CalculateTransformedFramesEnabled",
|
|
430
430
|
getFeatureFlagValue("calculateTransformedFramesEnabled"));
|
|
431
431
|
|
|
432
|
+
CoreFeatures::cacheLastTextMeasurement =
|
|
433
|
+
getFeatureFlagValue("enableTextMeasureCachePerShadowNode");
|
|
434
|
+
|
|
432
435
|
// Props setter pattern feature
|
|
433
436
|
CoreFeatures::enablePropIteratorSetter =
|
|
434
437
|
getFeatureFlagValue("enableCppPropsIteratorSetter");
|
|
@@ -16,7 +16,15 @@ else
|
|
|
16
16
|
source[:tag] = "v#{version}"
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
# We are using two different paths for react native because of the way how js_srcs_dir and output_dir options are used
|
|
20
|
+
# output_dir option usage was introduced in https://github.com/facebook/react-native/pull/36210
|
|
21
|
+
# React-rncore.podspec is the only podspec in the project that uses this option
|
|
22
|
+
# We should rethink this approach in T148704916
|
|
23
|
+
|
|
24
|
+
# Relative path to react native from iOS project root (e.g. <ios-project-root>/../node_modules/react-native)
|
|
25
|
+
react_native_dependency_path = ENV['REACT_NATIVE_PATH']
|
|
26
|
+
# Relative path to react native from current podspec
|
|
27
|
+
react_native_sources_path = '..'
|
|
20
28
|
|
|
21
29
|
Pod::Spec.new do |s|
|
|
22
30
|
s.name = "React-rncore"
|
|
@@ -33,10 +41,10 @@ Pod::Spec.new do |s|
|
|
|
33
41
|
|
|
34
42
|
|
|
35
43
|
use_react_native_codegen!(s, {
|
|
36
|
-
:react_native_path =>
|
|
37
|
-
:js_srcs_dir => "#{
|
|
44
|
+
:react_native_path => react_native_sources_path,
|
|
45
|
+
:js_srcs_dir => "#{react_native_sources_path}/Libraries",
|
|
38
46
|
:library_name => "rncore",
|
|
39
47
|
:library_type => "components",
|
|
40
|
-
:output_dir => "#{
|
|
48
|
+
:output_dir => "#{react_native_dependency_path}/ReactCommon"
|
|
41
49
|
})
|
|
42
50
|
end
|
|
@@ -24,6 +24,9 @@ bool EmptyReactNativeConfig::getBool(const std::string ¶m) const {
|
|
|
24
24
|
if (param == "react_fabric:enabled_layout_animations_ios") {
|
|
25
25
|
return true;
|
|
26
26
|
}
|
|
27
|
+
if (param == "react_fabric:enable_nstextstorage_caching") {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
27
30
|
return false;
|
|
28
31
|
}
|
|
29
32
|
|
|
@@ -33,7 +33,10 @@ typedef void (^InterceptorBlock)(std::string eventName, folly::dynamic event);
|
|
|
33
33
|
|
|
34
34
|
- (NSString *)componentViewName;
|
|
35
35
|
|
|
36
|
-
- (void)handleCommand:(NSString *)commandName
|
|
36
|
+
- (void)handleCommand:(NSString *)commandName
|
|
37
|
+
args:(NSArray *)args
|
|
38
|
+
reactTag:(NSInteger)tag
|
|
39
|
+
paperView:(UIView *)paperView;
|
|
37
40
|
|
|
38
41
|
@end
|
|
39
42
|
|