Skip to content

Commit ac0df9b

Browse files
Merge pull request #35 from mendix/moo/MOO-2316-upgrade-rn-v084
[MOO-2316] Upgrade RN to v084
2 parents c3c4a9c + 2ac4402 commit ac0df9b

114 files changed

Lines changed: 2836 additions & 2064 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/CI_DOCUMENTATION.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ All workflows use standardized tooling versions to ensure consistency:
2020
| ---------------- | --------- | ----------------------------- |
2121
| **Node.js** | `24` | `.nvmrc` |
2222
| **Yarn** | `4.12.0` | `package.json#packageManager` |
23-
| **React Native** | `0.83.4` | `package.json` |
24-
| **React** | `19.2.14` | `package.json` |
23+
| **React Native** | `0.84.1` | `package.json` |
24+
| **React** | `19.2.3` | `package.json` |
2525
| **TypeScript** | `5.9.3` | `package.json` |
2626

2727
### Android Tooling
@@ -55,7 +55,7 @@ All workflows use standardized tooling versions to ensure consistency:
5555

5656
| Tool | Version | Defined In |
5757
| ------------------------ | --------------------- | ----------------------- |
58-
| **React Native Harness** | `1.0.0-alpha.21` | `package.json` |
58+
| **React Native Harness** | `1.1.0` | `package.json` |
5959
| **Android Emulator** | Pixel_API_35 (API 35) | `rn-harness.config.mjs` |
6060
| **iOS Simulator** | iPhone 17 (iOS 26.2) | `rn-harness.config.mjs` |
6161

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,6 @@ lib/
9090

9191
# Fastlane.swift runner binary
9292
**/fastlane/FastlaneRunner
93+
94+
# Harness logs/crash reports
95+
example/.harness

MendixNative.podspec

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@ Pod::Spec.new do |s|
1414
s.source = { :git => "https://github.com/mendix/mendix-native.git", :tag => "#{s.version}" }
1515

1616
s.source_files = "ios/**/*.{h,m,mm,cpp,swift}"
17-
s.public_header_files = "ios/**/*.h"
18-
s.private_header_files = "ios/**/*.h"
17+
s.public_header_files = "ios/Modules/Helper/ReactHostHelper.h"
18+
s.private_header_files = "ios/TurboModules/**/*.h"
1919

2020
s.dependency "SSZipArchive"
2121
s.dependency "RNCAsyncStorage"
22+
s.dependency "ReactAppDependencyProvider"
2223

2324
install_modules_dependencies(s)
2425
end

android/build.gradle

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@ android {
3636
}
3737

3838
buildFeatures {
39-
dataBinding true
40-
viewBinding true
4139
buildConfig true
4240
}
4341

@@ -88,7 +86,7 @@ dependencies {
8886
kapt 'com.github.bumptech.glide:compiler:4.12.0'
8987

9088

91-
api "com.facebook.react:react-android:0.83.4"
89+
api "com.facebook.react:react-android:0.84.1"
9290
api project(':op-engineering_op-sqlite')
9391
api project(':react-native-async-storage_async-storage')
9492
api project(':react-native-gesture-handler')

android/src/main/java/com/facebook/react/devsupport/DevInternalSettings.kt

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

android/src/main/java/com/facebook/react/devsupport/DevSupportManagerHelpers.kt

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

android/src/main/java/com/mendix/mendixnative/MendixInitializer.kt

Lines changed: 10 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,25 @@
11
package com.mendix.mendixnative
22

33
import android.app.Activity
4-
import android.view.MotionEvent
54
import com.facebook.react.ReactHost
6-
import com.facebook.react.ReactInstanceEventListener
7-
import com.facebook.react.ReactNativeHost
8-
import com.facebook.react.bridge.ReactContext
9-
import com.facebook.react.common.ShakeDetector
105
import com.facebook.react.devsupport.DevSupportManagerBase
11-
import com.facebook.react.devsupport.attachMendixSupportManagerShakeDetector
12-
import com.facebook.react.devsupport.makeShakeDetector
136
import com.facebook.react.modules.network.OkHttpClientProvider
147
import com.mendix.mendixnative.config.AppPreferences
15-
import com.mendix.mendixnative.handler.DevMenuTouchEventHandler
168
import com.mendix.mendixnative.react.*
179
import com.mendix.mendixnative.request.MendixNetworkInterceptor
1810
import com.mendix.mendixnative.util.CookieEncryption
1911
import com.mendix.mendixnative.react.MxConfiguration
2012
import com.mendix.mendixnative.react.clearCachedReactNativeDevBundle
2113
import com.mendix.mendixnative.react.clearData
2214
import com.mendix.mendixnative.react.closeSqlDatabaseConnection
23-
import com.mendix.mendixnative.react.toggleElementInspector
24-
import com.mendixnative.MendixNativeModule
2515

2616
class MendixInitializer(
2717
private val context: Activity,
2818
private val reactHost: ReactHost,
29-
private val reactNativeHost: ReactNativeHost,
3019
private val hasRNDeveloperSupport: Boolean = false,
31-
) : ReactInstanceEventListener {
32-
private var shakeDetector: ShakeDetector? = null
33-
private var devMenuTouchEventHandler: DevMenuTouchEventHandler? = null
20+
) {
3421

35-
fun onCreate(
36-
mendixApp: MendixApp,
37-
devAppMenuHandler: DevAppMenuHandler = object : DevAppMenuHandler {
38-
override fun showDevAppMenu() {}
39-
},
40-
clearData: Boolean,
41-
) {
22+
fun onCreate(mendixApp: MendixApp, clearData: Boolean) {
4223
// Assign mendix xas id interceptor to okhttp
4324
CookieEncryption.init(this.context)
4425
if (CookieEncryption.isCookieEncryptionEnabled()) {
@@ -53,77 +34,25 @@ class MendixInitializer(
5334
MxConfiguration.runtimeUrl = runtimeUrl
5435
MxConfiguration.warningsFilter = mendixApp.warningsFilter
5536

56-
// This is here to make sure that a clean host instance is initialised.
57-
restartReactInstanceManager()
37+
// Reload only if there's already a running instance.
38+
if (reactHost.currentReactContext != null) {
39+
reactHost.reload("Clean start for new Mendix app")
40+
}
5841
if (clearData) clearData(context.application)
5942
if (hasRNDeveloperSupport) setupDeveloperApp(runtimeUrl, mendixApp)
60-
if (mendixApp.attachCustomDeveloperMenu) attachCustomDeveloperMenu(devAppMenuHandler)
61-
}
62-
63-
private fun restartReactInstanceManager() {
64-
if (reactNativeHost.hasInstance()) reactNativeHost.clear()
65-
// Pre-initialize reactInstanceManager to be available for other methods
66-
if (reactNativeHost.hasInstance()) reactNativeHost.reactInstanceManager
67-
}
68-
69-
private fun attachCustomDeveloperMenu(devAppMenuHandler: DevAppMenuHandler) {
70-
devMenuTouchEventHandler =
71-
DevMenuTouchEventHandler(object : DevMenuTouchEventHandler.DevMenuTouchListener {
72-
override fun onTap() {
73-
reactNativeHost.typeSafeNativeModule<MendixNativeModule>()?.reloadClientWithState()
74-
}
75-
76-
override fun onLongPress() {
77-
devAppMenuHandler.showDevAppMenu()
78-
}
79-
})
80-
81-
attachShakeDetector(devAppMenuHandler)
8243
}
8344

8445
fun onDestroy() {
85-
// Stop shaking as early as possible to avoid orphaned dialogs
86-
stopShakeDetector()
87-
8846
if (hasRNDeveloperSupport) {
8947
AppPreferences(context.applicationContext).setElementInspector(false)
90-
reactHost.removeReactInstanceEventListener(this)
9148
}
92-
93-
// We need to clear the host to allow for reinitialization of the Native Modules
94-
// Especially for when switching between apps
95-
reactNativeHost.clear()
49+
// Destroy the current instance but keep the host reusable — invalidate() is terminal
50+
// in bridgeless mode and would prevent the host from ever starting a new instance.
51+
reactHost.destroy("MendixInitializer.onDestroy()", null)
9652

9753
// We need to close all databases separately to avoid hitting a read only state exception
9854
// Databases need to close after we are done closing the react native host to avoid db locks
99-
closeSqlDatabaseConnection(reactNativeHost.reactApplicationContext())
100-
}
101-
102-
fun stopShakeDetector() {
103-
shakeDetector?.stop()
104-
}
105-
106-
override fun onReactContextInitialized(context: ReactContext) {
107-
val preferences = AppPreferences(context)
108-
if (preferences.isElementInspectorEnabled) {
109-
toggleElementInspector(context)
110-
}
111-
}
112-
113-
fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
114-
return devMenuTouchEventHandler?.handle(ev) ?: false
115-
}
116-
117-
private fun attachShakeDetector(devAppMenuHandler: DevAppMenuHandler) {
118-
if (shakeDetector == null) {
119-
shakeDetector = makeShakeDetector(context.applicationContext) {
120-
devAppMenuHandler.showDevAppMenu()
121-
}
122-
}
123-
124-
(reactHost.devSupportManager as? DevSupportManagerBase)?.run {
125-
attachMendixSupportManagerShakeDetector(shakeDetector!!, this)
126-
}
55+
closeSqlDatabaseConnection(reactHost.currentReactContext)
12756
}
12857

12958
private fun setupDeveloperApp(
@@ -137,7 +66,6 @@ class MendixInitializer(
13766
preferences.setDevMode((mendixApp.showExtendedDevMenu))
13867

13968
clearCachedReactNativeDevBundle(context.application)
140-
reactHost.addReactInstanceEventListener(this)
14169
}
14270
}
14371

android/src/main/java/com/mendix/mendixnative/MendixReactApplication.kt

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import com.facebook.react.common.annotations.UnstableReactNativeAPI
1010
import com.facebook.react.defaults.DefaultComponentsRegistry
1111
import com.facebook.react.defaults.DefaultReactHostDelegate
1212
import com.facebook.react.defaults.DefaultTurboModuleManagerDelegate
13+
import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener
1314
import com.facebook.react.devsupport.interfaces.RedBoxHandler
1415
import com.facebook.react.fabric.ComponentFactory
1516
import com.facebook.react.runtime.ReactHostImpl
@@ -20,6 +21,7 @@ import com.mendix.mendixnative.error.ErrorHandler
2021
import com.mendix.mendixnative.error.ErrorHandlerFactory
2122
import com.mendix.mendixnative.error.mapErrorHandlerToRedBox
2223
import com.mendix.mendixnative.handler.DummyErrorHandler
24+
import com.mendix.mendixnative.devsupport.MendixDevSupportManagerFactory
2325
import com.mendix.mendixnative.react.ota.OtaJSBundleUrlProvider
2426
import com.mendix.mendixnative.react.splash.MendixSplashScreenPresenter
2527
import com.mendixnative.MendixNativePackage
@@ -106,11 +108,12 @@ abstract class MendixReactApplication : Application(), MendixApplication, ErrorH
106108
val componentFactory = ComponentFactory()
107109
DefaultComponentsRegistry.register(componentFactory)
108110
ReactHostImpl(
109-
applicationContext,
110-
delegate,
111-
componentFactory,
112-
true /* allowPackagerServerAccess */,
113-
useDeveloperSupport,
111+
context = applicationContext,
112+
reactHostDelegate = delegate,
113+
componentFactory = componentFactory,
114+
allowPackagerServerAccess = true,
115+
useDevSupport = useDeveloperSupport,
116+
devSupportManagerFactory = MendixDevSupportManagerFactory(devBundleDownloadListener),
114117
)
115118
}
116119

@@ -158,4 +161,14 @@ abstract class MendixReactApplication : Application(), MendixApplication, ErrorH
158161

159162
open val jsBundleProvider: JSBundleFileProvider?
160163
get() = null
164+
165+
/**
166+
* Override this to provide a [DevBundleDownloadListener] that receives bundle download
167+
* progress, success, and failure callbacks. This is used to drive custom loading UIs.
168+
*
169+
* The listener is injected at [ReactHost] creation time via [MendixDevSupportManagerFactory].
170+
* Use a delegating holder pattern if the actual listener is created after app initialization.
171+
*/
172+
open val devBundleDownloadListener: DevBundleDownloadListener?
173+
get() = null
161174
}

android/src/main/java/com/mendix/mendixnative/activity/MendixReactActivity.kt

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package com.mendix.mendixnative.activity
22

33
import android.os.Bundle
44
import android.view.KeyEvent
5-
import android.view.MotionEvent
65
import com.facebook.react.ReactActivity
76
import com.facebook.react.ReactActivityDelegate
87
import com.facebook.react.bridge.ReactContext
@@ -31,8 +30,8 @@ open class MendixReactActivity : ReactActivity(), DevAppMenuHandler, LaunchScree
3130
?: throw ClassCastException("Application needs to implement MendixApplication")
3231

3332
mendixInitializer =
34-
MendixInitializer(this, reactHost, reactNativeHost, mendixApplication.useDeveloperSupport)
35-
mendixInitializer.onCreate(mendixApp!!, this, intent.getBooleanExtra(CLEAR_DATA, false))
33+
MendixInitializer(this, reactHost, mendixApplication.useDeveloperSupport)
34+
mendixInitializer.onCreate(mendixApp!!, intent.getBooleanExtra(CLEAR_DATA, false))
3635

3736
super.onCreate(null)
3837
}
@@ -42,12 +41,6 @@ open class MendixReactActivity : ReactActivity(), DevAppMenuHandler, LaunchScree
4241
super.onDestroy()
4342
}
4443

45-
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
46-
return if (mendixInitializer.dispatchTouchEvent(ev)) {
47-
true
48-
} else super.dispatchTouchEvent(ev)
49-
}
50-
5144
override fun getMainComponentName(): String? {
5245
return MAIN_COMPONENT_NAME
5346
}
@@ -66,7 +59,9 @@ open class MendixReactActivity : ReactActivity(), DevAppMenuHandler, LaunchScree
6659
return object : ReactActivityDelegate(this, mainComponentName) {
6760
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
6861
if (keyCode == KeyEvent.KEYCODE_MENU) {
69-
showDevAppMenu()
62+
if (mendixApp?.showExtendedDevMenu == true) {
63+
showDevAppMenu()
64+
}
7065
return true
7166
}
7267
return super.onKeyUp(keyCode, event)
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package com.mendix.mendixnative.devsupport
2+
3+
import android.content.Context
4+
import com.facebook.react.bridge.UiThreadUtil
5+
import com.facebook.react.common.SurfaceDelegateFactory
6+
import com.facebook.react.devsupport.DevSupportManagerBase
7+
import com.facebook.react.devsupport.ReactInstanceDevHelper
8+
import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener
9+
import com.facebook.react.devsupport.interfaces.DevLoadingViewManager
10+
import com.facebook.react.devsupport.interfaces.PausedInDebuggerOverlayManager
11+
import com.facebook.react.devsupport.interfaces.RedBoxHandler
12+
import com.facebook.react.packagerconnection.RequestHandler
13+
14+
/**
15+
* A public DevSupportManager implementation for Mendix apps in bridgeless mode.
16+
*
17+
* This mirrors the behavior of React Native's internal [BridgelessDevSupportManager]
18+
* but is accessible from external modules, allowing us to inject a custom
19+
* [DevBundleDownloadListener] at construction time without reflection.
20+
*/
21+
class MendixBridgelessDevSupportManager(
22+
applicationContext: Context,
23+
reactInstanceManagerHelper: ReactInstanceDevHelper,
24+
packagerPathForJSBundleName: String?,
25+
enableOnCreate: Boolean,
26+
redBoxHandler: RedBoxHandler?,
27+
devBundleDownloadListener: DevBundleDownloadListener?,
28+
minNumShakes: Int,
29+
customPackagerCommandHandlers: Map<String, RequestHandler>?,
30+
surfaceDelegateFactory: SurfaceDelegateFactory?,
31+
devLoadingViewManager: DevLoadingViewManager?,
32+
pausedInDebuggerOverlayManager: PausedInDebuggerOverlayManager?,
33+
) : DevSupportManagerBase(
34+
applicationContext,
35+
reactInstanceManagerHelper,
36+
packagerPathForJSBundleName,
37+
enableOnCreate,
38+
redBoxHandler,
39+
devBundleDownloadListener,
40+
minNumShakes,
41+
customPackagerCommandHandlers,
42+
surfaceDelegateFactory,
43+
devLoadingViewManager,
44+
pausedInDebuggerOverlayManager,
45+
) {
46+
override val uniqueTag: String get() = "MendixBridgeless"
47+
48+
override fun handleReloadJS() {
49+
UiThreadUtil.assertOnUiThread()
50+
hideRedboxDialog()
51+
reactInstanceDevHelper.reload("MendixBridgelessDevSupportManager.handleReloadJS()")
52+
}
53+
}

0 commit comments

Comments
 (0)