Skip to content

Commit 1ec9b64

Browse files
feat: enhance development experience with improved debug settings and event emission
1 parent c1b1b8a commit 1ec9b64

9 files changed

Lines changed: 40 additions & 46 deletions

File tree

example/ios/MendixNativeExample/AppDelegate.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ class AppDelegate: ReactAppProvider {
88
override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
99
setUpProvider()
1010
guard let bundleUrl = reactNativeDelegate?.bundleURL() else {
11-
fatalError("Unable to find index.js")
11+
let message = "No script URL provided. Make sure the metro packager is running or you have embedded a JS bundle in your application bundle."
12+
fatalError(message)
1213
}
1314
let mendixApp = MendixApp.init(
1415
identifier: nil,
@@ -21,6 +22,10 @@ class AppDelegate: ReactAppProvider {
2122
reactLoading: nil,
2223
enableThreeFingerGestures: false
2324
)
25+
26+
AppPreferences.devModeEnabled = true
27+
AppPreferences.remoteDebuggingEnabled = true
28+
2429
ReactNative.shared.setup(mendixApp, launchOptions: nil)
2530
ReactNative.shared.start()
2631
return super.application(application, didFinishLaunchingWithOptions: launchOptions)

ios/Modules/Helper/DevHelper.swift

Lines changed: 3 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,44 +2,11 @@ import Foundation
22
import React
33

44
public class DevHelper {
5-
6-
public static func showAppMenu() {
7-
devMenu?.show()
8-
}
9-
10-
public static func toggleElementInspector() {
11-
devSettings?.toggleElementInspector()
12-
}
13-
14-
// Modern Architecture: Access dev modules through ReactAppProvider's moduleRegistry
15-
// Works with RN 0.83+ where RCTBridge.current() returns nil
16-
public static var devSettings: RCTDevSettings? {
17-
return ReactAppProvider.getModule(name: RCTDevSettings.moduleName(), type: RCTDevSettings.self)
18-
}
19-
20-
public static var devMenu: RCTDevMenu? {
21-
return ReactAppProvider.getModule(name: RCTDevSettings.moduleName(), type: RCTDevMenu.self)
22-
}
23-
245
public static func setDebugMode(enabled: Bool) {
256
AppPreferences.remoteDebuggingEnabled = enabled
26-
27-
// Modern Architecture (RN 0.83+):
28-
// Debug operations are controlled from JavaScript via the DevSettings TurboModule.
29-
// Native code no longer needs to control debugging - it's all JavaScript-driven.
30-
//
31-
// To open the debugger from JavaScript:
32-
// import { DevSettings } from 'mendix-native';
33-
// DevSettings.openDebugger();
34-
//
35-
// This method now only stores the preference. Actual debug control is via JavaScript.
367
}
37-
38-
public static func hideDevLoadingView() {
39-
devLoadingView?.hide()
40-
}
41-
42-
public static var devLoadingView: RCTDevLoadingView? {
43-
return ReactAppProvider.getModule(name: RCTDevSettings.moduleName(), type: RCTDevLoadingView.self)
8+
9+
public static func setShakeToShowDevMenuEnabled(enabled: Bool) {
10+
ReactHostHelper().emitEvent("mendixSetShakeToShowDevMenu", payload: enabled)
4411
}
4512
}

ios/Modules/Helper/ReactAppProvider.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ open class ReactAppProvider: UIResponder, UIApplicationDelegate {
3737
controller.view = reactAppView()
3838
changeRoot(to: controller)
3939
}
40+
41+
public func start() {
42+
reactNativeFactory?.startReactNative(withModuleName: moduleName, in: window)
43+
}
4044

4145
public func reactAppView() -> UIView? {
4246
guard let view = reactNativeFactory?.rootViewFactory.view(withModuleName: reactRootViewName) else {

ios/Modules/Helper/ReactHostHelper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ NS_ASSUME_NONNULL_BEGIN
1414
- (nullable id) moduleForName: (NSString *) name;
1515
- (void) reloadClientWithState;
1616
- (BOOL) isReactAppActive;
17+
- (void) emitEvent: (nonnull NSString*) eventName payload: (nullable id) payload;
1718

1819
@end
1920

ios/Modules/Helper/ReactHostHelper.mm

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,17 @@ - (BOOL)isReactAppActive {
6262
}
6363
}
6464

65+
- (void)emitEvent:(nonnull NSString *)eventName payload:(nullable id)payload {
66+
RCTHost *reactHost = [self currentHost];
67+
68+
NSMutableArray *args = [NSMutableArray arrayWithObject:eventName];
69+
if (payload != nil) {
70+
[args addObject:payload];
71+
}
72+
73+
[reactHost callFunctionOnJSModule:@"RCTDeviceEventEmitter" method:@"emit" args:args];
74+
}
75+
6576
@end
6677

6778
NS_ASSUME_NONNULL_END

ios/Modules/ReactNative.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ open class ReactNative: NSObject, RCTReloadListener {
4848

4949
ReactAppProvider.shared()?.setReactViewController(mendixApp.reactLoading?.instantiateInitialViewController() ?? UIViewController())
5050

51-
DevHelper.devSettings?.isShakeToShowDevMenuEnabled = false
51+
DevHelper.setShakeToShowDevMenuEnabled(enabled: AppPreferences.devModeEnabled)
5252
DevHelper.setDebugMode(enabled: AppPreferences.devModeEnabled && AppPreferences.remoteDebuggingEnabled)
5353

5454
showSplashScreen()
@@ -75,7 +75,6 @@ open class ReactNative: NSObject, RCTReloadListener {
7575

7676
public func hideSplashScreen() {
7777
mendixApp?.splashScreenPresenter?.hide()
78-
DevHelper.hideDevLoadingView()
7978
}
8079

8180
// MARK: - Reload Methods

ios/TurboModules/MxReload/MxReload.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,4 @@
22

33
@interface MxReload : NativeMxReloadSpecBase <NativeMxReloadSpec>
44

5-
- (void)reloadClientWithState;
6-
75
@end

ios/TurboModules/MxReload/MxReload.mm

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,4 @@ - (void)exitApp:(nonnull RCTPromiseResolveBlock)resolve
2525
resolve(nil);
2626
}
2727

28-
- (void)reloadClientWithState {
29-
[self emitOnReloadWithState];
30-
}
31-
3228
@end

src/dev-settings.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,20 @@
1-
import { NativeModules, Platform } from 'react-native';
1+
import { DeviceEventEmitter, NativeModules, Platform } from 'react-native';
22

33
const NativeDevSettings = NativeModules.DevSettings;
44

5+
// Listen for native-to-JS calls to control shake gesture.
6+
// In RN 0.84+ bridgeless mode, native cannot directly set this on RCTDevSettings
7+
// because the TurboModule instance isn't accessible via moduleForName. Instead,
8+
// native uses RCTHost.callFunctionOnJSModule to emit this event.
9+
if (__DEV__ && Platform.OS === 'ios') {
10+
DeviceEventEmitter.addListener(
11+
'mendixSetShakeToShowDevMenu',
12+
(enabled: boolean) => {
13+
NativeDevSettings?.setIsShakeToShowDevMenuEnabled?.(enabled);
14+
}
15+
);
16+
}
17+
518
/**
619
* Controls debugging and development settings using React Native's built-in APIs.
720
*

0 commit comments

Comments
 (0)