diff --git a/android/src/main/java/com/zoontek/rnedgetoedge/RNEdgeToEdgeModuleImpl.kt b/android/src/main/java/com/zoontek/rnedgetoedge/RNEdgeToEdgeModuleImpl.kt index bbf3e4c..f514440 100644 --- a/android/src/main/java/com/zoontek/rnedgetoedge/RNEdgeToEdgeModuleImpl.kt +++ b/android/src/main/java/com/zoontek/rnedgetoedge/RNEdgeToEdgeModuleImpl.kt @@ -1,10 +1,10 @@ package com.zoontek.rnedgetoedge -import android.app.Activity import android.content.res.Configuration import android.graphics.Color import android.os.Build -import android.util.TypedValue +import android.os.Handler +import android.os.Looper import android.view.WindowManager import androidx.core.content.ContextCompat @@ -13,36 +13,33 @@ import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsControllerCompat import com.facebook.common.logging.FLog +import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReadableMap import com.facebook.react.common.ReactConstants object RNEdgeToEdgeModuleImpl { const val NAME = "RNEdgeToEdge" - private var isInitialHostResume = true - fun onHostResume(activity: Activity?) { - if (activity == null) { - return FLog.w(ReactConstants.TAG, "$NAME: Ignored, current activity is null.") - } + private fun applyEdgeToEdge(reactContext: ReactApplicationContext) { + val activity = reactContext.currentActivity + ?: return FLog.w(ReactConstants.TAG, "$NAME: Ignored, current activity is null.") activity.runOnUiThread { val window = activity.window val view = window.decorView val context = view.context - val isDarkMode = - view.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == - Configuration.UI_MODE_NIGHT_YES - WindowCompat.setDecorFitsSystemWindows(window, false) window.statusBarColor = Color.TRANSPARENT + window.navigationBarColor = ContextCompat.getColor(context, R.color.navigationBarColor) - window.navigationBarColor = when { - Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> Color.TRANSPARENT - Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !isDarkMode -> - ContextCompat.getColor(context, R.color.systemBarLightScrim) - else -> ContextCompat.getColor(context, R.color.systemBarDarkScrim) + val isDarkMode = + view.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == + Configuration.UI_MODE_NIGHT_YES + + WindowInsetsControllerCompat(window, view).run { + isAppearanceLightNavigationBars = !isDarkMode } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { @@ -50,38 +47,26 @@ object RNEdgeToEdgeModuleImpl { window.isNavigationBarContrastEnforced = true } - WindowInsetsControllerCompat(window, view).run { - if (isInitialHostResume) { - val typedValue = TypedValue() - - isAppearanceLightStatusBars = activity - .theme - .resolveAttribute(android.R.attr.windowLightStatusBar, typedValue, true) && - typedValue.data != 0 - } - - isInitialHostResume = false - isAppearanceLightNavigationBars = !isDarkMode - } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { window.attributes.layoutInDisplayCutoutMode = when { - Build.VERSION.SDK_INT >= Build.VERSION_CODES.R -> - WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS + 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 } } } } - fun onHostDestroy() { - isInitialHostResume = true + fun onHostResume(reactContext: ReactApplicationContext) { + applyEdgeToEdge(reactContext) } - fun setSystemBarsConfig(activity: Activity?, config: ReadableMap) { - if (activity == null) { - return FLog.w(ReactConstants.TAG, "$NAME: Ignored, current activity is null.") - } + fun onConfigChange(reactContext: ReactApplicationContext) { + Handler(Looper.getMainLooper()).postDelayed({ applyEdgeToEdge(reactContext) }, 100) + } + + fun setSystemBarsConfig(reactContext: ReactApplicationContext, config: ReadableMap) { + val activity = reactContext.currentActivity + ?: return FLog.w(ReactConstants.TAG, "$NAME: Ignored, current activity is null.") val statusBarHidden = config.takeIf { it.hasKey("statusBarHidden") }?.getBoolean("statusBarHidden") diff --git a/android/src/main/res/values-night-v27/styles.xml b/android/src/main/res/values-night-v27/styles.xml new file mode 100644 index 0000000..35c64a3 --- /dev/null +++ b/android/src/main/res/values-night-v27/styles.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/src/main/res/values-v26/styles.xml b/android/src/main/res/values-v26/styles.xml deleted file mode 100644 index ad04568..0000000 --- a/android/src/main/res/values-v26/styles.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - diff --git a/android/src/main/res/values-v27/colors.xml b/android/src/main/res/values-v27/colors.xml new file mode 100644 index 0000000..da6b559 --- /dev/null +++ b/android/src/main/res/values-v27/colors.xml @@ -0,0 +1,5 @@ + + + + #e6ffffff + diff --git a/android/src/main/res/values-v27/styles.xml b/android/src/main/res/values-v27/styles.xml index c0fc338..61f85c2 100644 --- a/android/src/main/res/values-v27/styles.xml +++ b/android/src/main/res/values-v27/styles.xml @@ -1,8 +1,11 @@ + + diff --git a/android/src/main/res/values-v29/colors.xml b/android/src/main/res/values-v29/colors.xml new file mode 100644 index 0000000..e6a17f3 --- /dev/null +++ b/android/src/main/res/values-v29/colors.xml @@ -0,0 +1,4 @@ + + + @android:color/transparent + diff --git a/android/src/main/res/values-v29/styles.xml b/android/src/main/res/values-v29/styles.xml index 83fe948..6658b45 100644 --- a/android/src/main/res/values-v29/styles.xml +++ b/android/src/main/res/values-v29/styles.xml @@ -4,6 +4,5 @@ shortEdges false true - @android:color/transparent diff --git a/android/src/main/res/values-v30/styles.xml b/android/src/main/res/values-v30/styles.xml index d16c1bc..74e4539 100644 --- a/android/src/main/res/values-v30/styles.xml +++ b/android/src/main/res/values-v30/styles.xml @@ -4,6 +4,5 @@ always false true - @android:color/transparent diff --git a/android/src/main/res/values/colors.xml b/android/src/main/res/values/colors.xml index fa8e93d..a45d90f 100644 --- a/android/src/main/res/values/colors.xml +++ b/android/src/main/res/values/colors.xml @@ -2,7 +2,5 @@ - #801b1b1b - - #e6ffffff + #801b1b1b diff --git a/android/src/main/res/values/styles.xml b/android/src/main/res/values/styles.xml index 8974fa4..39ba37e 100644 --- a/android/src/main/res/values/styles.xml +++ b/android/src/main/res/values/styles.xml @@ -8,9 +8,9 @@ false true @android:color/transparent + @color/navigationBarColor diff --git a/android/src/newarch/com/zoontek/rnedgetoedge/RNEdgeToEdgeModule.kt b/android/src/newarch/com/zoontek/rnedgetoedge/RNEdgeToEdgeModule.kt index 2651b4d..217c35b 100644 --- a/android/src/newarch/com/zoontek/rnedgetoedge/RNEdgeToEdgeModule.kt +++ b/android/src/newarch/com/zoontek/rnedgetoedge/RNEdgeToEdgeModule.kt @@ -1,19 +1,32 @@ package com.zoontek.rnedgetoedge +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter + import com.facebook.react.bridge.LifecycleEventListener import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReadableMap import com.facebook.react.module.annotations.ReactModule @ReactModule(name = RNEdgeToEdgeModuleImpl.NAME) -class RNEdgeToEdgeModule(reactContext: ReactApplicationContext?) : +class RNEdgeToEdgeModule(reactContext: ReactApplicationContext) : NativeRNEdgeToEdgeSpec(reactContext), LifecycleEventListener { + private val configChangeReceiver = object : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + RNEdgeToEdgeModuleImpl.onConfigChange(reactContext) + } + } + init { + reactApplicationContext.registerReceiver(configChangeReceiver, IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED)) reactApplicationContext.addLifecycleEventListener(this) } override fun invalidate() { + reactApplicationContext.unregisterReceiver(configChangeReceiver) reactApplicationContext.removeLifecycleEventListener(this) } @@ -22,16 +35,14 @@ class RNEdgeToEdgeModule(reactContext: ReactApplicationContext?) : } override fun onHostResume() { - RNEdgeToEdgeModuleImpl.onHostResume(currentActivity) + RNEdgeToEdgeModuleImpl.onHostResume(reactApplicationContext) } override fun onHostPause() {} - override fun onHostDestroy() { - RNEdgeToEdgeModuleImpl.onHostDestroy() - } + override fun onHostDestroy() {} override fun setSystemBarsConfig(config: ReadableMap) { - RNEdgeToEdgeModuleImpl.setSystemBarsConfig(currentActivity, config) + RNEdgeToEdgeModuleImpl.setSystemBarsConfig(reactApplicationContext, config) } } diff --git a/android/src/oldarch/com/zoontek/rnedgetoedge/RNBarsModule.kt b/android/src/oldarch/com/zoontek/rnedgetoedge/RNBarsModule.kt index 9f87282..455599b 100644 --- a/android/src/oldarch/com/zoontek/rnedgetoedge/RNBarsModule.kt +++ b/android/src/oldarch/com/zoontek/rnedgetoedge/RNBarsModule.kt @@ -1,5 +1,10 @@ package com.zoontek.rnedgetoedge +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter + import com.facebook.react.bridge.LifecycleEventListener import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReactContextBaseJavaModule @@ -8,14 +13,22 @@ import com.facebook.react.bridge.ReadableMap import com.facebook.react.module.annotations.ReactModule @ReactModule(name = RNEdgeToEdgeModuleImpl.NAME) -class RNEdgeToEdgeModule(reactContext: ReactApplicationContext?) : +class RNEdgeToEdgeModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext), LifecycleEventListener { + private val configChangeReceiver = object : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + RNEdgeToEdgeModuleImpl.onConfigChange(reactContext) + } + } + init { + reactApplicationContext.registerReceiver(configChangeReceiver, IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED)) reactApplicationContext.addLifecycleEventListener(this) } override fun invalidate() { + reactApplicationContext.unregisterReceiver(configChangeReceiver) reactApplicationContext.removeLifecycleEventListener(this) } @@ -24,17 +37,15 @@ class RNEdgeToEdgeModule(reactContext: ReactApplicationContext?) : } override fun onHostResume() { - RNEdgeToEdgeModuleImpl.onHostResume(currentActivity) + RNEdgeToEdgeModuleImpl.onHostResume(reactApplicationContext) } override fun onHostPause() {} - override fun onHostDestroy() { - RNEdgeToEdgeModuleImpl.onHostDestroy() - } + override fun onHostDestroy() {} @ReactMethod fun setSystemBarsConfig(config: ReadableMap) { - RNEdgeToEdgeModuleImpl.setSystemBarsConfig(currentActivity, config) + RNEdgeToEdgeModuleImpl.setSystemBarsConfig(reactApplicationContext, config) } } diff --git a/package.json b/package.json index ed6d72f..322b429 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-edge-to-edge", - "version": "0.1.2", + "version": "0.2.0", "license": "MIT", "description": "Effortlessly enable edge-to-edge display in React Native", "author": "Mathieu Acthernoene ",