react-native-inapp-inspector 1.1.27 → 1.1.29

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 (100) hide show
  1. package/android/src/main/java/com/inappinspector/NetworkInspectorModule.java +29 -46
  2. package/dist/commonjs/components/AppHeaderLogo.js +12 -15
  3. package/dist/commonjs/components/ConsoleLogCard.js +31 -7
  4. package/dist/commonjs/components/CopyButton.js +15 -1
  5. package/dist/commonjs/components/DomainHeader.js +56 -28
  6. package/dist/commonjs/components/ErrorBoundary.d.ts +1 -1
  7. package/dist/commonjs/components/ErrorBoundary.js +530 -100
  8. package/dist/commonjs/components/HighlightText.js +7 -1
  9. package/dist/commonjs/components/Inspector/AnalyticsTab.js +190 -126
  10. package/dist/commonjs/components/Inspector/BundleTab.d.ts +1 -0
  11. package/dist/commonjs/components/Inspector/BundleTab.js +145 -21
  12. package/dist/commonjs/components/Inspector/CrashTab.js +0 -8
  13. package/dist/commonjs/components/Inspector/InspectorHeader.js +17 -3
  14. package/dist/commonjs/components/Inspector/LogDetail.js +8 -5
  15. package/dist/commonjs/components/Inspector/MainScreen.js +4 -0
  16. package/dist/commonjs/components/Inspector/NetworkDetail.js +65 -24
  17. package/dist/commonjs/components/Inspector/PerformanceTab.d.ts +5 -0
  18. package/dist/commonjs/components/Inspector/PerformanceTab.js +588 -155
  19. package/dist/commonjs/components/Inspector/SettingsPanel.js +57 -22
  20. package/dist/commonjs/components/Inspector/TabBar.js +13 -1
  21. package/dist/commonjs/components/JsonViewer.js +25 -3
  22. package/dist/commonjs/components/LogCard.js +173 -40
  23. package/dist/commonjs/components/NetworkIcons.d.ts +112 -102
  24. package/dist/commonjs/components/Toast.d.ts +3 -0
  25. package/dist/commonjs/components/Toast.js +152 -0
  26. package/dist/commonjs/components/TouchableScale.d.ts +1 -0
  27. package/dist/commonjs/components/TouchableScale.js +3 -3
  28. package/dist/commonjs/components/TreeNode.js +1 -1
  29. package/dist/commonjs/constants/index.js +6 -6
  30. package/dist/commonjs/constants/version.d.ts +1 -1
  31. package/dist/commonjs/constants/version.js +1 -1
  32. package/dist/commonjs/customHooks/analyticsLogger.d.ts +1 -11
  33. package/dist/commonjs/customHooks/analyticsLogger.js +8 -1
  34. package/dist/commonjs/customHooks/bundleAnalyzer.js +121 -124
  35. package/dist/commonjs/customHooks/networkLogger.d.ts +1 -0
  36. package/dist/commonjs/customHooks/networkLogger.js +16 -0
  37. package/dist/commonjs/customHooks/performanceTracker.d.ts +74 -0
  38. package/dist/commonjs/customHooks/performanceTracker.js +546 -392
  39. package/dist/commonjs/customHooks/reduxLogger.d.ts +1 -0
  40. package/dist/commonjs/customHooks/reduxLogger.js +3 -1
  41. package/dist/commonjs/helpers/index.d.ts +4 -0
  42. package/dist/commonjs/helpers/index.js +92 -69
  43. package/dist/commonjs/helpers/toast.d.ts +4 -0
  44. package/dist/commonjs/helpers/toast.js +20 -0
  45. package/dist/commonjs/i18n/locales/en.json +229 -5
  46. package/dist/commonjs/index.d.ts +1 -1
  47. package/dist/commonjs/index.js +36 -2
  48. package/dist/commonjs/styles/index.d.ts +63 -15
  49. package/dist/commonjs/styles/index.js +79 -32
  50. package/dist/commonjs/types/interfaces.d.ts +3 -0
  51. package/dist/esm/components/AppHeaderLogo.js +12 -15
  52. package/dist/esm/components/ConsoleLogCard.js +33 -9
  53. package/dist/esm/components/CopyButton.js +15 -1
  54. package/dist/esm/components/DomainHeader.js +56 -28
  55. package/dist/esm/components/ErrorBoundary.d.ts +1 -1
  56. package/dist/esm/components/ErrorBoundary.js +498 -101
  57. package/dist/esm/components/HighlightText.js +7 -1
  58. package/dist/esm/components/Inspector/AnalyticsTab.js +191 -127
  59. package/dist/esm/components/Inspector/BundleTab.d.ts +1 -0
  60. package/dist/esm/components/Inspector/BundleTab.js +145 -23
  61. package/dist/esm/components/Inspector/CrashTab.js +0 -8
  62. package/dist/esm/components/Inspector/InspectorHeader.js +18 -4
  63. package/dist/esm/components/Inspector/LogDetail.js +10 -7
  64. package/dist/esm/components/Inspector/MainScreen.js +4 -0
  65. package/dist/esm/components/Inspector/NetworkDetail.js +66 -25
  66. package/dist/esm/components/Inspector/PerformanceTab.d.ts +5 -0
  67. package/dist/esm/components/Inspector/PerformanceTab.js +591 -158
  68. package/dist/esm/components/Inspector/SettingsPanel.js +57 -22
  69. package/dist/esm/components/Inspector/TabBar.js +13 -1
  70. package/dist/esm/components/JsonViewer.js +25 -3
  71. package/dist/esm/components/LogCard.js +175 -42
  72. package/dist/esm/components/NetworkIcons.d.ts +112 -102
  73. package/dist/esm/components/Toast.d.ts +3 -0
  74. package/dist/esm/components/Toast.js +117 -0
  75. package/dist/esm/components/TouchableScale.d.ts +1 -0
  76. package/dist/esm/components/TouchableScale.js +3 -3
  77. package/dist/esm/components/TreeNode.js +1 -1
  78. package/dist/esm/constants/index.js +6 -6
  79. package/dist/esm/constants/version.d.ts +1 -1
  80. package/dist/esm/constants/version.js +1 -1
  81. package/dist/esm/customHooks/analyticsLogger.d.ts +1 -11
  82. package/dist/esm/customHooks/analyticsLogger.js +6 -0
  83. package/dist/esm/customHooks/bundleAnalyzer.js +121 -124
  84. package/dist/esm/customHooks/networkLogger.d.ts +1 -0
  85. package/dist/esm/customHooks/networkLogger.js +16 -0
  86. package/dist/esm/customHooks/performanceTracker.d.ts +74 -0
  87. package/dist/esm/customHooks/performanceTracker.js +531 -391
  88. package/dist/esm/customHooks/reduxLogger.d.ts +1 -0
  89. package/dist/esm/customHooks/reduxLogger.js +1 -0
  90. package/dist/esm/helpers/index.d.ts +4 -0
  91. package/dist/esm/helpers/index.js +87 -69
  92. package/dist/esm/helpers/toast.d.ts +4 -0
  93. package/dist/esm/helpers/toast.js +15 -0
  94. package/dist/esm/i18n/locales/en.json +229 -5
  95. package/dist/esm/index.d.ts +1 -1
  96. package/dist/esm/index.js +24 -3
  97. package/dist/esm/styles/index.d.ts +63 -15
  98. package/dist/esm/styles/index.js +79 -32
  99. package/dist/esm/types/interfaces.d.ts +3 -0
  100. package/package.json +4 -1
@@ -51,8 +51,12 @@ const networkLogger_1 = require("../../customHooks/networkLogger");
51
51
  const consoleLogger_1 = require("../../customHooks/consoleLogger");
52
52
  const analyticsLogger_1 = require("../../customHooks/analyticsLogger");
53
53
  const crashHandler_1 = require("../../customHooks/crashHandler");
54
+ const reduxLogger_1 = require("../../customHooks/reduxLogger");
55
+ const analyticsLogger_2 = require("../../customHooks/analyticsLogger");
56
+ const i18n_1 = require("../../i18n");
54
57
  const NetworkIcons_1 = require("../NetworkIcons");
55
58
  const SettingsPanel = () => {
59
+ const { t } = (0, i18n_1.useTranslation)();
56
60
  const { settingsPage, setSettingsPage, settingsActiveSubTab, setSettingsActiveSubTab, tabVisibility, toggleTabVisibility, defaultTab, setDefaultTab, isDark, setIsDark, modalHeightPercent, setModalHeightPercent, modalAnimationType, setModalAnimationType, showDuplicateLogs, setShowDuplicateLogs, showConsoleLevels, setShowConsoleLevels, resetToDefaults, storage, logs, consoleLogs, analyticsEvents, reduxState, maxNetworkLogs, setMaxNetworkLogs, maxConsoleLogs, setMaxConsoleLogs, reduxAutoRefresh, setReduxAutoRefreshState, reduxExpandDepth, setReduxExpandDepth, switchActiveTab, setSelected, setSelectedEvent, setReduxState, crashRecords, maxCrashLogs, setMaxCrashLogs, } = (0, InspectorContext_1.useInspector)();
57
61
  const isPersistent = (0, settingsStore_1.isPersistentStorageAvailable)();
58
62
  const headerTopPadding = react_native_1.Platform.OS === 'ios' && modalHeightPercent >= 95 ? 44 : 0;
@@ -223,9 +227,14 @@ const SettingsPanel = () => {
223
227
  </react_native_1.View>
224
228
 
225
229
  {settingsTabs.map((tab, idx) => {
226
- const isVisible = tab.key === 'apis' || tabVisibility?.[tab.key];
230
+ const isReduxAvail = (0, reduxLogger_1.isReduxConnected)();
231
+ const isAnalyticsAvail = (0, analyticsLogger_2.isAnalyticsConnected)();
232
+ const isUnavailable = (tab.key === 'redux' && !isReduxAvail) ||
233
+ (tab.key === 'analytics' && !isAnalyticsAvail);
234
+ const isLocked = tab.key === 'apis' || isUnavailable;
235
+ const isVisible = tab.key === 'apis' ||
236
+ (Boolean(tabVisibility?.[tab.key]) && !isUnavailable);
227
237
  const isLast = idx === settingsTabs.length - 1;
228
- const isLocked = tab.key === 'apis';
229
238
  return (<react_native_1.View key={tab.key} style={{
230
239
  flexDirection: 'row',
231
240
  alignItems: 'center',
@@ -241,6 +250,7 @@ const SettingsPanel = () => {
241
250
  flexDirection: 'row',
242
251
  alignItems: 'center',
243
252
  gap: 8,
253
+ flexWrap: 'wrap',
244
254
  }}>
245
255
  {/* Small icon tile */}
246
256
  <react_native_1.View style={{
@@ -289,8 +299,28 @@ const SettingsPanel = () => {
289
299
  }}>
290
300
  {tab.label}
291
301
  </react_native_1.Text>
302
+ {/* Unavailable badge */}
303
+ {isUnavailable && (<react_native_1.View style={{
304
+ backgroundColor: `${AppColors_1.AppColors.amber500}18`,
305
+ borderRadius: 4,
306
+ paddingHorizontal: 5,
307
+ paddingVertical: 1.5,
308
+ borderWidth: 1,
309
+ borderColor: `${AppColors_1.AppColors.amber500}35`,
310
+ }}>
311
+ <react_native_1.Text style={{
312
+ fontFamily: AppFonts_1.AppFonts.interBold,
313
+ fontSize: 8,
314
+ color: AppColors_1.AppColors.amber700,
315
+ letterSpacing: 0.3,
316
+ }}>
317
+ {tab.key === 'redux'
318
+ ? t('settings.notConnectedBadge')
319
+ : t('settings.notDetectedBadge')}
320
+ </react_native_1.Text>
321
+ </react_native_1.View>)}
292
322
  {/* #6 — badge marks the configured default tab */}
293
- {tab.key === defaultTab && (<react_native_1.View style={{
323
+ {tab.key === defaultTab && !isUnavailable && (<react_native_1.View style={{
294
324
  flexDirection: 'row',
295
325
  alignItems: 'center',
296
326
  backgroundColor: `${AppColors_1.AppColors.purple}14`,
@@ -319,21 +349,21 @@ const SettingsPanel = () => {
319
349
  </react_native_1.View>)}
320
350
 
321
351
  {/* Settings gear icon next to label */}
322
- <TouchableScale_1.default onPress={() => {
323
- (0, InspectorContext_1.animateNextLayout)();
324
- setSettingsPage(tab.key);
325
- }} hitSlop={8} style={{
326
- marginLeft: 4,
327
- padding: 4,
328
- borderRadius: 6,
329
- backgroundColor: AppColors_1.AppColors.purpleShade50,
330
- borderWidth: 1,
331
- borderColor: `${AppColors_1.AppColors.purple}26`,
332
- alignItems: 'center',
333
- justifyContent: 'center',
334
- }}>
335
- <NetworkIcons_1.SettingsIcon color={AppColors_1.AppColors.purple} size={10}/>
336
- </TouchableScale_1.default>
352
+ {!isUnavailable && (<TouchableScale_1.default onPress={() => {
353
+ (0, InspectorContext_1.animateNextLayout)();
354
+ setSettingsPage(tab.key);
355
+ }} hitSlop={8} style={{
356
+ marginLeft: 4,
357
+ padding: 4,
358
+ borderRadius: 6,
359
+ backgroundColor: AppColors_1.AppColors.purpleShade50,
360
+ borderWidth: 1,
361
+ borderColor: `${AppColors_1.AppColors.purple}26`,
362
+ alignItems: 'center',
363
+ justifyContent: 'center',
364
+ }}>
365
+ <NetworkIcons_1.SettingsIcon color={AppColors_1.AppColors.purple} size={10}/>
366
+ </TouchableScale_1.default>)}
337
367
  </react_native_1.View>
338
368
 
339
369
  {/* Visibility Switch in VISIBILITY column */}
@@ -383,12 +413,17 @@ const SettingsPanel = () => {
383
413
  </TouchableScale_1.default>
384
414
  {isLocked && (<react_native_1.Text style={{
385
415
  fontFamily: AppFonts_1.AppFonts.interBold,
386
- fontSize: 8,
387
- color: AppColors_1.AppColors.grayTextWeak,
388
- letterSpacing: 0.4,
416
+ fontSize: 7.5,
417
+ color: isUnavailable
418
+ ? AppColors_1.AppColors.amber700
419
+ : AppColors_1.AppColors.grayTextWeak,
420
+ letterSpacing: 0.3,
389
421
  marginTop: 3,
422
+ textAlign: 'right',
390
423
  }}>
391
- REQUIRED
424
+ {tab.key === 'apis'
425
+ ? t('settings.requiredBadge')
426
+ : t('settings.readOnlyBadge')}
392
427
  </react_native_1.Text>)}
393
428
  </react_native_1.View>
394
429
  </react_native_1.View>);
@@ -10,8 +10,12 @@ const TouchableScale_1 = __importDefault(require("../TouchableScale"));
10
10
  const styles_1 = __importDefault(require("../../styles"));
11
11
  const AppColors_1 = require("../../styles/AppColors");
12
12
  const NetworkIcons_1 = require("../NetworkIcons");
13
+ const reduxLogger_1 = require("../../customHooks/reduxLogger");
14
+ const analyticsLogger_1 = require("../../customHooks/analyticsLogger");
13
15
  const TabBar = react_1.default.memo(() => {
14
16
  const { activeTab, switchActiveTab, tabVisibility, logs, consoleLogs, analyticsEvents, crashRecords, lastReadApisCount, lastReadLogsCount, lastReadCrashesCount, unreadPulseAnim, } = (0, InspectorContext_1.useInspector)();
17
+ const isReduxAvail = (0, reduxLogger_1.isReduxConnected)();
18
+ const isAnalyticsAvail = (0, analyticsLogger_1.isAnalyticsConnected)();
15
19
  return (<react_native_1.View style={styles_1.default.tabBarContainer}>
16
20
  <react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={{ paddingRight: 16 }}>
17
21
  {[
@@ -58,7 +62,15 @@ const TabBar = react_1.default.memo(() => {
58
62
  icon: 'crash',
59
63
  },
60
64
  ]
61
- .filter(tab => tabVisibility?.[tab.key])
65
+ .filter(tab => {
66
+ if (!tabVisibility?.[tab.key])
67
+ return false;
68
+ if (tab.key === 'redux' && !isReduxAvail)
69
+ return false;
70
+ if (tab.key === 'analytics' && !isAnalyticsAvail)
71
+ return false;
72
+ return true;
73
+ })
62
74
  .map(tab => {
63
75
  const isActive = activeTab === tab.key;
64
76
  const iconColor = isActive
@@ -95,7 +95,7 @@ const JsonTableRow = react_1.default.memo(({ itemKey, val, search, }) => {
95
95
  // ── JsonViewer Component ─────────────────────────────────────────────────────
96
96
  const JsonViewer = react_1.default.memo(({ data, search, forceOpen, defaultExpandDepth, wrap, fullHeight = false, maxHeight, mode: externalMode, onModeChange, hideTabs = false, }) => {
97
97
  const { t } = (0, i18n_1.useTranslation)();
98
- const [internalMode, setInternalMode] = (0, react_1.useState)('pretty');
98
+ const [internalMode, setInternalMode] = (0, react_1.useState)('raw');
99
99
  const mode = externalMode ?? internalMode;
100
100
  const setMode = (newMode) => {
101
101
  if (onModeChange) {
@@ -116,6 +116,10 @@ const JsonViewer = react_1.default.memo(({ data, search, forceOpen, defaultExpan
116
116
  return String(data);
117
117
  }
118
118
  }, [data]);
119
+ const [showFullRaw, setShowFullRaw] = (0, react_1.useState)(false);
120
+ const RAW_LIMIT = 50000;
121
+ const isTruncated = rawText.length > RAW_LIMIT && !showFullRaw;
122
+ const displayRawText = isTruncated ? rawText.slice(0, RAW_LIMIT) : rawText;
119
123
  (0, react_1.useEffect)(() => {
120
124
  if (externalMode) {
121
125
  setInternalMode(externalMode);
@@ -186,7 +190,7 @@ const JsonViewer = react_1.default.memo(({ data, search, forceOpen, defaultExpan
186
190
  <react_native_1.View style={contentWrapperStyle}>
187
191
  {mode === 'pretty' && (isEmpty ? (<react_native_1.View style={localStyles.emptyTable}>
188
192
  <react_native_1.Text style={localStyles.emptyTableText}>
189
- {t('network.emptyResponse')}
193
+ {t('network.jsonViewer.emptyPayload')}
190
194
  </react_native_1.Text>
191
195
  </react_native_1.View>) : (wrap ? (fullHeight ? (<react_native_1.ScrollView style={{ flex: 1 }} contentContainerStyle={{ flexGrow: 1 }}>
192
196
  <react_native_1.View style={[styles_1.default.codeBlock, { width: '100%' }]}>{tree}</react_native_1.View>
@@ -201,12 +205,30 @@ const JsonViewer = react_1.default.memo(({ data, search, forceOpen, defaultExpan
201
205
  </react_native_1.ScrollView>))))}
202
206
 
203
207
  {mode === 'raw' && (<react_native_1.ScrollView style={scrollStyle} contentContainerStyle={localStyles.rawContainer} showsVerticalScrollIndicator={true} nestedScrollEnabled={true}>
204
- <HighlightText_1.default text={rawText} search={search} detectLinks={true} style={localStyles.rawPlainText} highlightStyle={{
208
+ <HighlightText_1.default text={displayRawText} search={search} detectLinks={rawText.length < 20000} style={localStyles.rawPlainText} selectable={true} highlightStyle={{
205
209
  backgroundColor: AppColors_1.AppColors.yellowHighlight,
206
210
  color: AppColors_1.AppColors.primaryBlack,
207
211
  borderRadius: 3,
208
212
  paddingHorizontal: 2,
209
213
  }}/>
214
+ {isTruncated && (<react_native_1.TouchableOpacity onPress={() => setShowFullRaw(true)} style={{
215
+ marginTop: 10,
216
+ backgroundColor: `${AppColors_1.AppColors.brandPurple}15`,
217
+ paddingVertical: 8,
218
+ paddingHorizontal: 12,
219
+ borderRadius: 6,
220
+ alignItems: 'center',
221
+ borderWidth: 1,
222
+ borderColor: `${AppColors_1.AppColors.brandPurple}30`,
223
+ }}>
224
+ <react_native_1.Text style={{
225
+ fontFamily: AppFonts_1.AppFonts.interBold,
226
+ fontSize: 11,
227
+ color: AppColors_1.AppColors.brandPurple,
228
+ }}>
229
+ Showing first 50 KB ({Math.round(rawText.length / 1024)} KB total) · Tap to load full
230
+ </react_native_1.Text>
231
+ </react_native_1.TouchableOpacity>)}
210
232
  </react_native_1.ScrollView>)}
211
233
 
212
234
  {mode === 'table' && (fullHeight ? (<react_native_1.ScrollView style={scrollStyle}>
@@ -43,6 +43,7 @@ const AppColors_1 = require("../styles/AppColors");
43
43
  const constants_1 = require("../constants");
44
44
  const helpers_1 = require("../helpers");
45
45
  const NetworkIcons_1 = require("./NetworkIcons");
46
+ const AppFonts_1 = require("../styles/AppFonts");
46
47
  const styles_1 = __importDefault(require("../styles"));
47
48
  const HighlightText_1 = __importDefault(require("./HighlightText"));
48
49
  const TouchableScale_1 = __importDefault(require("./TouchableScale"));
@@ -50,6 +51,27 @@ const i18n_1 = require("../i18n");
50
51
  const LogCard = react_1.default.memo(function LogCard({ item, onPress, timelineMinStart, timelineTotalRange, isNew, isSelected, onToggleSelect, searchStr, }) {
51
52
  const { t } = (0, i18n_1.useTranslation)();
52
53
  const methodColor = constants_1.METHOD_COLORS[item.method] ?? constants_1.METHOD_COLORS.ALL;
54
+ const handleOpenUrl = (e) => {
55
+ e?.stopPropagation?.();
56
+ 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${item.url}`, [
57
+ { text: t('common.cancel') || 'Cancel', style: 'cancel' },
58
+ {
59
+ text: t('common.open') || 'Open',
60
+ onPress: () => {
61
+ react_native_1.Linking.canOpenURL(item.url)
62
+ .then(supported => {
63
+ if (supported) {
64
+ react_native_1.Linking.openURL(item.url);
65
+ }
66
+ else {
67
+ react_native_1.Linking.openURL(item.url).catch(() => { });
68
+ }
69
+ })
70
+ .catch(() => { });
71
+ },
72
+ },
73
+ ]);
74
+ };
53
75
  const isFailed = item.status === 0 || (item.status != null && item.status >= 400);
54
76
  const isLoading = item.status == null;
55
77
  const statusColor = (0, helpers_1.getStatusColor)(item.status);
@@ -75,10 +97,6 @@ const LogCard = react_1.default.memo(function LogCard({ item, onPress, timelineM
75
97
  }).start();
76
98
  }
77
99
  }, [isNew]);
78
- const path = (0, helpers_1.getPath)(item.url);
79
- const baseUrl = (0, helpers_1.getBaseUrl)(item.url) || item.url;
80
- const slug = path && path !== '/' ? path : item.url;
81
- const showSlug = slug !== baseUrl && slug !== item.url;
82
100
  const triggeredAt = (0, helpers_1.formatDateTime)(item.startTime);
83
101
  const isJson = item.url.split('?')[0].toLowerCase().endsWith('.json');
84
102
  return (<TouchableScale_1.default onPress={onPress} style={[
@@ -89,7 +107,7 @@ const LogCard = react_1.default.memo(function LogCard({ item, onPress, timelineM
89
107
  },
90
108
  ]}>
91
109
  <react_native_1.View style={styles_1.default.cardBody}>
92
- {/* Row 1: Header (Checkbox, Serial, Method Badge, Base URL / Host with HTTPS, Status Pill) */}
110
+ {/* Row 1: Header (Checkbox, Serial, Method Badge, Client Tag, Status Pill) */}
93
111
  <react_native_1.View style={styles_1.default.cardHeaderRow}>
94
112
  <react_native_1.View style={styles_1.default.cardHeaderLeft}>
95
113
  <react_native_1.Pressable onPress={() => onToggleSelect(item.id)} hitSlop={12} style={[
@@ -109,7 +127,122 @@ const LogCard = react_1.default.memo(function LogCard({ item, onPress, timelineM
109
127
  </react_native_1.Text>
110
128
  </react_native_1.View>
111
129
 
112
- <HighlightText_1.default text={baseUrl || item.url} search={searchStr} style={styles_1.default.cardHostText} highlightStyle={styles_1.default.highlight} numberOfLines={1} ellipsizeMode="tail"/>
130
+ {item.client && (<react_native_1.View style={[
131
+ styles_1.default.chip,
132
+ {
133
+ backgroundColor: item.client === 'axios'
134
+ ? `${AppColors_1.AppColors.purple}14`
135
+ : item.client === 'apollo' || item.client === 'graphql'
136
+ ? `${AppColors_1.AppColors.pink500}14`
137
+ : item.client === 'xhr'
138
+ ? `${AppColors_1.AppColors.amber500}14`
139
+ : `${AppColors_1.AppColors.sky500}14`,
140
+ borderColor: item.client === 'axios'
141
+ ? `${AppColors_1.AppColors.purple}30`
142
+ : item.client === 'apollo' || item.client === 'graphql'
143
+ ? `${AppColors_1.AppColors.pink500}30`
144
+ : item.client === 'xhr'
145
+ ? `${AppColors_1.AppColors.amber500}30`
146
+ : `${AppColors_1.AppColors.sky500}30`,
147
+ paddingHorizontal: 4.5,
148
+ paddingVertical: 1,
149
+ borderRadius: 4,
150
+ },
151
+ ]}>
152
+ <react_native_1.Text style={[
153
+ styles_1.default.chipText,
154
+ {
155
+ fontFamily: AppFonts_1.AppFonts.interBold,
156
+ fontSize: 8.5,
157
+ color: item.client === 'axios'
158
+ ? AppColors_1.AppColors.purple
159
+ : item.client === 'apollo' || item.client === 'graphql'
160
+ ? AppColors_1.AppColors.pink500
161
+ : item.client === 'xhr'
162
+ ? AppColors_1.AppColors.amber700
163
+ : AppColors_1.AppColors.sky600,
164
+ },
165
+ ]}>
166
+ {item.client.toUpperCase()}
167
+ </react_native_1.Text>
168
+ </react_native_1.View>)}
169
+
170
+ {/* Protocol / HTTPS Badge */}
171
+ <react_native_1.View style={[
172
+ styles_1.default.chip,
173
+ {
174
+ backgroundColor: item.url.toLowerCase().startsWith('https')
175
+ ? '#ECFDF5'
176
+ : '#FFFBEB',
177
+ borderColor: item.url.toLowerCase().startsWith('https')
178
+ ? '#A7F3D0'
179
+ : '#FDE68A',
180
+ paddingHorizontal: 4,
181
+ paddingVertical: 1,
182
+ borderRadius: 4,
183
+ },
184
+ ]}>
185
+ <react_native_1.Text style={[
186
+ styles_1.default.chipText,
187
+ {
188
+ fontFamily: AppFonts_1.AppFonts.interBold,
189
+ fontSize: 8,
190
+ color: item.url.toLowerCase().startsWith('https')
191
+ ? '#059669'
192
+ : '#D97706',
193
+ },
194
+ ]}>
195
+ {item.url.toLowerCase().startsWith('https') ? 'HTTPS' : 'HTTP'}
196
+ </react_native_1.Text>
197
+ </react_native_1.View>
198
+
199
+ {/* GraphQL Indicator */}
200
+ {(item.url.toLowerCase().includes('graphql') ||
201
+ item.client === 'apollo' ||
202
+ item.client === 'graphql') && (<react_native_1.View style={[
203
+ styles_1.default.chip,
204
+ {
205
+ backgroundColor: '#FDF2F8',
206
+ borderColor: '#FBCFE8',
207
+ paddingHorizontal: 4,
208
+ paddingVertical: 1,
209
+ borderRadius: 4,
210
+ },
211
+ ]}>
212
+ <react_native_1.Text style={[
213
+ styles_1.default.chipText,
214
+ {
215
+ fontFamily: AppFonts_1.AppFonts.interBold,
216
+ fontSize: 8,
217
+ color: '#DB2777',
218
+ },
219
+ ]}>
220
+ GQL
221
+ </react_native_1.Text>
222
+ </react_native_1.View>)}
223
+
224
+ {/* In-Line Duration / Latency Pill */}
225
+ {item.duration != null && !isFailed && (<react_native_1.View style={[
226
+ styles_1.default.chip,
227
+ {
228
+ backgroundColor: `${durationColor}12`,
229
+ borderColor: `${durationColor}2E`,
230
+ paddingHorizontal: 4.5,
231
+ paddingVertical: 1,
232
+ borderRadius: 4,
233
+ },
234
+ ]}>
235
+ <react_native_1.Text style={[
236
+ styles_1.default.chipText,
237
+ {
238
+ fontFamily: AppFonts_1.AppFonts.interBold,
239
+ fontSize: 8.5,
240
+ color: durationColor,
241
+ },
242
+ ]}>
243
+ {item.duration}ms
244
+ </react_native_1.Text>
245
+ </react_native_1.View>)}
113
246
  </react_native_1.View>
114
247
 
115
248
  <react_native_1.View style={[
@@ -146,42 +279,42 @@ const LogCard = react_1.default.memo(function LogCard({ item, onPress, timelineM
146
279
  </react_native_1.View>
147
280
  </react_native_1.View>
148
281
 
149
- {/* Row 2: Improved Slug Capsule Container */}
150
- {showSlug && (<react_native_1.View style={styles_1.default.cardSlugBox}>
151
- <react_native_1.View style={styles_1.default.slugLeft}>
152
- <react_native_1.Text style={styles_1.default.slugTag}>PATH</react_native_1.Text>
153
- <HighlightText_1.default text={slug} search={searchStr} style={styles_1.default.slugText} highlightStyle={styles_1.default.highlight} numberOfLines={1} ellipsizeMode="tail"/>
154
- </react_native_1.View>
282
+ {/* Row 2: Full URL Capsule Container (Clickable with link prompt) */}
283
+ <react_native_1.View style={styles_1.default.cardSlugBox}>
284
+ <react_native_1.Pressable onPress={handleOpenUrl} style={styles_1.default.slugLeft} hitSlop={6}>
285
+ <react_native_1.Text style={styles_1.default.slugTag}>URL ↗</react_native_1.Text>
286
+ <HighlightText_1.default text={item.url} search={searchStr} style={[styles_1.default.slugText, { color: AppColors_1.AppColors.skyBlue, textDecorationLine: 'underline' }]} highlightStyle={styles_1.default.highlight} numberOfLines={2} ellipsizeMode="middle"/>
287
+ </react_native_1.Pressable>
155
288
 
156
- <react_native_1.View style={styles_1.default.slugRight}>
157
- {isJson && (<react_native_1.View style={[
158
- styles_1.default.chip,
159
- {
160
- backgroundColor: `${AppColors_1.AppColors.darkOrange}12`,
161
- borderColor: `${AppColors_1.AppColors.darkOrange}28`,
162
- },
163
- ]}>
164
- <react_native_1.Text style={[styles_1.default.chipText, { color: AppColors_1.AppColors.darkOrange }]}>
165
- .json
166
- </react_native_1.Text>
167
- </react_native_1.View>)}
289
+ <react_native_1.View style={styles_1.default.slugRight}>
290
+ {isJson && (<react_native_1.View style={[
291
+ styles_1.default.chip,
292
+ {
293
+ backgroundColor: `${AppColors_1.AppColors.darkOrange}12`,
294
+ borderColor: `${AppColors_1.AppColors.darkOrange}28`,
295
+ },
296
+ ]}>
297
+ <react_native_1.Text style={[styles_1.default.chipText, { color: AppColors_1.AppColors.darkOrange }]}>
298
+ .json
299
+ </react_native_1.Text>
300
+ </react_native_1.View>)}
168
301
 
169
- {item.duplicateCount != null && item.duplicateCount > 1 && (<react_native_1.View style={[
170
- styles_1.default.chip,
171
- {
172
- backgroundColor: `${AppColors_1.AppColors.purple}12`,
173
- borderColor: `${AppColors_1.AppColors.purple}28`,
174
- },
175
- ]}>
176
- <react_native_1.Text style={[
177
- styles_1.default.chipText,
178
- { color: AppColors_1.AppColors.purple, fontWeight: '700' },
179
- ]}>
180
- ×{item.duplicateCount}
181
- </react_native_1.Text>
182
- </react_native_1.View>)}
183
- </react_native_1.View>
184
- </react_native_1.View>)}
302
+ {item.duplicateCount != null && item.duplicateCount > 1 && (<react_native_1.View style={[
303
+ styles_1.default.chip,
304
+ {
305
+ backgroundColor: `${AppColors_1.AppColors.purple}12`,
306
+ borderColor: `${AppColors_1.AppColors.purple}28`,
307
+ },
308
+ ]}>
309
+ <react_native_1.Text style={[
310
+ styles_1.default.chipText,
311
+ { color: AppColors_1.AppColors.purple, fontWeight: '700' },
312
+ ]}>
313
+ ×{item.duplicateCount}
314
+ </react_native_1.Text>
315
+ </react_native_1.View>)}
316
+ </react_native_1.View>
317
+ </react_native_1.View>
185
318
 
186
319
  {/* Row 3: Footer (Timestamp on Left, Response Size & Duration on Right) */}
187
320
  <react_native_1.View style={styles_1.default.cardFooterRow}>