diff --git a/packages/react-native/Libraries/Components/View/ReactNativeStyleAttributes.js b/packages/react-native/Libraries/Components/View/ReactNativeStyleAttributes.js index e739919845ee..c186586d9a09 100644 --- a/packages/react-native/Libraries/Components/View/ReactNativeStyleAttributes.js +++ b/packages/react-native/Libraries/Components/View/ReactNativeStyleAttributes.js @@ -127,6 +127,11 @@ const ReactNativeStyleAttributes: {[string]: AnyAttributeType, ...} = { */ experimental_mixBlendMode: true, + /** + * Isolation + */ + isolation: true, + /* * BoxShadow */ diff --git a/packages/react-native/Libraries/NativeComponent/BaseViewConfig.android.js b/packages/react-native/Libraries/NativeComponent/BaseViewConfig.android.js index 29f303eec7a5..b8a3a9d57c56 100644 --- a/packages/react-native/Libraries/NativeComponent/BaseViewConfig.android.js +++ b/packages/react-native/Libraries/NativeComponent/BaseViewConfig.android.js @@ -170,6 +170,7 @@ const validAttributesForNonEventProps = { process: require('../StyleSheet/processFilter').default, }, experimental_mixBlendMode: true, + isolation: true, opacity: true, elevation: true, shadowColor: {process: require('../StyleSheet/processColor').default}, diff --git a/packages/react-native/Libraries/NativeComponent/BaseViewConfig.ios.js b/packages/react-native/Libraries/NativeComponent/BaseViewConfig.ios.js index bcea251752de..d2259be0f8e9 100644 --- a/packages/react-native/Libraries/NativeComponent/BaseViewConfig.ios.js +++ b/packages/react-native/Libraries/NativeComponent/BaseViewConfig.ios.js @@ -228,6 +228,8 @@ const validAttributesForNonEventProps = { experimental_boxShadow: { process: require('../StyleSheet/processBoxShadow').default, }, + experimental_mixBlendMode: true, + isolation: true, borderTopWidth: true, borderTopColor: {process: require('../StyleSheet/processColor').default}, diff --git a/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts b/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts index ac67b1901b1c..016c8b860964 100644 --- a/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts +++ b/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts @@ -332,6 +332,7 @@ export interface ViewStyle extends FlexStyle, ShadowStyleIOS, TransformsStyle { * Controls whether the View can be the target of touch events. */ pointerEvents?: 'box-none' | 'none' | 'box-only' | 'auto' | undefined; + isolation?: 'auto' | 'isolate' | undefined; cursor?: CursorValue | undefined; } diff --git a/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js b/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js index c92c63016dc7..16e44fdfaa51 100644 --- a/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js +++ b/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js @@ -792,6 +792,7 @@ export type ____ViewStyle_InternalCore = $ReadOnly<{ experimental_filter?: $ReadOnlyArray | string, experimental_mixBlendMode?: ____BlendMode_Internal, experimental_backgroundImage?: $ReadOnlyArray | string, + isolation?: 'auto' | 'isolate', }>; export type ____ViewStyle_Internal = $ReadOnly<{ diff --git a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap index ad9ca9e408a4..1e2c11f92954 100644 --- a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap +++ b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap @@ -8408,6 +8408,7 @@ export type ____ViewStyle_InternalCore = $ReadOnly<{ experimental_filter?: $ReadOnlyArray | string, experimental_mixBlendMode?: ____BlendMode_Internal, experimental_backgroundImage?: $ReadOnlyArray | string, + isolation?: \\"auto\\" | \\"isolate\\", }>; export type ____ViewStyle_Internal = $ReadOnly<{ ...____ViewStyle_InternalCore, diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 5db9d368c98d..d473412490ff 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -8221,6 +8221,7 @@ public class com/facebook/react/views/view/ReactViewGroup : android/view/ViewGro public fun dispatchGenericMotionEvent (Landroid/view/MotionEvent;)Z public fun dispatchProvideStructure (Landroid/view/ViewStructure;)V protected fun dispatchSetPressed (Z)V + public fun draw (Landroid/graphics/Canvas;)V protected fun drawChild (Landroid/graphics/Canvas;Landroid/view/View;J)Z protected fun getChildDrawingOrder (II)I public fun getChildVisibleRect (Landroid/view/View;Landroid/graphics/Rect;Landroid/graphics/Point;)Z diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt index 275f6fbe871e..81c10d5daea8 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<275859c437f60e7733da2b238c911152>> + * @generated SignedSource<> */ /** @@ -70,6 +70,12 @@ public object ReactNativeFeatureFlags { @JvmStatic public fun enableAlignItemsBaselineOnFabricIOS(): Boolean = accessor.enableAlignItemsBaselineOnFabricIOS() + /** + * Enables mix-blend-mode prop on Android. + */ + @JvmStatic + public fun enableAndroidMixBlendModeProp(): Boolean = accessor.enableAndroidMixBlendModeProp() + /** * Use BackgroundStyleApplicator in place of other background/border drawing code */ diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt index 6c32b6fddcad..d8a31d09c548 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<50f259bf80948b672a8677307456d413>> */ /** @@ -27,6 +27,7 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso private var completeReactInstanceCreationOnBgThreadOnAndroidCache: Boolean? = null private var destroyFabricSurfacesInReactInstanceManagerCache: Boolean? = null private var enableAlignItemsBaselineOnFabricIOSCache: Boolean? = null + private var enableAndroidMixBlendModePropCache: Boolean? = null private var enableBackgroundStyleApplicatorCache: Boolean? = null private var enableCleanTextInputYogaNodeCache: Boolean? = null private var enableEagerRootViewAttachmentCache: Boolean? = null @@ -128,6 +129,15 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso return cached } + override fun enableAndroidMixBlendModeProp(): Boolean { + var cached = enableAndroidMixBlendModePropCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.enableAndroidMixBlendModeProp() + enableAndroidMixBlendModePropCache = cached + } + return cached + } + override fun enableBackgroundStyleApplicator(): Boolean { var cached = enableBackgroundStyleApplicatorCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt index 51ff0117ac27..330dd5442043 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<1d79b037e6e8cf2e7306b7f5b3798b9a>> + * @generated SignedSource<<3b5998555d0f27d3f83923cb516edb36>> */ /** @@ -42,6 +42,8 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun enableAlignItemsBaselineOnFabricIOS(): Boolean + @DoNotStrip @JvmStatic public external fun enableAndroidMixBlendModeProp(): Boolean + @DoNotStrip @JvmStatic public external fun enableBackgroundStyleApplicator(): Boolean @DoNotStrip @JvmStatic public external fun enableCleanTextInputYogaNode(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt index 96948995e2d0..ede54768f509 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<86db65691c73cff2843e81e053268892>> */ /** @@ -37,6 +37,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun enableAlignItemsBaselineOnFabricIOS(): Boolean = true + override fun enableAndroidMixBlendModeProp(): Boolean = false + override fun enableBackgroundStyleApplicator(): Boolean = true override fun enableCleanTextInputYogaNode(): Boolean = false diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt index 903f978fd9f2..8974ba53c5fe 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<408d66cdad8b708c06ca844cd6524ba4>> + * @generated SignedSource<> */ /** @@ -31,6 +31,7 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces private var completeReactInstanceCreationOnBgThreadOnAndroidCache: Boolean? = null private var destroyFabricSurfacesInReactInstanceManagerCache: Boolean? = null private var enableAlignItemsBaselineOnFabricIOSCache: Boolean? = null + private var enableAndroidMixBlendModePropCache: Boolean? = null private var enableBackgroundStyleApplicatorCache: Boolean? = null private var enableCleanTextInputYogaNodeCache: Boolean? = null private var enableEagerRootViewAttachmentCache: Boolean? = null @@ -139,6 +140,16 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces return cached } + override fun enableAndroidMixBlendModeProp(): Boolean { + var cached = enableAndroidMixBlendModePropCache + if (cached == null) { + cached = currentProvider.enableAndroidMixBlendModeProp() + accessedFeatureFlags.add("enableAndroidMixBlendModeProp") + enableAndroidMixBlendModePropCache = cached + } + return cached + } + override fun enableBackgroundStyleApplicator(): Boolean { var cached = enableBackgroundStyleApplicatorCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt index e1db6abce717..4343bc66c3e5 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<040b9cb9cec727e2eb31769712980528>> + * @generated SignedSource<<7260472dccd3ec3c9612727c6c337f24>> */ /** @@ -37,6 +37,8 @@ public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun enableAlignItemsBaselineOnFabricIOS(): Boolean + @DoNotStrip public fun enableAndroidMixBlendModeProp(): Boolean + @DoNotStrip public fun enableBackgroundStyleApplicator(): Boolean @DoNotStrip public fun enableCleanTextInputYogaNode(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java index 5ce62921824b..382055fbc79c 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java @@ -7,7 +7,6 @@ package com.facebook.react.uimanager; -import android.graphics.BlendMode; import android.graphics.Color; import android.graphics.Paint; import android.os.Build; @@ -118,7 +117,8 @@ public BaseViewManager(@Nullable ReactApplicationContext reactContext) { view.setTag(R.id.use_hardware_layer, null); view.setTag(R.id.filter, null); - LayerEffectsHelper.apply(view, null, null, null); + view.setTag(R.id.mix_blend_mode, null); + LayerEffectsHelper.apply(view, null, null); // setShadowColor if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { @@ -522,10 +522,7 @@ public void setAccessibilityLiveRegion(@NonNull T view, @Nullable String liveReg // hitting the unknown BlendMode type private static class LayerEffectsHelper { public static void apply( - @NonNull View view, - @Nullable ReadableArray filter, - @Nullable BlendMode mixBlendMode, - @Nullable Boolean useHWLayer) { + @NonNull View view, @Nullable ReadableArray filter, @Nullable Boolean useHWLayer) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { view.setRenderEffect(null); } @@ -541,11 +538,6 @@ public static void apply( } } - if (mixBlendMode != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - p = p == null ? new Paint() : p; - p.setBlendMode(mixBlendMode); - } - if (p == null) { int layerType = useHWLayer != null && useHWLayer ? View.LAYER_TYPE_HARDWARE : View.LAYER_TYPE_NONE; @@ -666,13 +658,9 @@ protected void onAfterUpdateTransaction(@NonNull T view) { } ReadableArray filter = (ReadableArray) view.getTag(R.id.filter); - BlendMode mixBlendMode = - Build.VERSION.SDK_INT >= Build.VERSION_CODES.S - ? (BlendMode) view.getTag(R.id.mix_blend_mode) - : null; Boolean useHWLayer = (Boolean) view.getTag(R.id.use_hardware_layer); - LayerEffectsHelper.apply(view, filter, mixBlendMode, useHWLayer); + LayerEffectsHelper.apply(view, filter, useHWLayer); } @Override diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BlendModeHelper.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BlendModeHelper.kt index 22fef9a2c9fd..80ccd6f6bf32 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BlendModeHelper.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BlendModeHelper.kt @@ -9,6 +9,7 @@ package com.facebook.react.uimanager import android.annotation.TargetApi import android.graphics.BlendMode +import android.os.Build @TargetApi(29) internal object BlendModeHelper { @@ -16,7 +17,9 @@ internal object BlendModeHelper { /** @see https://www.w3.org/TR/compositing-1/#mix-blend-mode */ @JvmStatic public fun parseMixBlendMode(mixBlendMode: String?): BlendMode? { - mixBlendMode ?: return null + if (mixBlendMode == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { + return null + } return when (mixBlendMode) { "normal" -> null diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java index ec9674e75854..a20a95bd15ad 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java @@ -12,13 +12,16 @@ import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.content.Context; +import android.graphics.BlendMode; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.Paint; import android.graphics.Path; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; +import android.os.Build; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; @@ -27,6 +30,7 @@ import androidx.annotation.Nullable; import com.facebook.common.logging.FLog; import com.facebook.infer.annotation.Assertions; +import com.facebook.react.R; import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactNoCrashSoftException; import com.facebook.react.bridge.ReactSoftExceptionLogger; @@ -819,6 +823,20 @@ private void removeFromArray(int index) { } } + private boolean needsIsolatedLayer() { + if (!ReactNativeFeatureFlags.enableAndroidMixBlendModeProp()) { + return false; + } + + for (int i = 0; i < getChildCount(); i++) { + if (getChildAt(i).getTag(R.id.mix_blend_mode) != null) { + return true; + } + } + + return false; + } + @VisibleForTesting public int getBackgroundColor() { if (ReactNativeFeatureFlags.enableBackgroundStyleApplicator()) { @@ -892,6 +910,13 @@ public void setOverflow(@Nullable String overflow) { @Override public void setOverflowInset(int left, int top, int right, int bottom) { + if (needsIsolatedLayer() + && (mOverflowInset.left != left + || mOverflowInset.top != top + || mOverflowInset.right != right + || mOverflowInset.bottom != bottom)) { + invalidate(); + } mOverflowInset.set(left, top, right, bottom); } @@ -911,6 +936,29 @@ public Rect getOverflowInset() { super.setBackground(drawable); } + @Override + public void draw(Canvas canvas) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q + && ViewUtil.getUIManagerType(this) == UIManagerType.FABRIC + && needsIsolatedLayer()) { + + // Check if the view is a stacking context and has children, if it does, do the rendering + // offscreen and then composite back. This follows the idea of group isolation on blending + // https://www.w3.org/TR/compositing-1/#isolationblending + Rect overflowInset = getOverflowInset(); + canvas.saveLayer( + overflowInset.left, + overflowInset.top, + getWidth() + -overflowInset.right, + getHeight() + -overflowInset.bottom, + null); + super.draw(canvas); + canvas.restore(); + } else { + super.draw(canvas); + } + } + @Override protected void dispatchDraw(Canvas canvas) { if (ReactNativeFeatureFlags.enableBackgroundStyleApplicator()) { @@ -950,8 +998,28 @@ protected boolean drawChild(Canvas canvas, View child, long drawingTime) { CanvasUtil.enableZ(canvas, true); } + BlendMode mixBlendMode = null; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && needsIsolatedLayer()) { + mixBlendMode = (BlendMode) child.getTag(R.id.mix_blend_mode); + if (mixBlendMode != null) { + Paint p = new Paint(); + p.setBlendMode(mixBlendMode); + Rect overflowInset = getOverflowInset(); + canvas.saveLayer( + overflowInset.left, + overflowInset.top, + getWidth() + -overflowInset.right, + getHeight() + -overflowInset.bottom, + p); + } + } + boolean result = super.drawChild(canvas, child, drawingTime); + if (mixBlendMode != null) { + canvas.restore(); + } + if (drawWithZ) { CanvasUtil.enableZ(canvas, false); } diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp index 71924a1f99f7..fb6dfb2ffd4b 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<5847fa577b3396b35e3bd363a5618978>> */ /** @@ -81,6 +81,12 @@ class ReactNativeFeatureFlagsProviderHolder return method(javaProvider_); } + bool enableAndroidMixBlendModeProp() override { + static const auto method = + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enableAndroidMixBlendModeProp"); + return method(javaProvider_); + } + bool enableBackgroundStyleApplicator() override { static const auto method = getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enableBackgroundStyleApplicator"); @@ -342,6 +348,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableAlignItemsBaselineOnFabricIOS( return ReactNativeFeatureFlags::enableAlignItemsBaselineOnFabricIOS(); } +bool JReactNativeFeatureFlagsCxxInterop::enableAndroidMixBlendModeProp( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::enableAndroidMixBlendModeProp(); +} + bool JReactNativeFeatureFlagsCxxInterop::enableBackgroundStyleApplicator( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::enableBackgroundStyleApplicator(); @@ -565,6 +576,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "enableAlignItemsBaselineOnFabricIOS", JReactNativeFeatureFlagsCxxInterop::enableAlignItemsBaselineOnFabricIOS), + makeNativeMethod( + "enableAndroidMixBlendModeProp", + JReactNativeFeatureFlagsCxxInterop::enableAndroidMixBlendModeProp), makeNativeMethod( "enableBackgroundStyleApplicator", JReactNativeFeatureFlagsCxxInterop::enableBackgroundStyleApplicator), diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h index b7274bcde5c3..fc55d3423db6 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<8862dfc0107d61550ec61078928350b6>> */ /** @@ -51,6 +51,9 @@ class JReactNativeFeatureFlagsCxxInterop static bool enableAlignItemsBaselineOnFabricIOS( facebook::jni::alias_ref); + static bool enableAndroidMixBlendModeProp( + facebook::jni::alias_ref); + static bool enableBackgroundStyleApplicator( facebook::jni::alias_ref); diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp index 549658d6f844..977711141014 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<0a5c752e7d7ae1edd9c495dce0557347>> */ /** @@ -49,6 +49,10 @@ bool ReactNativeFeatureFlags::enableAlignItemsBaselineOnFabricIOS() { return getAccessor().enableAlignItemsBaselineOnFabricIOS(); } +bool ReactNativeFeatureFlags::enableAndroidMixBlendModeProp() { + return getAccessor().enableAndroidMixBlendModeProp(); +} + bool ReactNativeFeatureFlags::enableBackgroundStyleApplicator() { return getAccessor().enableBackgroundStyleApplicator(); } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index 656fe5736b5d..1ac9d680e5bf 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<45ae072fb6a0b1ec404b3dc8adc13186>> + * @generated SignedSource<<0f3eb0af6d8f2012fc5169d59d38cbc4>> */ /** @@ -72,6 +72,11 @@ class ReactNativeFeatureFlags { */ RN_EXPORT static bool enableAlignItemsBaselineOnFabricIOS(); + /** + * Enables mix-blend-mode prop on Android. + */ + RN_EXPORT static bool enableAndroidMixBlendModeProp(); + /** * Use BackgroundStyleApplicator in place of other background/border drawing code */ diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index b4f8cf56b2b9..14c8a8db85b0 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<9e7498efd93e3c23b74219b7b30ec851>> + * @generated SignedSource<<1bd4ec2cfe8f5b4b0e714ce6379d4875>> */ /** @@ -155,6 +155,24 @@ bool ReactNativeFeatureFlagsAccessor::enableAlignItemsBaselineOnFabricIOS() { return flagValue.value(); } +bool ReactNativeFeatureFlagsAccessor::enableAndroidMixBlendModeProp() { + auto flagValue = enableAndroidMixBlendModeProp_.load(); + + if (!flagValue.has_value()) { + // This block is not exclusive but it is not necessary. + // If multiple threads try to initialize the feature flag, we would only + // be accessing the provider multiple times but the end state of this + // instance and the returned flag value would be the same. + + markFlagAsAccessed(7, "enableAndroidMixBlendModeProp"); + + flagValue = currentProvider_->enableAndroidMixBlendModeProp(); + enableAndroidMixBlendModeProp_ = flagValue; + } + + return flagValue.value(); +} + bool ReactNativeFeatureFlagsAccessor::enableBackgroundStyleApplicator() { auto flagValue = enableBackgroundStyleApplicator_.load(); @@ -164,7 +182,7 @@ bool ReactNativeFeatureFlagsAccessor::enableBackgroundStyleApplicator() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(7, "enableBackgroundStyleApplicator"); + markFlagAsAccessed(8, "enableBackgroundStyleApplicator"); flagValue = currentProvider_->enableBackgroundStyleApplicator(); enableBackgroundStyleApplicator_ = flagValue; @@ -182,7 +200,7 @@ bool ReactNativeFeatureFlagsAccessor::enableCleanTextInputYogaNode() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(8, "enableCleanTextInputYogaNode"); + markFlagAsAccessed(9, "enableCleanTextInputYogaNode"); flagValue = currentProvider_->enableCleanTextInputYogaNode(); enableCleanTextInputYogaNode_ = flagValue; @@ -200,7 +218,7 @@ bool ReactNativeFeatureFlagsAccessor::enableEagerRootViewAttachment() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(9, "enableEagerRootViewAttachment"); + markFlagAsAccessed(10, "enableEagerRootViewAttachment"); flagValue = currentProvider_->enableEagerRootViewAttachment(); enableEagerRootViewAttachment_ = flagValue; @@ -218,7 +236,7 @@ bool ReactNativeFeatureFlagsAccessor::enableEventEmitterRetentionDuringGesturesO // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(10, "enableEventEmitterRetentionDuringGesturesOnAndroid"); + markFlagAsAccessed(11, "enableEventEmitterRetentionDuringGesturesOnAndroid"); flagValue = currentProvider_->enableEventEmitterRetentionDuringGesturesOnAndroid(); enableEventEmitterRetentionDuringGesturesOnAndroid_ = flagValue; @@ -236,7 +254,7 @@ bool ReactNativeFeatureFlagsAccessor::enableFabricLogs() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(11, "enableFabricLogs"); + markFlagAsAccessed(12, "enableFabricLogs"); flagValue = currentProvider_->enableFabricLogs(); enableFabricLogs_ = flagValue; @@ -254,7 +272,7 @@ bool ReactNativeFeatureFlagsAccessor::enableFabricRendererExclusively() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(12, "enableFabricRendererExclusively"); + markFlagAsAccessed(13, "enableFabricRendererExclusively"); flagValue = currentProvider_->enableFabricRendererExclusively(); enableFabricRendererExclusively_ = flagValue; @@ -272,7 +290,7 @@ bool ReactNativeFeatureFlagsAccessor::enableGranularShadowTreeStateReconciliatio // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(13, "enableGranularShadowTreeStateReconciliation"); + markFlagAsAccessed(14, "enableGranularShadowTreeStateReconciliation"); flagValue = currentProvider_->enableGranularShadowTreeStateReconciliation(); enableGranularShadowTreeStateReconciliation_ = flagValue; @@ -290,7 +308,7 @@ bool ReactNativeFeatureFlagsAccessor::enableLongTaskAPI() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(14, "enableLongTaskAPI"); + markFlagAsAccessed(15, "enableLongTaskAPI"); flagValue = currentProvider_->enableLongTaskAPI(); enableLongTaskAPI_ = flagValue; @@ -308,7 +326,7 @@ bool ReactNativeFeatureFlagsAccessor::enableMicrotasks() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(15, "enableMicrotasks"); + markFlagAsAccessed(16, "enableMicrotasks"); flagValue = currentProvider_->enableMicrotasks(); enableMicrotasks_ = flagValue; @@ -326,7 +344,7 @@ bool ReactNativeFeatureFlagsAccessor::enablePropsUpdateReconciliationAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(16, "enablePropsUpdateReconciliationAndroid"); + markFlagAsAccessed(17, "enablePropsUpdateReconciliationAndroid"); flagValue = currentProvider_->enablePropsUpdateReconciliationAndroid(); enablePropsUpdateReconciliationAndroid_ = flagValue; @@ -344,7 +362,7 @@ bool ReactNativeFeatureFlagsAccessor::enableReportEventPaintTime() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(17, "enableReportEventPaintTime"); + markFlagAsAccessed(18, "enableReportEventPaintTime"); flagValue = currentProvider_->enableReportEventPaintTime(); enableReportEventPaintTime_ = flagValue; @@ -362,7 +380,7 @@ bool ReactNativeFeatureFlagsAccessor::enableSynchronousStateUpdates() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(18, "enableSynchronousStateUpdates"); + markFlagAsAccessed(19, "enableSynchronousStateUpdates"); flagValue = currentProvider_->enableSynchronousStateUpdates(); enableSynchronousStateUpdates_ = flagValue; @@ -380,7 +398,7 @@ bool ReactNativeFeatureFlagsAccessor::enableUIConsistency() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(19, "enableUIConsistency"); + markFlagAsAccessed(20, "enableUIConsistency"); flagValue = currentProvider_->enableUIConsistency(); enableUIConsistency_ = flagValue; @@ -398,7 +416,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecycling() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(20, "enableViewRecycling"); + markFlagAsAccessed(21, "enableViewRecycling"); flagValue = currentProvider_->enableViewRecycling(); enableViewRecycling_ = flagValue; @@ -416,7 +434,7 @@ bool ReactNativeFeatureFlagsAccessor::excludeYogaFromRawProps() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(21, "excludeYogaFromRawProps"); + markFlagAsAccessed(22, "excludeYogaFromRawProps"); flagValue = currentProvider_->excludeYogaFromRawProps(); excludeYogaFromRawProps_ = flagValue; @@ -434,7 +452,7 @@ bool ReactNativeFeatureFlagsAccessor::fetchImagesInViewPreallocation() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(22, "fetchImagesInViewPreallocation"); + markFlagAsAccessed(23, "fetchImagesInViewPreallocation"); flagValue = currentProvider_->fetchImagesInViewPreallocation(); fetchImagesInViewPreallocation_ = flagValue; @@ -452,7 +470,7 @@ bool ReactNativeFeatureFlagsAccessor::fixIncorrectScrollViewStateUpdateOnAndroid // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(23, "fixIncorrectScrollViewStateUpdateOnAndroid"); + markFlagAsAccessed(24, "fixIncorrectScrollViewStateUpdateOnAndroid"); flagValue = currentProvider_->fixIncorrectScrollViewStateUpdateOnAndroid(); fixIncorrectScrollViewStateUpdateOnAndroid_ = flagValue; @@ -470,7 +488,7 @@ bool ReactNativeFeatureFlagsAccessor::fixMappingOfEventPrioritiesBetweenFabricAn // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(24, "fixMappingOfEventPrioritiesBetweenFabricAndReact"); + markFlagAsAccessed(25, "fixMappingOfEventPrioritiesBetweenFabricAndReact"); flagValue = currentProvider_->fixMappingOfEventPrioritiesBetweenFabricAndReact(); fixMappingOfEventPrioritiesBetweenFabricAndReact_ = flagValue; @@ -488,7 +506,7 @@ bool ReactNativeFeatureFlagsAccessor::fixMissedFabricStateUpdatesOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(25, "fixMissedFabricStateUpdatesOnAndroid"); + markFlagAsAccessed(26, "fixMissedFabricStateUpdatesOnAndroid"); flagValue = currentProvider_->fixMissedFabricStateUpdatesOnAndroid(); fixMissedFabricStateUpdatesOnAndroid_ = flagValue; @@ -506,7 +524,7 @@ bool ReactNativeFeatureFlagsAccessor::forceBatchingMountItemsOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(26, "forceBatchingMountItemsOnAndroid"); + markFlagAsAccessed(27, "forceBatchingMountItemsOnAndroid"); flagValue = currentProvider_->forceBatchingMountItemsOnAndroid(); forceBatchingMountItemsOnAndroid_ = flagValue; @@ -524,7 +542,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxEnabledDebug() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(27, "fuseboxEnabledDebug"); + markFlagAsAccessed(28, "fuseboxEnabledDebug"); flagValue = currentProvider_->fuseboxEnabledDebug(); fuseboxEnabledDebug_ = flagValue; @@ -542,7 +560,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxEnabledRelease() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(28, "fuseboxEnabledRelease"); + markFlagAsAccessed(29, "fuseboxEnabledRelease"); flagValue = currentProvider_->fuseboxEnabledRelease(); fuseboxEnabledRelease_ = flagValue; @@ -560,7 +578,7 @@ bool ReactNativeFeatureFlagsAccessor::initEagerTurboModulesOnNativeModulesQueueA // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(29, "initEagerTurboModulesOnNativeModulesQueueAndroid"); + markFlagAsAccessed(30, "initEagerTurboModulesOnNativeModulesQueueAndroid"); flagValue = currentProvider_->initEagerTurboModulesOnNativeModulesQueueAndroid(); initEagerTurboModulesOnNativeModulesQueueAndroid_ = flagValue; @@ -578,7 +596,7 @@ bool ReactNativeFeatureFlagsAccessor::lazyAnimationCallbacks() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(30, "lazyAnimationCallbacks"); + markFlagAsAccessed(31, "lazyAnimationCallbacks"); flagValue = currentProvider_->lazyAnimationCallbacks(); lazyAnimationCallbacks_ = flagValue; @@ -596,7 +614,7 @@ bool ReactNativeFeatureFlagsAccessor::loadVectorDrawablesOnImages() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(31, "loadVectorDrawablesOnImages"); + markFlagAsAccessed(32, "loadVectorDrawablesOnImages"); flagValue = currentProvider_->loadVectorDrawablesOnImages(); loadVectorDrawablesOnImages_ = flagValue; @@ -614,7 +632,7 @@ bool ReactNativeFeatureFlagsAccessor::setAndroidLayoutDirection() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(32, "setAndroidLayoutDirection"); + markFlagAsAccessed(33, "setAndroidLayoutDirection"); flagValue = currentProvider_->setAndroidLayoutDirection(); setAndroidLayoutDirection_ = flagValue; @@ -632,7 +650,7 @@ bool ReactNativeFeatureFlagsAccessor::traceTurboModulePromiseRejectionsOnAndroid // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(33, "traceTurboModulePromiseRejectionsOnAndroid"); + markFlagAsAccessed(34, "traceTurboModulePromiseRejectionsOnAndroid"); flagValue = currentProvider_->traceTurboModulePromiseRejectionsOnAndroid(); traceTurboModulePromiseRejectionsOnAndroid_ = flagValue; @@ -650,7 +668,7 @@ bool ReactNativeFeatureFlagsAccessor::useFabricInterop() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(34, "useFabricInterop"); + markFlagAsAccessed(35, "useFabricInterop"); flagValue = currentProvider_->useFabricInterop(); useFabricInterop_ = flagValue; @@ -668,7 +686,7 @@ bool ReactNativeFeatureFlagsAccessor::useImmediateExecutorInAndroidBridgeless() // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(35, "useImmediateExecutorInAndroidBridgeless"); + markFlagAsAccessed(36, "useImmediateExecutorInAndroidBridgeless"); flagValue = currentProvider_->useImmediateExecutorInAndroidBridgeless(); useImmediateExecutorInAndroidBridgeless_ = flagValue; @@ -686,7 +704,7 @@ bool ReactNativeFeatureFlagsAccessor::useModernRuntimeScheduler() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(36, "useModernRuntimeScheduler"); + markFlagAsAccessed(37, "useModernRuntimeScheduler"); flagValue = currentProvider_->useModernRuntimeScheduler(); useModernRuntimeScheduler_ = flagValue; @@ -704,7 +722,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeViewConfigsInBridgelessMode() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(37, "useNativeViewConfigsInBridgelessMode"); + markFlagAsAccessed(38, "useNativeViewConfigsInBridgelessMode"); flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode(); useNativeViewConfigsInBridgelessMode_ = flagValue; @@ -722,7 +740,7 @@ bool ReactNativeFeatureFlagsAccessor::useNewReactImageViewBackgroundDrawing() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(38, "useNewReactImageViewBackgroundDrawing"); + markFlagAsAccessed(39, "useNewReactImageViewBackgroundDrawing"); flagValue = currentProvider_->useNewReactImageViewBackgroundDrawing(); useNewReactImageViewBackgroundDrawing_ = flagValue; @@ -740,7 +758,7 @@ bool ReactNativeFeatureFlagsAccessor::useOptimisedViewPreallocationOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(39, "useOptimisedViewPreallocationOnAndroid"); + markFlagAsAccessed(40, "useOptimisedViewPreallocationOnAndroid"); flagValue = currentProvider_->useOptimisedViewPreallocationOnAndroid(); useOptimisedViewPreallocationOnAndroid_ = flagValue; @@ -758,7 +776,7 @@ bool ReactNativeFeatureFlagsAccessor::useRuntimeShadowNodeReferenceUpdate() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(40, "useRuntimeShadowNodeReferenceUpdate"); + markFlagAsAccessed(41, "useRuntimeShadowNodeReferenceUpdate"); flagValue = currentProvider_->useRuntimeShadowNodeReferenceUpdate(); useRuntimeShadowNodeReferenceUpdate_ = flagValue; @@ -776,7 +794,7 @@ bool ReactNativeFeatureFlagsAccessor::useRuntimeShadowNodeReferenceUpdateOnLayou // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(41, "useRuntimeShadowNodeReferenceUpdateOnLayout"); + markFlagAsAccessed(42, "useRuntimeShadowNodeReferenceUpdateOnLayout"); flagValue = currentProvider_->useRuntimeShadowNodeReferenceUpdateOnLayout(); useRuntimeShadowNodeReferenceUpdateOnLayout_ = flagValue; @@ -794,7 +812,7 @@ bool ReactNativeFeatureFlagsAccessor::useStateAlignmentMechanism() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(42, "useStateAlignmentMechanism"); + markFlagAsAccessed(43, "useStateAlignmentMechanism"); flagValue = currentProvider_->useStateAlignmentMechanism(); useStateAlignmentMechanism_ = flagValue; @@ -812,7 +830,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModuleInterop() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(43, "useTurboModuleInterop"); + markFlagAsAccessed(44, "useTurboModuleInterop"); flagValue = currentProvider_->useTurboModuleInterop(); useTurboModuleInterop_ = flagValue; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h index 7471b7d91fe0..c698c81cdee4 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -38,6 +38,7 @@ class ReactNativeFeatureFlagsAccessor { bool completeReactInstanceCreationOnBgThreadOnAndroid(); bool destroyFabricSurfacesInReactInstanceManager(); bool enableAlignItemsBaselineOnFabricIOS(); + bool enableAndroidMixBlendModeProp(); bool enableBackgroundStyleApplicator(); bool enableCleanTextInputYogaNode(); bool enableEagerRootViewAttachment(); @@ -85,7 +86,7 @@ class ReactNativeFeatureFlagsAccessor { std::unique_ptr currentProvider_; bool wasOverridden_; - std::array, 44> accessedFeatureFlags_; + std::array, 45> accessedFeatureFlags_; std::atomic> commonTestFlag_; std::atomic> allowRecursiveCommitsWithSynchronousMountOnAndroid_; @@ -94,6 +95,7 @@ class ReactNativeFeatureFlagsAccessor { std::atomic> completeReactInstanceCreationOnBgThreadOnAndroid_; std::atomic> destroyFabricSurfacesInReactInstanceManager_; std::atomic> enableAlignItemsBaselineOnFabricIOS_; + std::atomic> enableAndroidMixBlendModeProp_; std::atomic> enableBackgroundStyleApplicator_; std::atomic> enableCleanTextInputYogaNode_; std::atomic> enableEagerRootViewAttachment_; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index 34dc9784a07f..c485548a317e 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<5984a783c431c11b00c2dd8321432235>> + * @generated SignedSource<> */ /** @@ -55,6 +55,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return true; } + bool enableAndroidMixBlendModeProp() override { + return false; + } + bool enableBackgroundStyleApplicator() override { return true; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index 1e7392fdba31..ebe5adb77169 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<362ab4dfd19d6f3189b3c3e5aafd009a>> + * @generated SignedSource<> */ /** @@ -32,6 +32,7 @@ class ReactNativeFeatureFlagsProvider { virtual bool completeReactInstanceCreationOnBgThreadOnAndroid() = 0; virtual bool destroyFabricSurfacesInReactInstanceManager() = 0; virtual bool enableAlignItemsBaselineOnFabricIOS() = 0; + virtual bool enableAndroidMixBlendModeProp() = 0; virtual bool enableBackgroundStyleApplicator() = 0; virtual bool enableCleanTextInputYogaNode() = 0; virtual bool enableEagerRootViewAttachment() = 0; diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index 56b406deca47..8cbd8b10ba58 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<64011b082abd3a72e5da2b933d5b4691>> */ /** @@ -72,6 +72,11 @@ bool NativeReactNativeFeatureFlags::enableAlignItemsBaselineOnFabricIOS( return ReactNativeFeatureFlags::enableAlignItemsBaselineOnFabricIOS(); } +bool NativeReactNativeFeatureFlags::enableAndroidMixBlendModeProp( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::enableAndroidMixBlendModeProp(); +} + bool NativeReactNativeFeatureFlags::enableBackgroundStyleApplicator( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::enableBackgroundStyleApplicator(); diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index 4bc9ec789057..7ca04034e0fb 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<6b0ad22b5e8302c1d4b0dae4d1f2eb19>> + * @generated SignedSource<<23af9284953b14cb18ff1ad71145c29b>> */ /** @@ -49,6 +49,8 @@ class NativeReactNativeFeatureFlags bool enableAlignItemsBaselineOnFabricIOS(jsi::Runtime& runtime); + bool enableAndroidMixBlendModeProp(jsi::Runtime& runtime); + bool enableBackgroundStyleApplicator(jsi::Runtime& runtime); bool enableCleanTextInputYogaNode(jsi::Runtime& runtime); diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp index f23240ec914b..8228b501f659 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp @@ -184,6 +184,14 @@ BaseViewProps::BaseViewProps( "experimental_mixBlendMode", sourceProps.mixBlendMode, {})), + isolation( + CoreFeatures::enablePropIteratorSetter ? sourceProps.isolation + : convertRawProp( + context, + rawProps, + "isolation", + sourceProps.isolation, + {})), transform( CoreFeatures::enablePropIteratorSetter ? sourceProps.transform : convertRawProp( @@ -330,6 +338,7 @@ void BaseViewProps::setProp( RAW_SET_PROP_SWITCH_CASE_BASIC(shouldRasterize); RAW_SET_PROP_SWITCH_CASE_BASIC(zIndex); RAW_SET_PROP_SWITCH_CASE_BASIC(pointerEvents); + RAW_SET_PROP_SWITCH_CASE_BASIC(isolation); RAW_SET_PROP_SWITCH_CASE_BASIC(hitSlop); RAW_SET_PROP_SWITCH_CASE_BASIC(onLayout); RAW_SET_PROP_SWITCH_CASE_BASIC(collapsable); diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.h b/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.h index 1e37eec1d697..edc01556c914 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -68,7 +69,10 @@ class BaseViewProps : public YogaStylableProps, public AccessibilityProps { std::vector backgroundImage{}; // MixBlendMode - BlendMode mixBlendMode; + BlendMode mixBlendMode{BlendMode::Normal}; + + // Isolate + Isolation isolation{Isolation::Auto}; // Transform Transform transform{}; diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp index 49099f87ef7e..ef13a094524f 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp @@ -63,6 +63,7 @@ void ViewShadowNode::initialize() noexcept { viewProps.removeClippedSubviews || viewProps.cursor != Cursor::Auto || !viewProps.filter.empty() || viewProps.mixBlendMode != BlendMode::Normal || + viewProps.isolation == Isolation::Isolate || HostPlatformViewTraitsInitializer::formsStackingContext(viewProps); bool formsView = formsStackingContext || 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 fdb4251b16e3..6681c69dfeb9 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -1184,6 +1185,27 @@ inline void fromRawValue( result = backgroundImage; } +inline void fromRawValue( + const PropsParserContext& /*context*/, + const RawValue& value, + Isolation& result) { + react_native_expect(value.hasType()); + result = Isolation::Auto; + if (!value.hasType()) { + return; + } + + auto rawIsolation = static_cast(value); + std::optional isolation = isolationFromString(rawIsolation); + + if (!isolation) { + LOG(ERROR) << "Could not parse isolation: " << rawIsolation; + return; + } + + result = isolation.value(); +} + template inline std::string toString(const std::array vec) { std::string s; diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/BlendMode.h b/packages/react-native/ReactCommon/react/renderer/graphics/BlendMode.h index 9399ff8e4b52..1afd7864f1ff 100644 --- a/packages/react-native/ReactCommon/react/renderer/graphics/BlendMode.h +++ b/packages/react-native/ReactCommon/react/renderer/graphics/BlendMode.h @@ -7,12 +7,8 @@ #pragma once -#include - #include -#include #include -#include namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/Isolation.h b/packages/react-native/ReactCommon/react/renderer/graphics/Isolation.h new file mode 100644 index 000000000000..941c4a1c28ab --- /dev/null +++ b/packages/react-native/ReactCommon/react/renderer/graphics/Isolation.h @@ -0,0 +1,31 @@ +/* + * 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 +#include + +namespace facebook::react { + +// https://www.w3.org/TR/compositing-1/#isolation +enum class Isolation { + Auto, + Isolate, +}; + +inline std::optional isolationFromString( + std::string_view isolationSetting) { + if (isolationSetting == "auto") { + return Isolation::Auto; + } else if (isolationSetting == "isolate") { + return Isolation::Isolate; + } else { + return std::nullopt; + } +} +} // namespace facebook::react diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index 2bb8924b9b6f..fef861070dd7 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -69,6 +69,10 @@ const definitions: FeatureFlagDefinitions = { description: 'Kill-switch to turn off support for aling-items:baseline on Fabric iOS.', }, + enableAndroidMixBlendModeProp: { + defaultValue: false, + description: 'Enables mix-blend-mode prop on Android.', + }, enableBackgroundStyleApplicator: { defaultValue: true, description: diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index 3d2ac1398e0f..35ff6f739edb 100644 --- a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<600cf82829a6912271f0e5d4cde3f9c8>> + * @generated SignedSource<> * @flow strict-local */ @@ -52,6 +52,7 @@ export type ReactNativeFeatureFlags = { completeReactInstanceCreationOnBgThreadOnAndroid: Getter, destroyFabricSurfacesInReactInstanceManager: Getter, enableAlignItemsBaselineOnFabricIOS: Getter, + enableAndroidMixBlendModeProp: Getter, enableBackgroundStyleApplicator: Getter, enableCleanTextInputYogaNode: Getter, enableEagerRootViewAttachment: Getter, @@ -184,6 +185,10 @@ export const destroyFabricSurfacesInReactInstanceManager: Getter = crea * Kill-switch to turn off support for aling-items:baseline on Fabric iOS. */ export const enableAlignItemsBaselineOnFabricIOS: Getter = createNativeFlagGetter('enableAlignItemsBaselineOnFabricIOS', true); +/** + * Enables mix-blend-mode prop on Android. + */ +export const enableAndroidMixBlendModeProp: Getter = createNativeFlagGetter('enableAndroidMixBlendModeProp', false); /** * Use BackgroundStyleApplicator in place of other background/border drawing code */ diff --git a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js index 97b556181a94..2bc7c7f7010b 100644 --- a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<9728234e0662758c72ba79b3cffbd4e5>> * @flow strict-local */ @@ -30,6 +30,7 @@ export interface Spec extends TurboModule { +completeReactInstanceCreationOnBgThreadOnAndroid?: () => boolean; +destroyFabricSurfacesInReactInstanceManager?: () => boolean; +enableAlignItemsBaselineOnFabricIOS?: () => boolean; + +enableAndroidMixBlendModeProp?: () => boolean; +enableBackgroundStyleApplicator?: () => boolean; +enableCleanTextInputYogaNode?: () => boolean; +enableEagerRootViewAttachment?: () => boolean; diff --git a/packages/rn-tester/js/assets/rubber-ducky.png b/packages/rn-tester/js/assets/rubber-ducky.png new file mode 100644 index 000000000000..7ea75f9a25ed Binary files /dev/null and b/packages/rn-tester/js/assets/rubber-ducky.png differ diff --git a/packages/rn-tester/js/examples/MixBlendMode/MixBlendModeExample.js b/packages/rn-tester/js/examples/MixBlendMode/MixBlendModeExample.js index 29e794738faa..c1c208db313d 100644 --- a/packages/rn-tester/js/examples/MixBlendMode/MixBlendModeExample.js +++ b/packages/rn-tester/js/examples/MixBlendMode/MixBlendModeExample.js @@ -24,14 +24,18 @@ function LayeredView(props: Props) { return ( <> - - - - Hello, World! + + + + + Hello, World! + - + ); @@ -54,6 +58,22 @@ function LayeredImage(props: Props) { ); } +function LayeredViewWithState(props: Props): React.Node { + const [s, setS] = React.useState(true); + setTimeout(() => setS(!s), 5000); + + return ; +} + +function LayeredImageWithState(props: Props): React.Node { + const [s, setS] = React.useState(true); + setTimeout(() => setS(!s), 5000); + + return ( + + ); +} + const styles = StyleSheet.create({ commonImage: { width: 200, @@ -65,9 +85,19 @@ const styles = StyleSheet.create({ flexDirection: 'row', justifyContent: 'space-around', }, + duckContainer: { + alignSelf: 'center', + width: 150, + height: 165, + backgroundColor: 'lime', + }, + duck: { + width: '100%', + height: '100%', + }, backdrop: { - opacity: 0.99, // Creating stacking context height: 110, + width: 110, }, commonView: { backgroundColor: 'cyan', @@ -108,7 +138,7 @@ const examples: Array = mixBlendModes.map(mode => ({ name: mode, render(): React.Node { return ( - + @@ -116,6 +146,167 @@ const examples: Array = mixBlendModes.map(mode => ({ }, })); +examples.push( + { + title: 'Text mix-blend-mode', + description: 'mix-blend-mode: Text mix-blend-mode', + name: 'text', + render(): React.Node { + return ( + + + 'OVERLAY' BLENDING ON TEXT + + + ); + }, + }, + { + title: 'Spec Example 1', + description: 'mix-blend-mode: Spec Example 1', + name: 'spec-example-1', + render(): React.Node { + return ( + + + + ); + }, + }, + { + title: 'Spec Example 2', + description: 'mix-blend-mode: Spec Example 2', + name: 'spec-example-2', + render(): React.Node { + return ( + + + + + + + + + ); + }, + }, + { + title: 'Spec Example 3', + description: 'mix-blend-mode: Spec Example 3', + name: 'spec-example-3', + render(): React.Node { + return ( + + + + + + ); + }, + }, + { + title: 'mix-blend-mode with state updates', + description: 'Turn mix-blend-mode difference on and off every 5 seconds', + render(): React.Node { + return ( + + + + + ); + }, + }, + { + title: 'mix-blend-mode & filter', + description: 'mix-blend-mode & filter', + name: 'mix-blend-mode-filter', + render(): React.Node { + return ( + + + + + ); + }, + }, +); + exports.title = 'MixBlendMode'; exports.category = 'UI'; exports.description =