Skip to content

Commit ecb3595

Browse files
authored
refactor: do not rely on deep imports (#1000)
## 📜 Description Don't rely on deep imports and provide a warning free compatibility with RN 0.80+ (by utilizing a more official and reliable way to substitute native module implementation). ## 💡 Motivation and Context Starting from `react-native@0.80` deep imports were deprecated and now if you try to use them you get a warning: > Deep imports from the 'react-native' package are deprecated In version `0.82` the ability to use deep imports will be completely removed. In preparation of that RN team opened a discussion on GitHub about those upcoming changes. This library uses deep imports to substitute `StatusBar` implementation. I [opened](react-native-community/discussions-and-proposals#893 (comment)) a thread to discuss how we can overcome it. While waiting for a proposed solution I discovered, that we can override native modules with own implementation - this is the case that I want to use. I want to substitute the implementation of `StatusBar` and fallback to default implementation if `EdgeToEdge` view is disabled. ## 📢 Changelog <!-- High level overview of important changes --> <!-- For example: fixed status bar manipulation; added new types declarations; --> <!-- If your changes don't affect one of platform/language below - then remove this platform/language --> ### JS - remove `monkey-patch` code; ### Android - rename `StatusBarManagerCompat` to `StatusBarManager` to match name of original module; - added `getConstants` method; - `StatusBarManagerCompat` now can override existing modules; - make `active` prop public; - make `setActive` setter field-setter to avoid compilation conflicts; - `StatusBarManagerCompat` now respects `active` props and fallbacks to `StatusBarManager` implementation if `edge-to-edge` view is disabled; - added helpers like `isEnabled`/`view` to `StatusBarManagerCompat` to reduce code duplication. ## 🤔 How Has This Been Tested? Tested manually on: - Pixel 7 Pro (API 36, real device); - Pixel 3A (API 33, emulator); ## 📸 Screenshots (if appropriate): https://github.com/user-attachments/assets/44a7e019-446b-4c7e-903f-7d4c87882b74 ## 📝 Checklist - [x] CI successfully passed - [x] I added new mocks and corresponding unit-tests if library API was changed
1 parent 60ec0ce commit ecb3595

10 files changed

Lines changed: 44 additions & 74 deletions

File tree

android/src/base/java/com/reactnativekeyboardcontroller/KeyboardControllerPackage.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class KeyboardControllerPackage : BaseReactPackage() {
4444
ReactModuleInfo(
4545
StatusBarManagerCompatModuleImpl.NAME,
4646
StatusBarManagerCompatModuleImpl.NAME,
47-
false, // canOverrideExistingModule
47+
true, // canOverrideExistingModule
4848
false, // needsEagerInit
4949
false, // isCxxModule
5050
isTurboModule, // isTurboModule

android/src/fabric/java/com/reactnativekeyboardcontroller/StatusBarManagerCompatModule.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ class StatusBarManagerCompatModule(
1010

1111
override fun getName(): String = StatusBarManagerCompatModuleImpl.NAME
1212

13+
override fun getConstants(): MutableMap<String, Any>? = module.getConstants()
14+
1315
override fun setHidden(hidden: Boolean) {
1416
module.setHidden(hidden)
1517
}

android/src/main/java/com/reactnativekeyboardcontroller/managers/KeyboardControllerViewManagerImpl.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class KeyboardControllerViewManagerImpl {
2828
view: EdgeToEdgeReactViewGroup,
2929
enabled: Boolean,
3030
) {
31-
view.setActive(enabled)
31+
view.active = enabled
3232
}
3333

3434
fun setStatusBarTranslucent(

android/src/main/java/com/reactnativekeyboardcontroller/modules/StatusBarManagerCompatModuleImpl.kt

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import androidx.core.view.WindowInsetsCompat
99
import androidx.core.view.WindowInsetsControllerCompat
1010
import com.facebook.react.bridge.ReactApplicationContext
1111
import com.facebook.react.bridge.UiThreadUtil
12+
import com.facebook.react.modules.statusbar.StatusBarModule
1213
import com.reactnativekeyboardcontroller.extensions.rootView
1314
import com.reactnativekeyboardcontroller.log.Logger
1415
import com.reactnativekeyboardcontroller.views.EdgeToEdgeReactViewGroup
@@ -19,10 +20,15 @@ private val TAG = StatusBarManagerCompatModuleImpl::class.qualifiedName
1920
class StatusBarManagerCompatModuleImpl(
2021
private val mReactContext: ReactApplicationContext,
2122
) {
23+
private var original = StatusBarModule(mReactContext)
2224
private var controller: WindowInsetsControllerCompat? = null
2325
private var lastActivity = WeakReference<Activity?>(null)
2426

2527
fun setHidden(hidden: Boolean) {
28+
if (!isEnabled()) {
29+
return original.setHidden(hidden)
30+
}
31+
2632
UiThreadUtil.runOnUiThread {
2733
if (hidden) {
2834
getController()?.hide(WindowInsetsCompat.Type.statusBars())
@@ -37,6 +43,10 @@ class StatusBarManagerCompatModuleImpl(
3743
color: Int,
3844
animated: Boolean,
3945
) {
46+
if (!isEnabled()) {
47+
return original.setColor(color.toDouble(), animated)
48+
}
49+
4050
val activity = mReactContext.currentActivity
4151
if (activity == null) {
4252
Logger.w(TAG, "StatusBarManagerCompatModule: Ignored status bar change, current activity is null.")
@@ -61,18 +71,27 @@ class StatusBarManagerCompatModuleImpl(
6171
}
6272

6373
fun setTranslucent(translucent: Boolean) {
74+
if (!isEnabled()) {
75+
return original.setTranslucent(translucent)
76+
}
77+
6478
UiThreadUtil.runOnUiThread {
65-
val view = mReactContext.rootView?.findViewWithTag<EdgeToEdgeReactViewGroup>(EdgeToEdgeReactViewGroup.VIEW_TAG)
66-
view?.forceStatusBarTranslucent(translucent)
79+
view()?.forceStatusBarTranslucent(translucent)
6780
}
6881
}
6982

7083
fun setStyle(style: String) {
84+
if (!isEnabled()) {
85+
return original.setStyle(style)
86+
}
87+
7188
UiThreadUtil.runOnUiThread {
7289
getController()?.isAppearanceLightStatusBars = style == "dark-content"
7390
}
7491
}
7592

93+
fun getConstants(): MutableMap<String, Any>? = original.constants
94+
7695
private fun getController(): WindowInsetsControllerCompat? {
7796
val activity = mReactContext.currentActivity
7897

@@ -94,8 +113,13 @@ class StatusBarManagerCompatModuleImpl(
94113
return this.controller
95114
}
96115

116+
private fun isEnabled(): Boolean = view()?.active ?: false
117+
118+
private fun view(): EdgeToEdgeReactViewGroup? =
119+
mReactContext.rootView?.findViewWithTag<EdgeToEdgeReactViewGroup>(EdgeToEdgeReactViewGroup.VIEW_TAG)
120+
97121
companion object {
98-
const val NAME = "StatusBarManagerCompat"
122+
const val NAME = "StatusBarManager"
99123
private const val DEFAULT_ANIMATION_TIME = 300L
100124
}
101125
}

android/src/main/java/com/reactnativekeyboardcontroller/views/EdgeToEdgeReactViewGroup.kt

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,16 @@ class EdgeToEdgeReactViewGroup(
3131
private var isStatusBarTranslucent = false
3232
private var isNavigationBarTranslucent = false
3333
private var isPreservingEdgeToEdge = false
34-
private var active = false
3534
private var isEdgeToEdge = false
35+
var active: Boolean = false
36+
set(value) {
37+
field = value
38+
if (value) {
39+
enable()
40+
} else {
41+
disable()
42+
}
43+
}
3644

3745
// internal class members
3846
private var eventView: ReactViewGroup? = null
@@ -223,16 +231,6 @@ class EdgeToEdgeReactViewGroup(
223231
fun setPreserveEdgeToEdge(isPreservingEdgeToEdge: Boolean) {
224232
this.isPreservingEdgeToEdge = isPreservingEdgeToEdge
225233
}
226-
227-
fun setActive(active: Boolean) {
228-
this.active = active
229-
230-
if (active) {
231-
this.enable()
232-
} else {
233-
this.disable()
234-
}
235-
}
236234
// endregion
237235

238236
// region external methods

android/src/paper/java/com/reactnativekeyboardcontroller/StatusBarManagerCompatModule.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ class StatusBarManagerCompatModule(
1414

1515
override fun getName(): String = StatusBarManagerCompatModuleImpl.NAME
1616

17+
override fun getConstants(): MutableMap<String, Any>? = module.getConstants()
18+
1719
@ReactMethod
1820
private fun setHidden(hidden: Boolean) {
1921
module.setHidden(hidden)

android/src/turbo/java/com/reactnativekeyboardcontroller/KeyboardControllerPackage.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class KeyboardControllerPackage : TurboReactPackage() {
4545
ReactModuleInfo(
4646
StatusBarManagerCompatModuleImpl.NAME,
4747
StatusBarManagerCompatModuleImpl.NAME,
48-
false, // canOverrideExistingModule
48+
true, // canOverrideExistingModule
4949
false, // needsEagerInit
5050
true, // hasConstants
5151
false, // isCxxModule

src/animated.tsx

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* eslint react/jsx-sort-props: off */
2-
import React, { useLayoutEffect, useMemo, useRef, useState } from "react";
2+
import React, { useMemo, useRef, useState } from "react";
33
import { Animated, Platform, StyleSheet } from "react-native";
44
import {
55
controlEdgeToEdgeValues,
@@ -11,7 +11,6 @@ import { KeyboardControllerView } from "./bindings";
1111
import { KeyboardContext } from "./context";
1212
import { focusedInputEventsMap, keyboardEventsMap } from "./event-mappings";
1313
import { useAnimatedValue, useEventHandlerRegistration } from "./internal";
14-
import { applyMonkeyPatch, revertMonkeyPatch } from "./monkey-patch";
1514
import {
1615
useAnimatedKeyboardHandler,
1716
useFocusedInputLayoutHandler,
@@ -216,15 +215,6 @@ export const KeyboardProvider = (props: KeyboardProviderProps) => {
216215
[],
217216
);
218217

219-
// layout effects
220-
useLayoutEffect(() => {
221-
if (enabled) {
222-
applyMonkeyPatch();
223-
} else {
224-
revertMonkeyPatch();
225-
}
226-
}, [enabled]);
227-
228218
if (__DEV__) {
229219
controlEdgeToEdgeValues({
230220
statusBarTranslucent,

src/monkey-patch.android.ts

Lines changed: 0 additions & 41 deletions
This file was deleted.

src/monkey-patch.ts

Lines changed: 0 additions & 5 deletions
This file was deleted.

0 commit comments

Comments
 (0)