react-native-inapp-inspector 2.2.3 → 2.2.5

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 (93) hide show
  1. package/dist/commonjs/components/AnalyticsDetail.js +5 -1
  2. package/dist/commonjs/components/AnalyticsEventCard.js +2 -1
  3. package/dist/commonjs/components/BrandSquareIcon.js +51 -117
  4. package/dist/commonjs/components/DiffViewer.js +1 -1
  5. package/dist/commonjs/components/Inspector/BundleTab.js +22 -0
  6. package/dist/commonjs/components/Inspector/DeviceInfoTab.d.ts +3 -0
  7. package/dist/commonjs/components/Inspector/DeviceInfoTab.js +835 -0
  8. package/dist/commonjs/components/Inspector/InspectorHeader.js +12 -14
  9. package/dist/commonjs/components/Inspector/LogDetail.js +6 -3
  10. package/dist/commonjs/components/Inspector/MainScreen.js +7 -3
  11. package/dist/commonjs/components/Inspector/NetworkTab.js +92 -15
  12. package/dist/commonjs/components/Inspector/PerformanceTab.js +38 -12
  13. package/dist/commonjs/components/Inspector/SettingsPanel.js +440 -229
  14. package/dist/commonjs/components/Inspector/StorageTab.d.ts +3 -0
  15. package/dist/commonjs/components/Inspector/StorageTab.js +892 -0
  16. package/dist/commonjs/components/Inspector/TabBar.js +14 -0
  17. package/dist/commonjs/components/Inspector/TelemetryConsentModal.js +12 -18
  18. package/dist/commonjs/components/Inspector/UpdateAvailableModal.js +4 -1
  19. package/dist/commonjs/components/NetworkIcons.d.ts +6 -0
  20. package/dist/commonjs/components/NetworkIcons.js +30 -1
  21. package/dist/commonjs/constants/version.d.ts +1 -1
  22. package/dist/commonjs/constants/version.js +1 -1
  23. package/dist/commonjs/customHooks/bundleAnalyzer.js +44 -22
  24. package/dist/commonjs/customHooks/storageInspector.d.ts +67 -0
  25. package/dist/commonjs/customHooks/storageInspector.js +486 -0
  26. package/dist/commonjs/i18n/locales/en.json +8 -2
  27. package/dist/commonjs/index.d.ts +1 -0
  28. package/dist/commonjs/index.js +16 -1
  29. package/dist/commonjs/native/NativeInspector.js +50 -26
  30. package/dist/commonjs/storage.d.ts +5 -0
  31. package/dist/commonjs/storage.js +18 -0
  32. package/dist/commonjs/types/enums.d.ts +5 -0
  33. package/dist/commonjs/types/enums.js +5 -0
  34. package/dist/esm/components/AnalyticsDetail.js +6 -2
  35. package/dist/esm/components/AnalyticsEventCard.js +2 -1
  36. package/dist/esm/components/BrandSquareIcon.js +52 -118
  37. package/dist/esm/components/DiffViewer.js +1 -1
  38. package/dist/esm/components/Inspector/BundleTab.js +22 -0
  39. package/dist/esm/components/Inspector/DeviceInfoTab.d.ts +3 -0
  40. package/dist/esm/components/Inspector/DeviceInfoTab.js +796 -0
  41. package/dist/esm/components/Inspector/InspectorHeader.js +13 -15
  42. package/dist/esm/components/Inspector/LogDetail.js +7 -4
  43. package/dist/esm/components/Inspector/MainScreen.js +7 -3
  44. package/dist/esm/components/Inspector/NetworkTab.js +93 -16
  45. package/dist/esm/components/Inspector/PerformanceTab.js +39 -13
  46. package/dist/esm/components/Inspector/SettingsPanel.js +441 -230
  47. package/dist/esm/components/Inspector/StorageTab.d.ts +3 -0
  48. package/dist/esm/components/Inspector/StorageTab.js +853 -0
  49. package/dist/esm/components/Inspector/TabBar.js +15 -1
  50. package/dist/esm/components/Inspector/TelemetryConsentModal.js +12 -18
  51. package/dist/esm/components/Inspector/UpdateAvailableModal.js +4 -1
  52. package/dist/esm/components/NetworkIcons.d.ts +6 -0
  53. package/dist/esm/components/NetworkIcons.js +23 -0
  54. package/dist/esm/constants/version.d.ts +1 -1
  55. package/dist/esm/constants/version.js +1 -1
  56. package/dist/esm/customHooks/bundleAnalyzer.js +44 -22
  57. package/dist/esm/customHooks/storageInspector.d.ts +67 -0
  58. package/dist/esm/customHooks/storageInspector.js +469 -0
  59. package/dist/esm/i18n/locales/en.json +8 -2
  60. package/dist/esm/index.d.ts +1 -0
  61. package/dist/esm/index.js +5 -0
  62. package/dist/esm/native/NativeInspector.js +51 -27
  63. package/dist/esm/storage.d.ts +5 -0
  64. package/dist/esm/storage.js +5 -0
  65. package/dist/esm/types/enums.d.ts +5 -0
  66. package/dist/esm/types/enums.js +5 -0
  67. package/ios/NetworkInspectorModule.mm +34 -19
  68. package/package.json +8 -1
  69. package/src/components/AnalyticsDetail.tsx +6 -1
  70. package/src/components/AnalyticsEventCard.tsx +2 -1
  71. package/src/components/BrandSquareIcon.tsx +109 -118
  72. package/src/components/DiffViewer.tsx +1 -1
  73. package/src/components/Inspector/BundleTab.tsx +29 -0
  74. package/src/components/Inspector/DeviceInfoTab.tsx +1204 -0
  75. package/src/components/Inspector/InspectorHeader.tsx +13 -14
  76. package/src/components/Inspector/LogDetail.tsx +15 -11
  77. package/src/components/Inspector/MainScreen.tsx +7 -3
  78. package/src/components/Inspector/NetworkTab.tsx +104 -16
  79. package/src/components/Inspector/PerformanceTab.tsx +46 -12
  80. package/src/components/Inspector/SettingsPanel.tsx +570 -304
  81. package/src/components/Inspector/StorageTab.tsx +1048 -0
  82. package/src/components/Inspector/TabBar.tsx +20 -0
  83. package/src/components/Inspector/TelemetryConsentModal.tsx +17 -52
  84. package/src/components/Inspector/UpdateAvailableModal.tsx +13 -1
  85. package/src/components/NetworkIcons.tsx +103 -0
  86. package/src/constants/version.ts +1 -1
  87. package/src/customHooks/bundleAnalyzer.ts +47 -22
  88. package/src/customHooks/storageInspector.ts +509 -0
  89. package/src/i18n/locales/en.json +8 -2
  90. package/src/index.tsx +21 -1
  91. package/src/native/NativeInspector.ts +56 -24
  92. package/src/storage.ts +18 -0
  93. package/src/types/enums.ts +5 -0
@@ -408,12 +408,28 @@ RCT_EXPORT_MODULE(NetworkInspectorModule);
408
408
  return YES;
409
409
  }
410
410
 
411
- - (void)handleMotionShakeNotification:(NSNotification *)notification {
412
- if (hasListeners) {
413
- [self sendEventWithName:@"onDeviceShake" body:@{}];
411
+ - (void)safeSendEvent:(NSString *)eventName body:(id)body {
412
+ if (!hasListeners) return;
413
+ @try {
414
+ if (self.bridge != nil) {
415
+ [self sendEventWithName:eventName body:body];
416
+ } else if ([self respondsToSelector:@selector(callableJSModules)]) {
417
+ id callable = [self valueForKey:@"callableJSModules"];
418
+ if (callable && [callable respondsToSelector:@selector(invokeExpectedMethod:method:args:)]) {
419
+ [callable invokeExpectedMethod:@"RCTDeviceEventEmitter"
420
+ method:@"emit"
421
+ args:body ? @[eventName, body] : @[eventName]];
422
+ }
423
+ }
424
+ } @catch (NSException *ex) {
425
+ NSLog(@"[InAppInspector] Safe sendEvent error: %@", ex.reason);
414
426
  }
415
427
  }
416
428
 
429
+ - (void)handleMotionShakeNotification:(NSNotification *)notification {
430
+ [self safeSendEvent:@"onDeviceShake" body:@{}];
431
+ }
432
+
417
433
  - (void)startObserving {
418
434
  hasListeners = YES;
419
435
  }
@@ -445,15 +461,13 @@ RCT_EXPORT_MODULE(NetworkInspectorModule);
445
461
  }
446
462
 
447
463
  - (void)emitCrashEventWithMessage:(NSString *)message stackTrace:(NSString *)stackTrace {
448
- if (hasListeners) {
449
- [self sendEventWithName:@"onNativeCrash"
450
- body:@{
451
- @"platform": @"ios",
452
- @"message": message ?: @"Unknown iOS Native Exception",
453
- @"stack": stackTrace ?: @"",
454
- @"timestamp": @([[NSDate date] timeIntervalSince1970] * 1000)
455
- }];
456
- }
464
+ [self safeSendEvent:@"onNativeCrash"
465
+ body:@{
466
+ @"platform": @"ios",
467
+ @"message": message ?: @"Unknown iOS Native Exception",
468
+ @"stack": stackTrace ?: @"",
469
+ @"timestamp": @([[NSDate date] timeIntervalSince1970] * 1000)
470
+ }];
457
471
  }
458
472
 
459
473
  RCT_EXPORT_METHOD(enableNativeCrashProtection:(RCTPromiseResolveBlock)resolve
@@ -586,18 +600,19 @@ RCT_EXPORT_METHOD(showFloatingButton:(NSDictionary *)options
586
600
  if (floatingButtonView == nil) {
587
601
  floatingButtonView = [[InAppInspectorFloatingView alloc] initWithFrame:CGRectMake(initialX, initialY, size, size)];
588
602
  floatingButtonView.layer.zPosition = 999999;
589
- __weak NetworkInspectorModule *weakSelf = self;
590
- floatingButtonView.onTapBlock = ^{
591
- NetworkInspectorModule *strongSelf = weakSelf ?: sharedInstance;
592
- if (strongSelf) {
593
- [strongSelf sendEventWithName:@"onFloatingButtonPress" body:@{}];
594
- }
595
- };
596
603
  } else {
597
604
  floatingButtonView.layer.zPosition = 999999;
598
605
  floatingButtonView.frame = CGRectMake(initialX, initialY, size, size);
599
606
  }
600
607
 
608
+ __weak NetworkInspectorModule *weakSelf = self;
609
+ floatingButtonView.onTapBlock = ^{
610
+ NetworkInspectorModule *strongSelf = weakSelf ?: sharedInstance;
611
+ if (strongSelf) {
612
+ [strongSelf safeSendEvent:@"onFloatingButtonPress" body:@{}];
613
+ }
614
+ };
615
+
601
616
  void (^attachToWindow)(void) = ^{
602
617
  UIWindow *activeWin = GetAppActiveWindow();
603
618
  if (!activeWin || !floatingButtonView) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-inapp-inspector",
3
- "version": "2.2.3",
3
+ "version": "2.2.5",
4
4
  "description": "The zero-config, all-in-one in-app debugger for React Native & Expo. Inspect Network (fetch/axios), Console logs, Stack Traces, Redux State, Firebase Analytics, and JS Bundle size directly on device.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -73,6 +73,13 @@
73
73
  "require": "./dist/commonjs/bundle.js",
74
74
  "default": "./dist/commonjs/bundle.js"
75
75
  },
76
+ "./storage": {
77
+ "react-native": "./dist/commonjs/storage.js",
78
+ "types": "./dist/commonjs/storage.d.ts",
79
+ "import": "./dist/esm/storage.js",
80
+ "require": "./dist/commonjs/storage.js",
81
+ "default": "./dist/commonjs/storage.js"
82
+ },
76
83
  "./package.json": "./package.json"
77
84
  },
78
85
  "files": [
@@ -37,6 +37,7 @@ import {
37
37
  RawIcon,
38
38
  TableIcon,
39
39
  DocIcon,
40
+ PackageIcon,
40
41
  } from './NetworkIcons';
41
42
 
42
43
  // Type Definition
@@ -312,8 +313,9 @@ const AnalyticsDetail = ({
312
313
 
313
314
  {itemsCount !== null && (
314
315
  <View style={detailStyles.itemsPill}>
316
+ <PackageIcon size={12} color="#1D4ED8" />
315
317
  <Text style={detailStyles.itemsValue}>
316
- 📦 {itemsCount} items
318
+ {itemsCount} items
317
319
  </Text>
318
320
  </View>
319
321
  )}
@@ -694,6 +696,9 @@ const detailStyles = StyleSheet.create({
694
696
  color: '#047857',
695
697
  },
696
698
  itemsPill: {
699
+ flexDirection: 'row',
700
+ alignItems: 'center',
701
+ gap: 4,
697
702
  backgroundColor: '#EFF6FF',
698
703
  paddingHorizontal: 7,
699
704
  paddingVertical: 3,
@@ -230,9 +230,10 @@ const AnalyticsEventCard = React.memo(function AnalyticsEventCard({
230
230
  borderColor: `${AppColors.brandPurple}25`,
231
231
  },
232
232
  ]}>
233
+ <SparkleIcon color={AppColors.brandPurple} size={10} />
233
234
  <Text
234
235
  style={[cardStyles.chipText, {color: AppColors.brandPurple, fontFamily: AppFonts.interBold}]}>
235
- {userPropCount} {t('analytics.props')}
236
+ {userPropCount} {t('analytics.props')}
236
237
  </Text>
237
238
  </View>
238
239
  )}
@@ -1,142 +1,133 @@
1
1
  import React from 'react';
2
- import Svg, {Circle, Path, G, Defs, LinearGradient, RadialGradient, Stop, Rect, Ellipse, Line} from 'react-native-svg';
2
+ import Svg, {
3
+ Circle,
4
+ Path,
5
+ G,
6
+ Defs,
7
+ LinearGradient,
8
+ RadialGradient,
9
+ Stop,
10
+ Rect,
11
+ Ellipse,
12
+ Line,
13
+ } from 'react-native-svg';
3
14
 
4
15
  export const BrandSquareIcon = ({size = 56}: {size?: number}) => {
5
16
  return (
6
17
  <Svg width={size} height={size} viewBox="0 0 256 256" fill="none">
7
18
  <Defs>
8
- <LinearGradient id="tileSquare" x1="30" y1="30" x2="210" y2="222" gradientUnits="userSpaceOnUse">
9
- <Stop offset="0" stopColor="#141B33"/>
10
- <Stop offset="1" stopColor="#0A0E1C"/>
19
+ <LinearGradient id="bs_tile" x1="0" y1="0" x2="256" y2="256" gradientUnits="userSpaceOnUse">
20
+ <Stop offset="0" stopColor="#1E1B4B" />
21
+ <Stop offset="1" stopColor="#0F172A" />
11
22
  </LinearGradient>
12
- <LinearGradient id="edgeSquare" x1="14" y1="22" x2="220" y2="228" gradientUnits="userSpaceOnUse">
13
- <Stop offset="0" stopColor="#3A4E7A"/>
14
- <Stop offset="1" stopColor="#1A2238"/>
23
+ <LinearGradient id="bs_beam" x1="0" y1="0" x2="256" y2="256" gradientUnits="userSpaceOnUse">
24
+ <Stop offset="0" stopColor="#818CF8" />
25
+ <Stop offset="0.5" stopColor="#A855F7" />
26
+ <Stop offset="1" stopColor="#EC4899" />
15
27
  </LinearGradient>
16
- <LinearGradient id="beamSquare" x1="70" y1="74" x2="194" y2="187" gradientUnits="userSpaceOnUse">
17
- <Stop offset="0" stopColor="#5EEAD4"/>
18
- <Stop offset="0.5" stopColor="#38BDF8"/>
19
- <Stop offset="1" stopColor="#A78BFA"/>
28
+ <LinearGradient id="bs_body" x1="0" y1="0" x2="0" y2="256" gradientUnits="userSpaceOnUse">
29
+ <Stop offset="0" stopColor="#312E81" />
30
+ <Stop offset="1" stopColor="#1E1B4B" />
20
31
  </LinearGradient>
21
- <RadialGradient id="haloSquare" cx="0.5" cy="0.45" r="0.55">
22
- <Stop offset="0" stopColor="#38BDF8" stopOpacity={0.12}/>
23
- <Stop offset="1" stopColor="#38BDF8" stopOpacity={0}/>
32
+ <RadialGradient id="bs_iris" cx="40%" cy="40%" r="60%">
33
+ <Stop offset="0" stopColor="#FDE047" />
34
+ <Stop offset="0.7" stopColor="#F59E0B" />
35
+ <Stop offset="1" stopColor="#D97706" />
24
36
  </RadialGradient>
25
- <LinearGradient id="owlbodySquare" x1="78" y1="60" x2="178" y2="186" gradientUnits="userSpaceOnUse">
26
- <Stop offset="0" stopColor="#202E55"/>
27
- <Stop offset="1" stopColor="#10182F"/>
28
- </LinearGradient>
29
- <LinearGradient id="beakSquare" x1="120" y1="151" x2="136" y2="168" gradientUnits="userSpaceOnUse">
30
- <Stop offset="0" stopColor="#FCD34D"/>
31
- <Stop offset="1" stopColor="#FB923C"/>
32
- </LinearGradient>
33
- <RadialGradient id="irisSquare" cx="0.42" cy="0.38" r="0.72">
34
- <Stop offset="0" stopColor="#FDE68A"/>
35
- <Stop offset="0.5" stopColor="#FBBF24"/>
36
- <Stop offset="1" stopColor="#F59E0B"/>
37
- </RadialGradient>
38
- <RadialGradient id="blushSquare" cx="0.5" cy="0.5" r="0.5">
39
- <Stop offset="0" stopColor="#FB7185" stopOpacity={0.5}/>
40
- <Stop offset="1" stopColor="#FB7185" stopOpacity={0}/>
41
- </RadialGradient>
42
- <LinearGradient id="wingSquare" x1="70" y1="120" x2="190" y2="206" gradientUnits="userSpaceOnUse">
43
- <Stop offset="0" stopColor="#1A2545"/>
44
- <Stop offset="1" stopColor="#0E1530"/>
45
- </LinearGradient>
46
- <LinearGradient id="faceplateSquare" x1="70" y1="72" x2="186" y2="152" gradientUnits="userSpaceOnUse">
47
- <Stop offset="0" stopColor="#35497E"/>
48
- <Stop offset="1" stopColor="#1E2D4D"/>
49
- </LinearGradient>
50
- <RadialGradient id="lensglassSquare" cx="0.4" cy="0.32" r="0.75">
51
- <Stop offset="0" stopColor="#7DE8FF" stopOpacity={0.22}/>
52
- <Stop offset="0.7" stopColor="#7DE8FF" stopOpacity={0.05}/>
53
- <Stop offset="1" stopColor="#7DE8FF" stopOpacity={0}/>
54
- </RadialGradient>
55
- <LinearGradient id="bellySquare" x1="94" y1="126" x2="162" y2="212" gradientUnits="userSpaceOnUse">
56
- <Stop offset="0" stopColor="#33477A"/>
57
- <Stop offset="1" stopColor="#1D2B53"/>
37
+ <LinearGradient id="bs_beak" x1="0" y1="0" x2="0" y2="20" gradientUnits="userSpaceOnUse">
38
+ <Stop offset="0" stopColor="#FBBF24" />
39
+ <Stop offset="1" stopColor="#F97316" />
58
40
  </LinearGradient>
59
41
  </Defs>
60
- <Rect x={8} y={8} width={240} height={240} rx={58} fill="url(#tileSquare)"/>
61
- <Rect x={8.6} y={8.6} width={238.8} height={238.8} rx={57.4} fill="none" stroke="url(#edgeSquare)" strokeOpacity={0.6} strokeWidth={1.2}/>
62
- <Circle cx={128} cy={128} r={104} fill="url(#haloSquare)"/>
63
- <G transform="translate(128 128) scale(1.16) translate(-128 -134)">
64
- {/* wing 1 */}
65
- <Path d="M74 124 C58 154 60 190 86 204 C79 176 77 148 88 126 Z" fill="url(#wingSquare)" stroke="url(#beamSquare)" strokeWidth={2.5} strokeOpacity={0.45}/>
66
- {/* wing 2 */}
67
- <Path d="M182 124 C198 154 196 190 170 204 C177 176 179 148 168 126 Z" fill="url(#wingSquare)" stroke="url(#beamSquare)" strokeWidth={2.5} strokeOpacity={0.45}/>
68
- {/* body */}
69
- <Path d="M62 150 C58 104 70 70 90 58 L98 42 L116 62 Q128 57 140 62 L158 42 L166 58 C186 70 198 104 194 150 C198 180 184 204 152 212 C140 216 116 216 104 212 C72 204 58 180 62 150 Z" fill="url(#owlbodySquare)" stroke="url(#beamSquare)" strokeWidth={4} strokeLinejoin="round"/>
70
-
71
- {/* inner-ear shadows */}
72
- <Path d="M99 48 L114 62 L104 63 L98 55 Z" fill="#080F22" opacity={0.5}/>
73
- <Path d="M157 48 L142 62 L152 63 L158 55 Z" fill="#080F22" opacity={0.5}/>
74
-
75
- {/* wing feather lines */}
76
- <G stroke="#22325A" strokeWidth={2.2} fill="none" strokeLinecap="round" opacity={0.75}>
77
- <Path d="M80 138 q-5 26 3 50"/>
78
- <Path d="M90 134 q-4 26 3 48"/>
79
- <Path d="M176 138 q5 26 -3 50"/>
80
- <Path d="M166 134 q4 26 -3 48"/>
81
- </G>
82
42
 
83
- {/* belly plate */}
84
- <Path d="M128 126 C151 126 164 148 162 174 C160 198 146 212 128 212 C110 212 96 198 94 174 C92 148 105 126 128 126 Z" fill="url(#bellySquare)"/>
43
+ {/* Rounded App Tile Background */}
44
+ <Rect x="8" y="8" width="240" height="240" rx="54" fill="url(#bs_tile)" />
45
+ <Rect
46
+ x="8"
47
+ y="8"
48
+ width="240"
49
+ height="240"
50
+ rx="54"
51
+ fill="none"
52
+ stroke="url(#bs_beam)"
53
+ strokeWidth="3"
54
+ strokeOpacity={0.4}
55
+ />
85
56
 
86
- {/* belly feather scallops */}
87
- <G stroke="#3E588C" strokeWidth={2.3} fill="none" strokeLinecap="round" opacity={0.4}>
88
- <Path d="M110 154 Q118 162 126 154"/>
89
- <Path d="M126 154 Q134 162 142 154"/>
90
- <Path d="M142 154 Q150 162 158 154"/>
91
- <Path d="M102 172 Q110 180 118 172"/>
92
- <Path d="M150 172 Q158 180 166 172"/>
93
- <Path d="M112 190 Q120 198 128 190"/>
94
- <Path d="M128 190 Q136 198 144 190"/>
95
- </G>
57
+ {/* Owl Outer Body Contour */}
58
+ <Path
59
+ d="M64 148 C60 102 72 68 92 56 L100 40 L118 60 Q128 55 138 60 L156 40 L164 56 C184 68 196 102 192 148 C196 178 182 202 150 210 C138 214 118 214 106 210 C74 202 60 178 64 148 Z"
60
+ fill="url(#bs_body)"
61
+ stroke="url(#bs_beam)"
62
+ strokeWidth="4"
63
+ strokeLinejoin="round"
64
+ />
96
65
 
97
- {/* developer chest screen + code emblem */}
98
- <Rect x={107} y={161} width={42} height={32} rx={9} fill="#0C1426" stroke="url(#beamSquare)" strokeWidth={2} strokeOpacity={0.7}/>
99
- <G stroke="#8FD0EC" strokeWidth={3} strokeLinecap="round" strokeLinejoin="round" fill="none">
100
- <Path d="M122 170 L115 177 L122 184"/>
101
- <Path d="M134 170 L141 177 L134 184"/>
102
- <Path d="M130 168 L126 186"/>
103
- </G>
66
+ {/* Wings */}
67
+ <Path
68
+ d="M74 124 C58 154 60 190 86 204 C79 176 77 148 88 126 Z"
69
+ fill="#1E1B4B"
70
+ stroke="#818CF8"
71
+ strokeWidth="2.5"
72
+ strokeOpacity={0.6}
73
+ />
74
+ <Path
75
+ d="M182 124 C198 154 196 190 170 204 C177 176 179 148 168 126 Z"
76
+ fill="#1E1B4B"
77
+ stroke="#818CF8"
78
+ strokeWidth="2.5"
79
+ strokeOpacity={0.6}
80
+ />
104
81
 
105
- {/* facial disc */}
106
- <Path d="M128 92 C148 70 186 78 186 108 C186 134 160 152 128 152 C96 152 70 134 70 108 C70 78 108 70 128 92 Z" fill="url(#faceplateSquare)" stroke="#52709E" strokeWidth={2.6} strokeOpacity={0.7}/>
107
- {/* facial-disc centre ridge */}
108
- <Path d="M128 96 L128 120" stroke="#52709E" strokeWidth={2} strokeLinecap="round" strokeOpacity={0.45}/>
82
+ {/* Belly Screen Plate */}
83
+ <Rect
84
+ x="105"
85
+ y="160"
86
+ width="46"
87
+ height="34"
88
+ rx="8"
89
+ fill="#0B0F19"
90
+ stroke="url(#bs_beam)"
91
+ strokeWidth="2"
92
+ />
93
+ {/* Code Emblem on Chest */}
94
+ <G stroke="#A5B4FC" strokeWidth="2.8" strokeLinecap="round" strokeLinejoin="round" fill="none">
95
+ <Path d="M120 171 L114 177 L120 183" />
96
+ <Path d="M136 171 L142 177 L136 183" />
97
+ <Path d="M130 169 L126 185" stroke="#EC4899" />
98
+ </G>
109
99
 
110
- {/* feet */}
111
- <G stroke="url(#beakSquare)" strokeWidth={5} strokeLinecap="round" fill="none">
112
- <Path d="M111 209 L105 224 M111 209 L111 226 M111 209 L117 224"/>
113
- <Path d="M145 209 L139 224 M145 209 L145 226 M145 209 L151 224"/>
114
- </G>
100
+ {/* Facial Disc & Mask */}
101
+ <Path
102
+ d="M128 92 C148 70 186 78 186 108 C186 134 160 152 128 152 C96 152 70 134 70 108 C70 78 108 70 128 92 Z"
103
+ fill="#2E1065"
104
+ stroke="#818CF8"
105
+ strokeWidth="2"
106
+ strokeOpacity={0.6}
107
+ />
115
108
 
116
- {/* normal eye: big cute yellow iris, dark pupil, sparkles */}
117
- <Circle cx={153} cy={107} r={17} fill="url(#irisSquare)" stroke="#1A1205" strokeWidth={2.2}/>
118
- <Circle cx={153} cy={108} r={8.2} fill="#0A0E18"/>
119
- <Circle cx={156.2} cy={104} r={3.1} fill="#ffffff" opacity={0.95}/>
120
- <Circle cx={149.6} cy={111} r={1.6} fill="#ffffff" opacity={0.7}/>
109
+ {/* Right Eye (Normal Cute Eye) */}
110
+ <Circle cx="154" cy="108" r="17" fill="url(#bs_iris)" stroke="#0F172A" strokeWidth="2" />
111
+ <Circle cx="154" cy="108" r="8.5" fill="#0F172A" />
112
+ <Circle cx="157" cy="105" r="3" fill="#FFFFFF" />
113
+ <Circle cx="151" cy="111" r="1.5" fill="#FFFFFF" opacity={0.8} />
121
114
 
122
- {/* beak */}
123
- <Path d="M123.5 123 Q128 121 132.5 123 Q131 132 128 134.5 Q125 132 123.5 123 Z" fill="url(#beakSquare)"/>
115
+ {/* Left Eye (Diagnostic Magnifier Lens) */}
116
+ <Circle cx="96" cy="104" r="20" fill="url(#bs_iris)" stroke="#0F172A" strokeWidth="2" />
117
+ <Circle cx="96" cy="104" r="10" fill="#0F172A" />
118
+ <Circle cx="99.5" cy="100.5" r="3.5" fill="#FFFFFF" />
119
+ <Circle cx="92" cy="107" r="1.8" fill="#FFFFFF" opacity={0.8} />
124
120
 
125
- {/* magnifier held to the big (debug) eye */}
126
- <Circle cx={95} cy={103} r={20} fill="url(#irisSquare)" stroke="#1A1205" strokeWidth={2.6}/>
127
- <Circle cx={95} cy={104} r={10} fill="#0A0E18"/>
128
- <Circle cx={98.6} cy={100} r={3.4} fill="#ffffff" opacity={0.95}/>
129
- <Circle cx={91} cy={107} r={1.8} fill="#ffffff" opacity={0.7}/>
130
- <Circle cx={95} cy={103} r={28} fill="url(#lensglassSquare)"/>
131
- <Path d="M77 87 A28 28 0 0 1 106 79" fill="none" stroke="#ffffff" strokeWidth={4} strokeLinecap="round" strokeOpacity={0.5}/>
132
- <Line x1={75} y1={123} x2={54} y2={147} stroke="#0A0F1C" strokeWidth={14} strokeLinecap="round"/>
133
- <Line x1={75} y1={123} x2={54} y2={147} stroke="url(#beamSquare)" strokeWidth={8.5} strokeLinecap="round"/>
134
- <Circle cx={95} cy={103} r={28} fill="none" stroke="url(#beamSquare)" strokeWidth={7}/>
121
+ {/* Magnifier Glass Ring & Handle */}
122
+ <Line x1="76" y1="124" x2="55" y2="148" stroke="#0F172A" strokeWidth="12" strokeLinecap="round" />
123
+ <Line x1="76" y1="124" x2="55" y2="148" stroke="url(#bs_beam)" strokeWidth="7" strokeLinecap="round" />
124
+ <Circle cx="96" cy="104" r="28" fill="#38BDF8" fillOpacity={0.12} stroke="url(#bs_beam)" strokeWidth="6" />
135
125
 
136
- {/* rosy cheeks */}
137
- <Ellipse cx={83} cy={127} rx={9} ry={6} fill="url(#blushSquare)"/>
138
- <Ellipse cx={167} cy={122} rx={9} ry={6} fill="url(#blushSquare)"/>
139
- </G>
126
+ {/* Beak */}
127
+ <Path
128
+ d="M123.5 123 Q128 121 132.5 123 Q131 132 128 134.5 Q125 132 123.5 123 Z"
129
+ fill="url(#bs_beak)"
130
+ />
140
131
  </Svg>
141
132
  );
142
133
  };
@@ -68,7 +68,7 @@ const DiffViewer = React.memo(
68
68
  <Text key={i} selectable={true} style={styles.diffChanged}>
69
69
  ~ <Text style={styles.codeKey}>{key}</Text>
70
70
  {JSON.stringify(d.oldVal)}{' '}
71
- <Text style={{color: AppColors.grayTextWeak}}>➔</Text>{' '}
71
+ <Text style={{color: AppColors.grayTextWeak}}>→</Text>{' '}
72
72
  {JSON.stringify(d.newVal)}
73
73
  </Text>
74
74
  );
@@ -1606,6 +1606,35 @@ const BundleTab = React.memo(() => {
1606
1606
  {t('bundle.liveAnalysisUnavailableSub')}
1607
1607
  </Text>
1608
1608
  </View>
1609
+ <TouchableScale
1610
+ onPress={refreshAnalysis}
1611
+ style={{
1612
+ backgroundColor: `${AppColors.amber700}18`,
1613
+ paddingHorizontal: 8,
1614
+ paddingVertical: 5,
1615
+ borderRadius: 6,
1616
+ borderWidth: 1,
1617
+ borderColor: `${AppColors.amber700}30`,
1618
+ flexDirection: 'row',
1619
+ alignItems: 'center',
1620
+ gap: 4,
1621
+ }}>
1622
+ {isAnalyzing ? (
1623
+ <ActivityIndicator size="small" color={AppColors.amber700} />
1624
+ ) : (
1625
+ <>
1626
+ <RefreshCcwIcon color={AppColors.amber700} size={11} />
1627
+ <Text
1628
+ style={{
1629
+ fontSize: 10.5,
1630
+ fontFamily: AppFonts.interBold,
1631
+ color: AppColors.amber700,
1632
+ }}>
1633
+ Retry
1634
+ </Text>
1635
+ </>
1636
+ )}
1637
+ </TouchableScale>
1609
1638
  </View>
1610
1639
  </View>
1611
1640
  )}