react-native-navigation-mode 1.2.7 → 1.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -67,12 +67,18 @@ class NavigationModeModule(reactContext: ReactApplicationContext) :
67
67
 
68
68
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
69
69
  val navBarInteractionMode = getNavBarInteractionMode(context)
70
+ val isGesture = if (navBarInteractionMode == 2) true else isGestureNavigationBySettings(context)
70
71
  result.putInt("interactionMode", navBarInteractionMode)
71
- result.putString("type", getNavigationTypeFromInteractionMode(navBarInteractionMode))
72
- result.putBoolean("isGestureNavigation", navBarInteractionMode == 2)
72
+ result.putString(
73
+ "type",
74
+ if (isGesture) "gesture" else getNavigationTypeFromInteractionMode(navBarInteractionMode)
75
+ )
76
+ result.putBoolean("isGestureNavigation", isGesture)
73
77
  } else {
74
- val gestureNavEnabled = isGestureNavigationEnabledLegacy(context)
78
+ val gestureNavEnabled = isGestureNavigationBySettings(context)
75
79
  result.putBoolean("isGestureNavigation", gestureNavEnabled)
80
+ // Set "type" for pre-Q devices so the field is always present in the result
81
+ result.putString("type", if (gestureNavEnabled) "gesture" else "unknown")
76
82
  }
77
83
 
78
84
  promise.resolve(result)
@@ -87,9 +93,10 @@ class NavigationModeModule(reactContext: ReactApplicationContext) :
87
93
 
88
94
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
89
95
  val navBarInteractionMode = getNavBarInteractionMode(context)
90
- promise.resolve(navBarInteractionMode == 2)
96
+ val isGesture = if (navBarInteractionMode == 2) true else isGestureNavigationBySettings(context)
97
+ promise.resolve(isGesture)
91
98
  } else {
92
- val gestureEnabled = isGestureNavigationEnabledLegacy(context)
99
+ val gestureEnabled = isGestureNavigationBySettings(context)
93
100
  promise.resolve(gestureEnabled)
94
101
  }
95
102
  } catch (e: Exception) {
@@ -120,17 +127,72 @@ class NavigationModeModule(reactContext: ReactApplicationContext) :
120
127
  }
121
128
  }
122
129
 
123
- private fun isGestureNavigationEnabledLegacy(context: Context): Boolean {
124
- // Legacy fallback using Settings.Secure (for pre-Android Q devices)
125
- // or as a backup when config_navBarInteractionMode is not available
126
- return try {
127
- val navBarMode = Settings.Secure.getString(
128
- context.contentResolver,
129
- "navigation_mode"
130
- )
131
- "2" == navBarMode
132
- } catch (e: Exception) {
133
- false
130
+ // Detects gesture navigation via Settings providers. Used as:
131
+ // - The sole detection method on pre-Android Q (API < 29) devices.
132
+ // - A supplementary fallback on Android Q+ when config_navBarInteractionMode does not
133
+ // return 2, since some OEM firmwares (e.g. Huawei Mate 30 Pro) leave that resource at
134
+ // its default value of 0 even after the user enables gesture navigation.
135
+ private fun isGestureNavigationBySettings(context: Context): Boolean {
136
+ // Standard AOSP key available on Android 10+ stock and most OEMs.
137
+ // "2" = gesture, "0" = 3-button, "1" = 2-button.
138
+ try {
139
+ val navBarMode = Settings.Secure.getString(
140
+ context.contentResolver,
141
+ "navigation_mode"
142
+ )
143
+ if ("2" == navBarMode) {
144
+ return true
145
+ }
146
+ if ("0" == navBarMode || "1" == navBarMode) {
147
+ return false
148
+ }
149
+ } catch (e: Exception) {
150
+ // Ignore and continue with OEM-specific fallbacks
151
+ }
152
+
153
+ // Huawei / Honor EMUI: written to Settings.Global when the user collapses the nav bar
154
+ // into the gesture handle. Value 1 = gestures enabled.
155
+ val huaweiNavigationBarMinGlobal = getGlobalIntSetting(context, "navigationbar_is_min")
156
+ if (huaweiNavigationBarMinGlobal != null) {
157
+ return huaweiNavigationBarMinGlobal == 1
158
+ }
159
+
160
+ // Huawei / Honor EMUI (alternate key seen on some firmware versions).
161
+ // Value 1 = gesture navigation enabled.
162
+ val huaweiSecureGesture = getSecureIntSetting(context, "secure_gesture_navigation")
163
+ if (huaweiSecureGesture != null) {
164
+ return huaweiSecureGesture == 1
165
+ }
166
+
167
+ // Xiaomi MIUI: set to 1 when the "full-screen gesture" nav bar is active.
168
+ val xiaomiForceGesture = getGlobalIntSetting(context, "force_fsg_nav_bar")
169
+ if (xiaomiForceGesture != null) {
170
+ return xiaomiForceGesture == 1
171
+ }
172
+
173
+ // Samsung One UI: toggled when the user switches to "Swipe gestures" in nav bar settings.
174
+ // Value 1 = gesture navigation enabled.
175
+ val samsungNavigationGesture = getSecureIntSetting(context, "navigation_gesture_on")
176
+ if (samsungNavigationGesture != null) {
177
+ return samsungNavigationGesture == 1
178
+ }
179
+
180
+ return false
181
+ }
182
+
183
+ private fun getSecureIntSetting(context: Context, key: String): Int? {
184
+ return try {
185
+ Settings.Secure.getInt(context.contentResolver, key)
186
+ } catch (e: Exception) {
187
+ null
188
+ }
189
+ }
190
+
191
+ private fun getGlobalIntSetting(context: Context, key: String): Int? {
192
+ return try {
193
+ Settings.Global.getInt(context.contentResolver, key)
194
+ } catch (e: Exception) {
195
+ null
196
+ }
134
197
  }
135
- }
136
198
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-navigation-mode",
3
- "version": "1.2.7",
3
+ "version": "1.2.8",
4
4
  "description": "Detect Android navigation mode (3-button, 2-button, or gesture)",
5
5
  "main": "./lib/module/index.js",
6
6
  "react-native": "./lib/module/index.js",
@@ -110,7 +110,7 @@
110
110
  "workspaces": [
111
111
  "example"
112
112
  ],
113
- "packageManager": "yarn@3.6.1",
113
+ "packageManager": "yarn@4.9.2",
114
114
  "jest": {
115
115
  "preset": "react-native",
116
116
  "modulePathIgnorePatterns": [