react-native-inapp-inspector 1.1.22 → 1.1.24

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 (31) hide show
  1. package/dist/commonjs/components/AnalyticsEventCard.js +5 -2
  2. package/dist/commonjs/components/ErrorBoundary.js +17 -8
  3. package/dist/commonjs/components/Inspector/BundleTab.d.ts +1 -0
  4. package/dist/commonjs/components/Inspector/BundleTab.js +172 -48
  5. package/dist/commonjs/components/Inspector/LogDetail.js +12 -6
  6. package/dist/commonjs/components/Inspector/PerformanceTab.js +12 -12
  7. package/dist/commonjs/components/Inspector/ReduxTab.js +6 -3
  8. package/dist/commonjs/components/NetworkIcons.d.ts +12 -0
  9. package/dist/commonjs/components/NetworkIcons.js +92 -1
  10. package/dist/commonjs/components/TreeNode.js +1 -1
  11. package/dist/commonjs/constants/version.d.ts +1 -1
  12. package/dist/commonjs/constants/version.js +1 -1
  13. package/dist/commonjs/customHooks/bundleAnalyzer.d.ts +1 -1
  14. package/dist/commonjs/customHooks/bundleAnalyzer.js +95 -28
  15. package/dist/commonjs/i18n/locales/en.json +24 -22
  16. package/dist/esm/components/AnalyticsEventCard.js +5 -2
  17. package/dist/esm/components/ErrorBoundary.js +17 -8
  18. package/dist/esm/components/Inspector/BundleTab.d.ts +1 -0
  19. package/dist/esm/components/Inspector/BundleTab.js +174 -50
  20. package/dist/esm/components/Inspector/LogDetail.js +13 -7
  21. package/dist/esm/components/Inspector/PerformanceTab.js +13 -13
  22. package/dist/esm/components/Inspector/ReduxTab.js +7 -4
  23. package/dist/esm/components/NetworkIcons.d.ts +12 -0
  24. package/dist/esm/components/NetworkIcons.js +79 -0
  25. package/dist/esm/components/TreeNode.js +2 -2
  26. package/dist/esm/constants/version.d.ts +1 -1
  27. package/dist/esm/constants/version.js +1 -1
  28. package/dist/esm/customHooks/bundleAnalyzer.d.ts +1 -1
  29. package/dist/esm/customHooks/bundleAnalyzer.js +96 -29
  30. package/dist/esm/i18n/locales/en.json +24 -22
  31. package/package.json +1 -1
@@ -6,8 +6,8 @@ import CopyButton from '../CopyButton';
6
6
  import HighlightText from '../HighlightText';
7
7
  import { AppColors } from '../../styles/AppColors';
8
8
  import { AppFonts } from '../../styles/AppFonts';
9
- import { PackageIcon, SearchIcon, ClearIcon, CircleAlertIcon, LayersIcon, LiveStateIcon, StorageIcon, MetadataIcon, } from '../NetworkIcons';
10
- import Svg, { Path, Rect, Circle, Ellipse, Defs, LinearGradient, Stop, } from 'react-native-svg';
9
+ import { PackageIcon, SearchIcon, ClearIcon, CircleAlertIcon, LayersIcon, LiveStateIcon, StorageIcon, MetadataIcon, FolderIcon, FolderOpenIcon, TrashIcon, LightbulbIcon, SparkleIcon, ClockIcon, } from '../NetworkIcons';
10
+ import Svg, { Path, Rect, Circle, Ellipse, G, Defs, LinearGradient, Stop, } from 'react-native-svg';
11
11
  import { analyzeHostAppBundle, getCachedBundleAnalysis, } from '../../customHooks/bundleAnalyzer';
12
12
  // ─── High-Fidelity Vector Package & NPM Logos ────────────────────────────────
13
13
  const PackageLogoRenderer = ({ name, size = 28 }) => {
@@ -124,6 +124,77 @@ const PackageLogoRenderer = ({ name, size = 28 }) => {
124
124
  </Svg>
125
125
  </View>);
126
126
  };
127
+ const BundleCategoryIcon = ({ type, size = 16, color = AppColors.purple }) => {
128
+ const stroke = { stroke: color, strokeWidth: 1.7, strokeLinecap: 'round', strokeLinejoin: 'round' };
129
+ const renderGlyph = () => {
130
+ switch (type) {
131
+ case 'folder':
132
+ return (<G>
133
+ <Path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z" {...stroke}/>
134
+ </G>);
135
+ case 'ban':
136
+ return (<G>
137
+ <Circle cx="12" cy="12" r="8.5" {...stroke}/>
138
+ <Path d="M5.5 5.5 18.5 18.5" {...stroke}/>
139
+ </G>);
140
+ case 'bolt':
141
+ return (<G>
142
+ <Path d="M13 2 4.5 13.5 H10.5 L9 22 19.5 9.5 H13.5 Z" {...stroke}/>
143
+ </G>);
144
+ case 'source':
145
+ return (<G>
146
+ <Path d="M8.5 7 L4 12 L8.5 17" {...stroke}/>
147
+ <Path d="M15.5 7 L20 12 L15.5 17" {...stroke}/>
148
+ <Path d="M13.5 4.5 L10.5 19.5" {...stroke}/>
149
+ </G>);
150
+ case 'deps':
151
+ return (<G>
152
+ <Rect x="4" y="4" width="16" height="16" rx="2.5" {...stroke}/>
153
+ <Path d="M4 9.5 H20" {...stroke}/>
154
+ <Path d="M9.5 9.5 V20" {...stroke}/>
155
+ </G>);
156
+ case 'media':
157
+ case 'image':
158
+ return (<G>
159
+ <Rect x="3.5" y="4.5" width="17" height="15" rx="2" {...stroke}/>
160
+ <Circle cx="9" cy="10" r="1.5" {...stroke}/>
161
+ <Path d="M3.5 17.5 L9.5 12.5 L14 16.5 L17 13.5 L20.5 17.5" {...stroke}/>
162
+ </G>);
163
+ case 'overhead':
164
+ return (<G>
165
+ <Circle cx="12" cy="12" r="3.2" {...stroke}/>
166
+ <Path d="M12 2.5 V5.5 M12 18.5 V21.5 M2.5 12 H5.5 M18.5 12 H21.5 M5.3 5.3 L7.4 7.4 M16.6 16.6 L18.7 18.7 M18.7 5.3 L16.6 7.4 M7.4 16.6 L5.3 18.7" {...stroke}/>
167
+ </G>);
168
+ case 'typescript':
169
+ return (<G>
170
+ <Path d="M6.5 3.5 H14 L18.5 8 V20.5 H6.5 Z" {...stroke}/>
171
+ <Path d="M14 3.5 V8 H18.5" {...stroke}/>
172
+ <Path d="M9.5 13.5 H15 M12 13.5 V16.5 M9.5 16.5 H13" {...stroke}/>
173
+ </G>);
174
+ case 'javascript':
175
+ return (<G>
176
+ <Path d="M9.5 3.5 C7.5 3.5 7.5 6.5 7.5 9 C7.5 11 6.5 12 5 12 C6.5 12 7.5 13 7.5 15 C7.5 17.5 7.5 20.5 9.5 20.5" {...stroke}/>
177
+ <Path d="M14.5 3.5 C16.5 3.5 16.5 6.5 16.5 9 C16.5 11 17.5 12 19 12 C17.5 12 16.5 13 16.5 15 C16.5 17.5 16.5 20.5 14.5 20.5" {...stroke}/>
178
+ </G>);
179
+ case 'font':
180
+ return (<G>
181
+ <Path d="M8 19 L12 5.5 L16 19" {...stroke}/>
182
+ <Path d="M9.4 14.5 H14.6" {...stroke}/>
183
+ </G>);
184
+ case 'json':
185
+ return (<G>
186
+ <Path d="M9 3.5 C7 3.5 7 6 7 8.5 C7 10.5 6 11.5 5 12 C6 12.5 7 13.5 7 15.5 C7 18 7 20.5 9 20.5" {...stroke}/>
187
+ <Circle cx="12" cy="12" r="1.1" fill={color}/>
188
+ <Path d="M15 3.5 C17 3.5 17 6 17 8.5 C17 10.5 18 11.5 19 12 C18 12.5 17 13.5 17 15.5 C17 18 17 20.5 15 20.5" {...stroke}/>
189
+ </G>);
190
+ default:
191
+ return null;
192
+ }
193
+ };
194
+ return (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
195
+ {renderGlyph()}
196
+ </Svg>);
197
+ };
127
198
  // ─── Media File Thumbnail Component ──────────────────────────────────────────
128
199
  const MediaPreviewThumbnail = ({ file }) => {
129
200
  const [loadError, setLoadError] = useState(false);
@@ -244,7 +315,7 @@ const BundleTreeNodeView = ({ node, level, search, totalBundleKb, collapsedFolde
244
315
  {isCollapsed ? '▶' : '▼'}
245
316
  </Text>
246
317
  </View>
247
- <Text style={{ fontSize: 16 }}>{isCollapsed ? '📁' : '📂'}</Text>
318
+ {isCollapsed ? (<FolderIcon color={AppColors.amber500} size={16}/>) : (<FolderOpenIcon color={AppColors.amber500} size={16}/>)}
248
319
  <HighlightText text={node.name + '/'} search={search} style={bundleStyles.treeFolderName} highlightStyle={bundleStyles.searchHighlight}/>
249
320
  <View style={bundleStyles.treeCountBadge}>
250
321
  <Text style={bundleStyles.treeCountBadgeText}>
@@ -322,27 +393,29 @@ const BundleTreeNodeView = ({ node, level, search, totalBundleKb, collapsedFolde
322
393
  isUnused && bundleStyles.adviceUnused,
323
394
  { marginLeft: 26, marginTop: 4 },
324
395
  ]}>
325
- <Text style={[
396
+ <View style={{ flexDirection: 'row', alignItems: 'flex-start', gap: 5 }}>
397
+ {isUnused ? (<TrashIcon color={AppColors.red600} size={12}/>) : file.status === 'warning' ? (<LightbulbIcon color={AppColors.amber800Warm} size={12}/>) : (<SparkleIcon color={AppColors.emerald700} size={12}/>)}
398
+ <Text style={[
326
399
  bundleStyles.adviceText,
327
400
  file.status === 'warning' && { color: AppColors.amber800Warm },
328
401
  file.status === 'optimal' && { color: AppColors.emerald700 },
329
402
  isUnused && { color: AppColors.red600 },
330
403
  ]}>
331
- {isUnused ? '🗑️ ' : file.status === 'warning' ? '💡 ' : '✨ '}
332
- {file.advice}
333
- </Text>
404
+ {file.advice}
405
+ </Text>
406
+ </View>
334
407
  </View>)}
335
408
  </View>);
336
409
  };
337
410
  const CATEGORY_TABS = [
338
- { key: 'ALL', labelKey: 'bundle.catAll', icon: '📁' },
339
- { key: 'UNUSED', labelKey: 'bundle.catUnused', icon: '🚫' },
340
- { key: 'CONSUMED', labelKey: 'bundle.catConsumed', icon: '' },
341
- { key: 'image', labelKey: 'bundle.catImages', icon: '🖼️' },
342
- { key: 'typescript', labelKey: 'bundle.catTypescript', icon: '📜' },
343
- { key: 'javascript', labelKey: 'bundle.catJavascript', icon: '⚙️' },
344
- { key: 'font', labelKey: 'bundle.catFonts', icon: '🔤' },
345
- { key: 'json', labelKey: 'bundle.catJson', icon: '📄' },
411
+ { key: 'ALL', labelKey: 'bundle.catAll', iconType: 'folder' },
412
+ { key: 'UNUSED', labelKey: 'bundle.catUnused', iconType: 'ban' },
413
+ { key: 'CONSUMED', labelKey: 'bundle.catConsumed', iconType: 'bolt' },
414
+ { key: 'image', labelKey: 'bundle.catImages', iconType: 'image' },
415
+ { key: 'typescript', labelKey: 'bundle.catTypescript', iconType: 'typescript' },
416
+ { key: 'javascript', labelKey: 'bundle.catJavascript', iconType: 'javascript' },
417
+ { key: 'font', labelKey: 'bundle.catFonts', iconType: 'font' },
418
+ { key: 'json', labelKey: 'bundle.catJson', iconType: 'json' },
346
419
  ];
347
420
  const CATEGORY_COLORS = {
348
421
  image: { label: 'Images & Media', color: AppColors.pink500, bg: AppColors.pink100 },
@@ -651,6 +724,21 @@ const BundleTab = React.memo(() => {
651
724
  </View>
652
725
  </View>
653
726
 
727
+ {/* Live analysis unavailable warning */}
728
+ {analysis && !analysis.isLive && (<View style={bundleStyles.liveWarningCard}>
729
+ <View style={{ flexDirection: 'row', alignItems: 'center', gap: 6, flex: 1 }}>
730
+ <CircleAlertIcon color={AppColors.amber700} size={16}/>
731
+ <View style={{ flex: 1 }}>
732
+ <Text style={bundleStyles.liveWarningTitle}>
733
+ {t('bundle.liveAnalysisUnavailable')}
734
+ </Text>
735
+ <Text style={bundleStyles.liveWarningDesc}>
736
+ {t('bundle.liveAnalysisUnavailableSub')}
737
+ </Text>
738
+ </View>
739
+ </View>
740
+ </View>)}
741
+
654
742
  {/* Development Bundle Split-Up (derived from the real running bundle) */}
655
743
  {analysis && (<View style={bundleStyles.sectionCard}>
656
744
  <View style={bundleStyles.sectionHeaderRow}>
@@ -669,28 +757,32 @@ const BundleTab = React.memo(() => {
669
757
 
670
758
  {[
671
759
  {
760
+ iconType: 'source',
672
761
  label: t('bundle.splitAppSource'),
673
762
  color: AppColors.sky500,
674
763
  ...analysis.splitUp.appSource,
675
764
  },
676
765
  {
766
+ iconType: 'deps',
677
767
  label: t('bundle.splitNodeModules'),
678
768
  color: AppColors.indigo500,
679
769
  ...analysis.splitUp.nodeModules,
680
770
  },
681
771
  {
772
+ iconType: 'media',
682
773
  label: t('bundle.splitAssetsMedia'),
683
774
  color: AppColors.pink500,
684
775
  ...analysis.splitUp.assetsMedia,
685
776
  },
686
777
  {
778
+ iconType: 'overhead',
687
779
  label: t('bundle.splitMetroOverhead'),
688
780
  color: AppColors.amber500,
689
781
  ...analysis.splitUp.metroDevOverhead,
690
782
  },
691
783
  ].map((part, idx) => (<View key={idx} style={bundleStyles.catRowCard}>
692
784
  <View style={bundleStyles.catRowTop}>
693
- <Text style={bundleStyles.catRowIcon}>{['📦', '🧩', '🖼️', '⚙️'][idx]}</Text>
785
+ <BundleCategoryIcon type={part.iconType} size={18} color={part.color}/>
694
786
  <View style={{ flex: 1 }}>
695
787
  <Text style={bundleStyles.catRowTitle}>{part.label}</Text>
696
788
  <Text style={bundleStyles.catRowDesc}>
@@ -767,7 +859,7 @@ const BundleTab = React.memo(() => {
767
859
  {/* Legend Grid */}
768
860
  <View style={bundleStyles.legendGrid}>
769
861
  <View style={bundleStyles.legendItem}>
770
- <View style={[bundleStyles.legendDot, { backgroundColor: AppColors.pink500 }]}/>
862
+ <BundleCategoryIcon type="image" size={13} color={AppColors.pink500}/>
771
863
  <Text style={bundleStyles.legendText}>
772
864
  {t('bundle.legendImages')}{' '}
773
865
  <Text style={bundleStyles.legendVal}>
@@ -776,7 +868,7 @@ const BundleTab = React.memo(() => {
776
868
  </Text>
777
869
  </View>
778
870
  <View style={bundleStyles.legendItem}>
779
- <View style={[bundleStyles.legendDot, { backgroundColor: AppColors.sky500 }]}/>
871
+ <BundleCategoryIcon type="typescript" size={13} color={AppColors.sky500}/>
780
872
  <Text style={bundleStyles.legendText}>
781
873
  {t('bundle.legendTs')}{' '}
782
874
  <Text style={bundleStyles.legendVal}>
@@ -785,7 +877,7 @@ const BundleTab = React.memo(() => {
785
877
  </Text>
786
878
  </View>
787
879
  <View style={bundleStyles.legendItem}>
788
- <View style={[bundleStyles.legendDot, { backgroundColor: AppColors.indigo500 }]}/>
880
+ <BundleCategoryIcon type="javascript" size={13} color={AppColors.indigo500}/>
789
881
  <Text style={bundleStyles.legendText}>
790
882
  {t('bundle.legendJs')}{' '}
791
883
  <Text style={bundleStyles.legendVal}>
@@ -794,7 +886,7 @@ const BundleTab = React.memo(() => {
794
886
  </Text>
795
887
  </View>
796
888
  <View style={bundleStyles.legendItem}>
797
- <View style={[bundleStyles.legendDot, { backgroundColor: AppColors.purple500 }]}/>
889
+ <BundleCategoryIcon type="font" size={13} color={AppColors.purple500}/>
798
890
  <Text style={bundleStyles.legendText}>
799
891
  {t('bundle.legendFonts')}{' '}
800
892
  <Text style={bundleStyles.legendVal}>
@@ -803,7 +895,7 @@ const BundleTab = React.memo(() => {
803
895
  </Text>
804
896
  </View>
805
897
  <View style={bundleStyles.legendItem}>
806
- <View style={[bundleStyles.legendDot, { backgroundColor: AppColors.emerald500 }]}/>
898
+ <BundleCategoryIcon type="json" size={13} color={AppColors.emerald500}/>
807
899
  <Text style={bundleStyles.legendText}>
808
900
  {t('bundle.legendJson')}{' '}
809
901
  <Text style={bundleStyles.legendVal}>
@@ -833,7 +925,7 @@ const BundleTab = React.memo(() => {
833
925
 
834
926
  {[
835
927
  {
836
- icon: '🖼️',
928
+ iconType: 'image',
837
929
  title: t('bundle.catImagesTitle'),
838
930
  count: summary.images.count,
839
931
  size: t('bundle.fileSizeKb', { size: summary.images.kb }),
@@ -842,7 +934,7 @@ const BundleTab = React.memo(() => {
842
934
  desc: t('bundle.catImagesDesc'),
843
935
  },
844
936
  {
845
- icon: '⚙️',
937
+ iconType: 'javascript',
846
938
  title: t('bundle.catJsTitle'),
847
939
  count: summary.js.count,
848
940
  size: t('bundle.fileSizeKb', { size: summary.js.kb }),
@@ -851,7 +943,7 @@ const BundleTab = React.memo(() => {
851
943
  desc: t('bundle.catJsDesc'),
852
944
  },
853
945
  {
854
- icon: '🔤',
946
+ iconType: 'font',
855
947
  title: t('bundle.catFontsTitle'),
856
948
  count: summary.fonts.count,
857
949
  size: t('bundle.fileSizeKb', { size: summary.fonts.kb }),
@@ -863,7 +955,7 @@ const BundleTab = React.memo(() => {
863
955
  .join(', ') || t('bundle.catFontsDesc'),
864
956
  },
865
957
  {
866
- icon: '📜',
958
+ iconType: 'typescript',
867
959
  title: t('bundle.catTsTitle'),
868
960
  count: summary.ts.count,
869
961
  size: t('bundle.fileSizeKb', { size: summary.ts.kb }),
@@ -872,7 +964,7 @@ const BundleTab = React.memo(() => {
872
964
  desc: t('bundle.catTsDesc'),
873
965
  },
874
966
  {
875
- icon: '📄',
967
+ iconType: 'json',
876
968
  title: t('bundle.catJsonTitle'),
877
969
  count: summary.json.count,
878
970
  size: t('bundle.fileSizeKb', { size: summary.json.kb }),
@@ -882,7 +974,7 @@ const BundleTab = React.memo(() => {
882
974
  },
883
975
  ].map((cat, cIdx) => (<View key={cIdx} style={bundleStyles.catRowCard}>
884
976
  <View style={bundleStyles.catRowTop}>
885
- <Text style={bundleStyles.catRowIcon}>{cat.icon}</Text>
977
+ <BundleCategoryIcon type={cat.iconType} size={18} color={cat.color}/>
886
978
  <View style={{ flex: 1 }}>
887
979
  <Text style={bundleStyles.catRowTitle}>{cat.title}</Text>
888
980
  <Text style={bundleStyles.catRowDesc}>
@@ -962,7 +1054,7 @@ const BundleTab = React.memo(() => {
962
1054
  tab.key === 'UNUSED' && isActive && { backgroundColor: AppColors.red500, borderColor: AppColors.red600 },
963
1055
  tab.key === 'CONSUMED' && isActive && { backgroundColor: AppColors.emerald600, borderColor: AppColors.emerald700 },
964
1056
  ]}>
965
- <Text style={bundleStyles.catPillIcon}>{tab.icon}</Text>
1057
+ <BundleCategoryIcon type={tab.iconType} size={12} color={isActive ? AppColors.white : AppColors.grayTextStrong}/>
966
1058
  <Text style={[
967
1059
  bundleStyles.catPillText,
968
1060
  isActive && bundleStyles.catPillTextActive,
@@ -1080,15 +1172,17 @@ const BundleTab = React.memo(() => {
1080
1172
  file.status === 'optimal' && bundleStyles.adviceOptimal,
1081
1173
  isUnused && bundleStyles.adviceUnused,
1082
1174
  ]}>
1175
+ <View style={{ flexDirection: 'row', alignItems: 'flex-start', gap: 5 }}>
1176
+ {isUnused ? (<TrashIcon color={AppColors.red600} size={12}/>) : file.status === 'warning' ? (<LightbulbIcon color={AppColors.amber800Warm} size={12}/>) : (<SparkleIcon color={AppColors.emerald700} size={12}/>)}
1083
1177
  <Text style={[
1084
1178
  bundleStyles.adviceText,
1085
1179
  file.status === 'warning' && { color: AppColors.amber800Warm },
1086
1180
  file.status === 'optimal' && { color: AppColors.emerald700 },
1087
1181
  isUnused && { color: AppColors.red600 },
1088
1182
  ]}>
1089
- {isUnused ? '🗑️ ' : file.status === 'warning' ? '💡 ' : '✨ '}
1090
1183
  {file.advice}
1091
1184
  </Text>
1185
+ </View>
1092
1186
  </View>)}
1093
1187
  </View>
1094
1188
  </View>);
@@ -1205,9 +1299,12 @@ const BundleTab = React.memo(() => {
1205
1299
 
1206
1300
  {/* Deprecation Warning Banner if deprecated */}
1207
1301
  {pkg.isDeprecated && pkg.deprecationReason && (<View style={bundleStyles.deprecationBox}>
1208
- <Text style={bundleStyles.deprecationText}>
1209
- ⚠️ {pkg.deprecationReason}
1210
- </Text>
1302
+ <View style={{ flexDirection: 'row', alignItems: 'center', gap: 5 }}>
1303
+ <CircleAlertIcon color={AppColors.errorColor} size={12}/>
1304
+ <Text style={bundleStyles.deprecationText}>
1305
+ {pkg.deprecationReason}
1306
+ </Text>
1307
+ </View>
1211
1308
  </View>)}
1212
1309
 
1213
1310
  <View style={bundleStyles.fileProgressTrack}>
@@ -1225,9 +1322,12 @@ const BundleTab = React.memo(() => {
1225
1322
  {pkg.type === 'direct' ? t('bundle.direct') : t('bundle.transitive')}
1226
1323
  </Text>
1227
1324
  </View>
1228
- {pkg.lastActive && (<Text style={bundleStyles.lastActiveText}>
1229
- 🕒 {pkg.lastActive}
1230
- </Text>)}
1325
+ {pkg.lastActive && (<View style={{ flexDirection: 'row', alignItems: 'center', gap: 4 }}>
1326
+ <ClockIcon color={AppColors.grayTextWeak} size={11}/>
1327
+ <Text style={bundleStyles.lastActiveText}>
1328
+ {pkg.lastActive}
1329
+ </Text>
1330
+ </View>)}
1231
1331
  </View>
1232
1332
 
1233
1333
  <View style={{ flexDirection: 'row', alignItems: 'center', gap: 8 }}>
@@ -1324,14 +1424,16 @@ const BundleTab = React.memo(() => {
1324
1424
  file.status === 'warning' && bundleStyles.adviceWarning,
1325
1425
  file.status === 'optimal' && bundleStyles.adviceOptimal,
1326
1426
  ]}>
1327
- <Text style={[
1427
+ <View style={{ flexDirection: 'row', alignItems: 'flex-start', gap: 5 }}>
1428
+ {file.status === 'warning' ? (<LightbulbIcon color={AppColors.amber800Warm} size={12}/>) : (<SparkleIcon color={AppColors.emerald700} size={12}/>)}
1429
+ <Text style={[
1328
1430
  bundleStyles.adviceText,
1329
1431
  file.status === 'warning' && { color: AppColors.amber800Warm },
1330
1432
  file.status === 'optimal' && { color: AppColors.emerald700 },
1331
1433
  ]}>
1332
- {file.status === 'warning' ? '💡 ' : '✨ '}
1333
- {file.advice}
1334
- </Text>
1434
+ {file.advice}
1435
+ </Text>
1436
+ </View>
1335
1437
  </View>)}
1336
1438
  </View>
1337
1439
  </View>))}
@@ -1376,12 +1478,16 @@ const BundleTab = React.memo(() => {
1376
1478
 
1377
1479
  {[
1378
1480
  {
1481
+ iconType: 'image',
1482
+ iconColor: AppColors.pink500,
1379
1483
  title: t('bundle.optTip1Title'),
1380
1484
  desc: t('bundle.optTip1Desc'),
1381
1485
  badge: t('bundle.highImpact'),
1382
1486
  badgeColor: AppColors.pink500,
1383
1487
  },
1384
1488
  {
1489
+ iconType: 'bolt',
1490
+ iconColor: isHermes ? AppColors.emerald500 : AppColors.amber500,
1385
1491
  title: t('bundle.optTip2Title'),
1386
1492
  desc: isHermes
1387
1493
  ? t('bundle.optTip2DescActive')
@@ -1390,18 +1496,24 @@ const BundleTab = React.memo(() => {
1390
1496
  badgeColor: isHermes ? AppColors.emerald500 : AppColors.amber500,
1391
1497
  },
1392
1498
  {
1499
+ iconType: 'font',
1500
+ iconColor: AppColors.purple500,
1393
1501
  title: t('bundle.optTip3Title'),
1394
1502
  desc: t('bundle.optTip3Desc'),
1395
1503
  badge: t('bundle.mediumImpact'),
1396
1504
  badgeColor: AppColors.purple500,
1397
1505
  },
1398
1506
  {
1507
+ iconType: 'source',
1508
+ iconColor: AppColors.sky500,
1399
1509
  title: t('bundle.optTip4Title'),
1400
1510
  desc: t('bundle.optTip4Desc'),
1401
1511
  badge: t('bundle.bestPractice'),
1402
1512
  badgeColor: AppColors.sky500,
1403
1513
  },
1404
1514
  {
1515
+ iconType: 'overhead',
1516
+ iconColor: AppColors.indigo500,
1405
1517
  title: t('bundle.optTip5Title'),
1406
1518
  desc: t('bundle.optTip5Desc'),
1407
1519
  badge: t('bundle.bestPractice'),
@@ -1413,6 +1525,7 @@ const BundleTab = React.memo(() => {
1413
1525
  <View style={bundleStyles.sNoBadge}>
1414
1526
  <Text style={bundleStyles.sNoText}>#{tIdx + 1}</Text>
1415
1527
  </View>
1528
+ <BundleCategoryIcon type={tip.iconType} size={14} color={tip.iconColor}/>
1416
1529
  <Text style={bundleStyles.tipTitle}>{tip.title}</Text>
1417
1530
  </View>
1418
1531
  <View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
@@ -1612,11 +1725,6 @@ const bundleStyles = StyleSheet.create({
1612
1725
  gap: 5,
1613
1726
  minWidth: '45%',
1614
1727
  },
1615
- legendDot: {
1616
- width: 8,
1617
- height: 8,
1618
- borderRadius: 4,
1619
- },
1620
1728
  legendText: {
1621
1729
  fontFamily: AppFonts.interMedium,
1622
1730
  fontSize: 11,
@@ -1640,9 +1748,6 @@ const bundleStyles = StyleSheet.create({
1640
1748
  gap: 8,
1641
1749
  marginBottom: 8,
1642
1750
  },
1643
- catRowIcon: {
1644
- fontSize: 16,
1645
- },
1646
1751
  catRowTitle: {
1647
1752
  fontFamily: AppFonts.interBold,
1648
1753
  fontSize: 12,
@@ -1718,9 +1823,6 @@ const bundleStyles = StyleSheet.create({
1718
1823
  backgroundColor: AppColors.brandPurple,
1719
1824
  borderColor: AppColors.brandPurple,
1720
1825
  },
1721
- catPillIcon: {
1722
- fontSize: 11,
1723
- },
1724
1826
  catPillText: {
1725
1827
  fontFamily: AppFonts.interMedium,
1726
1828
  fontSize: 11,
@@ -2108,6 +2210,28 @@ const bundleStyles = StyleSheet.create({
2108
2210
  borderWidth: 1,
2109
2211
  borderColor: AppColors.errorBorder,
2110
2212
  },
2213
+ liveWarningCard: {
2214
+ flexDirection: 'row',
2215
+ alignItems: 'center',
2216
+ backgroundColor: AppColors.amber100,
2217
+ borderWidth: 1,
2218
+ borderColor: AppColors.amber200,
2219
+ borderRadius: 10,
2220
+ padding: 12,
2221
+ marginBottom: 12,
2222
+ },
2223
+ liveWarningTitle: {
2224
+ fontFamily: AppFonts.interBold,
2225
+ fontSize: 12,
2226
+ color: AppColors.amber800Warm,
2227
+ marginBottom: 2,
2228
+ },
2229
+ liveWarningDesc: {
2230
+ fontFamily: AppFonts.interRegular,
2231
+ fontSize: 10.5,
2232
+ lineHeight: 14,
2233
+ color: AppColors.amber800Warm,
2234
+ },
2111
2235
  adviceBadge: {
2112
2236
  paddingHorizontal: 8,
2113
2237
  paddingVertical: 4,
@@ -6,7 +6,7 @@ import HighlightText from '../HighlightText';
6
6
  import JsonViewer from '../JsonViewer';
7
7
  import CopyButton from '../CopyButton';
8
8
  import SegmentedTabs from '../SegmentedTabs';
9
- import { ClearIcon, SearchIcon, PrettyIcon, RawIcon, TableIcon, LayersIcon, TerminalIcon, RequestIcon, InfoCircleIcon, } from '../NetworkIcons';
9
+ import { ClearIcon, SearchIcon, PrettyIcon, RawIcon, TableIcon, LayersIcon, TerminalIcon, RequestIcon, InfoCircleIcon, DocIcon, } from '../NetworkIcons';
10
10
  import { AppColors } from '../../styles/AppColors';
11
11
  import { AppFonts } from '../../styles/AppFonts';
12
12
  import styles from '../../styles';
@@ -268,14 +268,17 @@ const LogDetail = React.memo(() => {
268
268
  paddingVertical: 2,
269
269
  },
270
270
  ]}>
271
- <Text style={[
271
+ <View style={{ flexDirection: 'row', alignItems: 'center', gap: 3 }}>
272
+ <DocIcon color={AppColors.brandPurple} size={10}/>
273
+ <Text style={[
272
274
  styles.metaChipText,
273
275
  { color: AppColors.brandPurple, fontSize: 10, fontFamily: AppFonts.interBold },
274
276
  ]}>
275
- 📄 {originFrame.fileName}
276
- {originFrame.lineNumber ? `:${originFrame.lineNumber}` : ''}
277
- {originFrame.columnNumber ? `:${originFrame.columnNumber}` : ''}
278
- </Text>
277
+ {originFrame.fileName}
278
+ {originFrame.lineNumber ? `:${originFrame.lineNumber}` : ''}
279
+ {originFrame.columnNumber ? `:${originFrame.columnNumber}` : ''}
280
+ </Text>
281
+ </View>
279
282
  </View>)}
280
283
  </View>
281
284
 
@@ -711,6 +714,8 @@ const LogDetail = React.memo(() => {
711
714
  {frame.fileExt.toUpperCase()}
712
715
  </Text>
713
716
  </View>)}
717
+ <View style={{ flexDirection: 'row', alignItems: 'center', gap: 3 }}>
718
+ <DocIcon color={isTopFrame ? AppColors.brandPurple : AppColors.grayTextWeak} size={10}/>
714
719
  <Text style={{
715
720
  fontFamily: AppFonts.interMedium,
716
721
  fontSize: 10.5,
@@ -718,9 +723,10 @@ const LogDetail = React.memo(() => {
718
723
  ? AppColors.brandPurple
719
724
  : AppColors.grayTextWeak,
720
725
  }}>
721
- 📄 {frame.fileName}
726
+ {frame.fileName}
722
727
  </Text>
723
728
  </View>
729
+ </View>
724
730
 
725
731
  {/* Full path */}
726
732
  {frame.fullPath && frame.fullPath !== frame.fileName && (<Text selectable style={{
@@ -8,7 +8,7 @@ import { AppColors } from '../../styles/AppColors';
8
8
  import { AppFonts } from '../../styles/AppFonts';
9
9
  import { useTranslation } from '../../i18n';
10
10
  import { getRuntimeDiagnostics } from '../../helpers';
11
- import { SearchIcon, CircleXIcon, PerformanceIcon } from '../NetworkIcons';
11
+ import { SearchIcon, CircleXIcon, PerformanceIcon, BoltIcon, LightbulbIcon, WarningTriangleIcon, MapIcon, AtomIcon, BrainIcon, GlobeIcon, } from '../NetworkIcons';
12
12
  const PerformanceTab = React.memo(() => {
13
13
  const { t } = useTranslation();
14
14
  // ─── Real-Time FPS Tracking ────────────────────────────────────────────────
@@ -257,35 +257,35 @@ const PerformanceTab = React.memo(() => {
257
257
  <View style={perfStyles.filterRow}>
258
258
  <ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={{ gap: 6, paddingHorizontal: 12, paddingVertical: 4 }}>
259
259
  {[
260
- { key: 'ALL', label: t('performance.allLogs'), icon: '⚡', count: events.length },
260
+ { key: 'ALL', label: t('performance.allLogs'), Icon: BoltIcon, count: events.length },
261
261
  {
262
262
  key: 'JANKY',
263
263
  label: t('performance.jankySlow'),
264
- icon: '⚠️',
264
+ Icon: WarningTriangleIcon,
265
265
  count: events.filter(e => e.severity === 'warning' || e.severity === 'critical').length,
266
266
  },
267
267
  {
268
268
  key: 'NAVIGATION',
269
269
  label: t('performance.navigation'),
270
- icon: '🗺️',
270
+ Icon: MapIcon,
271
271
  count: events.filter(e => e.category === 'navigation').length,
272
272
  },
273
273
  {
274
274
  key: 'RENDER',
275
275
  label: t('performance.components'),
276
- icon: '⚛️',
276
+ Icon: AtomIcon,
277
277
  count: events.filter(e => e.category === 'render').length,
278
278
  },
279
279
  {
280
280
  key: 'MEMORY',
281
281
  label: t('performance.memoryGc'),
282
- icon: '🧠',
282
+ Icon: BrainIcon,
283
283
  count: events.filter(e => e.category === 'memory').length,
284
284
  },
285
285
  {
286
286
  key: 'IO',
287
287
  label: t('performance.networkIo'),
288
- icon: '🌐',
288
+ Icon: GlobeIcon,
289
289
  count: events.filter(e => e.category === 'io' || e.category === 'bridge').length,
290
290
  },
291
291
  ].map(tab => {
@@ -294,7 +294,7 @@ const PerformanceTab = React.memo(() => {
294
294
  perfStyles.filterPill,
295
295
  isActive && perfStyles.filterPillActive,
296
296
  ]}>
297
- <Text style={perfStyles.filterPillIcon}>{tab.icon}</Text>
297
+ <tab.Icon color={isActive ? AppColors.white : AppColors.grayTextStrong} size={12}/>
298
298
  <Text style={[
299
299
  perfStyles.filterPillText,
300
300
  isActive && perfStyles.filterPillTextActive,
@@ -487,7 +487,7 @@ const PerformanceTab = React.memo(() => {
487
487
  </View>
488
488
 
489
489
  {filteredEvents.length === 0 ? (<View style={perfStyles.emptyCard}>
490
- <Text style={{ fontSize: 28 }}>⚡</Text>
490
+ <BoltIcon color={AppColors.amber500} size={30}/>
491
491
  <Text style={perfStyles.emptyTitle}>{t('performance.emptyTitle')}</Text>
492
492
  <Text style={perfStyles.emptySub}>
493
493
  {t('performance.emptySubtitle')}
@@ -574,7 +574,10 @@ const PerformanceTab = React.memo(() => {
574
574
 
575
575
  {/* Actionable Optimization Tip */}
576
576
  {event.advice && (<View style={perfStyles.adviceCard}>
577
- <Text style={perfStyles.adviceHeading}>💡 {t('performance.optimizationTip')}</Text>
577
+ <View style={{ flexDirection: 'row', alignItems: 'center', gap: 5 }}>
578
+ <LightbulbIcon color={AppColors.purpleShade700} size={12}/>
579
+ <Text style={perfStyles.adviceHeading}>{t('performance.optimizationTip')}</Text>
580
+ </View>
578
581
  <Text style={perfStyles.adviceBodyText}>{event.advice}</Text>
579
582
  </View>)}
580
583
  </View>)}
@@ -665,9 +668,6 @@ const perfStyles = StyleSheet.create({
665
668
  backgroundColor: AppColors.brandPurple,
666
669
  borderColor: AppColors.brandPurple,
667
670
  },
668
- filterPillIcon: {
669
- fontSize: 11,
670
- },
671
671
  filterPillText: {
672
672
  fontFamily: AppFonts.interMedium,
673
673
  fontSize: 11,
@@ -10,7 +10,7 @@ import { getSize } from '../../helpers';
10
10
  import styles from '../../styles';
11
11
  import { AppColors } from '../../styles/AppColors';
12
12
  import { AppFonts } from '../../styles/AppFonts';
13
- import { TerminalIcon, SearchIcon, ClearIcon, ClockIcon, ForwardChevronIcon, SortArrowIcon, } from '../NetworkIcons';
13
+ import { TerminalIcon, SearchIcon, ClearIcon, ClockIcon, ForwardChevronIcon, SortArrowIcon, BoltIcon, TextAaIcon, } from '../NetworkIcons';
14
14
  const ReduxTab = React.memo(() => {
15
15
  const { reduxState, reduxLastActionMap, reduxSearch, setReduxSearch, setSelectedReduxSlice, } = useInspector();
16
16
  // Sort mode: 'latest' (newest updated first) vs 'alpha' (A-Z)
@@ -183,9 +183,12 @@ const ReduxTab = React.memo(() => {
183
183
  <Text style={reduxTabStyles.resultCount}>
184
184
  Showing {filteredSlices.length} of {sliceItems.length} state slices
185
185
  </Text>
186
- <Text style={reduxTabStyles.sortLabel}>
187
- {sortMode === 'latest' ? '⚡ Newest Updates First' : '🔤 Alphabetical (A-Z)'}
188
- </Text>
186
+ <View style={{ flexDirection: 'row', alignItems: 'center', gap: 4 }}>
187
+ {sortMode === 'latest' ? (<BoltIcon color={AppColors.brandPurple} size={11}/>) : (<TextAaIcon color={AppColors.brandPurple} size={11}/>)}
188
+ <Text style={reduxTabStyles.sortLabel}>
189
+ {sortMode === 'latest' ? 'Newest Updates First' : 'Alphabetical (A-Z)'}
190
+ </Text>
191
+ </View>
189
192
  </View>
190
193
  </View>
191
194