react-native-inapp-inspector 2.3.19 → 2.3.21

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 (353) hide show
  1. package/README.md +14 -14
  2. package/android/src/main/java/com/inappinspector/NetworkInspectorModule.kt +67 -0
  3. package/dist/commonjs/analytics.js +1 -24
  4. package/dist/commonjs/bundle.js +1 -16
  5. package/dist/commonjs/capture.js +1 -35
  6. package/dist/commonjs/components/AnalyticsDetail.js +92 -623
  7. package/dist/commonjs/components/AnalyticsEventCard.js +54 -350
  8. package/dist/commonjs/components/AnalyticsGraph.js +70 -370
  9. package/dist/commonjs/components/AnimatedEntrance.js +1 -11
  10. package/dist/commonjs/components/AppHeaderLogo.js +7 -134
  11. package/dist/commonjs/components/BrandCircleIcon.js +73 -118
  12. package/dist/commonjs/components/BrandSquareIcon.js +63 -108
  13. package/dist/commonjs/components/CodeSnippet.js +48 -623
  14. package/dist/commonjs/components/ConsoleLogCard.js +63 -537
  15. package/dist/commonjs/components/CopyButton.js +3 -89
  16. package/dist/commonjs/components/DiffViewer.js +19 -83
  17. package/dist/commonjs/components/DomainHeader.js +27 -127
  18. package/dist/commonjs/components/EmptyState.js +10 -87
  19. package/dist/commonjs/components/EndOfListFooter.js +7 -81
  20. package/dist/commonjs/components/ErrorBoundary.js +72 -566
  21. package/dist/commonjs/components/HeadersSection.js +31 -110
  22. package/dist/commonjs/components/HighlightText.js +17 -58
  23. package/dist/commonjs/components/Inspector/AboutModal.d.ts +6 -0
  24. package/dist/commonjs/components/Inspector/AboutModal.js +243 -0
  25. package/dist/commonjs/components/Inspector/AnalyticsFilterModal.js +98 -797
  26. package/dist/commonjs/components/Inspector/AnalyticsTab.js +284 -930
  27. package/dist/commonjs/components/Inspector/BundleTab.js +551 -2918
  28. package/dist/commonjs/components/Inspector/ConsoleTab.js +79 -492
  29. package/dist/commonjs/components/Inspector/CrashDetail.js +123 -672
  30. package/dist/commonjs/components/Inspector/CrashFilterModal.js +66 -498
  31. package/dist/commonjs/components/Inspector/CrashTab.js +98 -670
  32. package/dist/commonjs/components/Inspector/DebuggingTab.js +74 -875
  33. package/dist/commonjs/components/Inspector/DeviceInfoTab.js +143 -907
  34. package/dist/commonjs/components/Inspector/FabLauncher.js +42 -466
  35. package/dist/commonjs/components/Inspector/FeatureUnderDevNotice.js +6 -99
  36. package/dist/commonjs/components/Inspector/InspectorContext.js +1 -21
  37. package/dist/commonjs/components/Inspector/InspectorHeader.js +191 -1110
  38. package/dist/commonjs/components/Inspector/LogDetail.js +168 -994
  39. package/dist/commonjs/components/Inspector/MainScreen.js +52 -335
  40. package/dist/commonjs/components/Inspector/MediaGalleryTab.js +97 -644
  41. package/dist/commonjs/components/Inspector/MediaPreviewModal.js +90 -605
  42. package/dist/commonjs/components/Inspector/NavigationTracker.js +1 -12
  43. package/dist/commonjs/components/Inspector/NetworkDetail.js +89 -411
  44. package/dist/commonjs/components/Inspector/NetworkFilterModal.js +60 -576
  45. package/dist/commonjs/components/Inspector/NetworkTab.js +84 -514
  46. package/dist/commonjs/components/Inspector/NpmStarPrompt.js +18 -434
  47. package/dist/commonjs/components/Inspector/NpmUpdateToast.js +25 -298
  48. package/dist/commonjs/components/Inspector/PerformanceTab.js +182 -1397
  49. package/dist/commonjs/components/Inspector/ReduxDetail.js +188 -1089
  50. package/dist/commonjs/components/Inspector/ReduxTab.js +85 -701
  51. package/dist/commonjs/components/Inspector/SettingsPanel.js +427 -3807
  52. package/dist/commonjs/components/Inspector/SkeletonPlaceholder.js +11 -180
  53. package/dist/commonjs/components/Inspector/StorageTab.js +93 -826
  54. package/dist/commonjs/components/Inspector/TabBar.js +36 -334
  55. package/dist/commonjs/components/Inspector/UpdateAvailableModal.js +37 -412
  56. package/dist/commonjs/components/JsonViewer.js +168 -381
  57. package/dist/commonjs/components/LogCard.js +57 -567
  58. package/dist/commonjs/components/LogSyntaxHighlighter.js +11 -130
  59. package/dist/commonjs/components/MetaAccordion.js +69 -238
  60. package/dist/commonjs/components/MiniBarChart.js +3 -56
  61. package/dist/commonjs/components/MiniLineChart.js +3 -58
  62. package/dist/commonjs/components/NetworkIcons.d.ts +13 -0
  63. package/dist/commonjs/components/NetworkIcons.js +521 -1022
  64. package/dist/commonjs/components/QRCodeView.js +5 -79
  65. package/dist/commonjs/components/SectionHeader.js +15 -37
  66. package/dist/commonjs/components/SegmentedTabs.js +7 -62
  67. package/dist/commonjs/components/SkeletonPlaceholder.js +11 -180
  68. package/dist/commonjs/components/Slider.js +15 -243
  69. package/dist/commonjs/components/SourcePageCard.js +30 -89
  70. package/dist/commonjs/components/Toast.js +5 -147
  71. package/dist/commonjs/components/TouchableScale.js +3 -24
  72. package/dist/commonjs/components/TreeNode.js +55 -130
  73. package/dist/commonjs/console.js +1 -16
  74. package/dist/commonjs/constants/index.js +1 -32
  75. package/dist/commonjs/constants/telemetryConfig.js +1 -6
  76. package/dist/commonjs/constants/version.d.ts +1 -1
  77. package/dist/commonjs/constants/version.js +1 -4
  78. package/dist/commonjs/crash.js +1 -23
  79. package/dist/commonjs/customHooks/analyticsLogger.js +1 -250
  80. package/dist/commonjs/customHooks/bundleAnalyzer.js +1 -957
  81. package/dist/commonjs/customHooks/consoleLogger.js +6 -445
  82. package/dist/commonjs/customHooks/crashHandler.js +7 -656
  83. package/dist/commonjs/customHooks/logFilters.js +1 -23
  84. package/dist/commonjs/customHooks/networkLogger.js +2 -536
  85. package/dist/commonjs/customHooks/performanceTracker.js +63 -750
  86. package/dist/commonjs/customHooks/reduxLogger.js +2 -313
  87. package/dist/commonjs/customHooks/storageInspector.js +1 -435
  88. package/dist/commonjs/customHooks/useAccordion.js +1 -18
  89. package/dist/commonjs/decorators/index.js +1 -100
  90. package/dist/commonjs/helpers/gaAnalyticsRegistry.js +1 -148
  91. package/dist/commonjs/helpers/index.d.ts +1 -0
  92. package/dist/commonjs/helpers/index.js +8 -921
  93. package/dist/commonjs/helpers/memoryManager.js +1 -99
  94. package/dist/commonjs/helpers/qrGenerator.js +1 -367
  95. package/dist/commonjs/helpers/remoteConfig.js +1 -165
  96. package/dist/commonjs/helpers/searchQueryParser.js +1 -62
  97. package/dist/commonjs/helpers/settingsStore.js +1 -144
  98. package/dist/commonjs/helpers/telemetry.js +1 -501
  99. package/dist/commonjs/helpers/toast.js +1 -20
  100. package/dist/commonjs/i18n/index.js +1 -90
  101. package/dist/commonjs/i18n/locales/en.json +1 -1140
  102. package/dist/commonjs/index.js +5 -2168
  103. package/dist/commonjs/metro.js +6 -468
  104. package/dist/commonjs/native/NativeInspector.d.ts +1 -0
  105. package/dist/commonjs/native/NativeInspector.js +1 -415
  106. package/dist/commonjs/native/NativeNetworkInspector.js +1 -4
  107. package/dist/commonjs/network.js +1 -13
  108. package/dist/commonjs/performance.js +1 -29
  109. package/dist/commonjs/redux.js +1 -20
  110. package/dist/commonjs/storage.js +1 -14
  111. package/dist/commonjs/styles/AppColors.js +1 -423
  112. package/dist/commonjs/styles/AppFonts.js +1 -17
  113. package/dist/commonjs/styles/common.js +1 -190
  114. package/dist/commonjs/styles/index.d.ts +6 -0
  115. package/dist/commonjs/styles/index.js +1 -1589
  116. package/dist/commonjs/types/enums.d.ts +0 -1
  117. package/dist/commonjs/types/enums.js +1 -152
  118. package/dist/commonjs/types/index.js +1 -18
  119. package/dist/commonjs/types/interfaces.d.ts +2 -2
  120. package/dist/commonjs/types/interfaces.js +1 -2
  121. package/dist/esm/analytics.js +1 -2
  122. package/dist/esm/bundle.js +1 -2
  123. package/dist/esm/capture.js +1 -32
  124. package/dist/esm/components/AnalyticsDetail.js +171 -664
  125. package/dist/esm/components/AnalyticsEventCard.js +77 -335
  126. package/dist/esm/components/AnalyticsGraph.js +95 -357
  127. package/dist/esm/components/AnimatedEntrance.js +1 -6
  128. package/dist/esm/components/AppHeaderLogo.js +7 -94
  129. package/dist/esm/components/BrandCircleIcon.js +114 -119
  130. package/dist/esm/components/BrandSquareIcon.js +73 -78
  131. package/dist/esm/components/CodeSnippet.js +58 -595
  132. package/dist/esm/components/ConsoleLogCard.js +91 -526
  133. package/dist/esm/components/CopyButton.js +3 -51
  134. package/dist/esm/components/DiffViewer.js +22 -48
  135. package/dist/esm/components/DomainHeader.js +43 -138
  136. package/dist/esm/components/EmptyState.js +17 -56
  137. package/dist/esm/components/EndOfListFooter.js +15 -83
  138. package/dist/esm/components/ErrorBoundary.js +125 -582
  139. package/dist/esm/components/HeadersSection.js +52 -93
  140. package/dist/esm/components/HighlightText.js +17 -53
  141. package/dist/esm/components/Inspector/AboutModal.d.ts +6 -0
  142. package/dist/esm/components/Inspector/AboutModal.js +243 -0
  143. package/dist/esm/components/Inspector/AnalyticsFilterModal.js +225 -886
  144. package/dist/esm/components/Inspector/AnalyticsTab.js +296 -904
  145. package/dist/esm/components/Inspector/BundleTab.js +1175 -3502
  146. package/dist/esm/components/Inspector/ConsoleTab.js +113 -488
  147. package/dist/esm/components/Inspector/CrashDetail.js +236 -747
  148. package/dist/esm/components/Inspector/CrashFilterModal.js +149 -541
  149. package/dist/esm/components/Inspector/CrashTab.js +177 -711
  150. package/dist/esm/components/Inspector/DebuggingTab.js +164 -925
  151. package/dist/esm/components/Inspector/DeviceInfoTab.js +199 -924
  152. package/dist/esm/components/Inspector/FabLauncher.js +68 -454
  153. package/dist/esm/components/Inspector/FeatureUnderDevNotice.js +14 -70
  154. package/dist/esm/components/Inspector/InspectorContext.js +1 -12
  155. package/dist/esm/components/Inspector/InspectorHeader.js +282 -1163
  156. package/dist/esm/components/Inspector/LogDetail.js +235 -1023
  157. package/dist/esm/components/Inspector/MainScreen.js +78 -323
  158. package/dist/esm/components/Inspector/MediaGalleryTab.js +143 -650
  159. package/dist/esm/components/Inspector/MediaPreviewModal.js +138 -613
  160. package/dist/esm/components/Inspector/NavigationTracker.js +1 -10
  161. package/dist/esm/components/Inspector/NetworkDetail.js +138 -455
  162. package/dist/esm/components/Inspector/NetworkFilterModal.js +122 -597
  163. package/dist/esm/components/Inspector/NetworkTab.js +125 -517
  164. package/dist/esm/components/Inspector/NpmStarPrompt.js +58 -434
  165. package/dist/esm/components/Inspector/NpmUpdateToast.js +45 -281
  166. package/dist/esm/components/Inspector/PerformanceTab.js +393 -1570
  167. package/dist/esm/components/Inspector/ReduxDetail.js +307 -1170
  168. package/dist/esm/components/Inspector/ReduxTab.js +144 -722
  169. package/dist/esm/components/Inspector/SettingsPanel.js +643 -3985
  170. package/dist/esm/components/Inspector/SkeletonPlaceholder.js +30 -163
  171. package/dist/esm/components/Inspector/StorageTab.js +172 -866
  172. package/dist/esm/components/Inspector/TabBar.js +45 -305
  173. package/dist/esm/components/Inspector/UpdateAvailableModal.js +80 -418
  174. package/dist/esm/components/JsonViewer.js +179 -354
  175. package/dist/esm/components/LogCard.js +93 -565
  176. package/dist/esm/components/LogSyntaxHighlighter.js +11 -123
  177. package/dist/esm/components/MetaAccordion.js +136 -267
  178. package/dist/esm/components/MiniBarChart.js +3 -18
  179. package/dist/esm/components/MiniLineChart.js +3 -20
  180. package/dist/esm/components/NetworkIcons.d.ts +13 -0
  181. package/dist/esm/components/NetworkIcons.js +523 -838
  182. package/dist/esm/components/QRCodeView.js +8 -45
  183. package/dist/esm/components/SectionHeader.js +22 -39
  184. package/dist/esm/components/SegmentedTabs.js +8 -58
  185. package/dist/esm/components/SkeletonPlaceholder.js +30 -163
  186. package/dist/esm/components/Slider.js +24 -213
  187. package/dist/esm/components/SourcePageCard.js +65 -86
  188. package/dist/esm/components/Toast.js +10 -117
  189. package/dist/esm/components/TouchableScale.js +3 -19
  190. package/dist/esm/components/TreeNode.js +58 -95
  191. package/dist/esm/console.js +1 -2
  192. package/dist/esm/constants/index.js +1 -28
  193. package/dist/esm/constants/telemetryConfig.js +1 -3
  194. package/dist/esm/constants/version.d.ts +1 -1
  195. package/dist/esm/constants/version.js +1 -1
  196. package/dist/esm/crash.js +1 -2
  197. package/dist/esm/customHooks/analyticsLogger.js +1 -230
  198. package/dist/esm/customHooks/bundleAnalyzer.js +1 -944
  199. package/dist/esm/customHooks/consoleLogger.js +6 -432
  200. package/dist/esm/customHooks/crashHandler.js +7 -630
  201. package/dist/esm/customHooks/logFilters.js +1 -20
  202. package/dist/esm/customHooks/networkLogger.js +2 -519
  203. package/dist/esm/customHooks/performanceTracker.js +63 -723
  204. package/dist/esm/customHooks/reduxLogger.js +2 -293
  205. package/dist/esm/customHooks/storageInspector.js +1 -418
  206. package/dist/esm/customHooks/useAccordion.js +1 -16
  207. package/dist/esm/decorators/index.js +1 -95
  208. package/dist/esm/helpers/gaAnalyticsRegistry.js +1 -143
  209. package/dist/esm/helpers/index.d.ts +1 -0
  210. package/dist/esm/helpers/index.js +8 -861
  211. package/dist/esm/helpers/memoryManager.js +1 -91
  212. package/dist/esm/helpers/qrGenerator.js +1 -364
  213. package/dist/esm/helpers/remoteConfig.js +1 -160
  214. package/dist/esm/helpers/searchQueryParser.js +1 -59
  215. package/dist/esm/helpers/settingsStore.js +1 -134
  216. package/dist/esm/helpers/telemetry.js +1 -489
  217. package/dist/esm/helpers/toast.js +1 -15
  218. package/dist/esm/i18n/index.js +1 -78
  219. package/dist/esm/i18n/locales/en.json +1 -1140
  220. package/dist/esm/index.js +7 -1982
  221. package/dist/esm/metro.js +6 -459
  222. package/dist/esm/native/NativeInspector.d.ts +1 -0
  223. package/dist/esm/native/NativeInspector.js +1 -382
  224. package/dist/esm/native/NativeNetworkInspector.js +1 -2
  225. package/dist/esm/network.js +1 -1
  226. package/dist/esm/performance.js +1 -2
  227. package/dist/esm/redux.js +1 -1
  228. package/dist/esm/storage.js +1 -1
  229. package/dist/esm/styles/AppColors.js +1 -417
  230. package/dist/esm/styles/AppFonts.js +1 -13
  231. package/dist/esm/styles/common.js +1 -186
  232. package/dist/esm/styles/index.d.ts +6 -0
  233. package/dist/esm/styles/index.js +1 -1551
  234. package/dist/esm/types/enums.d.ts +0 -1
  235. package/dist/esm/types/enums.js +1 -149
  236. package/dist/esm/types/index.js +1 -2
  237. package/dist/esm/types/interfaces.d.ts +2 -2
  238. package/dist/esm/types/interfaces.js +1 -1
  239. package/ios/NetworkInspectorModule.mm +60 -12
  240. package/package.json +5 -3
  241. package/src/native/NativeInspector.ts +18 -0
  242. package/dist/commonjs/components/Inspector/FeedbackModal.d.ts +0 -7
  243. package/dist/commonjs/components/Inspector/FeedbackModal.js +0 -552
  244. package/dist/esm/components/Inspector/FeedbackModal.d.ts +0 -7
  245. package/dist/esm/components/Inspector/FeedbackModal.js +0 -515
  246. package/src/analytics.ts +0 -35
  247. package/src/bundle.ts +0 -25
  248. package/src/capture.ts +0 -109
  249. package/src/components/AnalyticsDetail.tsx +0 -870
  250. package/src/components/AnalyticsEventCard.tsx +0 -444
  251. package/src/components/AnalyticsGraph.tsx +0 -583
  252. package/src/components/AnimatedEntrance.tsx +0 -20
  253. package/src/components/AppHeaderLogo.tsx +0 -143
  254. package/src/components/BrandCircleIcon.tsx +0 -144
  255. package/src/components/BrandSquareIcon.tsx +0 -184
  256. package/src/components/CodeSnippet.tsx +0 -725
  257. package/src/components/ConsoleLogCard.tsx +0 -679
  258. package/src/components/CopyButton.tsx +0 -87
  259. package/src/components/DiffViewer.tsx +0 -82
  260. package/src/components/DomainHeader.tsx +0 -224
  261. package/src/components/EmptyState.tsx +0 -97
  262. package/src/components/EndOfListFooter.tsx +0 -100
  263. package/src/components/ErrorBoundary.tsx +0 -688
  264. package/src/components/HeadersSection.tsx +0 -172
  265. package/src/components/HighlightText.tsx +0 -100
  266. package/src/components/Inspector/AnalyticsFilterModal.tsx +0 -1250
  267. package/src/components/Inspector/AnalyticsTab.tsx +0 -1362
  268. package/src/components/Inspector/BundleTab.tsx +0 -4768
  269. package/src/components/Inspector/ConsoleTab.tsx +0 -726
  270. package/src/components/Inspector/CrashDetail.tsx +0 -997
  271. package/src/components/Inspector/CrashFilterModal.tsx +0 -721
  272. package/src/components/Inspector/CrashTab.tsx +0 -933
  273. package/src/components/Inspector/DebuggingTab.tsx +0 -1103
  274. package/src/components/Inspector/DeviceInfoTab.tsx +0 -1397
  275. package/src/components/Inspector/FabLauncher.tsx +0 -590
  276. package/src/components/Inspector/FeatureUnderDevNotice.tsx +0 -94
  277. package/src/components/Inspector/FeedbackModal.tsx +0 -626
  278. package/src/components/Inspector/InspectorContext.tsx +0 -28
  279. package/src/components/Inspector/InspectorHeader.tsx +0 -1583
  280. package/src/components/Inspector/LogDetail.tsx +0 -1431
  281. package/src/components/Inspector/MainScreen.tsx +0 -460
  282. package/src/components/Inspector/MediaGalleryTab.tsx +0 -829
  283. package/src/components/Inspector/MediaPreviewModal.tsx +0 -783
  284. package/src/components/Inspector/NavigationTracker.tsx +0 -13
  285. package/src/components/Inspector/NetworkDetail.tsx +0 -778
  286. package/src/components/Inspector/NetworkFilterModal.tsx +0 -730
  287. package/src/components/Inspector/NetworkTab.tsx +0 -820
  288. package/src/components/Inspector/NpmStarPrompt.tsx +0 -532
  289. package/src/components/Inspector/NpmUpdateToast.tsx +0 -387
  290. package/src/components/Inspector/PerformanceTab.tsx +0 -1967
  291. package/src/components/Inspector/ReduxDetail.tsx +0 -1651
  292. package/src/components/Inspector/ReduxTab.tsx +0 -987
  293. package/src/components/Inspector/SettingsPanel.tsx +0 -5136
  294. package/src/components/Inspector/SkeletonPlaceholder.tsx +0 -206
  295. package/src/components/Inspector/StorageTab.tsx +0 -1159
  296. package/src/components/Inspector/TabBar.tsx +0 -431
  297. package/src/components/Inspector/UpdateAvailableModal.tsx +0 -555
  298. package/src/components/JsonViewer.tsx +0 -549
  299. package/src/components/LogCard.tsx +0 -694
  300. package/src/components/LogSyntaxHighlighter.tsx +0 -178
  301. package/src/components/MetaAccordion.tsx +0 -355
  302. package/src/components/MiniBarChart.tsx +0 -42
  303. package/src/components/MiniLineChart.tsx +0 -33
  304. package/src/components/NetworkIcons.tsx +0 -2655
  305. package/src/components/QRCodeView.tsx +0 -75
  306. package/src/components/SectionHeader.tsx +0 -101
  307. package/src/components/SegmentedTabs.tsx +0 -84
  308. package/src/components/SkeletonPlaceholder.tsx +0 -206
  309. package/src/components/Slider.tsx +0 -300
  310. package/src/components/SourcePageCard.tsx +0 -150
  311. package/src/components/Toast.tsx +0 -131
  312. package/src/components/TouchableScale.tsx +0 -61
  313. package/src/components/TreeNode.tsx +0 -171
  314. package/src/console.ts +0 -24
  315. package/src/constants/index.ts +0 -41
  316. package/src/constants/telemetryConfig.ts +0 -4
  317. package/src/constants/version.ts +0 -3
  318. package/src/crash.ts +0 -32
  319. package/src/customHooks/analyticsLogger.ts +0 -336
  320. package/src/customHooks/bundleAnalyzer.ts +0 -1256
  321. package/src/customHooks/consoleLogger.ts +0 -530
  322. package/src/customHooks/crashHandler.ts +0 -944
  323. package/src/customHooks/logFilters.ts +0 -32
  324. package/src/customHooks/networkLogger.ts +0 -624
  325. package/src/customHooks/performanceTracker.ts +0 -1014
  326. package/src/customHooks/reduxLogger.ts +0 -406
  327. package/src/customHooks/storageInspector.ts +0 -513
  328. package/src/customHooks/useAccordion.tsx +0 -27
  329. package/src/decorators/index.ts +0 -184
  330. package/src/helpers/gaAnalyticsRegistry.ts +0 -204
  331. package/src/helpers/index.ts +0 -1092
  332. package/src/helpers/memoryManager.ts +0 -138
  333. package/src/helpers/qrGenerator.ts +0 -430
  334. package/src/helpers/remoteConfig.ts +0 -212
  335. package/src/helpers/searchQueryParser.ts +0 -84
  336. package/src/helpers/settingsStore.ts +0 -171
  337. package/src/helpers/telemetry.ts +0 -568
  338. package/src/helpers/toast.ts +0 -17
  339. package/src/i18n/index.ts +0 -104
  340. package/src/i18n/locales/en.json +0 -1141
  341. package/src/index.tsx +0 -2650
  342. package/src/metro.ts +0 -598
  343. package/src/network.ts +0 -22
  344. package/src/performance.ts +0 -38
  345. package/src/redux.ts +0 -23
  346. package/src/storage.ts +0 -18
  347. package/src/styles/AppColors.ts +0 -455
  348. package/src/styles/AppFonts.ts +0 -26
  349. package/src/styles/common.ts +0 -209
  350. package/src/styles/index.ts +0 -1606
  351. package/src/types/enums.ts +0 -210
  352. package/src/types/index.ts +0 -34
  353. package/src/types/interfaces.ts +0 -535
@@ -1,944 +0,0 @@
1
- import {
2
- LogBox,
3
- NativeModules,
4
- TurboModuleRegistry,
5
- NativeEventEmitter,
6
- Platform,
7
- AppState,
8
- Dimensions,
9
- } from 'react-native';
10
- import {CrashRecord, ParsedStackFrame, CrashBreadcrumb} from '../types';
11
- import {CrashExportFormat, CrashType} from '../types/enums';
12
- import {addLogFromCrash} from './consoleLogger';
13
- import {
14
- showNativeFloatingButton,
15
- setNativeFloatingButtonBadge,
16
- } from '../native/NativeInspector';
17
- import {t} from '../i18n';
18
-
19
- export interface CrashEventPayload {
20
- error: Error | any;
21
- isFatal?: boolean;
22
- message: string;
23
- stack?: string;
24
- timestamp: number;
25
- logId?: number;
26
- crashRecord?: CrashRecord;
27
- }
28
-
29
- export {CrashExportFormat};
30
-
31
- type CrashListener = (payload: CrashEventPayload) => void;
32
-
33
- let crashListeners: CrashListener[] = [];
34
- let isCrashHandlerInitialized = false;
35
- let lastHandledErrorTimestamp = 0;
36
- let crashRecordsStore: CrashRecord[] = [];
37
- let breadcrumbsStore: CrashBreadcrumb[] = [];
38
- const MAX_BREADCRUMBS = 50;
39
- let maxStoredCrashes = 100;
40
- const appStartTime = Date.now();
41
- let isCrashModuleEnabled = false;
42
-
43
- export const setCrashModuleEnabled = (enabled: boolean) => {
44
- isCrashModuleEnabled = enabled;
45
- };
46
-
47
- export const getCrashModuleEnabled = () => isCrashModuleEnabled;
48
-
49
- // ─── BREADCRUMB MANAGERS ───────────────────────────────────────────────────────
50
-
51
- export const setMaxCrashLogsLimit = (max: number): void => {
52
- maxStoredCrashes = Math.max(10, max);
53
- if (crashRecordsStore.length > maxStoredCrashes) {
54
- crashRecordsStore = crashRecordsStore.slice(0, maxStoredCrashes);
55
- }
56
- };
57
-
58
- export const getMaxCrashLogsLimit = (): number => maxStoredCrashes;
59
-
60
- export const pruneCrashRecords = (targetCount?: number): number => {
61
- const countToKeep = targetCount !== undefined ? Math.max(0, targetCount) : Math.floor(crashRecordsStore.length / 2);
62
- const pruned = crashRecordsStore.length - countToKeep;
63
- if (pruned > 0) {
64
- crashRecordsStore = crashRecordsStore.slice(0, countToKeep);
65
- }
66
- if (breadcrumbsStore.length > 20) {
67
- breadcrumbsStore = breadcrumbsStore.slice(0, 20);
68
- }
69
- return Math.max(0, pruned);
70
- };
71
-
72
- export const addCrashBreadcrumb = (
73
- type: CrashBreadcrumb['type'],
74
- message: string,
75
- data?: any,
76
- ): void => {
77
- if (!isCrashModuleEnabled) return;
78
- try {
79
- const entry: CrashBreadcrumb = {
80
- type,
81
- message,
82
- timestamp: Date.now(),
83
- data,
84
- };
85
- breadcrumbsStore.unshift(entry);
86
- if (breadcrumbsStore.length > MAX_BREADCRUMBS) {
87
- breadcrumbsStore = breadcrumbsStore.slice(0, MAX_BREADCRUMBS);
88
- }
89
- } catch {}
90
- };
91
-
92
- export const recordNavigationBreadcrumb = (
93
- fromRoute: string,
94
- toRoute: string,
95
- ): void => {
96
- addCrashBreadcrumb(
97
- 'navigation',
98
- t('crash.breadcrumbNavigation', {from: fromRoute || '/', to: toRoute || '/'}),
99
- {
100
- from: fromRoute,
101
- to: toRoute,
102
- },
103
- );
104
- };
105
-
106
- export const recordNetworkBreadcrumb = (
107
- url: string,
108
- method: string,
109
- status?: number,
110
- duration?: number,
111
- ): void => {
112
- const statusStr = status != null ? ` [${status}]` : '';
113
- const durStr = duration != null ? ` (${Math.round(duration)}ms)` : '';
114
- addCrashBreadcrumb(
115
- 'network',
116
- `${method.toUpperCase()} ${url}${statusStr}${durStr}`,
117
- {
118
- url,
119
- method,
120
- status,
121
- duration,
122
- },
123
- );
124
- };
125
-
126
- export const recordReduxBreadcrumb = (
127
- actionType: string,
128
- payload?: any,
129
- ): void => {
130
- addCrashBreadcrumb('redux', t('crash.breadcrumbAction', {actionType}), {
131
- type: actionType,
132
- payloadSummary:
133
- typeof payload === 'object' && payload !== null
134
- ? Object.keys(payload)
135
- : typeof payload,
136
- });
137
- };
138
-
139
- export const recordUserActionBreadcrumb = (
140
- action: string,
141
- metadata?: any,
142
- ): void => {
143
- addCrashBreadcrumb('user', action, metadata);
144
- };
145
-
146
- export const clearCrashBreadcrumbs = (): void => {
147
- breadcrumbsStore = [];
148
- };
149
-
150
- export const getCrashBreadcrumbs = (): CrashBreadcrumb[] => {
151
- return [...breadcrumbsStore];
152
- };
153
-
154
- // ─── STACK TRACE PARSING & INTELLIGENT SOURCE DETECTION ───────────────────────
155
-
156
- /**
157
- * Intelligent stack trace parser with multi-engine support:
158
- * - Hermes bytecode & source maps
159
- * - Android Java / Kotlin native frames
160
- * - iOS Objective-C / Swift symbols
161
- * - JavaScript standard V8 & SpiderMonkey
162
- */
163
- export const parseCrashStackTrace = (stack?: string): ParsedStackFrame[] => {
164
- if (!stack || typeof stack !== 'string') return [];
165
- const lines = stack.split('\n');
166
- const frames: ParsedStackFrame[] = [];
167
-
168
- for (const line of lines) {
169
- const trimmed = line.trim();
170
- if (!trimmed) continue;
171
-
172
- // Filter out internal wrapper noise
173
- if (
174
- trimmed.includes('crashHandler.ts') ||
175
- trimmed.includes('handleInterceptedCrash') ||
176
- trimmed.includes('addLogFromCrash') ||
177
- trimmed.includes('setupGlobalCrashHandler')
178
- ) {
179
- continue;
180
- }
181
-
182
- // Pattern 1: iOS/Hermes format: method@file:line:column or method@url:line:col
183
- const iosMatch = trimmed.match(/^([^@]+)@(.*):(\d+):(\d+)$/);
184
- if (iosMatch) {
185
- const [, method, file, lineNum, colNum] = iosMatch;
186
- const cleanFile = file.split('?')[0].split('/').pop() || file;
187
- const isAppCode =
188
- !file.includes('node_modules') &&
189
- !file.includes('react-native') &&
190
- !file.includes('react-dom') &&
191
- !file.includes('hermes') &&
192
- !file.includes('internal');
193
- frames.push({
194
- method: method.trim(),
195
- file: cleanFile,
196
- lineNumber: parseInt(lineNum, 10),
197
- column: parseInt(colNum, 10),
198
- raw: trimmed,
199
- isAppCode,
200
- });
201
- continue;
202
- }
203
-
204
- // Pattern 2: V8/Android JS format: at method (file:line:column)
205
- const androidMatch = trimmed.match(/^at\s+(.+)\s+\((.+):(\d+):(\d+)\)$/);
206
- if (androidMatch) {
207
- const [, method, file, lineNum, colNum] = androidMatch;
208
- const cleanFile = file.split('?')[0].split('/').pop() || file;
209
- const isAppCode =
210
- !file.includes('node_modules') &&
211
- !file.includes('react-native') &&
212
- !file.includes('react-dom') &&
213
- !file.includes('internal');
214
- frames.push({
215
- method: method.trim(),
216
- file: cleanFile,
217
- lineNumber: parseInt(lineNum, 10),
218
- column: parseInt(colNum, 10),
219
- raw: trimmed,
220
- isAppCode,
221
- });
222
- continue;
223
- }
224
-
225
- // Pattern 3: Simple at file:line:column
226
- const simpleMatch = trimmed.match(/^at\s+(.+):(\d+):(\d+)$/);
227
- if (simpleMatch) {
228
- const [, file, lineNum, colNum] = simpleMatch;
229
- const cleanFile = file.split('?')[0].split('/').pop() || file;
230
- const isAppCode =
231
- !file.includes('node_modules') && !file.includes('react-native');
232
- frames.push({
233
- method: '<anonymous>',
234
- file: cleanFile,
235
- lineNumber: parseInt(lineNum, 10),
236
- column: parseInt(colNum, 10),
237
- raw: trimmed,
238
- isAppCode,
239
- });
240
- continue;
241
- }
242
-
243
- // Pattern 4: Java / Android Native Frame: at com.pkg.Class.method(Class.java:123)
244
- const javaMatch = trimmed.match(
245
- /^at\s+([a-zA-Z0-9_$.]+)\(([a-zA-Z0-9_$]+\.java):(\d+)\)$/,
246
- );
247
- if (javaMatch) {
248
- const [, methodPath, fileName, lineNum] = javaMatch;
249
- const isAppCode =
250
- !methodPath.startsWith('com.facebook.react') &&
251
- !methodPath.startsWith('android.');
252
- frames.push({
253
- method: methodPath,
254
- file: fileName,
255
- lineNumber: parseInt(lineNum, 10),
256
- column: 0,
257
- raw: trimmed,
258
- isAppCode,
259
- });
260
- continue;
261
- }
262
-
263
- // Pattern 5: iOS Mach-O Symbol: 0 AppName 0x000000010... -[ViewController method] + 48
264
- const machOMatch = trimmed.match(
265
- /^\d+\s+([^\s]+)\s+(0x[0-9a-fA-F]+)\s+(.+)$/,
266
- );
267
- if (machOMatch) {
268
- const [, binaryName, address, symbol] = machOMatch;
269
- const isAppCode =
270
- !binaryName.startsWith('lib') &&
271
- !binaryName.startsWith('Core') &&
272
- !binaryName.startsWith('React');
273
- frames.push({
274
- method: symbol,
275
- file: binaryName,
276
- lineNumber: 0,
277
- column: 0,
278
- raw: trimmed,
279
- isAppCode,
280
- });
281
- continue;
282
- }
283
-
284
- // Pattern 6: Fallback for generic frame lines
285
- frames.push({
286
- method: trimmed.startsWith('at ') ? trimmed.slice(3) : trimmed,
287
- file: 'runtime',
288
- lineNumber: 0,
289
- column: 0,
290
- raw: trimmed,
291
- isAppCode: false,
292
- });
293
- }
294
-
295
- return frames;
296
- };
297
-
298
- // ─── DIAGNOSTICS & SYSTEM METRICS ─────────────────────────────────────────────
299
-
300
- const getMemoryDiagnostics = () => {
301
- try {
302
- const performance = (globalThis as any).performance;
303
- if (performance && performance.memory) {
304
- return {
305
- usedJSHeapSize: Math.round(
306
- performance.memory.usedJSHeapSize / (1024 * 1024),
307
- ),
308
- totalJSHeapSize: Math.round(
309
- performance.memory.totalJSHeapSize / (1024 * 1024),
310
- ),
311
- };
312
- }
313
- } catch {}
314
- return undefined;
315
- };
316
-
317
- const getScreenDimensions = () => {
318
- try {
319
- const window = Dimensions.get('window');
320
- return `${Math.round(window.width)}x${Math.round(window.height)} (${
321
- window.scale
322
- }x)`;
323
- } catch {
324
- return t('crash.unknown');
325
- }
326
- };
327
-
328
- /**
329
- * Computes a unique fingerprint signature to group recurring crash occurrences.
330
- */
331
- export const computeCrashFingerprint = (crash: CrashRecord): string => {
332
- const type = crash.type || 'js';
333
- const name = crash.name || 'Error';
334
- const topFrame =
335
- crash.parsedStack && crash.parsedStack.length > 0
336
- ? crash.parsedStack[0]
337
- : null;
338
- const location = topFrame
339
- ? `${topFrame.file}:${topFrame.lineNumber}`
340
- : 'unknown';
341
- return `${type}_${name}_${location}`;
342
- };
343
-
344
- // ─── CRASH RECORD MANAGEMENT & INTERCEPTION ───────────────────────────────────
345
-
346
- export const getCrashRecords = (): CrashRecord[] => {
347
- return [...crashRecordsStore];
348
- };
349
-
350
- export const clearCrashRecords = (): void => {
351
- crashRecordsStore = [];
352
- emitCrashEvent({
353
- error: null,
354
- message: '__CLEARED__',
355
- timestamp: Date.now(),
356
- });
357
- };
358
-
359
- export const subscribeCrashEvents = (listener: CrashListener): (() => void) => {
360
- crashListeners.push(listener);
361
- return () => {
362
- crashListeners = crashListeners.filter(l => l !== listener);
363
- };
364
- };
365
-
366
- export const emitCrashEvent = (payload: CrashEventPayload): void => {
367
- if (payload.message !== '__CLEARED__') {
368
- const now = Date.now();
369
- // Throttle duplicate rapid crash emissions within 250ms
370
- if (now - lastHandledErrorTimestamp < 250) {
371
- return;
372
- }
373
- lastHandledErrorTimestamp = now;
374
- }
375
-
376
- crashListeners.forEach(listener => {
377
- try {
378
- listener(payload);
379
- } catch {}
380
- });
381
- };
382
-
383
- /**
384
- * Core exception interceptor. Ingests all forms of errors, parses call stacks,
385
- * collects device telemetry, records breadcrumbs, and updates the store.
386
- */
387
- export const handleInterceptedCrash = (
388
- errorOrTitle: any,
389
- rawStack?: any,
390
- isFatal = false,
391
- customType?: CrashType,
392
- componentStack?: string,
393
- ): CrashRecord => {
394
- try {
395
- const errorObj =
396
- errorOrTitle instanceof Error
397
- ? errorOrTitle
398
- : typeof errorOrTitle === 'object' && errorOrTitle !== null
399
- ? errorOrTitle
400
- : new Error(String(errorOrTitle || t('crash.runtimeException')));
401
-
402
- const rawMsg =
403
- errorObj.message ||
404
- (typeof errorOrTitle === 'string' ? errorOrTitle : t('crash.runtimeException'));
405
-
406
- let stackString = '';
407
- if (typeof rawStack === 'string') {
408
- stackString = rawStack;
409
- } else if (Array.isArray(rawStack)) {
410
- stackString = rawStack
411
- .map(
412
- f =>
413
- `at ${f.methodName || '<anonymous>'} (${f.file || 'unknown'}:${
414
- f.lineNumber || 0
415
- }:${f.column || 0})`,
416
- )
417
- .join('\n');
418
- } else {
419
- stackString = errorObj.stack || new Error().stack || '';
420
- }
421
-
422
- // Determine Crash Type
423
- let inferredType: CrashType = customType || CrashType.Js;
424
- const lowMsg = rawMsg.toLowerCase();
425
- if (!customType) {
426
- if (
427
- lowMsg.includes('native') ||
428
- lowMsg.includes('sigsegv') ||
429
- lowMsg.includes('nsrange') ||
430
- lowMsg.includes('nullpointerexception') ||
431
- lowMsg.includes('fatal signal')
432
- ) {
433
- inferredType = CrashType.Native;
434
- } else if (
435
- lowMsg.includes('promise') ||
436
- lowMsg.includes('unhandled rejection') ||
437
- lowMsg.includes('unhandledrejection')
438
- ) {
439
- inferredType = CrashType.Promise;
440
- } else if (
441
- lowMsg.includes('render') ||
442
- lowMsg.includes('errorboundary') ||
443
- componentStack
444
- ) {
445
- inferredType = CrashType.Render;
446
- } else {
447
- inferredType = CrashType.Js;
448
- }
449
- }
450
-
451
- const now = new Date();
452
- const dateStr = now.toLocaleDateString();
453
- const timeStr = now.toLocaleTimeString();
454
-
455
- const parsedStack = parseCrashStackTrace(stackString);
456
-
457
- const log = addLogFromCrash(
458
- errorObj,
459
- `[${isFatal ? t('crash.logFatalCrash') : t('crash.logUnhandledError')}] ${rawMsg}`,
460
- stackString,
461
- isFatal,
462
- );
463
-
464
- const isHermes = typeof (globalThis as any).HermesInternal !== 'undefined';
465
- const isFabric =
466
- typeof (globalThis as any).nativeFabricUIManager !== 'undefined';
467
-
468
- const crashRecord: CrashRecord = {
469
- id: `crash_${Date.now()}_${Math.random().toString(36).substr(2, 6)}`,
470
- error: errorObj,
471
- isFatal,
472
- type: inferredType,
473
- message: rawMsg,
474
- name: errorObj.name || (isFatal ? t('crash.errorNameFatal') : t('crash.errorNameUnhandled')),
475
- stack: stackString,
476
- parsedStack,
477
- componentStack: componentStack || undefined,
478
- timestamp: Date.now(),
479
- dateStr,
480
- timeStr,
481
- deviceInfo: {
482
- platform: Platform.OS,
483
- osVersion: String(Platform.Version),
484
- rnVersion: (Platform.constants as any)?.reactNativeVersion
485
- ? `${(Platform.constants as any).reactNativeVersion.major}.${
486
- (Platform.constants as any).reactNativeVersion.minor
487
- }.${(Platform.constants as any).reactNativeVersion.patch}`
488
- : t('crash.unknown'),
489
- isHermes,
490
- isFabric,
491
- appState: AppState.currentState || 'active',
492
- },
493
- memoryInfo: getMemoryDiagnostics(),
494
- breadcrumbs: [...breadcrumbsStore],
495
- logId: log?.id,
496
- };
497
-
498
- crashRecordsStore.unshift(crashRecord);
499
- if (crashRecordsStore.length > maxStoredCrashes) {
500
- crashRecordsStore = crashRecordsStore.slice(0, maxStoredCrashes);
501
- }
502
-
503
- emitCrashEvent({
504
- error: errorObj,
505
- isFatal,
506
- message: `[${isFatal ? t('crash.logFatalCrash') : t('crash.logUnhandledError')}] ${rawMsg}`,
507
- stack: stackString,
508
- timestamp: Date.now(),
509
- logId: log?.id,
510
- crashRecord,
511
- });
512
-
513
- // Ensure native floating icon is visible & badged even if React UI is broken
514
- try {
515
- showNativeFloatingButton();
516
- setNativeFloatingButtonBadge(true);
517
- } catch {}
518
-
519
- return crashRecord;
520
- } catch (err: any) {
521
- const fallbackRecord: CrashRecord = {
522
- id: `crash_${Date.now()}`,
523
- isFatal: true,
524
- type: CrashType.Js,
525
- message: String(errorOrTitle || t('crash.unknownException')),
526
- timestamp: Date.now(),
527
- dateStr: new Date().toLocaleDateString(),
528
- timeStr: new Date().toLocaleTimeString(),
529
- };
530
- return fallbackRecord;
531
- }
532
- };
533
-
534
- /**
535
- * Manually report a caught error with custom metadata.
536
- */
537
- export const recordCustomCrash = (
538
- error: Error | string,
539
- options?: {
540
- isFatal?: boolean;
541
- type?: CrashType;
542
- componentStack?: string;
543
- },
544
- ): CrashRecord => {
545
- return handleInterceptedCrash(
546
- error,
547
- typeof error === 'object' ? (error as Error).stack : undefined,
548
- options?.isFatal ?? false,
549
- options?.type || CrashType.Custom,
550
- options?.componentStack,
551
- );
552
- };
553
-
554
- /**
555
- * Simulates a crash for developer testing without crashing the host app.
556
- * Uses real runtime Error objects — no mocked file paths or fake stacks.
557
- */
558
- export const simulateTestCrash = (
559
- type: CrashType = CrashType.Js,
560
- customMessage?: string,
561
- customStack?: string,
562
- ): CrashRecord => {
563
- const err = new Error(customMessage || _defaultSimMessage(type));
564
-
565
- return handleInterceptedCrash(
566
- type === CrashType.Native ? err.message : err,
567
- customStack || err.stack,
568
- type === CrashType.Native,
569
- type,
570
- type === CrashType.Render ? _buildComponentStack() : undefined,
571
- );
572
- };
573
-
574
- /** Generates a generic error message per type — no fake references. */
575
- const _defaultSimMessage = (type: CrashType): string => {
576
- switch (type) {
577
- case 'native':
578
- return t('crash.simNativeMessage');
579
- case 'promise':
580
- return t('crash.simPromiseMessage');
581
- case 'render':
582
- return t('crash.simRenderMessage');
583
- default:
584
- return t('crash.simJsMessage');
585
- }
586
- };
587
-
588
- /** Builds a component stack from the real React tree if possible. */
589
- const _buildComponentStack = (): string | undefined => {
590
- try {
591
- const err = new Error();
592
- if (err.stack) {
593
- // Return the live stack as a pseudo component-stack
594
- return err.stack
595
- .split('\n')
596
- .slice(1, 6)
597
- .map(line => ` ${line.trim()}`)
598
- .join('\n');
599
- }
600
- } catch {}
601
- return undefined;
602
- };
603
-
604
- // ─── EXPORT & REPORTING UTILITIES ─────────────────────────────────────────────
605
-
606
- /**
607
- * Formats a crash into Text, Markdown, or JSON.
608
- */
609
- export const exportCrashReport = (
610
- crash: CrashRecord,
611
- format: CrashExportFormat = 'text',
612
- ): string => {
613
- if (format === 'json') {
614
- return JSON.stringify(crash, null, 2);
615
- }
616
-
617
- const uptimeSec = Math.round((crash.timestamp - appStartTime) / 1000);
618
-
619
- if (format === 'markdown') {
620
- const lines: string[] = [];
621
- lines.push(`## ${t('crash.mdReportTitle', {name: crash.name || 'Error'})}`);
622
- lines.push(`> **${crash.message}**`);
623
- lines.push('');
624
- lines.push(
625
- `- **${t('crash.reportType')}** \`${crash.type.toUpperCase()}\``,
626
- );
627
- lines.push(
628
- `- **${t('crash.reportFatal')}** \`${
629
- crash.isFatal
630
- ? t('crash.mdSeverityFatal')
631
- : t('crash.mdSeverityHandled')
632
- }\``,
633
- );
634
- lines.push(
635
- `- **${t('crash.reportTimestamp')}** ${crash.dateStr} ${crash.timeStr}`,
636
- );
637
- lines.push(`- **${t('crash.reportUptime')}** ${uptimeSec}s`);
638
- lines.push(
639
- `- **${t(
640
- 'crash.reportPlatform',
641
- )}** ${crash.deviceInfo?.platform?.toUpperCase()} (v${
642
- crash.deviceInfo?.osVersion
643
- })`,
644
- );
645
- lines.push(
646
- `- **${t('crash.reportReactNative')}** v${
647
- crash.deviceInfo?.rnVersion || 'N/A'
648
- }`,
649
- );
650
- lines.push(
651
- `- **${t('crash.jsEngine')}** ${
652
- crash.deviceInfo?.isHermes ? t('crash.hermesEngine') : t('crash.jsc')
653
- }`,
654
- );
655
- lines.push(
656
- `- **${t('crash.reportArchitecture')}** ${
657
- crash.deviceInfo?.isFabric
658
- ? t('crash.reportFabricNew')
659
- : t('crash.reportPaperLegacy')
660
- }`,
661
- );
662
- if (crash.memoryInfo) {
663
- lines.push(
664
- `- **${t('crash.reportJsMemory')}** ${
665
- crash.memoryInfo.usedJSHeapSize
666
- } MB / ${crash.memoryInfo.totalJSHeapSize} MB`,
667
- );
668
- }
669
- lines.push('');
670
- lines.push(`### ${t('crash.mdStackTrace')}`);
671
- lines.push('```');
672
- lines.push(crash.stack || t('crash.reportNoStackTrace'));
673
- lines.push('```');
674
- if (crash.componentStack) {
675
- lines.push('');
676
- lines.push(`### ${t('crash.mdComponentHierarchy')}`);
677
- lines.push('```');
678
- lines.push(crash.componentStack);
679
- lines.push('```');
680
- }
681
- if (crash.breadcrumbs && crash.breadcrumbs.length > 0) {
682
- lines.push('');
683
- lines.push(`### ${t('crash.mdRecentBreadcrumbs')}`);
684
- crash.breadcrumbs.forEach(b => {
685
- const time = new Date(b.timestamp).toLocaleTimeString();
686
- lines.push(
687
- `- \`[${time}]\` **[${b.type.toUpperCase()}]** ${b.message}`,
688
- );
689
- });
690
- }
691
- return lines.join('\n');
692
- }
693
-
694
- // Standard Text format
695
- const lines: string[] = [];
696
- lines.push('====================================================');
697
- lines.push(` ${t('crash.reportTitle')} `);
698
- lines.push('====================================================');
699
- lines.push(`${t('crash.reportErrorName')} ${crash.name || 'Error'}`);
700
- lines.push(`${t('crash.reportMessage')} ${crash.message}`);
701
- lines.push(`${t('crash.reportType')} ${crash.type.toUpperCase()}`);
702
- lines.push(
703
- `${t('crash.reportFatal')} ${
704
- crash.isFatal ? t('crash.reportFatalYes') : t('crash.reportFatalNo')
705
- }`,
706
- );
707
- lines.push(
708
- `${t('crash.reportTimestamp')} ${crash.dateStr} ${crash.timeStr} (${
709
- crash.timestamp
710
- })`,
711
- );
712
- lines.push(
713
- `${t('crash.reportUptime')} ${t('crash.reportUptimeValue', {
714
- seconds: uptimeSec,
715
- })}`,
716
- );
717
- lines.push(
718
- `${t(
719
- 'crash.reportPlatform',
720
- )} ${crash.deviceInfo?.platform?.toUpperCase()} (v${
721
- crash.deviceInfo?.osVersion
722
- })`,
723
- );
724
- lines.push(
725
- `${t('crash.reportReactNative')} ${crash.deviceInfo?.rnVersion || 'N/A'}`,
726
- );
727
- lines.push(
728
- `${t('crash.reportHermes')} ${
729
- crash.deviceInfo?.isHermes
730
- ? t('crash.reportEnabled')
731
- : t('crash.reportDisabled')
732
- }`,
733
- );
734
- lines.push(
735
- `${t('crash.reportArchitecture')} ${
736
- crash.deviceInfo?.isFabric
737
- ? t('crash.reportFabricNew')
738
- : t('crash.reportPaperLegacy')
739
- }`,
740
- );
741
- lines.push(`${t('crash.reportScreenSize')} ${getScreenDimensions()}`);
742
- lines.push(
743
- `${t('crash.reportAppState')} ${
744
- crash.deviceInfo?.appState || 'active'
745
- }`,
746
- );
747
- if (crash.memoryInfo) {
748
- lines.push(
749
- `${t('crash.reportJsMemory')} ${
750
- crash.memoryInfo.usedJSHeapSize
751
- } MB / ${crash.memoryInfo.totalJSHeapSize} MB`,
752
- );
753
- }
754
- lines.push('----------------------------------------------------');
755
- lines.push(`${t('crash.reportStackTrace')}`);
756
- lines.push(crash.stack || t('crash.reportNoStackTrace'));
757
- if (crash.componentStack) {
758
- lines.push('----------------------------------------------------');
759
- lines.push(`${t('crash.reportComponentHierarchy')}`);
760
- lines.push(crash.componentStack);
761
- }
762
- if (crash.breadcrumbs && crash.breadcrumbs.length > 0) {
763
- lines.push('----------------------------------------------------');
764
- lines.push(`${t('crash.reportRecentBreadcrumbs')}`);
765
- crash.breadcrumbs.forEach(b => {
766
- const time = new Date(b.timestamp).toLocaleTimeString();
767
- lines.push(` [${time}] [${b.type.toUpperCase()}] ${b.message}`);
768
- });
769
- }
770
- lines.push('====================================================');
771
- return lines.join('\n');
772
- };
773
-
774
- // ─── GLOBAL HANDLER INITIALIZATION ────────────────────────────────────────────
775
-
776
- /**
777
- * Natively intercepts and prevents crashes, native RedBox dialogues,
778
- * unhandled JS errors, and unhandled promise rejections.
779
- */
780
- export const setupGlobalCrashHandler = (): void => {
781
- if (isCrashHandlerInitialized) return;
782
- isCrashHandlerInitialized = true;
783
-
784
- // 1. Completely silence React Native LogBox & RedBox overlays
785
- try {
786
- if (LogBox && typeof LogBox.ignoreAllLogs === 'function') {
787
- LogBox.ignoreAllLogs(true);
788
- }
789
- } catch {}
790
-
791
- try {
792
- // @ts-ignore
793
- const LogBoxData = (require as any)(
794
- 'react-native/Libraries/LogBox/Data/LogBoxData',
795
- );
796
- if (LogBoxData && typeof LogBoxData.setDisabled === 'function') {
797
- LogBoxData.setDisabled(true);
798
- }
799
- } catch {}
800
-
801
- // 2. Intercept Native Module: NetworkInspectorModule (Android & iOS)
802
- try {
803
- const networkInspectorModule = NativeModules?.NetworkInspectorModule;
804
- if (networkInspectorModule) {
805
- if (
806
- typeof networkInspectorModule.enableNativeCrashProtection === 'function'
807
- ) {
808
- networkInspectorModule.enableNativeCrashProtection();
809
- }
810
-
811
- const nativeEmitter = new NativeEventEmitter(networkInspectorModule);
812
- nativeEmitter.addListener('onNativeCrash', (event: any) => {
813
- const platform = event?.platform || Platform.OS;
814
- const msg = `[${platform.toUpperCase()} ${t('crash.nativeCrashTitle')}] ${
815
- event?.message || t('crash.nativeUncaughtException')
816
- }`;
817
- const stack = event?.stack || '';
818
- handleInterceptedCrash(msg, stack, true, 'native');
819
- });
820
- }
821
- } catch {}
822
-
823
- // 3. Intercept Native ExceptionsManager & RedBox modules (Bridge & TurboModules)
824
- try {
825
- const tmReg =
826
- (TurboModuleRegistry as any) || (globalThis as any).__turboModuleProxy;
827
- const nativeExceptionsManager =
828
- NativeModules?.ExceptionsManager ||
829
- (tmReg?.get ? tmReg.get('ExceptionsManager') : null);
830
-
831
- if (nativeExceptionsManager) {
832
- nativeExceptionsManager.reportFatalException = (
833
- title: string,
834
- stack: any,
835
- exceptionId?: number,
836
- ) => {
837
- handleInterceptedCrash(title, stack, true, 'native');
838
- try {
839
- if (typeof nativeExceptionsManager.dismissRedbox === 'function') {
840
- nativeExceptionsManager.dismissRedbox();
841
- }
842
- } catch {}
843
- };
844
-
845
- nativeExceptionsManager.reportSoftException = (
846
- title: string,
847
- stack: any,
848
- exceptionId?: number,
849
- ) => {
850
- handleInterceptedCrash(title, stack, false, 'js');
851
- try {
852
- if (typeof nativeExceptionsManager.dismissRedbox === 'function') {
853
- nativeExceptionsManager.dismissRedbox();
854
- }
855
- } catch {}
856
- };
857
-
858
- nativeExceptionsManager.reportException = (data: any) => {
859
- const msg = data?.message || data?.title || t('crash.nativeException');
860
- const stack = data?.stack || data?.rawStack;
861
- handleInterceptedCrash(msg, stack, data?.isFatal ?? true, 'js');
862
- try {
863
- if (typeof nativeExceptionsManager.dismissRedbox === 'function') {
864
- nativeExceptionsManager.dismissRedbox();
865
- }
866
- } catch {}
867
- };
868
-
869
- nativeExceptionsManager.updateExceptionMessage = () => {};
870
- try {
871
- if (typeof nativeExceptionsManager.dismissRedbox === 'function') {
872
- nativeExceptionsManager.dismissRedbox();
873
- }
874
- } catch {}
875
- }
876
-
877
- const nativeRedBox =
878
- NativeModules?.RedBox ||
879
- NativeModules?.RCTRedBox ||
880
- (tmReg?.get ? tmReg.get('RedBox') || tmReg.get('RCTRedBox') : null);
881
-
882
- if (nativeRedBox) {
883
- if (typeof nativeRedBox.showErrorMessage === 'function') {
884
- nativeRedBox.showErrorMessage = () => {};
885
- }
886
- if (typeof nativeRedBox.showUserError === 'function') {
887
- nativeRedBox.showUserError = () => {};
888
- }
889
- if (typeof nativeRedBox.dismiss === 'function') {
890
- nativeRedBox.dismiss();
891
- }
892
- }
893
- } catch {}
894
-
895
- // 4. Hook React Native ErrorUtils
896
- try {
897
- const globalObj = globalThis as any;
898
- const errorUtils = globalObj.ErrorUtils;
899
-
900
- if (errorUtils) {
901
- if (typeof errorUtils.setGlobalHandler === 'function') {
902
- errorUtils.setGlobalHandler((error: Error, isFatal?: boolean) => {
903
- handleInterceptedCrash(error, error?.stack, isFatal ?? false, 'js');
904
- // Suppress calling default crashing handler to prevent termination & RedBox
905
- });
906
- }
907
- if (typeof errorUtils.reportFatalError === 'function') {
908
- errorUtils.reportFatalError = (error: Error) => {
909
- handleInterceptedCrash(error, error?.stack, true, 'js');
910
- };
911
- }
912
- if (typeof errorUtils.reportError === 'function') {
913
- errorUtils.reportError = (error: Error) => {
914
- handleInterceptedCrash(error, error?.stack, false, 'js');
915
- };
916
- }
917
- }
918
- } catch {}
919
-
920
- // 5. Hook global Promise unhandled rejections
921
- try {
922
- const globalObj = globalThis as any;
923
-
924
- const handleUnhandledPromise = (eventOrError: any) => {
925
- try {
926
- const reason =
927
- eventOrError?.reason || eventOrError?.detail?.reason || eventOrError;
928
- const message =
929
- reason?.message || String(reason || t('crash.unhandledPromiseRejection'));
930
- const stack =
931
- reason?.stack || (eventOrError?.stack ?? new Error().stack);
932
-
933
- handleInterceptedCrash(reason, stack, false, 'promise');
934
- } catch {}
935
- };
936
-
937
- if (typeof globalObj.addEventListener === 'function') {
938
- globalObj.addEventListener('unhandledrejection', handleUnhandledPromise);
939
- }
940
- if (typeof globalObj.onunhandledrejection !== 'undefined') {
941
- globalObj.onunhandledrejection = handleUnhandledPromise;
942
- }
943
- } catch {}
944
- };