Skip to content

Commit f0732ee

Browse files
committed
feat: add Navigation Mode module for Android and iOS support
1 parent 8855ed2 commit f0732ee

File tree

6 files changed

+145
-0
lines changed

6 files changed

+145
-0
lines changed
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package com.mendix.mendixnative.react
2+
3+
import android.util.Log
4+
import com.facebook.react.bridge.ReactApplicationContext
5+
import com.facebook.react.bridge.ReactContextBaseJavaModule
6+
import com.facebook.react.bridge.ReactMethod
7+
8+
class NavigationModeModule(reactContext: ReactApplicationContext) :
9+
ReactContextBaseJavaModule(reactContext) {
10+
11+
companion object {
12+
const val TAG = "NavigationModeModule"
13+
const val NAVIGATION_BAR_INTERACTION_MODE_THREE_BUTTON = 0
14+
const val NAVIGATION_BAR_INTERACTION_MODE_TWO_BUTTON = 1
15+
const val NAVIGATION_BAR_INTERACTION_MODE_GESTURE = 2
16+
}
17+
18+
override fun getName(): String = "NavigationMode"
19+
20+
@ReactMethod(isBlockingSynchronousMethod = true)
21+
fun isNavigationBarActive(): Boolean {
22+
Log.d(TAG, "=== isNavigationBarActive called (sync) ===")
23+
return try {
24+
val context = reactApplicationContext
25+
Log.d(TAG, "Context: $context")
26+
27+
val resources = context.resources
28+
Log.d(TAG, "Resources: $resources")
29+
30+
val resourceId = resources.getIdentifier(
31+
"config_navBarInteractionMode",
32+
"integer",
33+
"android"
34+
)
35+
Log.d(TAG, "Resource ID: $resourceId")
36+
37+
val mode = if (resourceId > 0) {
38+
val retrievedMode = resources.getInteger(resourceId)
39+
Log.d(TAG, "Retrieved mode from resources: $retrievedMode")
40+
retrievedMode
41+
} else {
42+
Log.w(TAG, "Resource not found, defaulting to THREE_BUTTON (0)")
43+
NAVIGATION_BAR_INTERACTION_MODE_THREE_BUTTON
44+
}
45+
46+
Log.d(TAG, "Final mode value: $mode")
47+
48+
// Navigation bar is active for three-button and two-button modes
49+
val isActive = mode == NAVIGATION_BAR_INTERACTION_MODE_THREE_BUTTON ||
50+
mode == NAVIGATION_BAR_INTERACTION_MODE_TWO_BUTTON
51+
52+
Log.d(TAG, "Is navigation bar active: $isActive")
53+
Log.d(TAG, "Returning: $isActive")
54+
55+
isActive
56+
57+
} catch (e: Exception) {
58+
Log.e(TAG, "Error in isNavigationBarActive", e)
59+
false
60+
}
61+
}
62+
63+
@ReactMethod(isBlockingSynchronousMethod = true)
64+
fun getNavigationBarHeight(): Double {
65+
Log.d(TAG, "=== getNavigationBarHeight called (sync) ===")
66+
return try {
67+
val context = reactApplicationContext
68+
val resources = context.resources
69+
70+
val resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android")
71+
val height = if (resourceId > 0) {
72+
val heightPx = resources.getDimensionPixelSize(resourceId)
73+
// Convert to dp for React Native
74+
val density = resources.displayMetrics.density
75+
val heightDp = heightPx / density
76+
Log.d(TAG, "Navigation bar height: ${heightPx}px = ${heightDp}dp")
77+
heightDp.toDouble()
78+
} else {
79+
Log.w(TAG, "Navigation bar height resource not found, returning 0")
80+
0.0
81+
}
82+
83+
height
84+
85+
} catch (e: Exception) {
86+
Log.e(TAG, "Error in getNavigationBarHeight", e)
87+
0.0
88+
}
89+
}
90+
}

android/src/main/java/com/mendixnative/MendixNativeModule.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import com.mendix.mendixnative.encryption.MendixEncryptedStorageModule
1010
import com.mendix.mendixnative.react.MxConfiguration
1111
import com.mendix.mendixnative.react.NativeErrorHandler
1212
import com.mendix.mendixnative.react.NativeReloadHandler
13+
import com.mendix.mendixnative.react.NavigationModeModule
1314
import com.mendix.mendixnative.react.cookie.NativeCookieModule
1415
import com.mendix.mendixnative.react.download.NativeDownloadModule
1516
import com.mendix.mendixnative.react.fs.NativeFsModule
@@ -168,6 +169,14 @@ class MendixNativeModule(reactContext: ReactApplicationContext) : NativeMendixNa
168169
NativeErrorHandler(reactApplicationContext).handle(message, stackTrace)
169170
}
170171

172+
override fun navigationModeIsNavigationBarActive(): Boolean {
173+
return NavigationModeModule(reactApplicationContext).isNavigationBarActive()
174+
}
175+
176+
override fun navigationModeGetNavigationBarHeight(): Double {
177+
return NavigationModeModule(reactApplicationContext).getNavigationBarHeight()
178+
}
179+
171180
companion object {
172181
const val NAME = "MendixNative"
173182
}

ios/MendixNative.mm

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,5 +140,15 @@ - (void)fsReadAsText:(nonnull NSString *)filePath resolve:(nonnull RCTPromiseRes
140140
reject(@"NOT_SPPORTED", @"Read as text is not supported on iOS", nil);
141141
}
142142

143+
- (nonnull NSNumber *)navigationModeIsNavigationBarActive {
144+
// iOS doesn't have navigation bar like Android, always return false
145+
return [NSNumber numberWithBool:NO];
146+
}
147+
148+
- (double)navigationModeGetNavigationBarHeight {
149+
// iOS doesn't have navigation bar like Android, always return 0
150+
return 0.0;
151+
}
152+
143153

144154
@end

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ export * from './reload-handler';
88
export * from './encrypted-storage';
99
export * from './error-handler';
1010
export * from './file-system';
11+
export * from './navigation-mode';

src/navigation-mode.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import NativeMendixNative from './specs/NativeMendixNative';
2+
3+
/**
4+
* Navigation Mode Module
5+
*
6+
* Provides information about Android navigation bar state.
7+
* These methods are synchronous and Android-only.
8+
* On iOS, they always return false/0.
9+
*/
10+
11+
/**
12+
* Checks if the navigation bar is active on Android.
13+
* Returns true for three-button and two-button navigation modes.
14+
* Returns false for gesture navigation mode.
15+
* On iOS, always returns false.
16+
*
17+
* @returns {boolean} true if navigation bar is active, false otherwise
18+
*/
19+
export function isNavigationBarActive(): boolean {
20+
return NativeMendixNative.navigationModeIsNavigationBarActive();
21+
}
22+
23+
/**
24+
* Gets the navigation bar height in density-independent pixels (dp).
25+
* On Android, returns the actual navigation bar height.
26+
* On iOS, always returns 0.
27+
*
28+
* @returns {number} Navigation bar height in dp
29+
*/
30+
export function getNavigationBarHeight(): number {
31+
return NativeMendixNative.navigationModeGetNavigationBarHeight();
32+
}

src/specs/NativeMendixNative.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ export interface Spec extends TurboModule {
4848

4949
errorHandlerHandle(message: string, stackTrace: StackFrame[]): void;
5050

51+
navigationModeIsNavigationBarActive(): boolean;
52+
navigationModeGetNavigationBarHeight(): Double;
53+
5154
readonly onReloadWithState: EventEmitter<void>;
5255
readonly onDownloadProgress: EventEmitter<DownloadProgress>;
5356
}

0 commit comments

Comments
 (0)