diff --git a/android/src/base/java/com/reactnativekeyboardcontroller/KeyboardControllerPackage.kt b/android/src/base/java/com/reactnativekeyboardcontroller/KeyboardControllerPackage.kt index 0ff54d72eb..c7bcf169de 100644 --- a/android/src/base/java/com/reactnativekeyboardcontroller/KeyboardControllerPackage.kt +++ b/android/src/base/java/com/reactnativekeyboardcontroller/KeyboardControllerPackage.kt @@ -44,7 +44,7 @@ class KeyboardControllerPackage : BaseReactPackage() { ReactModuleInfo( StatusBarManagerCompatModuleImpl.NAME, StatusBarManagerCompatModuleImpl.NAME, - false, // canOverrideExistingModule + true, // canOverrideExistingModule false, // needsEagerInit false, // isCxxModule isTurboModule, // isTurboModule diff --git a/android/src/fabric/java/com/reactnativekeyboardcontroller/StatusBarManagerCompatModule.kt b/android/src/fabric/java/com/reactnativekeyboardcontroller/StatusBarManagerCompatModule.kt index 9715a53af1..14e2b10961 100644 --- a/android/src/fabric/java/com/reactnativekeyboardcontroller/StatusBarManagerCompatModule.kt +++ b/android/src/fabric/java/com/reactnativekeyboardcontroller/StatusBarManagerCompatModule.kt @@ -10,6 +10,8 @@ class StatusBarManagerCompatModule( override fun getName(): String = StatusBarManagerCompatModuleImpl.NAME + override fun getConstants(): MutableMap? = module.getConstants() + override fun setHidden(hidden: Boolean) { module.setHidden(hidden) } diff --git a/android/src/main/java/com/reactnativekeyboardcontroller/managers/KeyboardControllerViewManagerImpl.kt b/android/src/main/java/com/reactnativekeyboardcontroller/managers/KeyboardControllerViewManagerImpl.kt index 9ff85339cc..c4f7e05b28 100644 --- a/android/src/main/java/com/reactnativekeyboardcontroller/managers/KeyboardControllerViewManagerImpl.kt +++ b/android/src/main/java/com/reactnativekeyboardcontroller/managers/KeyboardControllerViewManagerImpl.kt @@ -28,7 +28,7 @@ class KeyboardControllerViewManagerImpl { view: EdgeToEdgeReactViewGroup, enabled: Boolean, ) { - view.setActive(enabled) + view.active = enabled } fun setStatusBarTranslucent( diff --git a/android/src/main/java/com/reactnativekeyboardcontroller/modules/StatusBarManagerCompatModuleImpl.kt b/android/src/main/java/com/reactnativekeyboardcontroller/modules/StatusBarManagerCompatModuleImpl.kt index 49e2610d94..31cf2ac57a 100644 --- a/android/src/main/java/com/reactnativekeyboardcontroller/modules/StatusBarManagerCompatModuleImpl.kt +++ b/android/src/main/java/com/reactnativekeyboardcontroller/modules/StatusBarManagerCompatModuleImpl.kt @@ -9,6 +9,7 @@ import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsControllerCompat import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.UiThreadUtil +import com.facebook.react.modules.statusbar.StatusBarModule import com.reactnativekeyboardcontroller.extensions.rootView import com.reactnativekeyboardcontroller.log.Logger import com.reactnativekeyboardcontroller.views.EdgeToEdgeReactViewGroup @@ -19,10 +20,15 @@ private val TAG = StatusBarManagerCompatModuleImpl::class.qualifiedName class StatusBarManagerCompatModuleImpl( private val mReactContext: ReactApplicationContext, ) { + private var original = StatusBarModule(mReactContext) private var controller: WindowInsetsControllerCompat? = null private var lastActivity = WeakReference(null) fun setHidden(hidden: Boolean) { + if (!isEnabled()) { + return original.setHidden(hidden) + } + UiThreadUtil.runOnUiThread { if (hidden) { getController()?.hide(WindowInsetsCompat.Type.statusBars()) @@ -37,6 +43,10 @@ class StatusBarManagerCompatModuleImpl( color: Int, animated: Boolean, ) { + if (!isEnabled()) { + return original.setColor(color.toDouble(), animated) + } + val activity = mReactContext.currentActivity if (activity == null) { Logger.w(TAG, "StatusBarManagerCompatModule: Ignored status bar change, current activity is null.") @@ -61,18 +71,27 @@ class StatusBarManagerCompatModuleImpl( } fun setTranslucent(translucent: Boolean) { + if (!isEnabled()) { + return original.setTranslucent(translucent) + } + UiThreadUtil.runOnUiThread { - val view = mReactContext.rootView?.findViewWithTag(EdgeToEdgeReactViewGroup.VIEW_TAG) - view?.forceStatusBarTranslucent(translucent) + view()?.forceStatusBarTranslucent(translucent) } } fun setStyle(style: String) { + if (!isEnabled()) { + return original.setStyle(style) + } + UiThreadUtil.runOnUiThread { getController()?.isAppearanceLightStatusBars = style == "dark-content" } } + fun getConstants(): MutableMap? = original.constants + private fun getController(): WindowInsetsControllerCompat? { val activity = mReactContext.currentActivity @@ -94,8 +113,13 @@ class StatusBarManagerCompatModuleImpl( return this.controller } + private fun isEnabled(): Boolean = view()?.active ?: false + + private fun view(): EdgeToEdgeReactViewGroup? = + mReactContext.rootView?.findViewWithTag(EdgeToEdgeReactViewGroup.VIEW_TAG) + companion object { - const val NAME = "StatusBarManagerCompat" + const val NAME = "StatusBarManager" private const val DEFAULT_ANIMATION_TIME = 300L } } diff --git a/android/src/main/java/com/reactnativekeyboardcontroller/views/EdgeToEdgeReactViewGroup.kt b/android/src/main/java/com/reactnativekeyboardcontroller/views/EdgeToEdgeReactViewGroup.kt index 3591e3f8d8..371d6a9553 100644 --- a/android/src/main/java/com/reactnativekeyboardcontroller/views/EdgeToEdgeReactViewGroup.kt +++ b/android/src/main/java/com/reactnativekeyboardcontroller/views/EdgeToEdgeReactViewGroup.kt @@ -31,8 +31,16 @@ class EdgeToEdgeReactViewGroup( private var isStatusBarTranslucent = false private var isNavigationBarTranslucent = false private var isPreservingEdgeToEdge = false - private var active = false private var isEdgeToEdge = false + var active: Boolean = false + set(value) { + field = value + if (value) { + enable() + } else { + disable() + } + } // internal class members private var eventView: ReactViewGroup? = null @@ -223,16 +231,6 @@ class EdgeToEdgeReactViewGroup( fun setPreserveEdgeToEdge(isPreservingEdgeToEdge: Boolean) { this.isPreservingEdgeToEdge = isPreservingEdgeToEdge } - - fun setActive(active: Boolean) { - this.active = active - - if (active) { - this.enable() - } else { - this.disable() - } - } // endregion // region external methods diff --git a/android/src/paper/java/com/reactnativekeyboardcontroller/StatusBarManagerCompatModule.kt b/android/src/paper/java/com/reactnativekeyboardcontroller/StatusBarManagerCompatModule.kt index 3dd44469b6..84809e9d9a 100644 --- a/android/src/paper/java/com/reactnativekeyboardcontroller/StatusBarManagerCompatModule.kt +++ b/android/src/paper/java/com/reactnativekeyboardcontroller/StatusBarManagerCompatModule.kt @@ -14,6 +14,8 @@ class StatusBarManagerCompatModule( override fun getName(): String = StatusBarManagerCompatModuleImpl.NAME + override fun getConstants(): MutableMap? = module.getConstants() + @ReactMethod private fun setHidden(hidden: Boolean) { module.setHidden(hidden) diff --git a/android/src/turbo/java/com/reactnativekeyboardcontroller/KeyboardControllerPackage.kt b/android/src/turbo/java/com/reactnativekeyboardcontroller/KeyboardControllerPackage.kt index 235d3ec9fb..9e8c1d7346 100644 --- a/android/src/turbo/java/com/reactnativekeyboardcontroller/KeyboardControllerPackage.kt +++ b/android/src/turbo/java/com/reactnativekeyboardcontroller/KeyboardControllerPackage.kt @@ -45,7 +45,7 @@ class KeyboardControllerPackage : TurboReactPackage() { ReactModuleInfo( StatusBarManagerCompatModuleImpl.NAME, StatusBarManagerCompatModuleImpl.NAME, - false, // canOverrideExistingModule + true, // canOverrideExistingModule false, // needsEagerInit true, // hasConstants false, // isCxxModule diff --git a/src/animated.tsx b/src/animated.tsx index 5aa199754d..d455ae264c 100644 --- a/src/animated.tsx +++ b/src/animated.tsx @@ -1,5 +1,5 @@ /* eslint react/jsx-sort-props: off */ -import React, { useLayoutEffect, useMemo, useRef, useState } from "react"; +import React, { useMemo, useRef, useState } from "react"; import { Animated, Platform, StyleSheet } from "react-native"; import { controlEdgeToEdgeValues, @@ -11,7 +11,6 @@ import { KeyboardControllerView } from "./bindings"; import { KeyboardContext } from "./context"; import { focusedInputEventsMap, keyboardEventsMap } from "./event-mappings"; import { useAnimatedValue, useEventHandlerRegistration } from "./internal"; -import { applyMonkeyPatch, revertMonkeyPatch } from "./monkey-patch"; import { useAnimatedKeyboardHandler, useFocusedInputLayoutHandler, @@ -216,15 +215,6 @@ export const KeyboardProvider = (props: KeyboardProviderProps) => { [], ); - // layout effects - useLayoutEffect(() => { - if (enabled) { - applyMonkeyPatch(); - } else { - revertMonkeyPatch(); - } - }, [enabled]); - if (__DEV__) { controlEdgeToEdgeValues({ statusBarTranslucent, diff --git a/src/monkey-patch.android.ts b/src/monkey-patch.android.ts deleted file mode 100644 index 986d4285e1..0000000000 --- a/src/monkey-patch.android.ts +++ /dev/null @@ -1,41 +0,0 @@ -// @ts-expect-error because there is no corresponding type definition -import * as NativeAndroidManager from "react-native/Libraries/Components/StatusBar/NativeStatusBarManagerAndroid"; - -const RCTStatusBarManagerCompat = - // eslint-disable-next-line @typescript-eslint/no-var-requires - require("./specs/NativeStatusBarManagerCompat").default; - -// Copy original default manager to keep its original state and methods -const OriginalNativeAndroidManager = { ...NativeAndroidManager.default }; - -// Create a new object that modifies the necessary methods -// On Android < 11 RN uses legacy API which breaks EdgeToEdge mode in RN, so -// in order to use library on all available platforms we have to monkey patch -// default RN implementation and use modern `WindowInsetsControllerCompat`. -const ModifiedNativeAndroidManager = { - ...NativeAndroidManager.default, // Spread original properties to keep existing functionality - setColor: (color: number, animated: boolean): void => { - RCTStatusBarManagerCompat.setColor(color, animated); - }, - setTranslucent: (translucent: boolean): void => { - RCTStatusBarManagerCompat.setTranslucent(translucent); - }, - setStyle: ( - statusBarStyle?: "default" | "dark-content" | "light-content", - ): void => { - RCTStatusBarManagerCompat.setStyle(statusBarStyle); - }, - setHidden: (hidden: boolean): void => { - RCTStatusBarManagerCompat.setHidden(hidden); - }, -}; - -// Define a function to apply the monkey patch -export const applyMonkeyPatch = () => { - Object.assign(NativeAndroidManager.default, ModifiedNativeAndroidManager); -}; - -// Define a function to revert changes back to the original state -export const revertMonkeyPatch = () => { - Object.assign(NativeAndroidManager.default, OriginalNativeAndroidManager); -}; diff --git a/src/monkey-patch.ts b/src/monkey-patch.ts deleted file mode 100644 index 08a1fa6984..0000000000 --- a/src/monkey-patch.ts +++ /dev/null @@ -1,5 +0,0 @@ -// stub for all platforms -const NOOP = () => {}; - -export const applyMonkeyPatch = NOOP; -export const revertMonkeyPatch = NOOP;