react-native-inapp-inspector 1.1.24 → 1.1.26

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 (114) hide show
  1. package/android/build.gradle +36 -0
  2. package/android/src/main/AndroidManifest.xml +3 -0
  3. package/android/src/main/java/com/inappinspector/NetworkInspectorModule.java +114 -0
  4. package/android/src/main/java/com/inappinspector/NetworkInspectorPackage.java +28 -0
  5. package/dist/commonjs/components/AnalyticsEventCard.js +94 -88
  6. package/dist/commonjs/components/ConsoleLogCard.js +49 -25
  7. package/dist/commonjs/components/ErrorBoundary.d.ts +1 -1
  8. package/dist/commonjs/components/ErrorBoundary.js +9 -145
  9. package/dist/commonjs/components/Inspector/AnalyticsFilterModal.d.ts +7 -0
  10. package/dist/commonjs/components/Inspector/AnalyticsFilterModal.js +1002 -0
  11. package/dist/commonjs/components/Inspector/AnalyticsTab.js +637 -10
  12. package/dist/commonjs/components/Inspector/BundleTab.d.ts +1 -1
  13. package/dist/commonjs/components/Inspector/BundleTab.js +826 -406
  14. package/dist/commonjs/components/Inspector/CrashDetail.d.ts +3 -0
  15. package/dist/commonjs/components/Inspector/CrashDetail.js +796 -0
  16. package/dist/commonjs/components/Inspector/CrashFilterModal.d.ts +20 -0
  17. package/dist/commonjs/components/Inspector/CrashFilterModal.js +597 -0
  18. package/dist/commonjs/components/Inspector/CrashTab.d.ts +3 -0
  19. package/dist/commonjs/components/Inspector/CrashTab.js +727 -0
  20. package/dist/commonjs/components/Inspector/InspectorContext.js +6 -1
  21. package/dist/commonjs/components/Inspector/InspectorHeader.js +65 -28
  22. package/dist/commonjs/components/Inspector/LogDetail.js +227 -114
  23. package/dist/commonjs/components/Inspector/MainScreen.js +13 -4
  24. package/dist/commonjs/components/Inspector/NetworkDetail.js +131 -81
  25. package/dist/commonjs/components/Inspector/PerformanceTab.js +20 -10
  26. package/dist/commonjs/components/Inspector/SettingsPanel.js +90 -1
  27. package/dist/commonjs/components/Inspector/TabBar.js +15 -3
  28. package/dist/commonjs/components/NetworkIcons.d.ts +25 -0
  29. package/dist/commonjs/components/NetworkIcons.js +188 -1
  30. package/dist/commonjs/components/SegmentedTabs.js +33 -23
  31. package/dist/commonjs/components/TreeNode.js +13 -12
  32. package/dist/commonjs/constants/version.d.ts +1 -1
  33. package/dist/commonjs/constants/version.js +1 -1
  34. package/dist/commonjs/customHooks/analyticsLogger.js +70 -44
  35. package/dist/commonjs/customHooks/bundleAnalyzer.d.ts +5 -1
  36. package/dist/commonjs/customHooks/bundleAnalyzer.js +497 -126
  37. package/dist/commonjs/customHooks/consoleLogger.d.ts +1 -0
  38. package/dist/commonjs/customHooks/consoleLogger.js +153 -51
  39. package/dist/commonjs/customHooks/crashHandler.d.ts +64 -0
  40. package/dist/commonjs/customHooks/crashHandler.js +681 -0
  41. package/dist/commonjs/customHooks/networkLogger.js +74 -49
  42. package/dist/commonjs/customHooks/performanceTracker.d.ts +8 -0
  43. package/dist/commonjs/customHooks/performanceTracker.js +44 -3
  44. package/dist/commonjs/decorators/index.d.ts +49 -0
  45. package/dist/commonjs/decorators/index.js +142 -0
  46. package/dist/commonjs/helpers/gaAnalyticsRegistry.d.ts +18 -0
  47. package/dist/commonjs/helpers/gaAnalyticsRegistry.js +174 -0
  48. package/dist/commonjs/helpers/index.d.ts +7 -4
  49. package/dist/commonjs/helpers/index.js +102 -64
  50. package/dist/commonjs/i18n/locales/en.json +182 -4
  51. package/dist/commonjs/index.d.ts +6 -0
  52. package/dist/commonjs/index.js +310 -8
  53. package/dist/commonjs/styles/index.d.ts +4 -1
  54. package/dist/commonjs/styles/index.js +22 -19
  55. package/dist/commonjs/types/enums.d.ts +156 -9
  56. package/dist/commonjs/types/enums.js +139 -2
  57. package/dist/commonjs/types/interfaces.d.ts +70 -1
  58. package/dist/esm/components/AnalyticsEventCard.js +95 -89
  59. package/dist/esm/components/ConsoleLogCard.js +49 -25
  60. package/dist/esm/components/ErrorBoundary.d.ts +1 -1
  61. package/dist/esm/components/ErrorBoundary.js +10 -113
  62. package/dist/esm/components/Inspector/AnalyticsFilterModal.d.ts +7 -0
  63. package/dist/esm/components/Inspector/AnalyticsFilterModal.js +964 -0
  64. package/dist/esm/components/Inspector/AnalyticsTab.js +639 -12
  65. package/dist/esm/components/Inspector/BundleTab.d.ts +1 -1
  66. package/dist/esm/components/Inspector/BundleTab.js +827 -407
  67. package/dist/esm/components/Inspector/CrashDetail.d.ts +3 -0
  68. package/dist/esm/components/Inspector/CrashDetail.js +758 -0
  69. package/dist/esm/components/Inspector/CrashFilterModal.d.ts +20 -0
  70. package/dist/esm/components/Inspector/CrashFilterModal.js +557 -0
  71. package/dist/esm/components/Inspector/CrashTab.d.ts +3 -0
  72. package/dist/esm/components/Inspector/CrashTab.js +689 -0
  73. package/dist/esm/components/Inspector/InspectorContext.js +1 -0
  74. package/dist/esm/components/Inspector/InspectorHeader.js +66 -29
  75. package/dist/esm/components/Inspector/LogDetail.js +227 -114
  76. package/dist/esm/components/Inspector/MainScreen.js +14 -5
  77. package/dist/esm/components/Inspector/NetworkDetail.js +132 -49
  78. package/dist/esm/components/Inspector/PerformanceTab.js +20 -10
  79. package/dist/esm/components/Inspector/SettingsPanel.js +91 -2
  80. package/dist/esm/components/Inspector/TabBar.js +16 -4
  81. package/dist/esm/components/NetworkIcons.d.ts +25 -0
  82. package/dist/esm/components/NetworkIcons.js +161 -0
  83. package/dist/esm/components/SegmentedTabs.js +33 -23
  84. package/dist/esm/components/TreeNode.js +13 -12
  85. package/dist/esm/constants/version.d.ts +1 -1
  86. package/dist/esm/constants/version.js +1 -1
  87. package/dist/esm/customHooks/analyticsLogger.js +70 -44
  88. package/dist/esm/customHooks/bundleAnalyzer.d.ts +5 -1
  89. package/dist/esm/customHooks/bundleAnalyzer.js +493 -125
  90. package/dist/esm/customHooks/consoleLogger.d.ts +1 -0
  91. package/dist/esm/customHooks/consoleLogger.js +151 -50
  92. package/dist/esm/customHooks/crashHandler.d.ts +64 -0
  93. package/dist/esm/customHooks/crashHandler.js +659 -0
  94. package/dist/esm/customHooks/networkLogger.js +74 -49
  95. package/dist/esm/customHooks/performanceTracker.d.ts +8 -0
  96. package/dist/esm/customHooks/performanceTracker.js +38 -1
  97. package/dist/esm/decorators/index.d.ts +49 -0
  98. package/dist/esm/decorators/index.js +137 -0
  99. package/dist/esm/helpers/gaAnalyticsRegistry.d.ts +18 -0
  100. package/dist/esm/helpers/gaAnalyticsRegistry.js +169 -0
  101. package/dist/esm/helpers/index.d.ts +7 -4
  102. package/dist/esm/helpers/index.js +100 -63
  103. package/dist/esm/i18n/locales/en.json +182 -4
  104. package/dist/esm/index.d.ts +6 -0
  105. package/dist/esm/index.js +262 -8
  106. package/dist/esm/styles/index.d.ts +4 -1
  107. package/dist/esm/styles/index.js +22 -19
  108. package/dist/esm/types/enums.d.ts +156 -9
  109. package/dist/esm/types/enums.js +138 -3
  110. package/dist/esm/types/interfaces.d.ts +70 -1
  111. package/ios/NetworkInspectorModule.h +6 -0
  112. package/ios/NetworkInspectorModule.m +125 -0
  113. package/package.json +5 -2
  114. package/react-native-inapp-inspector.podspec +18 -0
@@ -73,6 +73,7 @@ const LogDetail = react_1.default.memo(() => {
73
73
  const jsonContent = (0, react_1.useMemo)(() => (selectedLog ? (0, helpers_1.getJsonContent)(selectedLog.message) : null), [selectedLog]);
74
74
  const [stackViewMode, setStackViewMode] = (0, react_1.useState)('structured');
75
75
  const [stackSource, setStackSource] = (0, react_1.useState)('caller');
76
+ const [stackFilter, setStackFilter] = (0, react_1.useState)('app');
76
77
  const activeStackString = (0, react_1.useMemo)(() => {
77
78
  if (!selectedLog)
78
79
  return '';
@@ -81,21 +82,6 @@ const LogDetail = react_1.default.memo(() => {
81
82
  }
82
83
  return selectedLog.stack || selectedLog.caller || '';
83
84
  }, [selectedLog, stackSource]);
84
- const originFrame = (0, react_1.useMemo)(() => {
85
- if (!selectedLog)
86
- return null;
87
- if (selectedLog.caller && selectedLog.caller !== 'Unknown') {
88
- return (0, helpers_1.parseStackLine)(selectedLog.caller, true);
89
- }
90
- if (selectedLog.stack) {
91
- const firstLine = selectedLog.stack
92
- .split('\n')
93
- .find(l => l.trim().length > 0);
94
- if (firstLine)
95
- return (0, helpers_1.parseStackLine)(firstLine, true);
96
- }
97
- return null;
98
- }, [selectedLog]);
99
85
  const parsedStackFrames = (0, react_1.useMemo)(() => {
100
86
  if (!activeStackString)
101
87
  return [];
@@ -105,6 +91,29 @@ const LogDetail = react_1.default.memo(() => {
105
91
  .filter(l => l.length > 0)
106
92
  .map((line, idx) => (0, helpers_1.parseStackLine)(line, idx === 0));
107
93
  }, [activeStackString]);
94
+ const appStackFrames = (0, react_1.useMemo)(() => {
95
+ return parsedStackFrames.filter(f => f.frameType === 'app' || !f.isRuntimeNoise);
96
+ }, [parsedStackFrames]);
97
+ const displayedFrames = (0, react_1.useMemo)(() => {
98
+ if (stackFilter === 'app' && appStackFrames.length > 0) {
99
+ return appStackFrames;
100
+ }
101
+ return parsedStackFrames;
102
+ }, [stackFilter, appStackFrames, parsedStackFrames]);
103
+ const originFrame = (0, react_1.useMemo)(() => {
104
+ if (!selectedLog)
105
+ return null;
106
+ if (appStackFrames.length > 0) {
107
+ return appStackFrames[0];
108
+ }
109
+ if (selectedLog.caller && selectedLog.caller !== 'Unknown') {
110
+ return (0, helpers_1.parseStackLine)(selectedLog.caller, true);
111
+ }
112
+ if (parsedStackFrames.length > 0) {
113
+ return parsedStackFrames[0];
114
+ }
115
+ return null;
116
+ }, [selectedLog, appStackFrames, parsedStackFrames]);
108
117
  if (!selectedLog)
109
118
  return null;
110
119
  const isDark = AppColors_1.AppColors.primaryLight !== AppColors_1.AppColors.white;
@@ -138,14 +147,14 @@ const LogDetail = react_1.default.memo(() => {
138
147
  const subTabs = [
139
148
  {
140
149
  key: 'output',
141
- label: 'Output',
150
+ label: t('console.tabOutput'),
142
151
  icon: (isActive) => (<NetworkIcons_1.TerminalIcon color={isActive ? AppColors_1.AppColors.white : AppColors_1.AppColors.grayTextWeak} size={12}/>),
143
152
  },
144
153
  ...(hasMultipleArgs
145
154
  ? [
146
155
  {
147
156
  key: 'arguments',
148
- label: `Args (${selectedLog.rawArgs?.length})`,
157
+ label: t('console.tabArgs', { count: selectedLog.rawArgs?.length }),
149
158
  icon: (isActive) => (<NetworkIcons_1.RequestIcon color={isActive ? AppColors_1.AppColors.white : AppColors_1.AppColors.grayTextWeak} size={12}/>),
150
159
  },
151
160
  ]
@@ -154,14 +163,14 @@ const LogDetail = react_1.default.memo(() => {
154
163
  ? [
155
164
  {
156
165
  key: 'stack',
157
- label: 'Stack Trace',
166
+ label: t('console.tabStack'),
158
167
  icon: (isActive) => (<NetworkIcons_1.LayersIcon color={isActive ? AppColors_1.AppColors.white : AppColors_1.AppColors.grayTextWeak} size={12}/>),
159
168
  },
160
169
  ]
161
170
  : []),
162
171
  {
163
172
  key: 'metadata',
164
- label: 'Metadata',
173
+ label: t('console.tabMetadata'),
165
174
  icon: (isActive) => (<NetworkIcons_1.InfoCircleIcon color={isActive ? AppColors_1.AppColors.white : AppColors_1.AppColors.grayTextWeak} size={12}/>),
166
175
  },
167
176
  ];
@@ -291,7 +300,8 @@ const LogDetail = react_1.default.memo(() => {
291
300
  fontSize: 13,
292
301
  color: AppColors_1.AppColors.primaryBlack,
293
302
  lineHeight: 18,
294
- }} numberOfLines={1}>
303
+ flexShrink: 1,
304
+ }}>
295
305
  {originFrame?.functionName && originFrame.functionName !== '<anonymous>'
296
306
  ? `${originFrame.functionName}()`
297
307
  : originFrame?.fileName || t('console.consoleLog')}
@@ -306,11 +316,11 @@ const LogDetail = react_1.default.memo(() => {
306
316
  paddingVertical: 2,
307
317
  },
308
318
  ]}>
309
- <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 3 }}>
319
+ <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 3, flexWrap: 'wrap', flexShrink: 1 }}>
310
320
  <NetworkIcons_1.DocIcon color={AppColors_1.AppColors.brandPurple} size={10}/>
311
321
  <react_native_1.Text style={[
312
322
  styles_1.default.metaChipText,
313
- { color: AppColors_1.AppColors.brandPurple, fontSize: 10, fontFamily: AppFonts_1.AppFonts.interBold },
323
+ { color: AppColors_1.AppColors.brandPurple, fontSize: 10, fontFamily: AppFonts_1.AppFonts.interBold, flexShrink: 1 },
314
324
  ]}>
315
325
  {originFrame.fileName}
316
326
  {originFrame.lineNumber ? `:${originFrame.lineNumber}` : ''}
@@ -613,10 +623,12 @@ const LogDetail = react_1.default.memo(() => {
613
623
  ? AppColors_1.AppColors.primaryLight
614
624
  : AppColors_1.AppColors.grayBackground,
615
625
  }}>
626
+ {/* Header Top Row: Title, Mode switcher & Full copy */}
616
627
  <react_native_1.View style={{
617
628
  flexDirection: 'row',
618
629
  alignItems: 'center',
619
630
  justifyContent: 'space-between',
631
+ gap: 8,
620
632
  }}>
621
633
  <react_native_1.Text style={{
622
634
  fontFamily: AppFonts_1.AppFonts.interBold,
@@ -625,156 +637,257 @@ const LogDetail = react_1.default.memo(() => {
625
637
  textTransform: 'uppercase',
626
638
  letterSpacing: 0.4,
627
639
  }}>
628
- {stackSource === 'error' ? 'Error Exception Stack' : 'Call Stack'} ({parsedStackFrames.length} frames)
640
+ {stackSource === 'error'
641
+ ? t('console.errorStack', { count: parsedStackFrames.length })
642
+ : t('console.callStack', { count: parsedStackFrames.length })}
629
643
  </react_native_1.Text>
630
- <CopyButton_1.default value={activeStackString} label="Full Stack Trace"/>
644
+
645
+ <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 5 }}>
646
+ <react_native_1.View style={{
647
+ flexDirection: 'row',
648
+ backgroundColor: isDark ? AppColors_1.AppColors.primaryLight : AppColors_1.AppColors.white,
649
+ borderRadius: 7,
650
+ padding: 2,
651
+ borderWidth: 1,
652
+ borderColor: AppColors_1.AppColors.dividerColor,
653
+ }}>
654
+ <react_native_1.Pressable onPress={() => setStackViewMode('structured')} style={{
655
+ flexDirection: 'row',
656
+ alignItems: 'center',
657
+ gap: 3,
658
+ paddingVertical: 3.5,
659
+ paddingHorizontal: 7,
660
+ borderRadius: 5,
661
+ backgroundColor: stackViewMode === 'structured'
662
+ ? AppColors_1.AppColors.brandPurple
663
+ : 'transparent',
664
+ }}>
665
+ <NetworkIcons_1.LayersIcon color={stackViewMode === 'structured'
666
+ ? AppColors_1.AppColors.white
667
+ : AppColors_1.AppColors.grayTextWeak} size={11}/>
668
+ <react_native_1.Text style={{
669
+ fontFamily: AppFonts_1.AppFonts.interBold,
670
+ fontSize: 10,
671
+ color: stackViewMode === 'structured'
672
+ ? AppColors_1.AppColors.white
673
+ : AppColors_1.AppColors.grayTextStrong,
674
+ }}>
675
+ {t('console.cardsView')}
676
+ </react_native_1.Text>
677
+ </react_native_1.Pressable>
678
+
679
+ <react_native_1.Pressable onPress={() => setStackViewMode('raw')} style={{
680
+ flexDirection: 'row',
681
+ alignItems: 'center',
682
+ gap: 3,
683
+ paddingVertical: 3.5,
684
+ paddingHorizontal: 7,
685
+ borderRadius: 5,
686
+ backgroundColor: stackViewMode === 'raw'
687
+ ? AppColors_1.AppColors.brandPurple
688
+ : 'transparent',
689
+ }}>
690
+ <NetworkIcons_1.RawIcon color={stackViewMode === 'raw'
691
+ ? AppColors_1.AppColors.white
692
+ : AppColors_1.AppColors.grayTextWeak} size={11}/>
693
+ <react_native_1.Text style={{
694
+ fontFamily: AppFonts_1.AppFonts.interBold,
695
+ fontSize: 10,
696
+ color: stackViewMode === 'raw'
697
+ ? AppColors_1.AppColors.white
698
+ : AppColors_1.AppColors.grayTextStrong,
699
+ }}>
700
+ {t('console.rawTraceView')}
701
+ </react_native_1.Text>
702
+ </react_native_1.Pressable>
703
+ </react_native_1.View>
704
+
705
+ <CopyButton_1.default value={activeStackString} label={t('console.fullStackTrace')}/>
706
+ </react_native_1.View>
631
707
  </react_native_1.View>
632
708
 
633
709
  {/* Source Switcher if Error Stack exists */}
634
710
  {selectedLog.errorStack && (<SegmentedTabs_1.default tabs={[
635
711
  {
636
712
  key: 'caller',
637
- label: 'Call Origin Stack',
713
+ label: t('console.callOriginStack'),
638
714
  },
639
715
  {
640
716
  key: 'error',
641
- label: 'Error Thrown Stack',
717
+ label: t('console.errorThrownStack'),
642
718
  },
643
719
  ]} activeKey={stackSource} onChange={key => setStackSource(key)}/>)}
644
720
 
645
- {/* Structured vs Raw View Mode Tabs */}
721
+ {/* Scope Filter Tabs (Full Width) */}
646
722
  <SegmentedTabs_1.default tabs={[
647
723
  {
648
- key: 'structured',
649
- label: 'Structured Cards',
650
- icon: (isActive) => (<NetworkIcons_1.LayersIcon color={isActive ? AppColors_1.AppColors.white : AppColors_1.AppColors.grayTextWeak} size={12}/>),
724
+ key: 'app',
725
+ label: t('console.appCodeScope', { count: appStackFrames.length }),
651
726
  },
652
727
  {
653
- key: 'raw',
654
- label: 'Raw Trace',
655
- icon: (isActive) => (<NetworkIcons_1.RawIcon color={isActive ? AppColors_1.AppColors.white : AppColors_1.AppColors.grayTextWeak} size={12}/>),
728
+ key: 'all',
729
+ label: t('console.allFramesScope', { count: parsedStackFrames.length }),
656
730
  },
657
- ]} activeKey={stackViewMode} onChange={key => setStackViewMode(key)}/>
731
+ ]} activeKey={stackFilter} onChange={key => setStackFilter(key)}/>
658
732
  </react_native_1.View>
659
733
 
660
734
  {/* Stack Content: Structured Cards or Raw Full Trace */}
661
735
  {stackViewMode === 'structured' ? (<react_native_1.View style={{ padding: 12, gap: 10 }}>
662
- {parsedStackFrames.length > 0 ? (parsedStackFrames.map((frame, frameIdx) => {
736
+ {displayedFrames.length > 0 ? (displayedFrames.map((frame, frameIdx) => {
663
737
  const isTopFrame = frameIdx === 0;
738
+ const frameBadgeBg = frame.frameType === 'app'
739
+ ? `${AppColors_1.AppColors.brandPurple}15`
740
+ : frame.frameType === 'dependency'
741
+ ? `${AppColors_1.AppColors.amber500}18`
742
+ : frame.frameType === 'native'
743
+ ? `${AppColors_1.AppColors.sky500}18`
744
+ : AppColors_1.AppColors.grayBorderSecondary;
745
+ const frameBadgeText = frame.frameType === 'app'
746
+ ? AppColors_1.AppColors.brandPurple
747
+ : frame.frameType === 'dependency'
748
+ ? AppColors_1.AppColors.amber700
749
+ : frame.frameType === 'native'
750
+ ? AppColors_1.AppColors.sky500
751
+ : AppColors_1.AppColors.grayTextWeak;
664
752
  return (<react_native_1.View key={frameIdx} style={{
665
753
  backgroundColor: isTopFrame
666
754
  ? `${AppColors_1.AppColors.brandPurple}0A`
667
755
  : AppColors_1.AppColors.primaryLight,
668
- borderRadius: 8,
756
+ borderRadius: 10,
669
757
  borderWidth: 1,
670
758
  borderColor: isTopFrame
671
- ? `${AppColors_1.AppColors.brandPurple}30`
759
+ ? `${AppColors_1.AppColors.brandPurple}35`
672
760
  : AppColors_1.AppColors.dividerColor,
673
- padding: 10,
674
- gap: 5,
761
+ padding: 11,
762
+ gap: 6,
675
763
  }}>
676
- {/* Frame Header Row */}
764
+ {/* Frame Top Row: Origin / Category, File, Line badge, Copy */}
677
765
  <react_native_1.View style={{
678
766
  flexDirection: 'row',
679
767
  alignItems: 'center',
680
768
  justifyContent: 'space-between',
681
769
  gap: 6,
682
770
  }}>
683
- <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6, flex: 1 }}>
684
- <react_native_1.View style={{
685
- backgroundColor: isTopFrame
686
- ? AppColors_1.AppColors.brandPurple
687
- : AppColors_1.AppColors.grayBorderSecondary,
688
- borderRadius: 4,
689
- paddingHorizontal: 5,
690
- paddingVertical: 1.5,
691
- }}>
692
- <react_native_1.Text style={{
693
- fontFamily: AppFonts_1.AppFonts.interBold,
694
- fontSize: 9,
695
- color: isTopFrame
696
- ? AppColors_1.AppColors.white
697
- : AppColors_1.AppColors.grayTextStrong,
698
- }}>
699
- #{frameIdx + 1}
700
- {isTopFrame ? ' ORIGIN' : ''}
701
- </react_native_1.Text>
702
- </react_native_1.View>
703
-
704
- <HighlightText_1.default text={frame.functionName !== '<anonymous>' ? `${frame.functionName}()` : '<anonymous>'} search={detailSearch} style={{
705
- fontFamily: AppFonts_1.AppFonts.interBold,
706
- fontSize: 12,
707
- color: isTopFrame
708
- ? AppColors_1.AppColors.primaryBlack
709
- : AppColors_1.AppColors.grayTextStrong,
710
- }} highlightStyle={{
711
- backgroundColor: AppColors_1.AppColors.yellowHighlight,
712
- color: AppColors_1.AppColors.primaryBlack,
713
- }}/>
714
- </react_native_1.View>
715
-
716
- {frame.lineNumber && (<react_native_1.View style={{
717
- backgroundColor: `${AppColors_1.AppColors.teal600}15`,
718
- borderColor: `${AppColors_1.AppColors.teal600}30`,
719
- borderWidth: 1,
771
+ <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 5, flex: 1, flexWrap: 'wrap' }}>
772
+ {isTopFrame && (<react_native_1.View style={{
773
+ backgroundColor: AppColors_1.AppColors.brandPurple,
720
774
  borderRadius: 4,
721
- paddingHorizontal: 6,
775
+ paddingHorizontal: 5,
722
776
  paddingVertical: 1.5,
723
777
  }}>
724
- <react_native_1.Text style={{
778
+ <react_native_1.Text style={{
725
779
  fontFamily: AppFonts_1.AppFonts.interBold,
726
- fontSize: 9.5,
727
- color: AppColors_1.AppColors.teal600,
780
+ fontSize: 8.5,
781
+ color: AppColors_1.AppColors.white,
728
782
  }}>
729
- L{frame.lineNumber}
730
- {frame.columnNumber ? `:C${frame.columnNumber}` : ''}
731
- </react_native_1.Text>
732
- </react_native_1.View>)}
733
- </react_native_1.View>
783
+ {t('console.originBadge')}
784
+ </react_native_1.Text>
785
+ </react_native_1.View>)}
734
786
 
735
- {/* File Path Row */}
736
- <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6, flexWrap: 'wrap' }}>
737
- {frame.fileExt && frame.fileExt !== 'other' && (<react_native_1.View style={{
787
+ {frame.fileExt && frame.fileExt !== 'other' && (<react_native_1.View style={{
738
788
  backgroundColor: frame.fileExt === 'tsx' || frame.fileExt === 'ts'
739
789
  ? `${AppColors_1.AppColors.brandPurple}18`
740
790
  : `${AppColors_1.AppColors.teal600}18`,
741
- borderRadius: 3,
742
- paddingHorizontal: 4,
743
- paddingVertical: 1,
791
+ borderRadius: 4,
792
+ paddingHorizontal: 4.5,
793
+ paddingVertical: 1.5,
744
794
  }}>
745
- <react_native_1.Text style={{
795
+ <react_native_1.Text style={{
746
796
  fontFamily: AppFonts_1.AppFonts.interBold,
747
797
  fontSize: 8.5,
748
798
  color: frame.fileExt === 'tsx' || frame.fileExt === 'ts'
749
799
  ? AppColors_1.AppColors.brandPurple
750
800
  : AppColors_1.AppColors.teal600,
751
801
  }}>
752
- {frame.fileExt.toUpperCase()}
753
- </react_native_1.Text>
754
- </react_native_1.View>)}
755
- <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 3 }}>
756
- <NetworkIcons_1.DocIcon color={isTopFrame ? AppColors_1.AppColors.brandPurple : AppColors_1.AppColors.grayTextWeak} size={10}/>
757
- <react_native_1.Text style={{
758
- fontFamily: AppFonts_1.AppFonts.interMedium,
759
- fontSize: 10.5,
802
+ {frame.fileExt.toUpperCase()}
803
+ </react_native_1.Text>
804
+ </react_native_1.View>)}
805
+
806
+ <react_native_1.Text style={{
807
+ fontFamily: AppFonts_1.AppFonts.interBold,
808
+ fontSize: 11.5,
760
809
  color: isTopFrame
761
810
  ? AppColors_1.AppColors.brandPurple
762
- : AppColors_1.AppColors.grayTextWeak,
811
+ : AppColors_1.AppColors.primaryBlack,
763
812
  }}>
764
- {frame.fileName}
765
- </react_native_1.Text>
813
+ {frame.fileName}
814
+ </react_native_1.Text>
815
+ </react_native_1.View>
816
+
817
+ <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 4 }}>
818
+ {frame.lineNumber && (<react_native_1.View style={{
819
+ backgroundColor: `${AppColors_1.AppColors.teal600}15`,
820
+ borderColor: `${AppColors_1.AppColors.teal600}30`,
821
+ borderWidth: 1,
822
+ borderRadius: 4,
823
+ paddingHorizontal: 5,
824
+ paddingVertical: 1.5,
825
+ }}>
826
+ <react_native_1.Text style={{
827
+ fontFamily: AppFonts_1.AppFonts.interBold,
828
+ fontSize: 9.5,
829
+ color: AppColors_1.AppColors.teal600,
830
+ }}>
831
+ L{frame.lineNumber}{frame.columnNumber ? `:C${frame.columnNumber}` : ''}
832
+ </react_native_1.Text>
833
+ </react_native_1.View>)}
834
+ <CopyButton_1.default value={frame.copyableLocation} label={frame.fileName}/>
835
+ </react_native_1.View>
766
836
  </react_native_1.View>
837
+
838
+ {/* Middle Row: Function / Symbol Invocation */}
839
+ <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 5 }}>
840
+ <HighlightText_1.default text={frame.functionName !== '<anonymous>' ? `${frame.functionName}()` : '<anonymous>'} search={detailSearch} style={{
841
+ fontFamily: AppFonts_1.AppFonts.interBold,
842
+ fontSize: 12.5,
843
+ color: AppColors_1.AppColors.primaryBlack,
844
+ }} highlightStyle={{
845
+ backgroundColor: AppColors_1.AppColors.yellowHighlight,
846
+ color: AppColors_1.AppColors.primaryBlack,
847
+ }}/>
767
848
  </react_native_1.View>
768
849
 
769
- {/* Full path */}
770
- {frame.fullPath && frame.fullPath !== frame.fileName && (<react_native_1.Text selectable style={{
771
- fontFamily: AppFonts_1.AppFonts.interRegular,
772
- fontSize: 9.5,
773
- color: AppColors_1.AppColors.grayTextWeak,
774
- lineHeight: 14,
775
- }} numberOfLines={2}>
776
- {frame.fullPath}
777
- </react_native_1.Text>)}
850
+ {/* Bottom Row: Clean Relative Path & Execution Scope Tag */}
851
+ <react_native_1.View style={{
852
+ flexDirection: 'row',
853
+ alignItems: 'center',
854
+ justifyContent: 'space-between',
855
+ backgroundColor: isDark ? `${AppColors_1.AppColors.primaryBlack}25` : AppColors_1.AppColors.grayBackground,
856
+ borderRadius: 6,
857
+ paddingHorizontal: 8,
858
+ paddingVertical: 4.5,
859
+ gap: 6,
860
+ }}>
861
+ <react_native_1.Text selectable style={{
862
+ fontFamily: AppFonts_1.AppFonts.interRegular,
863
+ fontSize: 9.5,
864
+ color: AppColors_1.AppColors.grayTextStrong,
865
+ flex: 1,
866
+ }} numberOfLines={1}>
867
+ 📂 {frame.fullPath}
868
+ </react_native_1.Text>
869
+
870
+ <react_native_1.View style={{
871
+ backgroundColor: frameBadgeBg,
872
+ borderRadius: 4,
873
+ paddingHorizontal: 5,
874
+ paddingVertical: 1.5,
875
+ }}>
876
+ <react_native_1.Text style={{
877
+ fontFamily: AppFonts_1.AppFonts.interBold,
878
+ fontSize: 8.5,
879
+ color: frameBadgeText,
880
+ }}>
881
+ {frame.frameType === 'app'
882
+ ? t('console.appCodeBadge')
883
+ : frame.frameType === 'dependency'
884
+ ? t('console.dependencyBadge')
885
+ : frame.frameType === 'native'
886
+ ? t('console.nativeBadge')
887
+ : t('console.hermesVmBadge')}
888
+ </react_native_1.Text>
889
+ </react_native_1.View>
890
+ </react_native_1.View>
778
891
  </react_native_1.View>);
779
892
  })) : (<react_native_1.Text style={{
780
893
  fontFamily: AppFonts_1.AppFonts.interRegular,
@@ -783,7 +896,7 @@ const LogDetail = react_1.default.memo(() => {
783
896
  textAlign: 'center',
784
897
  paddingVertical: 16,
785
898
  }}>
786
- No call stack trace available for this log.
899
+ {t('console.noStackAvailable')}
787
900
  </react_native_1.Text>)}
788
901
  </react_native_1.View>) : (
789
902
  /* Raw Full Trace Monospace Block */
@@ -53,12 +53,14 @@ const ReduxTab_1 = __importDefault(require("./ReduxTab"));
53
53
  const ReduxDetail_1 = __importDefault(require("./ReduxDetail"));
54
54
  const BundleTab_1 = __importDefault(require("./BundleTab"));
55
55
  const PerformanceTab_1 = __importDefault(require("./PerformanceTab"));
56
+ const CrashTab_1 = __importDefault(require("./CrashTab"));
57
+ const CrashDetail_1 = __importDefault(require("./CrashDetail"));
56
58
  const SettingsPanel_1 = __importDefault(require("./SettingsPanel"));
57
59
  const styles_1 = __importDefault(require("../../styles"));
58
60
  const AppColors_1 = require("../../styles/AppColors");
59
61
  const NavigationTracker_1 = __importDefault(require("./NavigationTracker"));
60
62
  const MainScreen = () => {
61
- const { visible, modalAnimationType, closeModal, modalHeightPercent, selected, selectedEvent, selectedLog, selectedReduxSlice, selectedReduxAction, settingsPage, activeTab, isReady, isEnabled, hasNavigationContext, setNavState, } = (0, InspectorContext_1.useInspector)();
63
+ const { visible, modalAnimationType, closeModal, modalHeightPercent, selected, selectedEvent, selectedLog, selectedReduxSlice, selectedReduxAction, selectedCrash, settingsPage, activeTab, isReady, isEnabled, hasNavigationContext, setNavState, } = (0, InspectorContext_1.useInspector)();
62
64
  // Lazy-mount each tab on first visit and cache it in memory for 0ms instantaneous switching
63
65
  const [mountedTabs, setMountedTabs] = (0, react_1.useState)({
64
66
  [activeTab]: true,
@@ -73,9 +75,10 @@ const MainScreen = () => {
73
75
  const isDetailActive = (activeTab === 'apis' && selected != null) ||
74
76
  (activeTab === 'analytics' && selectedEvent != null) ||
75
77
  (activeTab === 'logs' && selectedLog != null) ||
76
- (activeTab === 'redux' && (selectedReduxSlice != null || selectedReduxAction != null));
78
+ (activeTab === 'redux' && (selectedReduxSlice != null || selectedReduxAction != null)) ||
79
+ (activeTab === 'crash' && selectedCrash != null);
77
80
  return (<>
78
- {isEnabled && <FabLauncher_1.default />}
81
+ {(react_native_1.Platform.OS === 'ios' || react_native_1.Platform.OS === 'android') && isEnabled && <FabLauncher_1.default />}
79
82
  <react_native_1.Modal visible={visible} animationType={modalAnimationType} transparent>
80
83
  {visible && (<ErrorBoundary_1.default onClose={closeModal}>
81
84
  <react_native_1.View style={styles_1.default.modalBackdrop}>
@@ -91,7 +94,7 @@ const MainScreen = () => {
91
94
  {/* ─── Horizontal Scrollable Tab Bar inside Content ─── */}
92
95
  {!isDetailActive && settingsPage === null ? (<TabBar_1.default />) : null}
93
96
 
94
- {isReady ? (isDetailActive ? (activeTab === 'apis' && selected != null ? (<NetworkDetail_1.default />) : activeTab === 'analytics' && selectedEvent != null ? (<AnalyticsDetail_1.default event={selectedEvent}/>) : activeTab === 'logs' && selectedLog != null ? (<LogDetail_1.default />) : activeTab === 'redux' ? (<ReduxDetail_1.default />) : null) : (<>
97
+ {isReady ? (isDetailActive ? (activeTab === 'apis' && selected != null ? (<NetworkDetail_1.default />) : activeTab === 'analytics' && selectedEvent != null ? (<AnalyticsDetail_1.default event={selectedEvent}/>) : activeTab === 'logs' && selectedLog != null ? (<LogDetail_1.default />) : activeTab === 'redux' ? (<ReduxDetail_1.default />) : activeTab === 'crash' && selectedCrash != null ? (<CrashDetail_1.default />) : null) : (<>
95
98
  <react_native_1.View style={{
96
99
  flex: 1,
97
100
  display: activeTab === 'apis' ? 'flex' : 'none',
@@ -128,6 +131,12 @@ const MainScreen = () => {
128
131
  }}>
129
132
  {mountedTabs.performance && <PerformanceTab_1.default />}
130
133
  </react_native_1.View>
134
+ <react_native_1.View style={{
135
+ flex: 1,
136
+ display: activeTab === 'crash' ? 'flex' : 'none',
137
+ }}>
138
+ {mountedTabs.crash && <CrashTab_1.default />}
139
+ </react_native_1.View>
131
140
  </>)) : (<react_native_1.View style={styles_1.default.empty}>
132
141
  <react_native_1.ActivityIndicator size="large" color={AppColors_1.AppColors.purple}/>
133
142
  <react_native_1.Text style={[styles_1.default.emptySub, { marginTop: 12 }]}>