react-native-inapp-inspector 1.1.10 → 1.1.12

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.
@@ -150,7 +150,8 @@ const NavigationTracker = ({ onStateChange }) => {
150
150
  return null;
151
151
  };
152
152
  const animateNextLayout = () => {
153
- react_native_1.LayoutAnimation.configureNext(react_native_1.LayoutAnimation.Presets.easeInEaseOut);
153
+ // Disabled LayoutAnimation to prevent iOS NSRangeException crashes under Fabric
154
+ // and Android rendering performance freezes.
154
155
  };
155
156
  const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
156
157
  // Set custom storage synchronously during render phase
@@ -174,7 +175,6 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
174
175
  const [search, setSearch] = (0, react_1.useState)('');
175
176
  const [detailSearch, setDetailSearch] = (0, react_1.useState)('');
176
177
  const [reduxSearch, setReduxSearch] = (0, react_1.useState)('');
177
- const [reduxActiveSubTab, setReduxActiveSubTab] = (0, react_1.useState)('timeline');
178
178
  const [apiDetailActiveTab, setApiDetailActiveTab] = (0, react_1.useState)('response');
179
179
  (0, react_1.useEffect)(() => {
180
180
  react_native_1.LogBox.ignoreAllLogs(enabled);
@@ -232,7 +232,7 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
232
232
  const [maxConsoleLogs, setMaxConsoleLogs] = (0, react_1.useState)(200);
233
233
  const [showConsoleLevels, setShowConsoleLevels] = (0, react_1.useState)({
234
234
  info: true,
235
- warn: true,
235
+ warn: false,
236
236
  error: true,
237
237
  });
238
238
  const visibleConsoleLogs = (0, react_1.useMemo)(() => {
@@ -741,7 +741,13 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
741
741
  const task = react_native_1.InteractionManager.runAfterInteractions(() => {
742
742
  setIsReady(true);
743
743
  });
744
- return () => task.cancel();
744
+ const fallbackTimer = setTimeout(() => {
745
+ setIsReady(true);
746
+ }, 350);
747
+ return () => {
748
+ task.cancel();
749
+ clearTimeout(fallbackTimer);
750
+ };
745
751
  }
746
752
  else {
747
753
  setIsReady(false);
@@ -754,9 +760,10 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
754
760
  (0, consoleLogger_1.setupConsoleLogger)();
755
761
  (0, analyticsLogger_1.autoSetupAnalyticsLogger)();
756
762
  let timeoutId;
763
+ let isFirstNetworkCall = true;
757
764
  const unsubscribe = (0, networkLogger_1.subscribeNetworkLogs)((raw) => {
758
765
  clearTimeout(timeoutId);
759
- timeoutId = setTimeout(() => {
766
+ const updateNetworkState = () => {
760
767
  const deduped = (0, helpers_1.deduplicateLogs)(raw);
761
768
  const incoming = new Set(deduped.map(l => l.id));
762
769
  const freshIds = new Set();
@@ -775,13 +782,24 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
775
782
  setTimeout(() => setNewLogIds(new Set()), 1200);
776
783
  }
777
784
  setLogs(deduped);
778
- }, 250);
785
+ };
786
+ if (isFirstNetworkCall) {
787
+ isFirstNetworkCall = false;
788
+ const deduped = (0, helpers_1.deduplicateLogs)(raw);
789
+ const incoming = new Set(deduped.map(l => l.id));
790
+ prevLogIdsRef.current = incoming;
791
+ setLogs(deduped);
792
+ }
793
+ else {
794
+ timeoutId = setTimeout(updateNetworkState, 250);
795
+ }
779
796
  });
780
797
  // ─── Analytics subscription ──────────────────────────────────────────────
781
798
  let analyticsTimeoutId;
799
+ let isFirstAnalyticsCall = true;
782
800
  const unsubscribeAnalytics = (0, analyticsLogger_1.subscribeAnalyticsEvents)((raw) => {
783
801
  clearTimeout(analyticsTimeoutId);
784
- analyticsTimeoutId = setTimeout(() => {
802
+ const updateAnalyticsState = () => {
785
803
  const incoming = new Set(raw.map(e => e.id));
786
804
  const freshIds = new Set();
787
805
  incoming.forEach(id => {
@@ -799,15 +817,31 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
799
817
  setTimeout(() => setNewEventIds(new Set()), 1200);
800
818
  }
801
819
  setAnalyticsEvents(raw);
802
- }, 200);
820
+ };
821
+ if (isFirstAnalyticsCall) {
822
+ isFirstAnalyticsCall = false;
823
+ const incoming = new Set(raw.map(e => e.id));
824
+ prevEventIdsRef.current = incoming;
825
+ setAnalyticsEvents(raw);
826
+ }
827
+ else {
828
+ analyticsTimeoutId = setTimeout(updateAnalyticsState, 200);
829
+ }
803
830
  });
804
831
  // ─── Console subscription ────────────────────────────────────────────────
805
832
  let consoleTimeoutId;
833
+ let isFirstConsoleCall = true;
806
834
  const unsubscribeConsole = (0, consoleLogger_1.subscribeConsoleLogs)((raw) => {
807
835
  clearTimeout(consoleTimeoutId);
808
- consoleTimeoutId = setTimeout(() => {
836
+ if (isFirstConsoleCall) {
837
+ isFirstConsoleCall = false;
809
838
  setConsoleLogs(raw);
810
- }, 200);
839
+ }
840
+ else {
841
+ consoleTimeoutId = setTimeout(() => {
842
+ setConsoleLogs(raw);
843
+ }, 200);
844
+ }
811
845
  });
812
846
  setWebViewLogs((0, webViewLogger_1.getWebViewLogs)());
813
847
  setWebViewNavHistory((0, webViewLogger_1.getWebViewNavHistory)());
@@ -817,24 +851,34 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
817
851
  setWebViewHtmlUrl((0, webViewLogger_1.getWebViewHtmlUrl)());
818
852
  // ─── WebView subscription ────────────────────────────────────────────────
819
853
  let webViewTimeoutId;
854
+ let isFirstWebViewCall = true;
820
855
  const unsubscribeWebView = (0, webViewLogger_1.subscribeWebView)(() => {
821
856
  clearTimeout(webViewTimeoutId);
822
- webViewTimeoutId = setTimeout(() => {
857
+ const updateWebViewState = () => {
823
858
  setWebViewLogs((0, webViewLogger_1.getWebViewLogs)());
824
859
  setWebViewNavHistory((0, webViewLogger_1.getWebViewNavHistory)());
825
860
  setWebViewHtml((0, webViewLogger_1.getWebViewHtml)());
826
861
  setWebViewCss((0, webViewLogger_1.getWebViewCss)());
827
862
  setWebViewJs((0, webViewLogger_1.getWebViewJs)());
828
863
  setWebViewHtmlUrl((0, webViewLogger_1.getWebViewHtmlUrl)());
829
- }, 200);
864
+ };
865
+ if (isFirstWebViewCall) {
866
+ isFirstWebViewCall = false;
867
+ updateWebViewState();
868
+ }
869
+ else {
870
+ webViewTimeoutId = setTimeout(updateWebViewState, 200);
871
+ }
830
872
  });
831
- setReduxState((0, reduxLogger_1.getReduxState)());
873
+ const initialReduxState = (0, reduxLogger_1.getReduxState)();
874
+ setReduxState(initialReduxState && typeof initialReduxState === 'object' ? { ...initialReduxState } : initialReduxState);
832
875
  setReduxActionHistory([...(0, reduxLogger_1.getActionHistory)()]);
833
876
  setReduxLastActionMap({ ...(0, reduxLogger_1.getLastActionForReducer)() });
834
877
  const unsubscribeRedux = (0, reduxLogger_1.subscribeReduxState)(() => {
835
878
  // New references each time guarantee the Redux tab updates live, even when
836
879
  // the root state object reference is unchanged or auto-refresh is paused.
837
- setReduxState((0, reduxLogger_1.getReduxState)());
880
+ const freshState = (0, reduxLogger_1.getReduxState)();
881
+ setReduxState(freshState && typeof freshState === 'object' ? { ...freshState } : freshState);
838
882
  setReduxActionHistory([...(0, reduxLogger_1.getActionHistory)()]);
839
883
  setReduxLastActionMap({ ...(0, reduxLogger_1.getLastActionForReducer)() });
840
884
  });
@@ -2145,6 +2189,97 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
2145
2189
  </TouchableScale_1.default>
2146
2190
  </react_native_1.View>
2147
2191
 
2192
+ {/* Divider */}
2193
+ <react_native_1.View style={{
2194
+ height: 1,
2195
+ backgroundColor: AppColors_1.AppColors.dividerColor,
2196
+ }}/>
2197
+
2198
+ {/* Logs Console Levels */}
2199
+ <react_native_1.View style={{
2200
+ paddingVertical: 12,
2201
+ paddingHorizontal: 14,
2202
+ }}>
2203
+ <react_native_1.View style={{
2204
+ flexDirection: 'row',
2205
+ alignItems: 'center',
2206
+ gap: 8,
2207
+ }}>
2208
+ <react_native_1.View style={{
2209
+ width: 20,
2210
+ height: 20,
2211
+ borderRadius: 6,
2212
+ backgroundColor: AppColors_1.AppColors.purpleShade50,
2213
+ borderWidth: 1,
2214
+ borderColor: 'rgba(104,75,155,0.2)',
2215
+ alignItems: 'center',
2216
+ justifyContent: 'center',
2217
+ }}>
2218
+ <NetworkIcons_1.TerminalIcon color={AppColors_1.AppColors.purple} size={11}/>
2219
+ </react_native_1.View>
2220
+ <react_native_1.View style={{ flex: 1 }}>
2221
+ <react_native_1.Text style={{
2222
+ fontFamily: AppFonts_1.AppFonts.interBold,
2223
+ fontSize: 13,
2224
+ color: AppColors_1.AppColors.primaryBlack,
2225
+ }}>
2226
+ Logs Console Levels
2227
+ </react_native_1.Text>
2228
+ <react_native_1.Text style={{
2229
+ fontFamily: AppFonts_1.AppFonts.interRegular,
2230
+ fontSize: 11,
2231
+ color: AppColors_1.AppColors.grayText,
2232
+ marginTop: 1,
2233
+ }}>
2234
+ Toggle which log levels are visible in the Logs tab
2235
+ </react_native_1.Text>
2236
+ </react_native_1.View>
2237
+ </react_native_1.View>
2238
+
2239
+ <react_native_1.View style={{
2240
+ flexDirection: 'row',
2241
+ gap: 8,
2242
+ marginTop: 10,
2243
+ }}>
2244
+ {([
2245
+ { key: 'info', label: 'Info', color: '#3B82F6' },
2246
+ { key: 'warn', label: 'Warning', color: '#F59E0B' },
2247
+ { key: 'error', label: 'Error', color: '#EF4444' },
2248
+ ]).map(level => {
2249
+ const isActive = showConsoleLevels[level.key];
2250
+ return (<TouchableScale_1.default key={level.key} onPress={() => setShowConsoleLevels(prev => ({
2251
+ ...prev,
2252
+ [level.key]: !prev[level.key],
2253
+ }))} style={{
2254
+ flex: 1,
2255
+ flexDirection: 'row',
2256
+ alignItems: 'center',
2257
+ justifyContent: 'center',
2258
+ gap: 6,
2259
+ paddingVertical: 8,
2260
+ borderRadius: 8,
2261
+ borderWidth: 1.5,
2262
+ borderColor: isActive ? level.color : AppColors_1.AppColors.grayBorderSecondary,
2263
+ backgroundColor: isActive ? `${level.color}0D` : AppColors_1.AppColors.primaryLight,
2264
+ }}>
2265
+ <react_native_1.View style={{
2266
+ width: 8,
2267
+ height: 8,
2268
+ borderRadius: 4,
2269
+ backgroundColor: isActive ? level.color : AppColors_1.AppColors.grayBorderSecondary,
2270
+ }}/>
2271
+ <react_native_1.Text style={{
2272
+ fontFamily: AppFonts_1.AppFonts.interBold,
2273
+ fontSize: 11,
2274
+ color: isActive ? level.color : AppColors_1.AppColors.grayText,
2275
+ }}>
2276
+ {level.label}
2277
+ </react_native_1.Text>
2278
+ </TouchableScale_1.default>);
2279
+ })}
2280
+ </react_native_1.View>
2281
+ </react_native_1.View>
2282
+
2148
2283
  {/* Divider */}
2149
2284
  <react_native_1.View style={{
2150
2285
  height: 1,
@@ -3474,129 +3609,8 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
3474
3609
  <react_native_1.Text style={styles_1.default.emptySub}>Connected store state is empty.</react_native_1.Text>
3475
3610
  </react_native_1.View>);
3476
3611
  }
3477
- // Build hierarchical tree: Store -> Reducers -> Action -> Data.
3478
- // These come from component state (refreshed on every dispatch) so the view stays live.
3479
3612
  const lastActionMap = reduxLastActionMap;
3480
- const actionHistory = reduxActionHistory;
3481
3613
  return (<react_native_1.ScrollView style={styles_1.default.detailScroll} contentContainerStyle={{ paddingBottom: 24 }}>
3482
- {/* Tab View Selection Segments */}
3483
- <react_native_1.View style={{
3484
- flexDirection: 'row',
3485
- backgroundColor: AppColors_1.AppColors.grayBackground,
3486
- borderRadius: 10,
3487
- padding: 3,
3488
- marginHorizontal: 16,
3489
- marginTop: 12,
3490
- marginBottom: 12,
3491
- borderWidth: 1,
3492
- borderColor: AppColors_1.AppColors.dividerColor,
3493
- }}>
3494
- <react_native_1.TouchableOpacity onPress={() => {
3495
- animateNextLayout();
3496
- setReduxActiveSubTab('timeline');
3497
- }} style={{
3498
- flex: 1,
3499
- paddingVertical: 6,
3500
- alignItems: 'center',
3501
- justifyContent: 'center',
3502
- borderRadius: 8,
3503
- backgroundColor: reduxActiveSubTab === 'timeline'
3504
- ? AppColors_1.AppColors.purple
3505
- : 'transparent',
3506
- }}>
3507
- <react_native_1.View style={{
3508
- flexDirection: 'row',
3509
- alignItems: 'center',
3510
- justifyContent: 'center',
3511
- gap: 6,
3512
- }}>
3513
- <ReduxTreeView_1.ReduxTimelineIcon color={reduxActiveSubTab === 'timeline'
3514
- ? '#FFFFFF'
3515
- : AppColors_1.AppColors.grayText} size={13}/>
3516
- <react_native_1.Text style={{
3517
- fontFamily: AppFonts_1.AppFonts.interBold,
3518
- fontSize: 11,
3519
- color: reduxActiveSubTab === 'timeline'
3520
- ? '#FFFFFF'
3521
- : AppColors_1.AppColors.grayText,
3522
- }}>
3523
- Action Timeline
3524
- </react_native_1.Text>
3525
- <react_native_1.View style={{
3526
- minWidth: 18,
3527
- paddingHorizontal: 5,
3528
- height: 16,
3529
- borderRadius: 8,
3530
- alignItems: 'center',
3531
- justifyContent: 'center',
3532
- backgroundColor: reduxActiveSubTab === 'timeline'
3533
- ? 'rgba(255,255,255,0.28)'
3534
- : AppColors_1.AppColors.dividerColor,
3535
- }}>
3536
- <react_native_1.Text style={{
3537
- fontFamily: AppFonts_1.AppFonts.interBold,
3538
- fontSize: 9,
3539
- color: reduxActiveSubTab === 'timeline'
3540
- ? '#FFFFFF'
3541
- : AppColors_1.AppColors.grayText,
3542
- }}>
3543
- {actionHistory.length}
3544
- </react_native_1.Text>
3545
- </react_native_1.View>
3546
- </react_native_1.View>
3547
- </react_native_1.TouchableOpacity>
3548
- <react_native_1.TouchableOpacity onPress={() => {
3549
- animateNextLayout();
3550
- setReduxActiveSubTab('tree');
3551
- }} style={{
3552
- flex: 1,
3553
- paddingVertical: 6,
3554
- alignItems: 'center',
3555
- justifyContent: 'center',
3556
- borderRadius: 8,
3557
- backgroundColor: reduxActiveSubTab === 'tree' ? AppColors_1.AppColors.purple : 'transparent',
3558
- }}>
3559
- <react_native_1.View style={{
3560
- flexDirection: 'row',
3561
- alignItems: 'center',
3562
- justifyContent: 'center',
3563
- gap: 6,
3564
- }}>
3565
- <ReduxTreeView_1.ReduxTreeIcon color={reduxActiveSubTab === 'tree' ? '#FFFFFF' : AppColors_1.AppColors.grayText} size={13}/>
3566
- <react_native_1.Text style={{
3567
- fontFamily: AppFonts_1.AppFonts.interBold,
3568
- fontSize: 11,
3569
- color: reduxActiveSubTab === 'tree'
3570
- ? '#FFFFFF'
3571
- : AppColors_1.AppColors.grayText,
3572
- }}>
3573
- Store Tree
3574
- </react_native_1.Text>
3575
- <react_native_1.View style={{
3576
- minWidth: 18,
3577
- paddingHorizontal: 5,
3578
- height: 16,
3579
- borderRadius: 8,
3580
- alignItems: 'center',
3581
- justifyContent: 'center',
3582
- backgroundColor: reduxActiveSubTab === 'tree'
3583
- ? 'rgba(255,255,255,0.28)'
3584
- : AppColors_1.AppColors.dividerColor,
3585
- }}>
3586
- <react_native_1.Text style={{
3587
- fontFamily: AppFonts_1.AppFonts.interBold,
3588
- fontSize: 9,
3589
- color: reduxActiveSubTab === 'tree'
3590
- ? '#FFFFFF'
3591
- : AppColors_1.AppColors.grayText,
3592
- }}>
3593
- {reducerKeys.length}
3594
- </react_native_1.Text>
3595
- </react_native_1.View>
3596
- </react_native_1.View>
3597
- </react_native_1.TouchableOpacity>
3598
- </react_native_1.View>
3599
-
3600
3614
  {/* Search Bar */}
3601
3615
  <react_native_1.View style={{
3602
3616
  flexDirection: 'row',
@@ -3604,15 +3618,14 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
3604
3618
  backgroundColor: AppColors_1.AppColors.grayBackground,
3605
3619
  borderRadius: 8,
3606
3620
  marginHorizontal: 16,
3621
+ marginTop: 16,
3607
3622
  marginBottom: 12,
3608
3623
  paddingHorizontal: 10,
3609
3624
  borderWidth: 1,
3610
3625
  borderColor: AppColors_1.AppColors.dividerColor,
3611
3626
  height: 36,
3612
3627
  }}>
3613
- <react_native_1.TextInput placeholder={reduxActiveSubTab === 'timeline'
3614
- ? 'Search actions or payloads...'
3615
- : 'Search Redux keys or values...'} placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={reduxSearch} onChangeText={setReduxSearch} style={{
3628
+ <react_native_1.TextInput placeholder="Search Redux keys or values..." placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={reduxSearch} onChangeText={setReduxSearch} style={{
3616
3629
  flex: 1,
3617
3630
  fontFamily: AppFonts_1.AppFonts.interRegular,
3618
3631
  fontSize: 12,
@@ -3633,7 +3646,7 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
3633
3646
  marginHorizontal: 16,
3634
3647
  padding: 12,
3635
3648
  }}>
3636
- {reduxActiveSubTab === 'timeline' ? (<ReduxTreeView_1.ReduxActionTimeline history={actionHistory} onClear={reduxLogger_1.clearActionHistory} search={reduxSearch}/>) : (<ReduxTreeView_1.ReduxTreeView state={reduxState} lastActionMap={lastActionMap} search={reduxSearch}/>)}
3649
+ <ReduxTreeView_1.ReduxTreeView state={reduxState} lastActionMap={lastActionMap} search={reduxSearch}/>
3637
3650
  </react_native_1.View>
3638
3651
  </react_native_1.ScrollView>);
3639
3652
  };
@@ -3759,14 +3772,50 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
3759
3772
  }}>
3760
3773
  <NetworkIcons_1.BrandSquareIcon size={45}/>
3761
3774
  </react_native_1.View>
3762
- <react_native_1.View style={{ gap: 3 }}>
3763
- <react_native_1.Text style={[styles_1.default.headerTitle]}>
3764
- RN InApp Inspector
3775
+ <react_native_1.View style={{ gap: 2, flex: 1 }}>
3776
+ <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
3777
+ <react_native_1.Text style={[styles_1.default.headerTitle]} numberOfLines={1}>
3778
+ {(0, helpers_1.getAppName)()}{' '}
3779
+ <react_native_1.Text style={{ fontFamily: AppFonts_1.AppFonts.interRegular, fontSize: 13, color: 'rgba(255,255,255,0.6)' }}>
3780
+ (Inspector)
3781
+ </react_native_1.Text>
3782
+ </react_native_1.Text>
3783
+ {/* #1 — pulsing dot when a newer version is on NPM */}
3784
+ {updateAvailable && (<react_native_1.Pressable hitSlop={10} onPress={() => react_native_1.Alert.alert('Update Available', `react-native-inapp-inspector v${latestNpmVersion} is available on NPM (installed: v${constants_1.LIB_VERSION}).`, [
3785
+ { text: 'Later', style: 'cancel' },
3786
+ {
3787
+ text: 'View on NPM',
3788
+ onPress: () => react_native_1.Linking.openURL('https://www.npmjs.com/package/react-native-inapp-inspector').catch(() => { }),
3789
+ },
3790
+ ])} style={{
3791
+ alignItems: 'center',
3792
+ justifyContent: 'center',
3793
+ }}>
3794
+ <react_native_1.Animated.View style={{
3795
+ width: 8,
3796
+ height: 8,
3797
+ borderRadius: 4,
3798
+ backgroundColor: '#4ADE80',
3799
+ borderWidth: 1,
3800
+ borderColor: 'rgba(255,255,255,0.9)',
3801
+ opacity: activePulseAnim,
3802
+ transform: [{ scale: unreadPulseAnim }],
3803
+ }}/>
3804
+ </react_native_1.Pressable>)}
3805
+ </react_native_1.View>
3806
+ <react_native_1.Text style={{
3807
+ fontFamily: AppFonts_1.AppFonts.interRegular,
3808
+ fontSize: 10.5,
3809
+ color: 'rgba(255, 255, 255, 0.6)',
3810
+ marginTop: 1,
3811
+ }} selectable={true} numberOfLines={1}>
3812
+ {(0, helpers_1.getBundleIdentifier)()}
3765
3813
  </react_native_1.Text>
3766
3814
  <react_native_1.View style={{
3767
3815
  flexDirection: 'row',
3768
3816
  alignItems: 'center',
3769
3817
  gap: 6,
3818
+ marginTop: 4,
3770
3819
  }}>
3771
3820
  {/* OS chip */}
3772
3821
  <react_native_1.View style={{
@@ -3843,29 +3892,6 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
3843
3892
  </react_native_1.Text>
3844
3893
  </react_native_1.View>
3845
3894
  </react_native_1.View>
3846
-
3847
- {/* #1 — pulsing dot when a newer version is on NPM */}
3848
- {updateAvailable && (<react_native_1.Pressable hitSlop={10} onPress={() => react_native_1.Alert.alert('Update Available', `react-native-inapp-inspector v${latestNpmVersion} is available on NPM (installed: v${constants_1.LIB_VERSION}).`, [
3849
- { text: 'Later', style: 'cancel' },
3850
- {
3851
- text: 'View on NPM',
3852
- onPress: () => react_native_1.Linking.openURL('https://www.npmjs.com/package/react-native-inapp-inspector').catch(() => { }),
3853
- },
3854
- ])} style={{
3855
- alignItems: 'center',
3856
- justifyContent: 'center',
3857
- }}>
3858
- <react_native_1.Animated.View style={{
3859
- width: 8,
3860
- height: 8,
3861
- borderRadius: 4,
3862
- backgroundColor: '#4ADE80',
3863
- borderWidth: 1,
3864
- borderColor: 'rgba(255,255,255,0.9)',
3865
- opacity: activePulseAnim,
3866
- transform: [{ scale: unreadPulseAnim }],
3867
- }}/>
3868
- </react_native_1.Pressable>)}
3869
3895
  </react_native_1.View>
3870
3896
  </react_native_1.View>
3871
3897
  </react_native_1.View>) : null}
@@ -4150,14 +4176,6 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
4150
4176
  </react_native_1.Pressable>)}
4151
4177
  </react_native_1.View>
4152
4178
  {analyticsSubTab === 'ga_events' && (<react_native_1.View style={styles_1.default.toolbarRight}>
4153
- <TouchableScale_1.default style={[
4154
- styles_1.default.toolbarBtn,
4155
- !hideScreenView && styles_1.default.toolbarBtnActive,
4156
- ]} onPress={() => setHideScreenView(prev => !prev)} hitSlop={10}>
4157
- <NetworkIcons_1.ScreenIcon color={!hideScreenView
4158
- ? AppColors_1.AppColors.purple
4159
- : AppColors_1.AppColors.grayTextStrong} size={18}/>
4160
- </TouchableScale_1.default>
4161
4179
  <TouchableScale_1.default style={{
4162
4180
  flexDirection: 'row',
4163
4181
  alignItems: 'center',
@@ -4288,109 +4306,118 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
4288
4306
 
4289
4307
  {isReady ? (activeTab === 'insights' ? (<react_native_1.ScrollView style={styles_1.default.insightsContainer} contentContainerStyle={styles_1.default.insightsContent} showsVerticalScrollIndicator={false}>
4290
4308
  {renderInsightsDashboard()}
4291
- </react_native_1.ScrollView>) : activeTab === 'analytics' ? (selectedEvent != null ? (<AnalyticsDetail_1.default event={selectedEvent}/>) : analyticsSubTab === 'top_events' ? (<react_native_1.FlatList data={topEventsArray} keyExtractor={item => item[0]} contentContainerStyle={[
4292
- styles_1.default.listContent,
4293
- { paddingHorizontal: 16, paddingTop: 16 },
4294
- ]} renderItem={({ item: [name, count], index }) => {
4295
- const maxCount = topEventsArray[0]?.[1] || 1;
4296
- const color = (0, AnalyticsEventCard_1.getEventColor)(name);
4297
- return (<AnimatedEntrance_1.default index={index} distance={8} style={[
4298
- styles_1.default.analyticsTopEventsCard,
4299
- { marginBottom: 12, paddingVertical: 16 },
4300
- ]}>
4301
- <react_native_1.View style={styles_1.default.analyticsTopEventRow}>
4302
- <react_native_1.View style={{
4303
- flexDirection: 'row',
4304
- alignItems: 'center',
4305
- gap: 8,
4306
- flex: 1,
4307
- }}>
4308
- <react_native_1.View style={[
4309
- styles_1.default.analyticsIconCircle,
4310
- { backgroundColor: `${color}1A` },
4311
- ]}>
4312
- <react_native_svg_1.default width={14} height={14} viewBox="0 0 24 24" fill={color}>
4313
- <react_native_svg_1.Circle cx="12" cy="12" r="10" opacity="0.3"/>
4314
- <react_native_svg_1.Path d="M7 14l3-3 4 4 6-6" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" fill="none"/>
4315
- </react_native_svg_1.default>
4316
- </react_native_1.View>
4317
- <react_native_1.Text style={styles_1.default.analyticsTopEventName} numberOfLines={2}>
4318
- {name}
4309
+ </react_native_1.ScrollView>) : activeTab === 'analytics' ? (<react_native_1.View style={{ flex: 1 }}>
4310
+ {selectedEvent != null ? (<AnalyticsDetail_1.default event={selectedEvent}/>) : analyticsSubTab === 'top_events' ? (<react_native_1.FlatList data={topEventsArray} keyExtractor={item => item[0]} contentContainerStyle={[
4311
+ styles_1.default.listContent,
4312
+ { paddingHorizontal: 16, paddingTop: 12 },
4313
+ ]} renderItem={({ item: [name, count], index }) => {
4314
+ const maxCount = topEventsArray[0]?.[1] || 1;
4315
+ const pct = Math.max(6, (count / maxCount) * 100);
4316
+ const color = (0, AnalyticsEventCard_1.getEventColor)(name);
4317
+ return (<AnimatedEntrance_1.default index={index} distance={8} style={[
4318
+ styles_1.default.analyticsTopEventsCard,
4319
+ { marginBottom: 6, paddingVertical: 10, paddingHorizontal: 12 },
4320
+ ]}>
4321
+ <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 10 }}>
4322
+ <react_native_1.Text style={{
4323
+ fontFamily: AppFonts_1.AppFonts.interBold,
4324
+ fontSize: 11,
4325
+ color: color,
4326
+ width: 18,
4327
+ textAlign: 'center',
4328
+ }}>
4329
+ {index + 1}
4319
4330
  </react_native_1.Text>
4331
+ <react_native_1.View style={{ flex: 1, gap: 4 }}>
4332
+ <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }}>
4333
+ <react_native_1.Text style={{
4334
+ fontFamily: AppFonts_1.AppFonts.interMedium,
4335
+ fontSize: 12.5,
4336
+ color: AppColors_1.AppColors.primaryBlack,
4337
+ flex: 1,
4338
+ }} numberOfLines={1}>
4339
+ {name}
4340
+ </react_native_1.Text>
4341
+ <react_native_1.Text style={{
4342
+ fontFamily: AppFonts_1.AppFonts.interBold,
4343
+ fontSize: 12,
4344
+ color: color,
4345
+ marginLeft: 8,
4346
+ }}>
4347
+ {count}
4348
+ </react_native_1.Text>
4349
+ </react_native_1.View>
4350
+ <react_native_1.View style={{ height: 3, backgroundColor: AppColors_1.AppColors.grayBackground, borderRadius: 2, overflow: 'hidden' }}>
4351
+ <react_native_linear_gradient_1.default colors={[color, `${color}88`]} start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }} style={{
4352
+ height: '100%',
4353
+ borderRadius: 2,
4354
+ width: `${pct}%`,
4355
+ }}/>
4356
+ </react_native_1.View>
4357
+ </react_native_1.View>
4320
4358
  </react_native_1.View>
4321
- <react_native_1.View style={styles_1.default.analyticsTopEventBarWrap}>
4322
- <react_native_linear_gradient_1.default colors={[color, `${color}99`]} start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }} style={[
4323
- styles_1.default.analyticsTopEventBar,
4324
- {
4325
- width: `${Math.max(6, (count / maxCount) * 100)}%`,
4326
- },
4327
- ]}/>
4328
- </react_native_1.View>
4329
- <react_native_1.Text style={styles_1.default.analyticsTopEventCount}>
4330
- {count}
4331
- </react_native_1.Text>
4359
+ </AnimatedEntrance_1.default>);
4360
+ }} ListEmptyComponent={<react_native_1.View style={styles_1.default.emptyContainer}>
4361
+ <react_native_1.View style={styles_1.default.emptyIconWrap}>
4362
+ <NetworkIcons_1.EmptyRadarIcon color={AppColors_1.AppColors.purple} size={32}/>
4332
4363
  </react_native_1.View>
4333
- </AnimatedEntrance_1.default>);
4334
- }} ListEmptyComponent={<react_native_1.View style={styles_1.default.emptyContainer}>
4335
- <react_native_1.View style={styles_1.default.emptyIconWrap}>
4336
- <NetworkIcons_1.EmptyRadarIcon color={AppColors_1.AppColors.purple} size={32}/>
4337
- </react_native_1.View>
4338
- <react_native_1.Text style={styles_1.default.emptyTitle}>No Top Events</react_native_1.Text>
4339
- </react_native_1.View>}/>) : (<react_native_1.FlatList data={filteredAnalyticsEvents} keyExtractor={item => item.id.toString()} renderItem={({ item, index }) => {
4340
- const prev = filteredAnalyticsEvents[index + 1];
4341
- const next = filteredAnalyticsEvents[index - 1];
4342
- const msSincePrev = prev
4343
- ? item.timestamp - prev.timestamp
4344
- : undefined;
4345
- const thisMin = Math.floor(item.timestamp / 60000);
4346
- const nextMin = next
4347
- ? Math.floor(next.timestamp / 60000)
4348
- : -1;
4349
- const showTimestamp = index === 0 || thisMin !== nextMin;
4350
- return (<AnimatedEntrance_1.default index={index} distance={8}>
4351
- <AnalyticsEventCard_1.default event={item} onPress={() => {
4352
- animateNextLayout();
4353
- setSelectedEvent(item);
4354
- }} isNew={newEventIds.has(item.id)} searchStr={analyticsSearch} isFirst={index === 0} isLast={index === filteredAnalyticsEvents.length - 1} msSincePrev={msSincePrev} showTimestamp={showTimestamp} computedScreenName={(() => {
4355
- let screenName = item.screenName ||
4356
- item.screenClass ||
4357
- item.pageTitle ||
4358
- item.pageLocation ||
4359
- item.params?.firebase_screen ||
4360
- item.params?.screen_name ||
4361
- item.params?.firebase_screen_class ||
4362
- item.params?.screen_class;
4363
- const routeInfo = logRouteMapRef.current.get(item.id + 1000000);
4364
- if (!screenName) {
4365
- if (routeInfo &&
4366
- routeInfo.path !== 'Navigators') {
4367
- const parts = routeInfo.path.split(' ➔ ');
4368
- screenName = parts[parts.length - 1];
4364
+ <react_native_1.Text style={styles_1.default.emptyTitle}>No Top Events</react_native_1.Text>
4365
+ </react_native_1.View>}/>) : (<react_native_1.FlatList data={filteredAnalyticsEvents} keyExtractor={item => item.id.toString()} renderItem={({ item, index }) => {
4366
+ const prev = filteredAnalyticsEvents[index + 1];
4367
+ const next = filteredAnalyticsEvents[index - 1];
4368
+ const msSincePrev = prev
4369
+ ? item.timestamp - prev.timestamp
4370
+ : undefined;
4371
+ const thisMin = Math.floor(item.timestamp / 60000);
4372
+ const nextMin = next
4373
+ ? Math.floor(next.timestamp / 60000)
4374
+ : -1;
4375
+ const showTimestamp = index === 0 || thisMin !== nextMin;
4376
+ return (<AnimatedEntrance_1.default index={index} distance={8}>
4377
+ <AnalyticsEventCard_1.default event={item} onPress={() => {
4378
+ animateNextLayout();
4379
+ setSelectedEvent(item);
4380
+ }} isNew={newEventIds.has(item.id)} searchStr={analyticsSearch} isFirst={index === 0} isLast={index === filteredAnalyticsEvents.length - 1} msSincePrev={msSincePrev} showTimestamp={showTimestamp} computedScreenName={(() => {
4381
+ let screenName = item.screenName ||
4382
+ item.screenClass ||
4383
+ item.pageTitle ||
4384
+ item.pageLocation ||
4385
+ item.params?.firebase_screen ||
4386
+ item.params?.screen_name ||
4387
+ item.params?.firebase_screen_class ||
4388
+ item.params?.screen_class;
4389
+ const routeInfo = logRouteMapRef.current.get(item.id + 1000000);
4390
+ if (!screenName) {
4391
+ if (routeInfo &&
4392
+ routeInfo.path !== 'Navigators') {
4393
+ const parts = routeInfo.path.split(' ➔ ');
4394
+ screenName = parts[parts.length - 1];
4395
+ }
4369
4396
  }
4370
- }
4371
- return screenName;
4372
- })()}/>
4373
- </AnimatedEntrance_1.default>);
4374
- }} initialNumToRender={20} maxToRenderPerBatch={20} windowSize={5} removeClippedSubviews ListEmptyComponent={<react_native_1.View style={styles_1.default.emptyContainer}>
4375
- <react_native_1.View style={styles_1.default.emptyIconWrap}>
4376
- <NetworkIcons_1.EmptyRadarIcon color={AppColors_1.AppColors.purple} size={32}/>
4377
- </react_native_1.View>
4378
- <react_native_1.Text style={styles_1.default.emptyTitle}>
4379
- {analyticsSearch.length > 0
4380
- ? 'No matching events'
4381
- : 'No analytics events yet'}
4382
- </react_native_1.Text>
4383
- <react_native_1.Text style={styles_1.default.emptySub}>
4384
- {analyticsSearch.length > 0
4385
- ? 'Try adjusting your search.'
4386
- : 'Call setupAnalyticsLogger(analytics()) at app start.'}
4387
- </react_native_1.Text>
4388
- </react_native_1.View>} contentContainerStyle={[
4389
- styles_1.default.listContent,
4390
- filteredAnalyticsEvents.length === 0 && {
4391
- flexGrow: 1,
4392
- },
4393
- ]} keyboardShouldPersistTaps="handled"/>)) : activeTab === 'apis' && selected == null ? (<react_native_1.View style={{ flex: 1 }}>
4397
+ return screenName;
4398
+ })()}/>
4399
+ </AnimatedEntrance_1.default>);
4400
+ }} initialNumToRender={20} maxToRenderPerBatch={20} windowSize={5} removeClippedSubviews={false} ListEmptyComponent={<react_native_1.View style={styles_1.default.emptyContainer}>
4401
+ <react_native_1.View style={styles_1.default.emptyIconWrap}>
4402
+ <NetworkIcons_1.EmptyRadarIcon color={AppColors_1.AppColors.purple} size={32}/>
4403
+ </react_native_1.View>
4404
+ <react_native_1.Text style={styles_1.default.emptyTitle}>
4405
+ {analyticsSearch.length > 0
4406
+ ? 'No matching events'
4407
+ : 'No analytics events yet'}
4408
+ </react_native_1.Text>
4409
+ <react_native_1.Text style={styles_1.default.emptySub}>
4410
+ {analyticsSearch.length > 0
4411
+ ? 'Try adjusting your search.'
4412
+ : 'Call setupAnalyticsLogger(analytics()) at app start.'}
4413
+ </react_native_1.Text>
4414
+ </react_native_1.View>} contentContainerStyle={[
4415
+ styles_1.default.listContent,
4416
+ filteredAnalyticsEvents.length === 0 && {
4417
+ flexGrow: 1,
4418
+ },
4419
+ ]} keyboardShouldPersistTaps="handled"/>)}
4420
+ </react_native_1.View>) : activeTab === 'apis' && selected == null ? (<react_native_1.View style={{ flex: 1 }}>
4394
4421
  <react_native_1.FlatList ref={apisListRef} data={groupedData} keyExtractor={item => item?.id?.toString()} renderItem={renderItem} initialNumToRender={10} maxToRenderPerBatch={10} windowSize={5} removeClippedSubviews={true} ListHeaderComponent={<react_native_1.View style={{ marginTop: 8 }}>
4395
4422
  <react_native_1.View style={styles_1.default.toolbarRow}>
4396
4423
  <react_native_1.View style={styles_1.default.searchContainer}>