Add edge-to-edge opt-in support (#52088)

Summary:
This follows https://github.com/facebook/react-native/pull/47554

Compared to the initial proposal, I had to remove the `edgeToEdgeEnabled` property from the root `gradle.properties` and put it in the app `gradle.properties` instead (explaining the `AgpConfiguratorUtils.kt` / `GenerateEntryPointTask.kt` / `ProjectUtils.kt` / `PropertyUtils.kt` changes)

This PR:
- Enable edge-to-edge for `MainActivity` (when `edgeToEdgeEnabled` is set to `true`)
- Disable `StatusBar` `backgroundColor` and `translucent` (when `edgeToEdgeEnabled` is set to `true`)
- Enforce `statusBarTranslucent` and `navigationBarTranslucent` on `Modal` when edge-to-edge is enabled
- Add an `isEdgeToEdge` constant to `DeviceInfoModule` for [`react-native-is-edge-to-edge`](https://github.com/zoontek/react-native-edge-to-edge/tree/main/react-native-is-edge-to-edge) detection

## Changelog:

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->

- [Android] [Added] - Add edge-to-edge opt-in support

Pull Request resolved: https://github.com/facebook/react-native/pull/52088

Test Plan:
- Update `enableEdgeToEdge` value in `packages/rn-tester/android/app/gradle.properties`
- Recompile

https://github.com/user-attachments/assets/4c6beb98-fa88-427c-b62d-a42ffe5330f0

Rollback Plan:

Reviewed By: cortinico

Differential Revision: D76834213

Pulled By: alanleedev

fbshipit-source-id: c39b2cff1a5e94e31306e3b35651aa2de83d2fe6
This commit is contained in:
Mathieu Acthernoene
2025-06-27 06:16:23 -07:00
committed by Facebook GitHub Bot
parent 78c9671c24
commit 09ef774ff6
17 changed files with 200 additions and 54 deletions
@@ -70,6 +70,7 @@ abstract class GenerateEntryPointTask : DefaultTask() {
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger;
import com.facebook.react.views.view.WindowUtilKt;
import com.facebook.react.soloader.OpenSourceMergedSoMapping;
import com.facebook.soloader.SoLoader;
@@ -93,6 +94,10 @@ abstract class GenerateEntryPointTask : DefaultTask() {
if ({{packageName}}.BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
DefaultNewArchitectureEntryPoint.load();
}
if ({{packageName}}.BuildConfig.IS_EDGE_TO_EDGE_ENABLED) {
WindowUtilKt.setEdgeToEdgeFeatureFlagOn();
}
}
}
"""
@@ -11,6 +11,7 @@ import com.android.build.api.variant.ApplicationAndroidComponentsExtension
import com.android.build.api.variant.LibraryAndroidComponentsExtension
import com.android.build.gradle.LibraryExtension
import com.facebook.react.ReactExtension
import com.facebook.react.utils.ProjectUtils.isEdgeToEdgeEnabled
import com.facebook.react.utils.ProjectUtils.isHermesEnabled
import com.facebook.react.utils.ProjectUtils.isNewArchEnabled
import java.io.File
@@ -39,6 +40,8 @@ internal object AgpConfiguratorUtils {
project.isNewArchEnabled(extension).toString())
ext.defaultConfig.buildConfigField(
"boolean", "IS_HERMES_ENABLED", project.isHermesEnabled.toString())
ext.defaultConfig.buildConfigField(
"boolean", "IS_EDGE_TO_EDGE_ENABLED", project.isEdgeToEdgeEnabled.toString())
}
}
project.pluginManager.withPlugin("com.android.application", action)
@@ -11,9 +11,11 @@ import com.facebook.react.ReactExtension
import com.facebook.react.model.ModelPackageJson
import com.facebook.react.utils.KotlinStdlibCompatUtils.lowercaseCompat
import com.facebook.react.utils.KotlinStdlibCompatUtils.toBooleanStrictOrNullCompat
import com.facebook.react.utils.PropertyUtils.EDGE_TO_EDGE_ENABLED
import com.facebook.react.utils.PropertyUtils.HERMES_ENABLED
import com.facebook.react.utils.PropertyUtils.NEW_ARCH_ENABLED
import com.facebook.react.utils.PropertyUtils.REACT_NATIVE_ARCHITECTURES
import com.facebook.react.utils.PropertyUtils.SCOPED_EDGE_TO_EDGE_ENABLED
import com.facebook.react.utils.PropertyUtils.SCOPED_HERMES_ENABLED
import com.facebook.react.utils.PropertyUtils.SCOPED_NEW_ARCH_ENABLED
import com.facebook.react.utils.PropertyUtils.SCOPED_REACT_NATIVE_ARCHITECTURES
@@ -59,6 +61,13 @@ internal object ProjectUtils {
HERMES_FALLBACK
}
internal val Project.isEdgeToEdgeEnabled: Boolean
get() =
(project.hasProperty(EDGE_TO_EDGE_ENABLED) &&
project.property(EDGE_TO_EDGE_ENABLED).toString().toBoolean()) ||
(project.hasProperty(SCOPED_EDGE_TO_EDGE_ENABLED) &&
project.property(SCOPED_EDGE_TO_EDGE_ENABLED).toString().toBoolean())
internal val Project.useThirdPartyJSC: Boolean
get() =
(project.hasProperty(USE_THIRD_PARTY_JSC) &&
@@ -14,10 +14,14 @@ object PropertyUtils {
const val NEW_ARCH_ENABLED = "newArchEnabled"
const val SCOPED_NEW_ARCH_ENABLED = "react.newArchEnabled"
/** Public property that toggles the New Architecture */
/** Public property that toggles Hermes */
const val HERMES_ENABLED = "hermesEnabled"
const val SCOPED_HERMES_ENABLED = "react.hermesEnabled"
/** Public property that toggles edge-to-edge */
const val EDGE_TO_EDGE_ENABLED = "edgeToEdgeEnabled"
const val SCOPED_EDGE_TO_EDGE_ENABLED = "react.edgeToEdgeEnabled"
/** Public property that excludes jsctooling from core */
const val USE_THIRD_PARTY_JSC = "useThirdPartyJSC"
const val SCOPED_USE_THIRD_PARTY_JSC = "react.useThirdPartyJSC"
@@ -55,6 +55,7 @@ class GenerateEntryPointTaskTest {
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger;
import com.facebook.react.views.view.WindowUtilKt;
import com.facebook.react.soloader.OpenSourceMergedSoMapping;
import com.facebook.soloader.SoLoader;
@@ -78,6 +79,10 @@ class GenerateEntryPointTaskTest {
if (com.facebook.react.BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
DefaultNewArchitectureEntryPoint.load();
}
if (com.facebook.react.BuildConfig.IS_EDGE_TO_EDGE_ENABLED) {
WindowUtilKt.setEdgeToEdgeFeatureFlagOn();
}
}
}
"""
@@ -12,6 +12,7 @@ import com.facebook.react.model.ModelCodegenConfig
import com.facebook.react.model.ModelPackageJson
import com.facebook.react.tests.createProject
import com.facebook.react.utils.ProjectUtils.getReactNativeArchitectures
import com.facebook.react.utils.ProjectUtils.isEdgeToEdgeEnabled
import com.facebook.react.utils.ProjectUtils.isHermesEnabled
import com.facebook.react.utils.ProjectUtils.isNewArchEnabled
import com.facebook.react.utils.ProjectUtils.needsCodegenFromPackageJson
@@ -98,7 +99,7 @@ class ProjectUtilsTest {
}
@Test
fun isNewArchEnabled_withDisabledViaProperty_returnsFalse() {
fun isHermesEnabled_withDisabledViaProperty_returnsFalse() {
val project = createProject()
project.extensions.extraProperties.set("hermesEnabled", "false")
assertThat(project.isHermesEnabled).isFalse()
@@ -150,6 +151,32 @@ class ProjectUtilsTest {
assertThat(project.isHermesEnabled).isTrue()
}
@Test
fun isEdgeToEdgeEnabled_returnsFalseByDefault() {
assertThat(createProject().isEdgeToEdgeEnabled).isFalse()
}
@Test
fun isEdgeToEdgeEnabled_withDisabledViaProperty_returnsFalse() {
val project = createProject()
project.extensions.extraProperties.set("edgeToEdgeEnabled", "false")
assertThat(project.isEdgeToEdgeEnabled).isFalse()
}
@Test
fun isEdgeToEdgeEnabled_withEnabledViaProperty_returnsTrue() {
val project = createProject()
project.extensions.extraProperties.set("edgeToEdgeEnabled", "true")
assertThat(project.isEdgeToEdgeEnabled).isTrue()
}
@Test
fun isEdgeToEdgeEnabled_withInvalidViaProperty_returnsFalse() {
val project = createProject()
project.extensions.extraProperties.set("edgeToEdgeEnabled", "¯\\_(ツ)_/¯")
assertThat(project.isEdgeToEdgeEnabled).isFalse()
}
@Test
fun needsCodegenFromPackageJson_withCodegenConfigInPackageJson_returnsTrue() {
val project = createProject()
@@ -6673,3 +6673,8 @@ public class com/facebook/react/views/view/ReactViewManager : com/facebook/react
public final class com/facebook/react/views/view/ReactViewManager$Companion {
}
public final class com/facebook/react/views/view/WindowUtilKt {
public static final fun isEdgeToEdgeFeatureFlagOn ()Z
public static final fun setEdgeToEdgeFeatureFlagOn ()V
}
@@ -15,6 +15,7 @@ import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.Window;
import androidx.annotation.Nullable;
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.bridge.Callback;
@@ -23,6 +24,7 @@ import com.facebook.react.common.annotations.DeprecatedInNewArchitecture;
import com.facebook.react.interfaces.fabric.ReactSurface;
import com.facebook.react.internal.featureflags.ReactNativeNewArchitectureFeatureFlags;
import com.facebook.react.modules.core.PermissionListener;
import com.facebook.react.views.view.WindowUtilKt;
import com.facebook.systrace.Systrace;
/**
@@ -57,7 +59,7 @@ public class ReactActivityDelegate {
/**
* Public API to populate the launch options that will be passed to React. Here you can customize
* the values that will be passed as `initialProperties` to the Renderer.
* the values that will be passed as 'initialProperties' to the Renderer.
*
* @return Either null or a key-value map as a Bundle
*/
@@ -121,8 +123,16 @@ public class ReactActivityDelegate {
() -> {
String mainComponentName = getMainComponentName();
final Bundle launchOptions = composeLaunchOptions();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && isWideColorGamutEnabled()) {
mActivity.getWindow().setColorMode(ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT);
if (mActivity != null) {
Window window = mActivity.getWindow();
if (window != null) {
if (WindowUtilKt.isEdgeToEdgeFeatureFlagOn()) {
WindowUtilKt.enableEdgeToEdge(window);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && isWideColorGamutEnabled()) {
window.setColorMode(ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT);
}
}
}
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()) {
mReactDelegate =
@@ -16,6 +16,7 @@ import com.facebook.react.bridge.ReadableMap
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.uimanager.DisplayMetricsHolder.getDisplayMetricsWritableMap
import com.facebook.react.uimanager.DisplayMetricsHolder.initDisplayMetricsIfNotInitialized
import com.facebook.react.views.view.isEdgeToEdgeFeatureFlagOn
/** Module that exposes Android Constants to JS. */
@ReactModule(name = NativeDeviceInfoSpec.NAME)
@@ -34,7 +35,11 @@ internal class DeviceInfoModule(reactContext: ReactApplicationContext) :
// Cache the initial dimensions for later comparison in emitUpdateDimensionsEvent
previousDisplayMetrics = displayMetrics.copy()
return mapOf("Dimensions" to displayMetrics.toHashMap())
return mapOf(
"Dimensions" to displayMetrics.toHashMap(),
"isEdgeToEdge" to isEdgeToEdgeFeatureFlagOn,
)
}
override fun onHostResume() {
@@ -23,6 +23,7 @@ import com.facebook.react.common.ReactConstants
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.uimanager.DisplayMetricsHolder.getStatusBarHeightPx
import com.facebook.react.uimanager.PixelUtil
import com.facebook.react.views.view.isEdgeToEdgeFeatureFlagOn
import com.facebook.react.views.view.setStatusBarTranslucency
import com.facebook.react.views.view.setStatusBarVisibility
@@ -54,6 +55,12 @@ internal class StatusBarModule(reactContext: ReactApplicationContext?) :
"StatusBarModule: Ignored status bar change, current activity is null.")
return
}
if (isEdgeToEdgeFeatureFlagOn) {
FLog.w(
ReactConstants.TAG,
"StatusBarModule: Ignored status bar change, current activity is edge-to-edge.")
return
}
UiThreadUtil.runOnUiThread(
object : GuardedRunnable(reactApplicationContext) {
override fun runGuarded() {
@@ -82,6 +89,12 @@ internal class StatusBarModule(reactContext: ReactApplicationContext?) :
"StatusBarModule: Ignored status bar change, current activity is null.")
return
}
if (isEdgeToEdgeFeatureFlagOn) {
FLog.w(
ReactConstants.TAG,
"StatusBarModule: Ignored status bar change, current activity is edge-to-edge.")
return
}
UiThreadUtil.runOnUiThread(
object : GuardedRunnable(reactApplicationContext) {
override fun runGuarded() {
@@ -53,8 +53,10 @@ import com.facebook.react.uimanager.events.EventDispatcher
import com.facebook.react.views.common.ContextUtils
import com.facebook.react.views.modal.ReactModalHostView.DialogRootViewGroup
import com.facebook.react.views.view.ReactViewGroup
import com.facebook.react.views.view.disableEdgeToEdge
import com.facebook.react.views.view.enableEdgeToEdge
import com.facebook.react.views.view.isEdgeToEdgeFeatureFlagOn
import com.facebook.react.views.view.setStatusBarTranslucency
import com.facebook.react.views.view.setSystemBarsTranslucency
import com.facebook.yoga.annotations.DoNotStrip
/**
@@ -81,16 +83,19 @@ public class ReactModalHostView(context: ThemedReactContext) :
public var transparent: Boolean = false
public var onShowListener: DialogInterface.OnShowListener? = null
public var onRequestCloseListener: OnRequestCloseListener? = null
public var statusBarTranslucent: Boolean = false
get() = field || isEdgeToEdgeFeatureFlagOn
set(value) {
field = value
createNewDialog = true
createNewDialog = !isEdgeToEdgeFeatureFlagOn
}
public var navigationBarTranslucent: Boolean = false
get() = field || isEdgeToEdgeFeatureFlagOn
set(value) {
field = value
createNewDialog = true
createNewDialog = !isEdgeToEdgeFeatureFlagOn
}
public var animationType: String? = null
@@ -378,9 +383,10 @@ public class ReactModalHostView(context: ThemedReactContext) :
}
// Navigation bar cannot be translucent without status bar being translucent too
dialogWindow.setSystemBarsTranslucency(navigationBarTranslucent)
if (!navigationBarTranslucent) {
if (navigationBarTranslucent) {
dialogWindow.enableEdgeToEdge()
} else {
dialogWindow.disableEdgeToEdge()
dialogWindow.setStatusBarTranslucency(statusBarTranslucent)
}
@@ -416,6 +422,13 @@ public class ReactModalHostView(context: ThemedReactContext) :
val dialogWindowInsetsController =
WindowInsetsControllerCompat(dialogWindow, dialogWindow.decorView)
if (isEdgeToEdgeFeatureFlagOn) {
activityWindowInsetsController.systemBarsBehavior =
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
dialogWindowInsetsController.systemBarsBehavior =
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
}
dialogWindowInsetsController.isAppearanceLightStatusBars =
activityWindowInsetsController.isAppearanceLightStatusBars
@@ -13,9 +13,30 @@ import android.view.Window
import android.view.WindowManager
import androidx.core.view.ViewCompat
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat
import com.facebook.react.views.common.UiModeUtils
// The light scrim color used in the platform API 29+
// https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/com/android/internal/policy/DecorView.java;drc=6ef0f022c333385dba2c294e35b8de544455bf19;l=142
internal val LightNavigationBarColor = Color.argb(0xe6, 0xFF, 0xFF, 0xFF)
// The dark scrim color used in the platform.
// https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/res/res/color/system_bar_background_semi_transparent.xml
// https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/res/remote_color_resources_res/values/colors.xml;l=67
internal val DarkNavigationBarColor = Color.argb(0x80, 0x1b, 0x1b, 0x1b)
/**
* This does not enable or apply edge-to-edge behavior, it simply tracks whether it has been flagged
* as enabled elsewhere in the application.
*/
public var isEdgeToEdgeFeatureFlagOn: Boolean = false
private set
public fun setEdgeToEdgeFeatureFlagOn() {
isEdgeToEdgeFeatureFlagOn = true
}
@Suppress("DEPRECATION")
internal fun Window.setStatusBarTranslucency(isTranslucent: Boolean) {
// If the status bar is translucent hook into the window insets calculations
@@ -45,59 +66,74 @@ internal fun Window.setStatusBarVisibility(isHidden: Boolean) {
@Suppress("DEPRECATION")
private fun Window.statusBarHide() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// Ensure the content extends into the cutout area
attributes.layoutInDisplayCutoutMode =
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
setDecorFitsSystemWindows(false)
if (isEdgeToEdgeFeatureFlagOn) {
WindowInsetsControllerCompat(this, decorView).run {
systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
hide(WindowInsetsCompat.Type.statusBars())
}
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// Ensure the content extends into the cutout area
attributes.layoutInDisplayCutoutMode =
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
setDecorFitsSystemWindows(false)
}
addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN)
}
addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN)
}
@Suppress("DEPRECATION")
private fun Window.statusBarShow() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
attributes.layoutInDisplayCutoutMode =
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
setDecorFitsSystemWindows(true)
if (isEdgeToEdgeFeatureFlagOn) {
WindowInsetsControllerCompat(this, decorView).run {
systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
show(WindowInsetsCompat.Type.statusBars())
}
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
attributes.layoutInDisplayCutoutMode =
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
setDecorFitsSystemWindows(true)
}
addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN)
clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
}
addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN)
clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
}
@Suppress("DEPRECATION")
internal fun Window.setSystemBarsTranslucency(isTranslucent: Boolean) {
WindowCompat.setDecorFitsSystemWindows(this, !isTranslucent)
internal fun Window.enableEdgeToEdge() {
WindowCompat.setDecorFitsSystemWindows(this, false)
if (isTranslucent) {
val isDarkMode = UiModeUtils.isDarkMode(context)
val isDarkMode = UiModeUtils.isDarkMode(context)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
isStatusBarContrastEnforced = false
isNavigationBarContrastEnforced = true
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
isStatusBarContrastEnforced = false
isNavigationBarContrastEnforced = true
}
statusBarColor = Color.TRANSPARENT
navigationBarColor =
statusBarColor = Color.TRANSPARENT
navigationBarColor =
when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> Color.TRANSPARENT
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !isDarkMode -> LightNavigationBarColor
else -> DarkNavigationBarColor
}
WindowInsetsControllerCompat(this, decorView).run {
isAppearanceLightNavigationBars = !isDarkMode
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
attributes.layoutInDisplayCutoutMode =
when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> Color.TRANSPARENT
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 && !isDarkMode ->
Color.argb(0xe6, 0xFF, 0xFF, 0xFF)
else -> Color.argb(0x80, 0x1b, 0x1b, 0x1b)
Build.VERSION.SDK_INT >= Build.VERSION_CODES.R ->
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
else -> WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
}
WindowInsetsControllerCompat(this, this.decorView).run {
isAppearanceLightNavigationBars = !isDarkMode
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
attributes.layoutInDisplayCutoutMode =
when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.R ->
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
else -> WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
}
}
}
}
internal fun Window.disableEdgeToEdge() {
WindowCompat.setDecorFitsSystemWindows(this, true)
}
@@ -28,8 +28,10 @@ using DimensionsPayload = NativeDeviceInfoDimensionsPayload<
std::optional<DisplayMetricsAndroid>,
std::optional<DisplayMetricsAndroid>>;
using DeviceInfoConstants =
NativeDeviceInfoDeviceInfoConstants<DimensionsPayload, std::optional<bool>>;
using DeviceInfoConstants = NativeDeviceInfoDeviceInfoConstants<
DimensionsPayload,
std::optional<bool>,
std::optional<bool>>;
template <>
struct Bridging<DisplayMetrics>
@@ -36,6 +36,7 @@ export type DimensionsPayload = {
export type DeviceInfoConstants = {
+Dimensions: DimensionsPayload,
+isEdgeToEdge?: boolean,
+isIPhoneX_deprecated?: boolean,
};
@@ -7,3 +7,5 @@ android.useAndroidX=true
newArchEnabled=true
# RN-Tester is running with Hermes always enabled
hermesEnabled=true
# RN-Tester is running with EdgeToEdge always enabled
edgeToEdgeEnabled=true
@@ -33,6 +33,7 @@ import com.facebook.react.uiapp.component.MyNativeViewManager
import com.facebook.react.uiapp.component.ReportFullyDrawnViewManager
import com.facebook.react.uimanager.ReactShadowNode
import com.facebook.react.uimanager.ViewManager
import com.facebook.react.views.view.setEdgeToEdgeFeatureFlagOn
import com.facebook.soloader.SoLoader
internal class RNTesterApplication : Application(), ReactApplication {
@@ -135,5 +136,9 @@ internal class RNTesterApplication : Application(), ReactApplication {
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
load()
}
if (BuildConfig.IS_EDGE_TO_EDGE_ENABLED) {
setEdgeToEdgeFeatureFlagOn()
}
}
}
@@ -10,3 +10,4 @@ android.useAndroidX=true
reactNativeArchitectures=arm64-v8a
newArchEnabled=true
hermesEnabled=true
edgeToEdgeEnabled=false