react-native-list 1.0.0 → 2.0.0-alpha.1

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.
Files changed (200) hide show
  1. package/README.md +190 -32
  2. package/ReactNativeList.podspec +39 -0
  3. package/android/CMakeLists.txt +48 -0
  4. package/android/build.gradle +151 -0
  5. package/android/fix-prefab.gradle +51 -0
  6. package/android/gradle.properties +5 -0
  7. package/android/src/main/AndroidManifest.xml +2 -0
  8. package/android/src/main/cpp/JHybridUiListModule.cpp +192 -0
  9. package/android/src/main/cpp/JHybridUiListModule.h +50 -0
  10. package/android/src/main/cpp/cpp-adapter.cpp +12 -0
  11. package/android/src/main/java/com/hannojg/reactnativelist/ReactNativeListPackage.kt +27 -0
  12. package/android/src/main/java/com/margelo/nitro/reactnativelist/HybridNativeListDataSource.kt +146 -0
  13. package/android/src/main/java/com/margelo/nitro/reactnativelist/HybridNativeListLayout.kt +86 -0
  14. package/android/src/main/java/com/margelo/nitro/reactnativelist/HybridUiListModule.kt +116 -0
  15. package/android/src/main/java/com/margelo/nitro/reactnativelist/HybridUiListView.kt +410 -0
  16. package/android/src/main/java/com/margelo/nitro/reactnativelist/HybridViewHolder.kt +9 -0
  17. package/android/src/main/java/com/margelo/nitro/reactnativelist/NativeListAdapter.kt +217 -0
  18. package/ios/DataSource/HybridNativeListDataSource.swift +213 -0
  19. package/ios/HybridObjects/HybridUiListModule.swift +49 -0
  20. package/ios/HybridObjects/HybridViewHolder.swift +16 -0
  21. package/ios/Layout/HybridNativeListLayout.swift +128 -0
  22. package/ios/Utils/ErrorUtils.h +26 -0
  23. package/ios/Utils/HybridIOSWorkletsModuleProxyHolder.swift +10 -0
  24. package/ios/Utils/SurfaceHelper.h +20 -0
  25. package/ios/Utils/SurfaceHelper.mm +144 -0
  26. package/ios/Utils/SurfacePresenterRegistry.h +17 -0
  27. package/ios/Utils/SurfacePresenterRegistry.m +31 -0
  28. package/ios/Utils/TurboModuleInstaller.h +18 -0
  29. package/ios/Utils/TurboModuleInstaller.mm +267 -0
  30. package/ios/Views/HostCell.swift +216 -0
  31. package/ios/Views/HybridUiListView.swift +695 -0
  32. package/metro/RendererProxyThreadSwitch.js +66 -0
  33. package/metro-config.d.ts +1 -0
  34. package/metro-config.js +52 -0
  35. package/nitro.json +47 -0
  36. package/nitrogen/generated/.gitattributes +1 -0
  37. package/nitrogen/generated/android/ReactNativeList+autolinking.cmake +99 -0
  38. package/nitrogen/generated/android/ReactNativeList+autolinking.gradle +27 -0
  39. package/nitrogen/generated/android/ReactNativeListOnLoad.cpp +156 -0
  40. package/nitrogen/generated/android/ReactNativeListOnLoad.hpp +34 -0
  41. package/nitrogen/generated/android/c++/JFunc_bool_NativeListItem_NativeListItem.hpp +83 -0
  42. package/nitrogen/generated/android/c++/JFunc_bool_double_NativeListItem_double.hpp +83 -0
  43. package/nitrogen/generated/android/c++/JFunc_double_std__string.hpp +78 -0
  44. package/nitrogen/generated/android/c++/JHybridIOSWorkletsModuleProxyHolderSpec.cpp +49 -0
  45. package/nitrogen/generated/android/c++/JHybridIOSWorkletsModuleProxyHolderSpec.hpp +63 -0
  46. package/nitrogen/generated/android/c++/JHybridNativeLinearListLayoutSpec.cpp +63 -0
  47. package/nitrogen/generated/android/c++/JHybridNativeLinearListLayoutSpec.hpp +65 -0
  48. package/nitrogen/generated/android/c++/JHybridNativeListDataSourceSpec.cpp +101 -0
  49. package/nitrogen/generated/android/c++/JHybridNativeListDataSourceSpec.hpp +70 -0
  50. package/nitrogen/generated/android/c++/JHybridNativeListLayoutSpec.cpp +49 -0
  51. package/nitrogen/generated/android/c++/JHybridNativeListLayoutSpec.hpp +63 -0
  52. package/nitrogen/generated/android/c++/JHybridUiListModuleSpec.cpp +65 -0
  53. package/nitrogen/generated/android/c++/JHybridUiListModuleSpec.hpp +64 -0
  54. package/nitrogen/generated/android/c++/JHybridUiListViewSpec.cpp +92 -0
  55. package/nitrogen/generated/android/c++/JHybridUiListViewSpec.hpp +67 -0
  56. package/nitrogen/generated/android/c++/JHybridViewHolderSpec.cpp +49 -0
  57. package/nitrogen/generated/android/c++/JHybridViewHolderSpec.hpp +63 -0
  58. package/nitrogen/generated/android/c++/JNativeItemSizeEstimate.hpp +61 -0
  59. package/nitrogen/generated/android/c++/JNativeLinearListLayoutConfig.hpp +81 -0
  60. package/nitrogen/generated/android/c++/JNativeLinearListLayoutIOSConfig.hpp +59 -0
  61. package/nitrogen/generated/android/c++/JNativeListItem.hpp +76 -0
  62. package/nitrogen/generated/android/c++/JVariant_NullType_HybridIOSWorkletsModuleProxyHolderSpec.cpp +26 -0
  63. package/nitrogen/generated/android/c++/JVariant_NullType_HybridIOSWorkletsModuleProxyHolderSpec.hpp +72 -0
  64. package/nitrogen/generated/android/c++/views/JHybridUiListViewStateUpdater.cpp +53 -0
  65. package/nitrogen/generated/android/c++/views/JHybridUiListViewStateUpdater.hpp +49 -0
  66. package/nitrogen/generated/android/c++/views/JHybridViewHolderStateUpdater.cpp +53 -0
  67. package/nitrogen/generated/android/c++/views/JHybridViewHolderStateUpdater.hpp +49 -0
  68. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/Func_bool_NativeListItem_NativeListItem.kt +80 -0
  69. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/Func_bool_double_NativeListItem_double.kt +80 -0
  70. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/Func_double_std__string.kt +80 -0
  71. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridIOSWorkletsModuleProxyHolderSpec.kt +52 -0
  72. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridNativeLinearListLayoutSpec.kt +54 -0
  73. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridNativeListDataSourceSpec.kt +87 -0
  74. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridNativeListLayoutSpec.kt +52 -0
  75. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridUiListModuleSpec.kt +59 -0
  76. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridUiListViewSpec.kt +76 -0
  77. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridViewHolderSpec.kt +53 -0
  78. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/NativeItemSizeEstimate.kt +56 -0
  79. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/NativeLinearListLayoutConfig.kt +76 -0
  80. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/NativeLinearListLayoutIOSConfig.kt +51 -0
  81. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/NativeListItem.kt +71 -0
  82. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/ReactNativeListOnLoad.kt +35 -0
  83. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/Variant_NullType_HybridIOSWorkletsModuleProxyHolderSpec.kt +62 -0
  84. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/views/HybridUiListViewManager.kt +80 -0
  85. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/views/HybridUiListViewStateUpdater.kt +23 -0
  86. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/views/HybridViewHolderManager.kt +80 -0
  87. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/views/HybridViewHolderStateUpdater.kt +23 -0
  88. package/nitrogen/generated/ios/ReactNativeList+autolinking.rb +62 -0
  89. package/nitrogen/generated/ios/ReactNativeList-Swift-Cxx-Bridge.cpp +162 -0
  90. package/nitrogen/generated/ios/ReactNativeList-Swift-Cxx-Bridge.hpp +368 -0
  91. package/nitrogen/generated/ios/ReactNativeList-Swift-Cxx-Umbrella.hpp +92 -0
  92. package/nitrogen/generated/ios/ReactNativeListAutolinking.mm +83 -0
  93. package/nitrogen/generated/ios/ReactNativeListAutolinking.swift +86 -0
  94. package/nitrogen/generated/ios/c++/HybridIOSWorkletsModuleProxyHolderSpecSwift.cpp +11 -0
  95. package/nitrogen/generated/ios/c++/HybridIOSWorkletsModuleProxyHolderSpecSwift.hpp +75 -0
  96. package/nitrogen/generated/ios/c++/HybridNativeLinearListLayoutSpecSwift.cpp +11 -0
  97. package/nitrogen/generated/ios/c++/HybridNativeLinearListLayoutSpecSwift.hpp +92 -0
  98. package/nitrogen/generated/ios/c++/HybridNativeListDataSourceSpecSwift.cpp +11 -0
  99. package/nitrogen/generated/ios/c++/HybridNativeListDataSourceSpecSwift.hpp +132 -0
  100. package/nitrogen/generated/ios/c++/HybridNativeListLayoutSpecSwift.cpp +11 -0
  101. package/nitrogen/generated/ios/c++/HybridNativeListLayoutSpecSwift.hpp +75 -0
  102. package/nitrogen/generated/ios/c++/HybridUiListModuleSpecSwift.cpp +11 -0
  103. package/nitrogen/generated/ios/c++/HybridUiListModuleSpecSwift.hpp +93 -0
  104. package/nitrogen/generated/ios/c++/HybridUiListViewSpecSwift.cpp +11 -0
  105. package/nitrogen/generated/ios/c++/HybridUiListViewSpecSwift.hpp +121 -0
  106. package/nitrogen/generated/ios/c++/HybridViewHolderSpecSwift.cpp +11 -0
  107. package/nitrogen/generated/ios/c++/HybridViewHolderSpecSwift.hpp +75 -0
  108. package/nitrogen/generated/ios/c++/views/HybridUiListViewComponent.mm +118 -0
  109. package/nitrogen/generated/ios/c++/views/HybridViewHolderComponent.mm +118 -0
  110. package/nitrogen/generated/ios/swift/Func_bool_NativeListItem_NativeListItem.swift +47 -0
  111. package/nitrogen/generated/ios/swift/Func_bool_double_NativeListItem_double.swift +47 -0
  112. package/nitrogen/generated/ios/swift/Func_double_std__string.swift +47 -0
  113. package/nitrogen/generated/ios/swift/HybridIOSWorkletsModuleProxyHolderSpec.swift +55 -0
  114. package/nitrogen/generated/ios/swift/HybridIOSWorkletsModuleProxyHolderSpec_cxx.swift +128 -0
  115. package/nitrogen/generated/ios/swift/HybridNativeLinearListLayoutSpec.swift +55 -0
  116. package/nitrogen/generated/ios/swift/HybridNativeLinearListLayoutSpec_cxx.swift +140 -0
  117. package/nitrogen/generated/ios/swift/HybridNativeListDataSourceSpec.swift +62 -0
  118. package/nitrogen/generated/ios/swift/HybridNativeListDataSourceSpec_cxx.swift +222 -0
  119. package/nitrogen/generated/ios/swift/HybridNativeListLayoutSpec.swift +55 -0
  120. package/nitrogen/generated/ios/swift/HybridNativeListLayoutSpec_cxx.swift +128 -0
  121. package/nitrogen/generated/ios/swift/HybridUiListModuleSpec.swift +56 -0
  122. package/nitrogen/generated/ios/swift/HybridUiListModuleSpec_cxx.swift +175 -0
  123. package/nitrogen/generated/ios/swift/HybridUiListViewSpec.swift +59 -0
  124. package/nitrogen/generated/ios/swift/HybridUiListViewSpec_cxx.swift +227 -0
  125. package/nitrogen/generated/ios/swift/HybridViewHolderSpec.swift +55 -0
  126. package/nitrogen/generated/ios/swift/HybridViewHolderSpec_cxx.swift +147 -0
  127. package/nitrogen/generated/ios/swift/NativeItemSizeEstimate.swift +60 -0
  128. package/nitrogen/generated/ios/swift/NativeLinearListLayoutConfig.swift +60 -0
  129. package/nitrogen/generated/ios/swift/NativeLinearListLayoutIOSConfig.swift +35 -0
  130. package/nitrogen/generated/ios/swift/NativeListItem.swift +75 -0
  131. package/nitrogen/generated/ios/swift/Variant_NullType__any_HybridIOSWorkletsModuleProxyHolderSpec_.swift +30 -0
  132. package/nitrogen/generated/shared/c++/HybridIOSWorkletsModuleProxyHolderSpec.cpp +21 -0
  133. package/nitrogen/generated/shared/c++/HybridIOSWorkletsModuleProxyHolderSpec.hpp +62 -0
  134. package/nitrogen/generated/shared/c++/HybridNativeLinearListLayoutSpec.cpp +22 -0
  135. package/nitrogen/generated/shared/c++/HybridNativeLinearListLayoutSpec.hpp +67 -0
  136. package/nitrogen/generated/shared/c++/HybridNativeListDataSourceSpec.cpp +28 -0
  137. package/nitrogen/generated/shared/c++/HybridNativeListDataSourceSpec.hpp +72 -0
  138. package/nitrogen/generated/shared/c++/HybridNativeListLayoutSpec.cpp +21 -0
  139. package/nitrogen/generated/shared/c++/HybridNativeListLayoutSpec.hpp +62 -0
  140. package/nitrogen/generated/shared/c++/HybridUiListModuleSpec.cpp +22 -0
  141. package/nitrogen/generated/shared/c++/HybridUiListModuleSpec.hpp +68 -0
  142. package/nitrogen/generated/shared/c++/HybridUiListViewSpec.cpp +25 -0
  143. package/nitrogen/generated/shared/c++/HybridUiListViewSpec.hpp +79 -0
  144. package/nitrogen/generated/shared/c++/HybridUiManagerHelperSpec.cpp +23 -0
  145. package/nitrogen/generated/shared/c++/HybridUiManagerHelperSpec.hpp +65 -0
  146. package/nitrogen/generated/shared/c++/HybridViewHolderSpec.cpp +21 -0
  147. package/nitrogen/generated/shared/c++/HybridViewHolderSpec.hpp +62 -0
  148. package/nitrogen/generated/shared/c++/NativeItemSizeEstimate.hpp +87 -0
  149. package/nitrogen/generated/shared/c++/NativeLinearListLayoutConfig.hpp +105 -0
  150. package/nitrogen/generated/shared/c++/NativeLinearListLayoutIOSConfig.hpp +85 -0
  151. package/nitrogen/generated/shared/c++/NativeListItem.hpp +101 -0
  152. package/nitrogen/generated/shared/c++/views/HybridUiListViewComponent.cpp +72 -0
  153. package/nitrogen/generated/shared/c++/views/HybridUiListViewComponent.hpp +109 -0
  154. package/nitrogen/generated/shared/c++/views/HybridViewHolderComponent.cpp +72 -0
  155. package/nitrogen/generated/shared/c++/views/HybridViewHolderComponent.hpp +109 -0
  156. package/nitrogen/generated/shared/json/UiListViewConfig.json +9 -0
  157. package/nitrogen/generated/shared/json/ViewHolderConfig.json +9 -0
  158. package/package.json +152 -5
  159. package/react-native.config.js +16 -0
  160. package/src/ListDataSource.ts +232 -0
  161. package/src/ListLayout.ts +95 -0
  162. package/src/UiListModule.ts +5 -0
  163. package/src/hooks/useChangeEffect.ts +50 -0
  164. package/src/index.tsx +49 -0
  165. package/src/privateGlobals.ts +20 -0
  166. package/src/renderer/fabric/RenderHelper.ts +29 -0
  167. package/src/renderer/fabric/UiManagerHelper.ts +5 -0
  168. package/src/renderer/react/ReactFabricMirror.bundle.js +1984 -0
  169. package/src/renderer/react/ReactFabricMirror.ts +766 -0
  170. package/src/renderer/react/ReactFabricRenderer.ts +11 -0
  171. package/src/specs/IOSWorkletsModuleProxyHolder.nitro.ts +6 -0
  172. package/src/specs/NativeLinearListLayout.nitro.ts +23 -0
  173. package/src/specs/NativeListDataSource.nitro.ts +28 -0
  174. package/src/specs/NativeListLayout.nitro.ts +6 -0
  175. package/src/specs/UIListModule.nitro.ts +13 -0
  176. package/src/specs/UIManagerHelper.nitro.ts +34 -0
  177. package/src/specs/UiListView.nitro.ts +31 -0
  178. package/src/specs/ViewHolder.nitro.ts +11 -0
  179. package/src/views/List.tsx +525 -0
  180. package/src/views/UiListHostComponent.ts +8 -0
  181. package/FillRateHelper.js +0 -179
  182. package/FlatList.js +0 -494
  183. package/LICENSE.md +0 -31
  184. package/ListView/__mocks__/ListViewMock.js +0 -55
  185. package/MetroListView.js +0 -166
  186. package/SectionList.js +0 -291
  187. package/ViewabilityHelper.js +0 -260
  188. package/VirtualizeUtils.js +0 -163
  189. package/VirtualizedList.js +0 -861
  190. package/VirtualizedSectionList.js +0 -397
  191. package/__flowtests__/FlatList-flowtest.js +0 -90
  192. package/__flowtests__/SectionList-flowtest.js +0 -89
  193. package/__tests__/FillRateHelper-test.js +0 -106
  194. package/__tests__/FlatList-test.js +0 -64
  195. package/__tests__/SectionList-test.js +0 -67
  196. package/__tests__/ViewabilityHelper-test.js +0 -359
  197. package/__tests__/VirtualizeUtils-test.js +0 -74
  198. package/__tests__/__snapshots__/FlatList-test.js.snap +0 -251
  199. package/__tests__/__snapshots__/SectionList-test.js.snap +0 -283
  200. package/index.js +0 -5
@@ -0,0 +1,192 @@
1
+ #include "JHybridUiListModule.h"
2
+ #include "WorkletsUiCallInvoker.hpp"
3
+ #include "HybridUiManagerHelper.hpp"
4
+
5
+ #include <NitroModules/CallInvokerDispatcher.hpp>
6
+ #include <NitroModules/InstallNitro.hpp>
7
+ #include <react/utils/jsi-utils.h>
8
+ #include <react/fabric/FabricUIManagerBinding.h>
9
+ #include <worklets/android/WorkletsModule.h>
10
+
11
+ namespace margelo::nitro::reactnativelist
12
+ {
13
+ static bool isOnAndroidUiThread()
14
+ {
15
+ return getpid() == gettid();
16
+ }
17
+
18
+ std::shared_ptr<react::CallInvoker> JHybridUiListModule::uiCallInvoker_ = nullptr;
19
+ std::shared_ptr<worklets::WorkletRuntime> JHybridUiListModule::uiWorkletRuntime_ = nullptr;
20
+
21
+ void JHybridUiListModule::registerNatives()
22
+ {
23
+ javaClassStatic()->registerNatives({
24
+ makeNativeMethod("prepareUiRuntime",
25
+ prepareUiRuntime),
26
+ makeNativeMethod("getUiCallInvokerHolder",
27
+ getUiCallInvokerHolder),
28
+ makeNativeMethod("getUiRuntimeExecutor",
29
+ getUiRuntimeExecutor),
30
+ makeNativeMethod("setupEventInterceptor",
31
+ setupEventInterceptor),
32
+ });
33
+ }
34
+
35
+ std::shared_ptr<react::CallInvoker> JHybridUiListModule::getOrInitCallInvoker(
36
+ jni::alias_ref<worklets::WorkletsModule::javaobject> workletsModule)
37
+ {
38
+ if (!workletsModule)
39
+ {
40
+ throw std::runtime_error("WorkletsModule reference is null");
41
+ }
42
+
43
+ auto workletsModuleProxy =
44
+ workletsModule->cthis()->getWorkletsModuleProxy();
45
+
46
+ if (!workletsModuleProxy)
47
+ {
48
+ throw std::runtime_error("Failed to get WorkletsModuleProxy from WorkletsModule");
49
+ }
50
+
51
+ auto uiScheduler = workletsModuleProxy->getUIScheduler();
52
+ if (!uiScheduler)
53
+ {
54
+ throw std::runtime_error("Failed to get UIScheduler from WorkletsModuleProxy");
55
+ }
56
+
57
+ auto uiWorkletRuntime = workletsModuleProxy->getUIWorkletRuntime();
58
+ if (!uiWorkletRuntime)
59
+ {
60
+ throw std::runtime_error("Failed to get UIWorkletRuntime from WorkletsModuleProxy");
61
+ }
62
+
63
+ if (uiCallInvoker_ && uiWorkletRuntime_ == uiWorkletRuntime)
64
+ {
65
+ return uiCallInvoker_;
66
+ }
67
+
68
+ uiWorkletRuntime_ = uiWorkletRuntime;
69
+ uiCallInvoker_ = std::make_shared<WorkletsUiCallInvoker>(uiScheduler, uiWorkletRuntime, isOnAndroidUiThread);
70
+ return uiCallInvoker_;
71
+ }
72
+
73
+ jni::local_ref<react::CallInvokerHolder::javaobject>
74
+ JHybridUiListModule::getUiCallInvokerHolder(
75
+ jni::alias_ref<JHybridUiListModule> jThis,
76
+ jni::alias_ref<worklets::WorkletsModule::javaobject> workletsModule)
77
+ {
78
+ std::shared_ptr<react::CallInvoker> uiCallInvoker = getOrInitCallInvoker(workletsModule);
79
+
80
+ return react::CallInvokerHolder::newObjectCxxArgs(uiCallInvoker);
81
+ }
82
+
83
+ bool JHybridUiListModule::prepareUiRuntime(
84
+ jni::alias_ref<JHybridUiListModule> jThis,
85
+ jni::alias_ref<worklets::WorkletsModule::javaobject> workletsModule)
86
+ {
87
+ if (!workletsModule)
88
+ {
89
+ throw std::runtime_error("WorkletsModule reference is null");
90
+ }
91
+
92
+ auto workletsModuleProxy =
93
+ workletsModule->cthis()->getWorkletsModuleProxy();
94
+
95
+ if (!workletsModuleProxy)
96
+ {
97
+ throw std::runtime_error("Failed to get WorkletsModuleProxy from WorkletsModule");
98
+ }
99
+
100
+ auto uiWorkletRuntime = workletsModuleProxy->getUIWorkletRuntime();
101
+ if (!uiWorkletRuntime)
102
+ {
103
+ throw std::runtime_error("Failed to get UIWorkletRuntime from WorkletsModuleProxy");
104
+ }
105
+
106
+ std::shared_ptr<react::CallInvoker> uiCallInvoker = getOrInitCallInvoker(workletsModule);
107
+
108
+ // React Native checks this global while installing TurboModule bindings.
109
+ // Worklets creates a separate UI runtime, so we mirror the bridgeless marker there.
110
+ bool hasNativeModuleProxy = false;
111
+ uiWorkletRuntime->runSync([&hasNativeModuleProxy](jsi::Runtime &runtime)
112
+ {
113
+ auto global = runtime.global();
114
+ if (!global.hasProperty(runtime, "RN$Bridgeless"))
115
+ {
116
+ react::defineReadOnlyGlobal(runtime, "RN$Bridgeless", jsi::Value(true));
117
+ }
118
+
119
+ hasNativeModuleProxy = global.hasProperty(runtime, "nativeModuleProxy");
120
+ });
121
+
122
+ // Do not call the Android Nitro TurboModule installer from the UI runtime.
123
+ // That installer reads ReactApplicationContext.javaScriptContextHolder, which always
124
+ // points at the main RN JS runtime. Install Nitro directly into Worklets' UI runtime
125
+ // so UI-thread imports can reuse global.NitroModulesProxy instead of reinstalling on RN.
126
+ uiWorkletRuntime->runSync([uiCallInvoker](jsi::Runtime &runtime)
127
+ {
128
+ if (runtime.global().hasProperty(runtime, "NitroModulesProxy"))
129
+ {
130
+ return;
131
+ }
132
+
133
+ if (runtime.global().hasProperty(runtime, "__nitroDispatcher"))
134
+ {
135
+ margelo::nitro::install(runtime);
136
+ return;
137
+ }
138
+
139
+ auto dispatcher =
140
+ std::make_shared<margelo::nitro::CallInvokerDispatcher>(uiCallInvoker);
141
+ margelo::nitro::install(runtime, dispatcher);
142
+ });
143
+
144
+ return hasNativeModuleProxy;
145
+ }
146
+
147
+ jni::local_ref<react::JRuntimeExecutor::javaobject>
148
+ JHybridUiListModule::getUiRuntimeExecutor(
149
+ jni::alias_ref<JHybridUiListModule> jThis,
150
+ jni::alias_ref<worklets::WorkletsModule::javaobject> workletsModule)
151
+ {
152
+ std::shared_ptr<react::CallInvoker> uiCallInvoker = getOrInitCallInvoker(workletsModule);
153
+
154
+ RuntimeExecutor uiRuntimeExecutor = [uiCallInvoker](auto callback)
155
+ {
156
+ if (isOnAndroidUiThread())
157
+ {
158
+ uiCallInvoker->invokeSync(std::move(callback));
159
+ return;
160
+ }
161
+
162
+ uiCallInvoker->invokeAsync(std::move(callback));
163
+ };
164
+
165
+ return react::JRuntimeExecutor::newObjectCxxArgs(uiRuntimeExecutor);
166
+ }
167
+
168
+ void JHybridUiListModule::setupEventInterceptor(
169
+ jni::alias_ref<JHybridUiListModule> jThis,
170
+ jni::alias_ref<JFabricUIManager::javaobject> fabricUIManager)
171
+ {
172
+ if (!uiCallInvoker_)
173
+ {
174
+ throw std::runtime_error(
175
+ "UI CallInvoker must be initialized before setting up event interceptor");
176
+ }
177
+
178
+ if (!fabricUIManager)
179
+ {
180
+ throw std::runtime_error("FabricUIManager reference is null");
181
+ }
182
+ std::shared_ptr<react::Scheduler> scheduler = fabricUIManager->getBinding()->getScheduler();
183
+
184
+ if (!scheduler)
185
+ {
186
+ throw std::runtime_error("Failed to get Scheduler from FabricUIManager");
187
+ }
188
+
189
+ HybridUiManagerHelper::setupEventInterceptor(scheduler, uiCallInvoker_);
190
+ }
191
+
192
+ } // namespace margelo::nitro::reactnativelist
@@ -0,0 +1,50 @@
1
+ #pragma once
2
+
3
+ #include <ReactCommon/CallInvokerHolder.h>
4
+ #include <react/jni/JRuntimeExecutor.h>
5
+ #include <fbjni/fbjni.h>
6
+ #include <react/fabric/JFabricUIManager.h>
7
+ #include <react/renderer/core/EventListener.h>
8
+ #include <worklets/WorkletRuntime/WorkletRuntime.h>
9
+ #include <worklets/android/WorkletsModule.h>
10
+
11
+ namespace margelo::nitro::reactnativelist
12
+ {
13
+
14
+ using namespace facebook;
15
+
16
+ struct JHybridUiListModule : public jni::JavaClass<JHybridUiListModule>
17
+ {
18
+ static auto constexpr kJavaDescriptor =
19
+ "Lcom/margelo/nitro/reactnativelist/HybridUiListModule;";
20
+
21
+ static void registerNatives();
22
+
23
+ private:
24
+ static jni::local_ref<react::CallInvokerHolder::javaobject>
25
+ getUiCallInvokerHolder(
26
+ jni::alias_ref<JHybridUiListModule> jThis,
27
+ jni::alias_ref<worklets::WorkletsModule::javaobject> workletsModule);
28
+
29
+ static jni::local_ref<react::JRuntimeExecutor::javaobject>
30
+ getUiRuntimeExecutor(
31
+ jni::alias_ref<JHybridUiListModule> jThis,
32
+ jni::alias_ref<worklets::WorkletsModule::javaobject> workletsModule);
33
+
34
+ static bool prepareUiRuntime(
35
+ jni::alias_ref<JHybridUiListModule> jThis,
36
+ jni::alias_ref<worklets::WorkletsModule::javaobject> workletsModule);
37
+
38
+ static void setupEventInterceptor(
39
+ jni::alias_ref<JHybridUiListModule> jThis,
40
+ jni::alias_ref<JFabricUIManager::javaobject> fabricUIManager);
41
+
42
+ static std::shared_ptr<react::CallInvoker> getOrInitCallInvoker(jni::alias_ref<worklets::WorkletsModule::javaobject> workletsModule);
43
+
44
+ private:
45
+ static std::shared_ptr<react::CallInvoker> uiCallInvoker_;
46
+ static std::shared_ptr<worklets::WorkletRuntime> uiWorkletRuntime_;
47
+ static std::shared_ptr<const react::EventListener> eventInterceptor_;
48
+ };
49
+
50
+ } // namespace margelo::nitro::reactnativelist
@@ -0,0 +1,12 @@
1
+ #include <jni.h>
2
+ #include "ReactNativeListOnLoad.hpp"
3
+ #include "JHybridUiListModule.h"
4
+
5
+ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *)
6
+ {
7
+ return facebook::jni::initialize(vm, []() {
8
+ margelo::nitro::reactnativelist::registerAllNatives();
9
+ // Register additional native methods (not generated by Nitrogen)
10
+ margelo::nitro::reactnativelist::JHybridUiListModule::registerNatives();
11
+ });
12
+ }
@@ -0,0 +1,27 @@
1
+ package com.hannojg.reactnativelist
2
+
3
+ import com.facebook.react.bridge.NativeModule
4
+ import com.facebook.react.bridge.ReactApplicationContext
5
+ import com.facebook.react.module.model.ReactModuleInfoProvider
6
+ import com.facebook.react.BaseReactPackage
7
+ import com.facebook.react.uimanager.ViewManager
8
+ import com.margelo.nitro.reactnativelist.ReactNativeListOnLoad
9
+ import com.margelo.nitro.reactnativelist.views.HybridUiListViewManager
10
+
11
+ class ReactNativeListPackage : BaseReactPackage() {
12
+ override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? = null
13
+
14
+ override fun getReactModuleInfoProvider(): ReactModuleInfoProvider = ReactModuleInfoProvider { HashMap() }
15
+
16
+ override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<in Nothing, in Nothing>> {
17
+ val viewManagers = ArrayList<ViewManager<*, *>>()
18
+ viewManagers.add(HybridUiListViewManager())
19
+ return viewManagers
20
+ }
21
+
22
+ companion object {
23
+ init {
24
+ ReactNativeListOnLoad.initializeNative()
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,146 @@
1
+ package com.margelo.nitro.reactnativelist
2
+
3
+ import androidx.recyclerview.widget.DiffUtil
4
+
5
+ internal interface NativeListDataSourceObserver {
6
+ fun dataSourceDidReload(diffResult: DiffUtil.DiffResult?, animated: Boolean)
7
+ fun dataSourceDidInsert(index: Int)
8
+ fun dataSourceDidUpdate(index: Int, previousItem: NativeListItem)
9
+ fun dataSourceDidRemove(index: Int, removedItem: NativeListItem)
10
+ fun dataSourceDidMove(fromIndex: Int, toIndex: Int)
11
+ }
12
+
13
+ class HybridNativeListDataSource : HybridNativeListDataSourceSpec() {
14
+ internal var observer: NativeListDataSourceObserver? = null
15
+ private var items: List<NativeListItem> = emptyList()
16
+ private var isContentEqual: (oldItem: NativeListItem, newItem: NativeListItem) -> Boolean =
17
+ { _, _ -> false }
18
+
19
+ override fun dispose() {
20
+ observer = null
21
+ items = emptyList()
22
+ isContentEqual = { _, _ -> false }
23
+ }
24
+
25
+ override fun setContentEqualCallback(
26
+ isContentEqual: (oldItem: NativeListItem, newItem: NativeListItem) -> Boolean
27
+ ) {
28
+ this.isContentEqual = isContentEqual
29
+ }
30
+
31
+ override fun replaceData(items: Array<NativeListItem>, animated: Boolean) {
32
+ val nextItems = items.toList()
33
+ if (!animated) {
34
+ this.items = nextItems
35
+ observer?.dataSourceDidReload(null, false)
36
+ return
37
+ }
38
+
39
+ val previousItems = this.items
40
+ val callback = NativeDiffCallback(previousItems, nextItems, isContentEqual)
41
+ val diffResult = DiffUtil.calculateDiff(callback, true)
42
+ this.items = nextItems
43
+ observer?.dataSourceDidReload(diffResult, true)
44
+ }
45
+
46
+ override fun insertItem(index: Double, item: NativeListItem) {
47
+ val itemIndex = validateInsertionIndex(index.toInt())
48
+ val mutableItems = items.toMutableList()
49
+ mutableItems.add(itemIndex, item)
50
+ items = mutableItems
51
+ observer?.dataSourceDidInsert(itemIndex)
52
+ }
53
+
54
+ override fun updateItem(index: Double, item: NativeListItem) {
55
+ val itemIndex = validateExistingIndex(index.toInt())
56
+ val mutableItems = items.toMutableList()
57
+ val previousItem = mutableItems[itemIndex]
58
+ mutableItems[itemIndex] = item
59
+ items = mutableItems
60
+ observer?.dataSourceDidUpdate(itemIndex, previousItem)
61
+ }
62
+
63
+ override fun removeItem(index: Double) {
64
+ val itemIndex = validateExistingIndex(index.toInt())
65
+ val mutableItems = items.toMutableList()
66
+ val removedItem = mutableItems.removeAt(itemIndex)
67
+ items = mutableItems
68
+ observer?.dataSourceDidRemove(itemIndex, removedItem)
69
+ }
70
+
71
+ override fun moveItem(fromIndex: Double, toIndex: Double) {
72
+ val sourceIndex = validateExistingIndex(fromIndex.toInt())
73
+ val targetIndex = validateExistingIndex(toIndex.toInt())
74
+ val mutableItems = items.toMutableList()
75
+ val item = mutableItems.removeAt(sourceIndex)
76
+ mutableItems.add(targetIndex, item)
77
+ items = mutableItems
78
+ observer?.dataSourceDidMove(sourceIndex, targetIndex)
79
+ }
80
+
81
+ override fun getCount(): Double {
82
+ return items.size.toDouble()
83
+ }
84
+
85
+ override fun getItem(index: Double): NativeListItem {
86
+ val itemIndex = validateExistingIndex(index.toInt())
87
+ return getItemAt(itemIndex)
88
+ }
89
+
90
+ internal fun getItemAt(index: Int): NativeListItem {
91
+ return items[index]
92
+ }
93
+
94
+ internal fun getCountAsInt(): Int {
95
+ return items.size
96
+ }
97
+
98
+ private fun validateExistingIndex(index: Int): Int {
99
+ if (index < 0 || index >= items.size) {
100
+ throw IndexOutOfBoundsException("List index $index is out of bounds.")
101
+ }
102
+ return index
103
+ }
104
+
105
+ private fun validateInsertionIndex(index: Int): Int {
106
+ if (index < 0 || index > items.size) {
107
+ throw IndexOutOfBoundsException("List index $index is out of bounds.")
108
+ }
109
+ return index
110
+ }
111
+ }
112
+
113
+ private class NativeDiffCallback(
114
+ private val oldItems: List<NativeListItem>,
115
+ private val newItems: List<NativeListItem>,
116
+ private val isContentEqual: (oldItem: NativeListItem, newItem: NativeListItem) -> Boolean
117
+ ) : DiffUtil.Callback() {
118
+
119
+ override fun getOldListSize(): Int {
120
+ return oldItems.size
121
+ }
122
+
123
+ override fun getNewListSize(): Int {
124
+ return newItems.size
125
+ }
126
+
127
+ override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
128
+ val oldItem = oldItems[oldItemPosition]
129
+ val newItem = newItems[newItemPosition]
130
+ return oldItem.key == newItem.key && oldItem.type == newItem.type
131
+ }
132
+
133
+ override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
134
+ val oldItem = oldItems[oldItemPosition]
135
+ val newItem = newItems[newItemPosition]
136
+
137
+ if (oldItem.width != newItem.width) {
138
+ return false
139
+ }
140
+ if (oldItem.height != newItem.height) {
141
+ return false
142
+ }
143
+
144
+ return isContentEqual(oldItem, newItem)
145
+ }
146
+ }
@@ -0,0 +1,86 @@
1
+ package com.margelo.nitro.reactnativelist
2
+
3
+ import android.graphics.Rect
4
+ import android.view.View
5
+ import androidx.recyclerview.widget.LinearLayoutManager
6
+ import androidx.recyclerview.widget.RecyclerView
7
+ import com.facebook.react.uimanager.ThemedReactContext
8
+ import kotlin.math.roundToInt
9
+
10
+ open class HybridNativeListLayout : HybridNativeListLayoutSpec()
11
+
12
+ internal interface NativeListLayoutProvider {
13
+ fun applyTo(recyclerView: RecyclerView, reactContext: ThemedReactContext)
14
+ fun itemContentInsets(reactContext: ThemedReactContext): ItemContentInsets
15
+ }
16
+
17
+ data class ItemContentInsets(
18
+ val horizontal: Int,
19
+ val vertical: Int
20
+ )
21
+
22
+ class HybridNativeLinearListLayout :
23
+ HybridNativeLinearListLayoutSpec(),
24
+ NativeListLayoutProvider {
25
+ private var topInset = 16
26
+ private var bottomInset = 16
27
+ private var itemSpacing = 12
28
+ private var itemHorizontalInset = 0
29
+ private var itemVerticalInset = 0
30
+
31
+ override fun dispose() {
32
+ topInset = 16
33
+ bottomInset = 16
34
+ itemSpacing = 12
35
+ itemHorizontalInset = 0
36
+ itemVerticalInset = 0
37
+ }
38
+
39
+ override fun setConfig(config: NativeLinearListLayoutConfig) {
40
+ topInset = config.topInset.roundToInt()
41
+ bottomInset = config.bottomInset.roundToInt()
42
+ itemSpacing = config.itemSpacing.roundToInt()
43
+ itemHorizontalInset = config.itemHorizontalInset.roundToInt()
44
+ itemVerticalInset = config.itemVerticalInset.roundToInt()
45
+ }
46
+
47
+ override fun applyTo(recyclerView: RecyclerView, reactContext: ThemedReactContext) {
48
+ recyclerView.layoutManager = LinearLayoutManager(reactContext)
49
+ recyclerView.clipToPadding = false
50
+ val density = reactContext.resources.displayMetrics.density
51
+ val topPadding = (topInset * density).roundToInt()
52
+ val bottomPadding = (bottomInset * density).roundToInt()
53
+ val spacing = (itemSpacing * density).roundToInt()
54
+
55
+ while (recyclerView.itemDecorationCount > 0) {
56
+ recyclerView.removeItemDecorationAt(0)
57
+ }
58
+
59
+ recyclerView.setPadding(0, topPadding, 0, bottomPadding)
60
+ recyclerView.addItemDecoration(LinearSpacingDecoration(spacing))
61
+ }
62
+
63
+ override fun itemContentInsets(reactContext: ThemedReactContext): ItemContentInsets {
64
+ val density = reactContext.resources.displayMetrics.density
65
+ val horizontal = (itemHorizontalInset * density).roundToInt()
66
+ val vertical = (itemVerticalInset * density).roundToInt()
67
+ return ItemContentInsets(horizontal, vertical)
68
+ }
69
+ }
70
+
71
+ private class LinearSpacingDecoration(
72
+ private val itemSpacing: Int
73
+ ) : RecyclerView.ItemDecoration() {
74
+ override fun getItemOffsets(
75
+ outRect: Rect,
76
+ view: View,
77
+ parent: RecyclerView,
78
+ state: RecyclerView.State
79
+ ) {
80
+ val position = parent.getChildAdapterPosition(view)
81
+ val itemCount = state.itemCount
82
+ if (position >= 0 && position < itemCount - 1) {
83
+ outRect.bottom = itemSpacing
84
+ }
85
+ }
86
+ }
@@ -0,0 +1,116 @@
1
+ package com.margelo.nitro.reactnativelist
2
+
3
+ import com.facebook.react.ReactActivity
4
+ import com.facebook.react.ReactPackage
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.bridge.RuntimeExecutor
7
+ import com.facebook.react.bridge.UiThreadUtil
8
+ import com.facebook.react.common.annotations.FrameworkAPI
9
+ import com.facebook.react.common.annotations.UnstableReactNativeAPI
10
+ import com.facebook.react.fabric.FabricUIManager
11
+ import com.facebook.react.internal.turbomodule.core.TurboModuleManager
12
+ import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler
13
+ import com.facebook.react.runtime.ReactHostDelegate
14
+ import com.facebook.react.runtime.ReactHostImpl
15
+ import com.facebook.react.turbomodule.core.CallInvokerHolderImpl
16
+ import com.facebook.react.turbomodule.core.interfaces.NativeMethodCallInvokerHolder
17
+ import com.facebook.react.uimanager.UIManagerHelper
18
+ import com.facebook.react.uimanager.common.UIManagerType
19
+ import com.margelo.nitro.NitroModules
20
+ import com.swmansion.worklets.WorkletsModule
21
+ import java.util.ArrayList
22
+ import kotlin.concurrent.Volatile
23
+
24
+ class HybridUiListModule : HybridUiListModuleSpec() {
25
+ override fun iosGetWorkletsModule(): HybridIOSWorkletsModuleProxyHolderSpec {
26
+ throw IllegalStateException("iosGetWorkletsModule is iOS-only and must not be called on Android.")
27
+ }
28
+
29
+ @OptIn(UnstableReactNativeAPI::class, FrameworkAPI::class)
30
+ override fun setupRuntime(workletsModuleHolder: Variant_NullType_HybridIOSWorkletsModuleProxyHolderSpec?) {
31
+ if (!UiThreadUtil.isOnUiThread()) {
32
+ throw IllegalStateException("setupRuntime must be called on the UI thread!")
33
+ }
34
+
35
+ val context: ReactApplicationContext = NitroModules.applicationContext
36
+ ?: throw IllegalStateException("ReactApplicationContext is null! Is Nitro installed?")
37
+
38
+ val workletsModule = context.getNativeModule(WorkletsModule::class.java)
39
+ ?: throw IllegalStateException("WorkletsModule is null! Is the WorkletsModule properly registered?")
40
+ val nativeModuleProxyInstalled = prepareUiRuntime(workletsModule)
41
+
42
+ if (!nativeModuleProxyInstalled) {
43
+ val reactActivity = context.currentActivity as? ReactActivity
44
+ ?: throw IllegalStateException("Current activity is not a ReactActivity!")
45
+ val reactHost = reactActivity.reactActivityDelegate.reactHost
46
+ ?: throw IllegalStateException("ReactNativeHost is null!")
47
+
48
+ // Next: Create a TurboModuleManager for the UI runtime, which will set global.nativeModuleProxy
49
+ // This is whats being used when doing NativeModule.MyNativeModule in JS!
50
+ // TODO: i use a bunch of internals here, can this be improved?
51
+ val reactHostImpl = reactHost as? ReactHostImpl
52
+ ?: throw IllegalStateException("ReactHost is not a ReactHostImpl! Is the New Architecture enabled?")
53
+
54
+ val reactHostDelegateField = reactHostImpl.javaClass.getDeclaredField("reactHostDelegate")
55
+ reactHostDelegateField.isAccessible = true
56
+ val reactHostDelegate = reactHostDelegateField.get(reactHostImpl) as? ReactHostDelegate
57
+ ?: throw IllegalStateException("ReactHostDelegate is null! Is the New Architecture enabled?")
58
+
59
+ // Get nativeMethodCallInvokerHolder from reactInstance, which lives on reactHostImpl
60
+ val reactInstanceField = reactHostImpl.javaClass.getDeclaredField("reactInstance")
61
+ reactInstanceField.isAccessible = true
62
+ val reactInstance = reactInstanceField.get(reactHostImpl)
63
+ ?: throw IllegalStateException("ReactInstance is null! Is the New Architecture enabled?")
64
+ val getNativeMethodCallInvokerHolderMethod = reactInstance.javaClass.getDeclaredMethod("getNativeMethodCallInvokerHolder")
65
+ getNativeMethodCallInvokerHolderMethod.isAccessible = true
66
+ val nativeMethodCallInvokerHolder = getNativeMethodCallInvokerHolderMethod.invoke(reactInstance) as? NativeMethodCallInvokerHolder
67
+ ?: throw IllegalStateException("NativeMethodCallInvokerHolder is null! Is the New Architecture enabled?")
68
+
69
+ val reactPackages: MutableList<ReactPackage> = ArrayList<ReactPackage>()
70
+ val coreReactPackageClass = Class.forName("com.facebook.react.runtime.CoreReactPackage")
71
+ val constructor = coreReactPackageClass.declaredConstructors.first()
72
+ constructor.isAccessible = true
73
+ // TODO: this will create dev support modules on the UI runtime which is unnecessary overhead we don't need!
74
+ // In a past version i simply put in the most important core modules from JS, which was somewhat nicer.
75
+ val coreReactPackage = constructor.newInstance(reactHost.devSupportManager, DefaultHardwareBackBtnHandler {}) as ReactPackage
76
+ reactPackages.add(coreReactPackage)
77
+ reactPackages.addAll(reactHostDelegate.reactPackages)
78
+
79
+ val turboModuleManagerDelegate = reactHostDelegate.turboModuleManagerDelegateBuilder
80
+ .setPackages(reactPackages)
81
+ .setReactApplicationContext(context)
82
+ .build()
83
+
84
+ val uiCallInvokerHolder = getUiCallInvokerHolder(workletsModule)
85
+ val uiRuntimeExecutor = getUiRuntimeExecutor(workletsModule)
86
+
87
+ // This will install the JSI bindings
88
+ uiTurboModuleManager = TurboModuleManager(
89
+ // TurboModuleManager will call jni -> cpp, to actually setup nativeModuleProxy
90
+ runtimeExecutor = uiRuntimeExecutor,
91
+ delegate = turboModuleManagerDelegate,
92
+ jsCallInvokerHolder = uiCallInvokerHolder,
93
+ nativeMethodCallInvokerHolder = nativeMethodCallInvokerHolder
94
+ )
95
+ }
96
+
97
+ val uiManager = UIManagerHelper.getUIManager(context, UIManagerType.FABRIC)
98
+ ?: throw IllegalStateException("Fabric UIManager is null! Is the Fabric architecture enabled?")
99
+ val fabricUIManager = uiManager as? FabricUIManager
100
+ ?: throw IllegalStateException("UIManager is not a FabricUIManager! Is the Fabric architecture enabled?")
101
+ setupEventInterceptor(fabricUIManager)
102
+ }
103
+
104
+ @OptIn(FrameworkAPI::class)
105
+ private external fun prepareUiRuntime(workletsModule: WorkletsModule): Boolean
106
+
107
+ @OptIn(FrameworkAPI::class)
108
+ private external fun getUiCallInvokerHolder(workletsModule: WorkletsModule): CallInvokerHolderImpl
109
+
110
+ private external fun getUiRuntimeExecutor(workletsModule: WorkletsModule): RuntimeExecutor
111
+
112
+ private external fun setupEventInterceptor(fabricUIManager: FabricUIManager)
113
+
114
+ @Volatile
115
+ private lateinit var uiTurboModuleManager: TurboModuleManager
116
+ }