react-native-inapp-inspector 1.1.28 → 1.1.31

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 (77) hide show
  1. package/android/src/main/java/com/inappinspector/NetworkInspectorModule.java +29 -80
  2. package/dist/commonjs/components/AnalyticsDetail.js +668 -108
  3. package/dist/commonjs/components/AppHeaderLogo.js +15 -15
  4. package/dist/commonjs/components/ConsoleLogCard.js +112 -66
  5. package/dist/commonjs/components/CopyButton.js +15 -1
  6. package/dist/commonjs/components/DomainHeader.js +64 -32
  7. package/dist/commonjs/components/HighlightText.js +7 -1
  8. package/dist/commonjs/components/Inspector/AnalyticsTab.js +332 -221
  9. package/dist/commonjs/components/Inspector/ConsoleTab.js +162 -56
  10. package/dist/commonjs/components/Inspector/InspectorHeader.js +70 -119
  11. package/dist/commonjs/components/Inspector/LogDetail.js +53 -17
  12. package/dist/commonjs/components/Inspector/MainScreen.js +4 -0
  13. package/dist/commonjs/components/Inspector/NetworkDetail.js +24 -24
  14. package/dist/commonjs/components/Inspector/NetworkTab.js +4 -1
  15. package/dist/commonjs/components/Inspector/ReduxDetail.js +237 -42
  16. package/dist/commonjs/components/Inspector/ReduxTab.js +456 -35
  17. package/dist/commonjs/components/JsonViewer.js +26 -4
  18. package/dist/commonjs/components/LogCard.js +103 -11
  19. package/dist/commonjs/components/NetworkIcons.js +19 -10
  20. package/dist/commonjs/components/Toast.d.ts +3 -0
  21. package/dist/commonjs/components/Toast.js +152 -0
  22. package/dist/commonjs/components/TouchableScale.d.ts +1 -0
  23. package/dist/commonjs/components/TouchableScale.js +3 -3
  24. package/dist/commonjs/components/TreeNode.js +12 -2
  25. package/dist/commonjs/constants/index.js +6 -6
  26. package/dist/commonjs/constants/version.d.ts +1 -1
  27. package/dist/commonjs/constants/version.js +1 -1
  28. package/dist/commonjs/customHooks/reduxLogger.js +128 -5
  29. package/dist/commonjs/helpers/index.d.ts +4 -0
  30. package/dist/commonjs/helpers/index.js +107 -92
  31. package/dist/commonjs/helpers/toast.d.ts +4 -0
  32. package/dist/commonjs/helpers/toast.js +20 -0
  33. package/dist/commonjs/i18n/locales/en.json +49 -3
  34. package/dist/commonjs/styles/AppColors.d.ts +6 -0
  35. package/dist/commonjs/styles/AppColors.js +6 -0
  36. package/dist/commonjs/styles/index.d.ts +82 -15
  37. package/dist/commonjs/styles/index.js +92 -26
  38. package/dist/commonjs/types/interfaces.d.ts +7 -0
  39. package/dist/esm/components/AnalyticsDetail.js +670 -110
  40. package/dist/esm/components/AppHeaderLogo.js +15 -15
  41. package/dist/esm/components/ConsoleLogCard.js +114 -68
  42. package/dist/esm/components/CopyButton.js +15 -1
  43. package/dist/esm/components/DomainHeader.js +64 -32
  44. package/dist/esm/components/HighlightText.js +7 -1
  45. package/dist/esm/components/Inspector/AnalyticsTab.js +334 -223
  46. package/dist/esm/components/Inspector/ConsoleTab.js +163 -57
  47. package/dist/esm/components/Inspector/InspectorHeader.js +71 -120
  48. package/dist/esm/components/Inspector/LogDetail.js +55 -19
  49. package/dist/esm/components/Inspector/MainScreen.js +4 -0
  50. package/dist/esm/components/Inspector/NetworkDetail.js +25 -25
  51. package/dist/esm/components/Inspector/NetworkTab.js +4 -1
  52. package/dist/esm/components/Inspector/ReduxDetail.js +239 -44
  53. package/dist/esm/components/Inspector/ReduxTab.js +458 -37
  54. package/dist/esm/components/JsonViewer.js +26 -4
  55. package/dist/esm/components/LogCard.js +105 -13
  56. package/dist/esm/components/NetworkIcons.js +19 -10
  57. package/dist/esm/components/Toast.d.ts +3 -0
  58. package/dist/esm/components/Toast.js +117 -0
  59. package/dist/esm/components/TouchableScale.d.ts +1 -0
  60. package/dist/esm/components/TouchableScale.js +3 -3
  61. package/dist/esm/components/TreeNode.js +12 -2
  62. package/dist/esm/constants/index.js +6 -6
  63. package/dist/esm/constants/version.d.ts +1 -1
  64. package/dist/esm/constants/version.js +1 -1
  65. package/dist/esm/customHooks/reduxLogger.js +128 -5
  66. package/dist/esm/helpers/index.d.ts +4 -0
  67. package/dist/esm/helpers/index.js +102 -92
  68. package/dist/esm/helpers/toast.d.ts +4 -0
  69. package/dist/esm/helpers/toast.js +15 -0
  70. package/dist/esm/i18n/locales/en.json +49 -3
  71. package/dist/esm/styles/AppColors.d.ts +6 -0
  72. package/dist/esm/styles/AppColors.js +6 -0
  73. package/dist/esm/styles/index.d.ts +82 -15
  74. package/dist/esm/styles/index.js +92 -26
  75. package/dist/esm/types/interfaces.d.ts +7 -0
  76. package/ios/NetworkInspectorModule.m +0 -10
  77. package/package.json +13 -10
@@ -118,27 +118,60 @@ const LogDetail = react_1.default.memo(() => {
118
118
  return null;
119
119
  const isDark = AppColors_1.AppColors.primaryLight !== AppColors_1.AppColors.white;
120
120
  const getTypeColors = () => {
121
- if (selectedLog.type === 'error') {
121
+ const type = (selectedLog.type || 'log').toLowerCase();
122
+ const method = (selectedLog.sourceMethod || type).toLowerCase();
123
+ if (type === 'error' || method === 'error') {
122
124
  return {
123
- border: AppColors_1.AppColors.errorColor,
124
- badgeBg: `${AppColors_1.AppColors.errorColor}15`,
125
- badgeText: AppColors_1.AppColors.errorColor,
125
+ border: AppColors_1.AppColors.red500,
126
+ badgeBg: AppColors_1.AppColors.red100,
127
+ badgeText: AppColors_1.AppColors.redErrorText,
126
128
  label: 'ERROR',
129
+ methodBorder: AppColors_1.AppColors.errorBorder,
130
+ methodBg: AppColors_1.AppColors.red100,
131
+ methodText: AppColors_1.AppColors.redErrorText,
127
132
  };
128
133
  }
129
- if (selectedLog.type === 'warn') {
134
+ if (type === 'warn' || method === 'warn') {
130
135
  return {
131
- border: AppColors_1.AppColors.lightOrange,
132
- badgeBg: `${AppColors_1.AppColors.lightOrange}15`,
133
- badgeText: AppColors_1.AppColors.darkOrange || AppColors_1.AppColors.lightOrange,
136
+ border: AppColors_1.AppColors.amber500,
137
+ badgeBg: AppColors_1.AppColors.amber100,
138
+ badgeText: AppColors_1.AppColors.amber800Warm,
134
139
  label: 'WARN',
140
+ methodBorder: AppColors_1.AppColors.amber200,
141
+ methodBg: AppColors_1.AppColors.amber100,
142
+ methodText: AppColors_1.AppColors.amber800Warm,
143
+ };
144
+ }
145
+ if (type === 'debug' || method === 'debug') {
146
+ return {
147
+ border: AppColors_1.AppColors.violet500,
148
+ badgeBg: AppColors_1.AppColors.purple100,
149
+ badgeText: AppColors_1.AppColors.violet600,
150
+ label: 'DEBUG',
151
+ methodBorder: AppColors_1.AppColors.purple200,
152
+ methodBg: AppColors_1.AppColors.purple100,
153
+ methodText: AppColors_1.AppColors.violet600,
154
+ };
155
+ }
156
+ if (type === 'info' || method === 'info') {
157
+ return {
158
+ border: AppColors_1.AppColors.sky500,
159
+ badgeBg: AppColors_1.AppColors.sky100,
160
+ badgeText: AppColors_1.AppColors.sky600,
161
+ label: 'INFO',
162
+ methodBorder: AppColors_1.AppColors.sky400,
163
+ methodBg: AppColors_1.AppColors.sky100,
164
+ methodText: AppColors_1.AppColors.sky600,
135
165
  };
136
166
  }
137
167
  return {
138
- border: AppColors_1.AppColors.purple,
139
- badgeBg: `${AppColors_1.AppColors.purple}15`,
140
- badgeText: AppColors_1.AppColors.purple,
141
- label: 'INFO',
168
+ border: AppColors_1.AppColors.indigo500,
169
+ badgeBg: AppColors_1.AppColors.indigo50,
170
+ badgeText: AppColors_1.AppColors.indigo600Alt,
171
+ label: 'LOG',
172
+ methodBorder: AppColors_1.AppColors.indigo400,
173
+ methodBg: AppColors_1.AppColors.indigo50,
174
+ methodText: AppColors_1.AppColors.indigo600Alt,
142
175
  };
143
176
  };
144
177
  const typeColors = getTypeColors();
@@ -307,16 +340,18 @@ const LogDetail = react_1.default.memo(() => {
307
340
  : originFrame?.fileName || t('console.consoleLog')}
308
341
  </react_native_1.Text>
309
342
 
310
- {originFrame?.fileName && (<react_native_1.View style={[
343
+ {originFrame?.fileName && (<react_native_1.Pressable onPress={() => (0, helpers_1.openInVSCode)(originFrame.rawFilePath ||
344
+ originFrame.fullPath ||
345
+ originFrame.fileName, originFrame.lineNumber, originFrame.columnNumber)} hitSlop={8} style={[
311
346
  styles_1.default.metaChip,
312
347
  {
313
- backgroundColor: `${AppColors_1.AppColors.brandPurple}12`,
314
- borderColor: `${AppColors_1.AppColors.brandPurple}30`,
348
+ backgroundColor: `${AppColors_1.AppColors.brandPurple}15`,
349
+ borderColor: `${AppColors_1.AppColors.brandPurple}40`,
315
350
  paddingHorizontal: 7,
316
351
  paddingVertical: 2,
317
352
  },
318
353
  ]}>
319
- <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 3, flexWrap: 'wrap', flexShrink: 1 }}>
354
+ <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 4, flexShrink: 1 }}>
320
355
  <NetworkIcons_1.DocIcon color={AppColors_1.AppColors.brandPurple} size={10}/>
321
356
  <react_native_1.Text style={[
322
357
  styles_1.default.metaChipText,
@@ -326,8 +361,9 @@ const LogDetail = react_1.default.memo(() => {
326
361
  {originFrame.lineNumber ? `:${originFrame.lineNumber}` : ''}
327
362
  {originFrame.columnNumber ? `:${originFrame.columnNumber}` : ''}
328
363
  </react_native_1.Text>
364
+ <NetworkIcons_1.ExternalLinkIcon color={AppColors_1.AppColors.brandPurple} size={9}/>
329
365
  </react_native_1.View>
330
- </react_native_1.View>)}
366
+ </react_native_1.Pressable>)}
331
367
  </react_native_1.View>
332
368
 
333
369
  {/* Enhanced metadata metrics row */}
@@ -56,6 +56,7 @@ const PerformanceTab_1 = __importDefault(require("./PerformanceTab"));
56
56
  const CrashTab_1 = __importDefault(require("./CrashTab"));
57
57
  const CrashDetail_1 = __importDefault(require("./CrashDetail"));
58
58
  const SettingsPanel_1 = __importDefault(require("./SettingsPanel"));
59
+ const Toast_1 = __importDefault(require("../Toast"));
59
60
  const styles_1 = __importDefault(require("../../styles"));
60
61
  const AppColors_1 = require("../../styles/AppColors");
61
62
  const NavigationTracker_1 = __importDefault(require("./NavigationTracker"));
@@ -153,6 +154,9 @@ const MainScreen = () => {
153
154
  ]}>
154
155
  <SettingsPanel_1.default />
155
156
  </react_native_1.View>)}
157
+
158
+ {/* Bottom floating toast notification */}
159
+ <Toast_1.default />
156
160
  </react_native_1.View>
157
161
  </react_native_1.View>
158
162
  </ErrorBoundary_1.default>)}
@@ -25,6 +25,26 @@ const NetworkIcons_1 = require("../NetworkIcons");
25
25
  const NetworkDetail = react_1.default.memo(() => {
26
26
  const { t } = (0, i18n_1.useTranslation)();
27
27
  const { selected, detailDisplayUrl, apiDetailActiveTab, setApiDetailActiveTab, detailSearch, setDetailSearch, reqExpanded, setReqExpanded, resExpanded, setResExpanded, showReqDiff, setShowReqDiff, showResDiff, setShowResDiff, prevRequestData, prevResponseData, logRouteMapRef, } = (0, InspectorContext_1.useInspector)();
28
+ const handleOpenUrl = () => {
29
+ react_native_1.Alert.alert(t('common.openInBrowser') || 'Open in Browser', `${t('common.openInBrowserPrompt') || 'Are you sure you want to open this URL in your external browser?'}\n\n${detailDisplayUrl}`, [
30
+ { text: t('common.cancel') || 'Cancel', style: 'cancel' },
31
+ {
32
+ text: t('common.open') || 'Open',
33
+ onPress: () => {
34
+ react_native_1.Linking.canOpenURL(detailDisplayUrl)
35
+ .then(supported => {
36
+ if (supported) {
37
+ react_native_1.Linking.openURL(detailDisplayUrl);
38
+ }
39
+ else {
40
+ react_native_1.Linking.openURL(detailDisplayUrl).catch(() => { });
41
+ }
42
+ })
43
+ .catch(() => { });
44
+ },
45
+ },
46
+ ]);
47
+ };
28
48
  if (!selected)
29
49
  return null;
30
50
  return (<react_native_1.View style={{ flex: 1 }}>
@@ -232,7 +252,7 @@ const NetworkDetail = react_1.default.memo(() => {
232
252
  </react_native_1.View>
233
253
 
234
254
  <react_native_1.View style={styles_1.default.detailInfoRight}>
235
- <TouchableScale_1.default style={[styles_1.default.iconSquareBtn, { backgroundColor: `${AppColors_1.AppColors.sky600}15` }]} onPress={() => react_native_1.Linking.openURL(detailDisplayUrl)} hitSlop={12}>
255
+ <TouchableScale_1.default style={[styles_1.default.iconSquareBtn, { backgroundColor: `${AppColors_1.AppColors.sky600}15` }]} onPress={handleOpenUrl} hitSlop={12}>
236
256
  <NetworkIcons_1.ExternalLinkIcon color={AppColors_1.AppColors.sky600} size={14}/>
237
257
  </TouchableScale_1.default>
238
258
  <CopyButton_1.default value={(0, helpers_1.getFetchCommand)(selected)} label="fetch()" iconType="fetch"/>
@@ -250,7 +270,7 @@ const NetworkDetail = react_1.default.memo(() => {
250
270
  padding: 10,
251
271
  marginTop: 8,
252
272
  gap: 6,
253
- }} onPress={() => react_native_1.Linking.openURL(detailDisplayUrl)}>
273
+ }} onPress={handleOpenUrl}>
254
274
  <react_native_1.View style={{
255
275
  flexDirection: 'row',
256
276
  alignItems: 'center',
@@ -433,7 +453,7 @@ const NetworkDetail = react_1.default.memo(() => {
433
453
  if (!reqExpanded && !showReqDiff)
434
454
  setReqExpanded(true);
435
455
  }}/>
436
- {showReqDiff ? (<DiffViewer_1.default oldData={prevRequestData} newData={selected.request} forceOpen={reqExpanded}/>) : reqExpanded ? (<JsonViewer_1.default data={selected.request} search={detailSearch} forceOpen/>) : (<react_native_1.View style={styles_1.default.codeBlock}>
456
+ {showReqDiff ? (<DiffViewer_1.default oldData={prevRequestData} newData={selected.request} forceOpen={reqExpanded}/>) : reqExpanded ? (<JsonViewer_1.default data={selected.request} search={detailSearch}/>) : (<react_native_1.View style={styles_1.default.codeBlock}>
437
457
  <react_native_1.Text style={[
438
458
  styles_1.default.codeText,
439
459
  { color: AppColors_1.AppColors.grayTextWeak },
@@ -452,26 +472,6 @@ const NetworkDetail = react_1.default.memo(() => {
452
472
  <NetworkIcons_1.ClearIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
453
473
  </react_native_1.Pressable>)}
454
474
  </react_native_1.View>
455
- {selected.response != null && (<react_native_1.View style={{
456
- flexDirection: 'row',
457
- alignItems: 'center',
458
- gap: 4,
459
- paddingHorizontal: 10,
460
- height: 34,
461
- borderRadius: 8,
462
- borderWidth: 1,
463
- borderColor: `${AppColors_1.AppColors.purple}30`,
464
- backgroundColor: `${AppColors_1.AppColors.purple}10`,
465
- }}>
466
- <NetworkIcons_1.SizeIcon color={AppColors_1.AppColors.purple} size={12}/>
467
- <react_native_1.Text style={{
468
- fontFamily: AppFonts_1.AppFonts.interBold,
469
- fontSize: 10.5,
470
- color: AppColors_1.AppColors.purple,
471
- }}>
472
- {(0, helpers_1.getSize)(selected.response)}
473
- </react_native_1.Text>
474
- </react_native_1.View>)}
475
475
  </react_native_1.View>
476
476
 
477
477
  <react_native_1.View style={styles_1.default.sectionContainer}>
@@ -480,7 +480,7 @@ const NetworkDetail = react_1.default.memo(() => {
480
480
  if (!resExpanded && !showResDiff)
481
481
  setResExpanded(true);
482
482
  }}/>
483
- {showResDiff ? (<DiffViewer_1.default oldData={prevResponseData} newData={selected.response} forceOpen={resExpanded}/>) : resExpanded ? (<JsonViewer_1.default data={selected.response} search={detailSearch} forceOpen wrap/>) : (<react_native_1.View style={styles_1.default.codeBlock}>
483
+ {showResDiff ? (<DiffViewer_1.default oldData={prevResponseData} newData={selected.response} forceOpen={resExpanded}/>) : resExpanded ? (<JsonViewer_1.default data={selected.response} search={detailSearch} wrap/>) : (<react_native_1.View style={styles_1.default.codeBlock}>
484
484
  <react_native_1.Text style={[
485
485
  styles_1.default.codeText,
486
486
  { color: AppColors_1.AppColors.grayTextWeak },
@@ -105,7 +105,10 @@ const NetworkTab = react_1.default.memo(() => {
105
105
  </AnimatedEntrance_1.default>);
106
106
  }
107
107
  const { log, isLast, color } = item;
108
- return (<AnimatedEntrance_1.default index={index} distance={8} style={styles_1.default.treeNodeRow}>
108
+ return (<AnimatedEntrance_1.default index={index} distance={8} style={[
109
+ styles_1.default.treeNodeRow,
110
+ isLast && styles_1.default.treeNodeRowLast,
111
+ ]}>
109
112
  <react_native_1.View style={styles_1.default.treeLines}>
110
113
  <react_native_1.View style={[
111
114
  styles_1.default.modernTreeLine,
@@ -53,6 +53,50 @@ const settingsStore_1 = require("../../helpers/settingsStore");
53
53
  const AppColors_1 = require("../../styles/AppColors");
54
54
  const AppFonts_1 = require("../../styles/AppFonts");
55
55
  const NetworkIcons_1 = require("../NetworkIcons");
56
+ const getOriginBadge = (originType) => {
57
+ switch (originType) {
58
+ case 'saga':
59
+ return {
60
+ label: 'SAGA',
61
+ icon: '⚡',
62
+ bg: AppColors_1.AppColors.purple100,
63
+ text: AppColors_1.AppColors.brandPurple,
64
+ border: AppColors_1.AppColors.purple200,
65
+ };
66
+ case 'thunk':
67
+ return {
68
+ label: 'THUNK',
69
+ icon: '⚛️',
70
+ bg: AppColors_1.AppColors.amber100,
71
+ text: AppColors_1.AppColors.amber800Warm,
72
+ border: AppColors_1.AppColors.amber200,
73
+ };
74
+ case 'ui':
75
+ return {
76
+ label: 'UI',
77
+ icon: '📱',
78
+ bg: AppColors_1.AppColors.sky100,
79
+ text: AppColors_1.AppColors.sky600,
80
+ border: AppColors_1.AppColors.sky400,
81
+ };
82
+ case 'listener':
83
+ return {
84
+ label: 'LISTENER',
85
+ icon: '👂',
86
+ bg: AppColors_1.AppColors.teal100,
87
+ text: AppColors_1.AppColors.teal700,
88
+ border: AppColors_1.AppColors.teal400,
89
+ };
90
+ default:
91
+ return {
92
+ label: 'DIRECT',
93
+ icon: '⚡',
94
+ bg: AppColors_1.AppColors.slate100,
95
+ text: AppColors_1.AppColors.slate700,
96
+ border: AppColors_1.AppColors.slate200,
97
+ };
98
+ }
99
+ };
56
100
  const ReduxDetail = react_1.default.memo(() => {
57
101
  const { t } = (0, i18n_1.useTranslation)();
58
102
  const { reduxState, reduxLastActionMap, selectedReduxSlice, selectedReduxAction, setSelectedReduxSlice, setSelectedReduxAction, } = (0, InspectorContext_1.useInspector)();
@@ -174,29 +218,46 @@ const ReduxDetail = react_1.default.memo(() => {
174
218
  : 0;
175
219
  const lastAction = reduxLastActionMap[selectedReduxSlice];
176
220
  const sliceTabs = [
177
- { key: 'live', label: 'Live State', icon: () => <NetworkIcons_1.LiveStateIcon color={AppColors_1.AppColors.purple} size={11}/> },
178
- { key: 'timeline', label: `Timeline (${sliceActions.length})`, icon: () => <NetworkIcons_1.TimelineIcon color={AppColors_1.AppColors.purple} size={11}/> },
179
- { key: 'persisted', label: isPersisted ? 'Persisted' : 'Storage', icon: () => <NetworkIcons_1.StorageIcon color={AppColors_1.AppColors.purple} size={11}/> },
180
- { key: 'metadata', label: 'Metadata', icon: () => <NetworkIcons_1.MetadataIcon color={AppColors_1.AppColors.purple} size={11}/> },
221
+ {
222
+ key: 'live',
223
+ label: t('redux.liveState'),
224
+ icon: (isActive) => (<NetworkIcons_1.LiveStateIcon color={isActive ? AppColors_1.AppColors.white : AppColors_1.AppColors.grayText} size={12}/>),
225
+ },
226
+ {
227
+ key: 'timeline',
228
+ label: `${t('redux.timeline')} (${sliceActions.length})`,
229
+ icon: (isActive) => (<NetworkIcons_1.TimelineIcon color={isActive ? AppColors_1.AppColors.white : AppColors_1.AppColors.grayText} size={12}/>),
230
+ },
231
+ {
232
+ key: 'persisted',
233
+ label: isPersisted ? t('redux.persisted') : t('redux.storage'),
234
+ icon: (isActive) => (<NetworkIcons_1.StorageIcon color={isActive ? AppColors_1.AppColors.white : AppColors_1.AppColors.grayText} size={12}/>),
235
+ },
236
+ {
237
+ key: 'metadata',
238
+ label: t('redux.metadata'),
239
+ icon: (isActive) => (<NetworkIcons_1.MetadataIcon color={isActive ? AppColors_1.AppColors.white : AppColors_1.AppColors.grayText} size={12}/>),
240
+ },
181
241
  ];
182
242
  return (<react_native_1.View style={{ flex: 1, backgroundColor: AppColors_1.AppColors.grayBackground }}>
183
243
  {/* Info Header Bar */}
184
244
  <react_native_1.View style={reduxDetailStyles.infoBar}>
185
245
  <react_native_1.View style={reduxDetailStyles.infoTopRow}>
186
246
  <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6, flexWrap: 'wrap', flex: 1 }}>
187
- <react_native_1.View style={[reduxDetailStyles.methodBadge, { backgroundColor: AppColors_1.AppColors.purple }]}>
188
- <react_native_1.Text style={reduxDetailStyles.methodBadgeText}>SLICE</react_native_1.Text>
247
+ <react_native_1.View style={[reduxDetailStyles.methodBadge, { backgroundColor: AppColors_1.AppColors.indigo600Alt }]}>
248
+ <react_native_1.Text style={reduxDetailStyles.methodBadgeText}>{t('redux.slice')}</react_native_1.Text>
189
249
  </react_native_1.View>
190
250
  <react_native_1.Text style={reduxDetailStyles.sliceNameText}>
191
251
  {selectedReduxSlice}
192
252
  </react_native_1.Text>
193
253
  {isPersisted ? (<react_native_1.View style={reduxDetailStyles.persistedChip}>
194
- <react_native_1.Text style={reduxDetailStyles.persistedChipText}>PERSISTED</react_native_1.Text>
254
+ <NetworkIcons_1.StorageIcon color={AppColors_1.AppColors.emerald700} size={10}/>
255
+ <react_native_1.Text style={reduxDetailStyles.persistedChipText}>{t('redux.persisted').toUpperCase()}</react_native_1.Text>
195
256
  </react_native_1.View>) : (<react_native_1.View style={reduxDetailStyles.inMemoryChip}>
196
- <react_native_1.Text style={reduxDetailStyles.inMemoryChipText}>IN-MEMORY</react_native_1.Text>
257
+ <react_native_1.Text style={reduxDetailStyles.inMemoryChipText}>{t('redux.inMemory').toUpperCase()}</react_native_1.Text>
197
258
  </react_native_1.View>)}
198
259
  {lastAction?.timestamp && (<react_native_1.View style={reduxDetailStyles.timePill}>
199
- <NetworkIcons_1.ClockIcon color={AppColors_1.AppColors.purple} size={10}/>
260
+ <NetworkIcons_1.ClockIcon color={AppColors_1.AppColors.violet600} size={10}/>
200
261
  <react_native_1.Text style={reduxDetailStyles.timeText}>
201
262
  {lastAction.timestamp}
202
263
  </react_native_1.Text>
@@ -204,26 +265,29 @@ const ReduxDetail = react_1.default.memo(() => {
204
265
  </react_native_1.View>
205
266
 
206
267
  {/* Copy Button */}
207
- <CopyButton_1.default value={() => (sliceTab === 'live' ? sliceData : persistedData)} label="Slice JSON"/>
268
+ <CopyButton_1.default value={() => (sliceTab === 'live' ? sliceData : persistedData)} label={t('redux.sliceJson')}/>
208
269
  </react_native_1.View>
209
270
 
210
271
  {/* Sub Stats Row */}
211
272
  <react_native_1.View style={reduxDetailStyles.subStatsRow}>
212
- <react_native_1.View style={reduxDetailStyles.statPill}>
213
- <react_native_1.Text style={reduxDetailStyles.statLabel}>Root Keys:</react_native_1.Text>
214
- <react_native_1.Text style={reduxDetailStyles.statValue}>{fieldsCount}</react_native_1.Text>
273
+ <react_native_1.View style={[reduxDetailStyles.statPill, { backgroundColor: AppColors_1.AppColors.indigo50, borderColor: AppColors_1.AppColors.indigo400 }]}>
274
+ <NetworkIcons_1.LayersIcon color={AppColors_1.AppColors.indigo600Alt} size={11}/>
275
+ <react_native_1.Text style={[reduxDetailStyles.statLabel, { color: AppColors_1.AppColors.indigo600Alt }]}>{t('redux.keys')}:</react_native_1.Text>
276
+ <react_native_1.Text style={[reduxDetailStyles.statValue, { color: AppColors_1.AppColors.indigo600Alt }]}>{fieldsCount}</react_native_1.Text>
215
277
  </react_native_1.View>
216
- <react_native_1.View style={reduxDetailStyles.statPill}>
217
- <react_native_1.Text style={reduxDetailStyles.statLabel}>Size:</react_native_1.Text>
218
- <react_native_1.Text style={reduxDetailStyles.statValue}>{(0, helpers_1.getSize)(sliceData)}</react_native_1.Text>
278
+ <react_native_1.View style={[reduxDetailStyles.statPill, { backgroundColor: AppColors_1.AppColors.sky100, borderColor: AppColors_1.AppColors.sky400 }]}>
279
+ <react_native_1.Text style={[reduxDetailStyles.statLabel, { color: AppColors_1.AppColors.sky600 }]}>{t('redux.size')}:</react_native_1.Text>
280
+ <react_native_1.Text style={[reduxDetailStyles.statValue, { color: AppColors_1.AppColors.sky600 }]}>{(0, helpers_1.getSize)(sliceData)}</react_native_1.Text>
219
281
  </react_native_1.View>
220
- <react_native_1.View style={reduxDetailStyles.statPill}>
221
- <react_native_1.Text style={reduxDetailStyles.statLabel}>Timeline:</react_native_1.Text>
222
- <react_native_1.Text style={reduxDetailStyles.statValue}>{sliceActions.length} actions</react_native_1.Text>
282
+ <react_native_1.View style={[reduxDetailStyles.statPill, { backgroundColor: AppColors_1.AppColors.purple100, borderColor: AppColors_1.AppColors.purple200 }]}>
283
+ <NetworkIcons_1.TimelineIcon color={AppColors_1.AppColors.violet600} size={11}/>
284
+ <react_native_1.Text style={[reduxDetailStyles.statLabel, { color: AppColors_1.AppColors.brandPurple }]}>{t('redux.timeline')}:</react_native_1.Text>
285
+ <react_native_1.Text style={[reduxDetailStyles.statValue, { color: AppColors_1.AppColors.brandPurple }]}>{sliceActions.length}</react_native_1.Text>
223
286
  </react_native_1.View>
224
- {lastAction && (<react_native_1.View style={[reduxDetailStyles.statPill, { flex: 1, minWidth: 140 }]}>
225
- <react_native_1.Text style={reduxDetailStyles.statLabel}>Last Action:</react_native_1.Text>
226
- <react_native_1.Text style={reduxDetailStyles.statValue} numberOfLines={1}>
287
+ {lastAction && (<react_native_1.View style={[reduxDetailStyles.statPill, { backgroundColor: AppColors_1.AppColors.amber100, borderColor: AppColors_1.AppColors.amber200, flex: 1, minWidth: 140 }]}>
288
+ <NetworkIcons_1.BoltIcon color={AppColors_1.AppColors.amber800Warm} size={11}/>
289
+ <react_native_1.Text style={[reduxDetailStyles.statLabel, { color: AppColors_1.AppColors.amber800Warm }]}>{t('redux.last')}:</react_native_1.Text>
290
+ <react_native_1.Text style={[reduxDetailStyles.statValue, { color: AppColors_1.AppColors.amber800Warm }]} numberOfLines={1}>
227
291
  {lastAction.type}
228
292
  </react_native_1.Text>
229
293
  </react_native_1.View>)}
@@ -250,15 +314,45 @@ const ReduxDetail = react_1.default.memo(() => {
250
314
  </react_native_1.Text>
251
315
  </react_native_1.View>) : (sliceActions.map((action, aIdx) => {
252
316
  const isExpanded = expandedActionId === action.id;
317
+ const originMeta = getOriginBadge(action.originType);
318
+ const callerBasename = action.callerFile
319
+ ? action.callerFile.split('/').pop()
320
+ : null;
253
321
  return (<AnimatedEntrance_1.default key={action.id} index={aIdx} distance={6}>
254
322
  <TouchableScale_1.default onPress={() => setExpandedActionId(isExpanded ? null : action.id)} style={reduxDetailStyles.timelineCard}>
255
323
  <react_native_1.View style={reduxDetailStyles.timelineHeader}>
256
- <react_native_1.View style={reduxDetailStyles.actionBadge}>
257
- <react_native_1.Text style={reduxDetailStyles.actionBadgeText}>
258
- #{action.id}
259
- </react_native_1.Text>
324
+ <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6, flex: 1, minWidth: 0, flexWrap: 'wrap' }}>
325
+ <react_native_1.View style={reduxDetailStyles.actionBadge}>
326
+ <react_native_1.Text style={reduxDetailStyles.actionBadgeText}>
327
+ #{action.id}
328
+ </react_native_1.Text>
329
+ </react_native_1.View>
330
+ {/* Origin Badge */}
331
+ <react_native_1.View style={{
332
+ flexDirection: 'row',
333
+ alignItems: 'center',
334
+ gap: 3,
335
+ backgroundColor: originMeta.bg,
336
+ paddingHorizontal: 6,
337
+ paddingVertical: 2,
338
+ borderRadius: 4,
339
+ borderWidth: 1,
340
+ borderColor: originMeta.border,
341
+ }}>
342
+ <react_native_1.Text style={{ fontSize: 9 }}>{originMeta.icon}</react_native_1.Text>
343
+ <react_native_1.Text style={{
344
+ fontFamily: AppFonts_1.AppFonts.interBold,
345
+ fontSize: 8.5,
346
+ color: originMeta.text,
347
+ letterSpacing: 0.3,
348
+ }}>
349
+ {originMeta.label}
350
+ </react_native_1.Text>
351
+ </react_native_1.View>
352
+
353
+ <HighlightText_1.default text={action.type} search={detailSearch} style={reduxDetailStyles.actionTitle} highlightStyle={reduxDetailStyles.highlight}/>
260
354
  </react_native_1.View>
261
- <HighlightText_1.default text={action.type} search={detailSearch} style={reduxDetailStyles.actionTitle} highlightStyle={reduxDetailStyles.highlight}/>
355
+
262
356
  <react_native_1.View style={reduxDetailStyles.timePill}>
263
357
  <NetworkIcons_1.ClockIcon color={AppColors_1.AppColors.purple} size={10}/>
264
358
  <react_native_1.Text style={reduxDetailStyles.timeText}>
@@ -267,22 +361,120 @@ const ReduxDetail = react_1.default.memo(() => {
267
361
  </react_native_1.View>
268
362
  </react_native_1.View>
269
363
 
270
- {/* Expanded Payload & Diff Viewer */}
364
+ {/* Trigger caller preview row */}
365
+ {action.callerFile && (<react_native_1.View style={{
366
+ flexDirection: 'row',
367
+ alignItems: 'center',
368
+ justifyContent: 'space-between',
369
+ marginTop: 5,
370
+ marginBottom: 2,
371
+ paddingHorizontal: 7,
372
+ paddingVertical: 3,
373
+ backgroundColor: AppColors_1.AppColors.grayBackground,
374
+ borderRadius: 5,
375
+ borderWidth: 1,
376
+ borderColor: AppColors_1.AppColors.dividerColor,
377
+ }}>
378
+ <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 4, flex: 1, minWidth: 0 }}>
379
+ <react_native_1.Text style={{ fontFamily: AppFonts_1.AppFonts.interMedium, fontSize: 9.5, color: AppColors_1.AppColors.grayTextWeak }}>
380
+ {t('redux.triggeredFrom')}
381
+ </react_native_1.Text>
382
+ <react_native_1.Text style={{
383
+ fontFamily: AppFonts_1.AppFonts.interBold,
384
+ fontSize: 9.5,
385
+ color: AppColors_1.AppColors.sky600,
386
+ }} numberOfLines={1}>
387
+ {callerBasename}:{action.callerLine || 1}
388
+ </react_native_1.Text>
389
+ </react_native_1.View>
390
+
391
+ <react_native_1.Pressable onPress={() => (0, helpers_1.openInVSCode)(action.callerFile, action.callerLine, action.callerCol)} hitSlop={8} style={{
392
+ flexDirection: 'row',
393
+ alignItems: 'center',
394
+ gap: 3,
395
+ backgroundColor: AppColors_1.AppColors.sky100,
396
+ paddingHorizontal: 5,
397
+ paddingVertical: 1.5,
398
+ borderRadius: 3,
399
+ }}>
400
+ <NetworkIcons_1.ExternalLinkIcon color={AppColors_1.AppColors.sky600} size={9}/>
401
+ <react_native_1.Text style={{ fontFamily: AppFonts_1.AppFonts.interBold, fontSize: 8.5, color: AppColors_1.AppColors.sky600 }}>
402
+ {t('redux.openInEditor')}
403
+ </react_native_1.Text>
404
+ </react_native_1.Pressable>
405
+ </react_native_1.View>)}
406
+
407
+ {/* Expanded Payload, Diff Viewer & Call Stack */}
271
408
  {isExpanded ? (<react_native_1.View style={reduxDetailStyles.expandedContent}>
409
+ {/* Call Stack Trace Box */}
410
+ {action.stack ? (<react_native_1.View style={{ marginBottom: 10 }}>
411
+ <react_native_1.Text style={reduxDetailStyles.expandedSectionTitle}>
412
+ {t('redux.callStack')}:
413
+ </react_native_1.Text>
414
+ <react_native_1.View style={{
415
+ backgroundColor: AppColors_1.AppColors.grayBackground,
416
+ borderRadius: 8,
417
+ padding: 8,
418
+ borderWidth: 1,
419
+ borderColor: AppColors_1.AppColors.dividerColor,
420
+ gap: 4,
421
+ }}>
422
+ {action.stack
423
+ .split('\n')
424
+ .map(l => l.trim())
425
+ .filter(l => l.length > 0 && !l.includes('reduxLogger') && !l.includes('inspectorReduxMiddleware'))
426
+ .slice(0, 8)
427
+ .map((frameLine, fIdx) => {
428
+ const parsed = (0, helpers_1.parseStackLine)(frameLine, fIdx === 0);
429
+ const isApp = parsed.frameType === 'app';
430
+ return (<react_native_1.Pressable key={fIdx} onPress={() => {
431
+ if (parsed.fileName !== 'Unknown') {
432
+ (0, helpers_1.openInVSCode)(parsed.fullPath || parsed.fileName, parsed.lineNumber, parsed.columnNumber);
433
+ }
434
+ }} style={{
435
+ flexDirection: 'row',
436
+ alignItems: 'center',
437
+ justifyContent: 'space-between',
438
+ paddingVertical: 2.5,
439
+ borderBottomWidth: fIdx < 7 ? 0.5 : 0,
440
+ borderBottomColor: AppColors_1.AppColors.dividerColor,
441
+ }}>
442
+ <react_native_1.View style={{ flex: 1, minWidth: 0 }}>
443
+ <react_native_1.Text style={{
444
+ fontFamily: isApp ? AppFonts_1.AppFonts.interBold : AppFonts_1.AppFonts.interRegular,
445
+ fontSize: 9.5,
446
+ color: isApp ? AppColors_1.AppColors.primaryBlack : AppColors_1.AppColors.grayTextWeak,
447
+ }} numberOfLines={1}>
448
+ {parsed.functionName || 'anonymous'}
449
+ </react_native_1.Text>
450
+ <react_native_1.Text style={{
451
+ fontFamily: AppFonts_1.AppFonts.interRegular,
452
+ fontSize: 8.5,
453
+ color: isApp ? AppColors_1.AppColors.sky600 : AppColors_1.AppColors.grayTextWeak,
454
+ }} numberOfLines={1}>
455
+ {parsed.fileName}:{parsed.lineNumber || 1}:{parsed.columnNumber || 1}
456
+ </react_native_1.Text>
457
+ </react_native_1.View>
458
+ {isApp && (<NetworkIcons_1.ExternalLinkIcon color={AppColors_1.AppColors.sky600} size={10}/>)}
459
+ </react_native_1.Pressable>);
460
+ })}
461
+ </react_native_1.View>
462
+ </react_native_1.View>) : null}
463
+
272
464
  {action.payload !== undefined && (<react_native_1.View style={{ marginBottom: 10 }}>
273
465
  <react_native_1.Text style={reduxDetailStyles.expandedSectionTitle}>
274
- Action Payload:
466
+ {t('redux.actionPayload')}
275
467
  </react_native_1.Text>
276
468
  <JsonViewer_1.default data={action.payload} search={detailSearch} forceOpen={true}/>
277
469
  </react_native_1.View>)}
278
470
 
279
471
  <react_native_1.Text style={reduxDetailStyles.expandedSectionTitle}>
280
- State Changes (Diff):
472
+ {t('redux.stateChangesDiff')}
281
473
  </react_native_1.Text>
282
474
  <DiffViewer_1.default oldData={action.prevState?.[selectedReduxSlice] || {}} newData={action.nextState?.[selectedReduxSlice] || {}} forceOpen={true}/>
283
475
  </react_native_1.View>) : (<react_native_1.View style={reduxDetailStyles.collapsedPrompt}>
284
476
  <react_native_1.Text style={reduxDetailStyles.collapsedPromptText}>
285
- Tap to inspect action payload & diff changes
477
+ {t('redux.tapToInspectAction')}
286
478
  </react_native_1.Text>
287
479
  <NetworkIcons_1.ForwardChevronIcon color={AppColors_1.AppColors.grayTextWeak} size={12}/>
288
480
  </react_native_1.View>)}
@@ -365,12 +557,15 @@ const reduxDetailStyles = react_native_1.StyleSheet.create({
365
557
  color: AppColors_1.AppColors.primaryBlack,
366
558
  },
367
559
  persistedChip: {
368
- backgroundColor: '#D1FAE5',
560
+ flexDirection: 'row',
561
+ alignItems: 'center',
562
+ gap: 3.5,
563
+ backgroundColor: '#ECFDF5',
369
564
  paddingHorizontal: 6,
370
565
  paddingVertical: 2,
371
566
  borderRadius: 4,
372
567
  borderWidth: 1,
373
- borderColor: AppColors_1.AppColors.emeraldBorder,
568
+ borderColor: '#A7F3D0',
374
569
  },
375
570
  persistedChipText: {
376
571
  fontFamily: AppFonts_1.AppFonts.interBold,
@@ -378,22 +573,22 @@ const reduxDetailStyles = react_native_1.StyleSheet.create({
378
573
  color: '#047857',
379
574
  },
380
575
  inMemoryChip: {
381
- backgroundColor: '#F3E8FF',
576
+ backgroundColor: '#EEF2FF',
382
577
  paddingHorizontal: 6,
383
578
  paddingVertical: 2,
384
579
  borderRadius: 4,
385
580
  borderWidth: 1,
386
- borderColor: '#E9D5FF',
581
+ borderColor: '#C7D2FE',
387
582
  },
388
583
  inMemoryChipText: {
389
584
  fontFamily: AppFonts_1.AppFonts.interBold,
390
585
  fontSize: 9,
391
- color: '#7E22CE',
586
+ color: '#4338CA',
392
587
  },
393
588
  subStatsRow: {
394
589
  flexDirection: 'row',
395
590
  alignItems: 'center',
396
- gap: 8,
591
+ gap: 6,
397
592
  flexWrap: 'wrap',
398
593
  },
399
594
  statPill: {
@@ -401,20 +596,20 @@ const reduxDetailStyles = react_native_1.StyleSheet.create({
401
596
  alignItems: 'center',
402
597
  gap: 4,
403
598
  backgroundColor: AppColors_1.AppColors.grayBackground,
404
- paddingHorizontal: 8,
405
- paddingVertical: 4,
599
+ paddingHorizontal: 7,
600
+ paddingVertical: 3.5,
406
601
  borderRadius: 6,
407
602
  borderWidth: 1,
408
603
  borderColor: AppColors_1.AppColors.dividerColor,
409
604
  },
410
605
  statLabel: {
411
- fontFamily: AppFonts_1.AppFonts.interMedium,
412
- fontSize: 10.5,
606
+ fontFamily: AppFonts_1.AppFonts.interBold,
607
+ fontSize: 10,
413
608
  color: AppColors_1.AppColors.grayTextWeak,
414
609
  },
415
610
  statValue: {
416
611
  fontFamily: AppFonts_1.AppFonts.interBold,
417
- fontSize: 11,
612
+ fontSize: 10.5,
418
613
  color: AppColors_1.AppColors.primaryBlack,
419
614
  },
420
615
  searchContainer: {