react-native-inapp-inspector 1.1.0 → 1.1.1

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.
package/dist/esm/index.js CHANGED
@@ -11,7 +11,7 @@ import CopyButton from './components/CopyButton';
11
11
  import SectionHeader from './components/SectionHeader';
12
12
  import EmptyState from './components/EmptyState';
13
13
  import JsonViewer from './components/JsonViewer';
14
- import { ReduxTreeView, ReduxActionTimeline } from './components/ReduxTreeView';
14
+ import { ReduxTreeView, ReduxActionTimeline, ReduxTimelineIcon, ReduxTreeIcon, } from './components/ReduxTreeView';
15
15
  import DomainHeader from './components/DomainHeader';
16
16
  import DiffViewer from './components/DiffViewer';
17
17
  import LogCard from './components/LogCard';
@@ -100,7 +100,7 @@ const previewInspectScript = `
100
100
  true;
101
101
  `;
102
102
  import { getReduxState, subscribeReduxState, setReduxAutoRefresh, getLastActionForReducer, getActionHistory, clearActionHistory, } from './customHooks/reduxLogger';
103
- import { METHOD_COLORS, STATUS_FILTERS } from './constants';
103
+ import { METHOD_COLORS, STATUS_FILTERS, LIB_VERSION } from './constants';
104
104
  const NavigationTracker = ({ onStateChange }) => {
105
105
  const navState = useNavigationState(state => state);
106
106
  useEffect(() => {
@@ -114,6 +114,12 @@ const animateNextLayout = () => {
114
114
  const NetworkInspector = ({ enabled = true, }) => {
115
115
  const [isDark, setIsDark] = useState(false);
116
116
  const [reduxState, setReduxState] = useState(null);
117
+ // Action timeline + per-reducer last action are kept in component state so the
118
+ // Redux tab re-renders live on every dispatch, independent of the state tree ref.
119
+ const [reduxActionHistory, setReduxActionHistory] = useState([]);
120
+ const [reduxLastActionMap, setReduxLastActionMap] = useState({});
121
+ // Inspector panel height as a percentage of the screen (configurable in Settings).
122
+ const [modalHeightPercent, setModalHeightPercent] = useState(90);
117
123
  const [expandedReducers, setExpandedReducers] = useState({});
118
124
  const [logs, setLogs] = useState([]);
119
125
  const [visible, setVisible] = useState(false);
@@ -480,8 +486,14 @@ const NetworkInspector = ({ enabled = true, }) => {
480
486
  }, 200);
481
487
  });
482
488
  setReduxState(getReduxState());
489
+ setReduxActionHistory([...getActionHistory()]);
490
+ setReduxLastActionMap({ ...getLastActionForReducer() });
483
491
  const unsubscribeRedux = subscribeReduxState(() => {
492
+ // New references each time guarantee the Redux tab updates live, even when
493
+ // the root state object reference is unchanged or auto-refresh is paused.
484
494
  setReduxState(getReduxState());
495
+ setReduxActionHistory([...getActionHistory()]);
496
+ setReduxLastActionMap({ ...getLastActionForReducer() });
485
497
  });
486
498
  return () => {
487
499
  unsubscribe();
@@ -995,7 +1007,7 @@ const NetworkInspector = ({ enabled = true, }) => {
995
1007
  fontSize: 10.5,
996
1008
  color: '#FFFFFF',
997
1009
  }}>
998
- v1.0.13
1010
+ v{LIB_VERSION}
999
1011
  </Text>
1000
1012
  </View>
1001
1013
  </View>
@@ -1163,24 +1175,50 @@ const NetworkInspector = ({ enabled = true, }) => {
1163
1175
  width: 38,
1164
1176
  height: 22,
1165
1177
  borderRadius: 11,
1166
- backgroundColor: isVisible
1167
- ? AppColors.purple
1168
- : AppColors.grayBorderSecondary,
1178
+ backgroundColor: isLocked
1179
+ ? AppColors.grayBackground
1180
+ : isVisible
1181
+ ? AppColors.purple
1182
+ : AppColors.grayBorderSecondary,
1183
+ borderWidth: isLocked ? 1.5 : 0,
1184
+ borderColor: isLocked
1185
+ ? AppColors.grayBorderSecondary
1186
+ : 'transparent',
1187
+ borderStyle: isLocked ? 'dashed' : 'solid',
1169
1188
  padding: 2,
1170
1189
  justifyContent: 'center',
1171
1190
  alignItems: isVisible ? 'flex-end' : 'flex-start',
1191
+ opacity: isLocked ? 0.9 : 1,
1172
1192
  }}>
1173
1193
  <View style={{
1174
1194
  width: 18,
1175
1195
  height: 18,
1176
1196
  borderRadius: 9,
1177
- backgroundColor: '#FFFFFF',
1197
+ backgroundColor: isLocked
1198
+ ? AppColors.grayBorderSecondary
1199
+ : '#FFFFFF',
1200
+ alignItems: 'center',
1201
+ justifyContent: 'center',
1178
1202
  shadowColor: '#000',
1179
- shadowOpacity: 0.15,
1203
+ shadowOpacity: isLocked ? 0 : 0.15,
1180
1204
  shadowRadius: 1.5,
1181
1205
  shadowOffset: { width: 0, height: 1 },
1182
- }}/>
1206
+ }}>
1207
+ {isLocked && (<Svg width={10} height={10} viewBox="0 0 24 24" fill="none">
1208
+ <Path d="M7 10V7a5 5 0 0 1 10 0v3" stroke={AppColors.grayText} strokeWidth="2.2" strokeLinecap="round"/>
1209
+ <Path d="M5 10h14v9a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1z" fill={AppColors.grayText}/>
1210
+ </Svg>)}
1211
+ </View>
1183
1212
  </TouchableScale>
1213
+ {isLocked && (<Text style={{
1214
+ fontFamily: AppFonts.interBold,
1215
+ fontSize: 8,
1216
+ color: AppColors.grayTextWeak,
1217
+ letterSpacing: 0.4,
1218
+ marginTop: 3,
1219
+ }}>
1220
+ REQUIRED
1221
+ </Text>)}
1184
1222
  </View>
1185
1223
  </View>);
1186
1224
  })}
@@ -1269,6 +1307,86 @@ const NetworkInspector = ({ enabled = true, }) => {
1269
1307
  }}/>
1270
1308
  </TouchableScale>
1271
1309
  </View>
1310
+
1311
+ {/* Divider */}
1312
+ <View style={{
1313
+ height: 1,
1314
+ backgroundColor: AppColors.dividerColor,
1315
+ }}/>
1316
+
1317
+ {/* Modal Height */}
1318
+ <View style={{
1319
+ paddingVertical: 12,
1320
+ paddingHorizontal: 14,
1321
+ }}>
1322
+ <View style={{
1323
+ flexDirection: 'row',
1324
+ alignItems: 'center',
1325
+ gap: 8,
1326
+ }}>
1327
+ <View style={{
1328
+ width: 20,
1329
+ height: 20,
1330
+ borderRadius: 6,
1331
+ backgroundColor: AppColors.purpleShade50,
1332
+ borderWidth: 1,
1333
+ borderColor: 'rgba(104,75,155,0.2)',
1334
+ alignItems: 'center',
1335
+ justifyContent: 'center',
1336
+ }}>
1337
+ <ScreenIcon color={AppColors.purple} size={11}/>
1338
+ </View>
1339
+ <View style={{ flex: 1 }}>
1340
+ <Text style={{
1341
+ fontFamily: AppFonts.interBold,
1342
+ fontSize: 13,
1343
+ color: AppColors.primaryBlack,
1344
+ }}>
1345
+ Modal Height
1346
+ </Text>
1347
+ <Text style={{
1348
+ fontFamily: AppFonts.interRegular,
1349
+ fontSize: 11,
1350
+ color: AppColors.grayText,
1351
+ marginTop: 1,
1352
+ }}>
1353
+ Height of the inspector panel relative to the screen
1354
+ </Text>
1355
+ </View>
1356
+ </View>
1357
+
1358
+ {/* Segmented picker */}
1359
+ <View style={{
1360
+ flexDirection: 'row',
1361
+ backgroundColor: AppColors.grayBackground,
1362
+ borderRadius: 8,
1363
+ padding: 2.5,
1364
+ marginTop: 10,
1365
+ borderWidth: 1,
1366
+ borderColor: AppColors.dividerColor,
1367
+ }}>
1368
+ {[50, 70, 90, 100].map(opt => {
1369
+ const isActive = modalHeightPercent === opt;
1370
+ return (<TouchableScale key={opt} onPress={() => setModalHeightPercent(opt)} style={{
1371
+ flex: 1,
1372
+ paddingVertical: 6,
1373
+ alignItems: 'center',
1374
+ borderRadius: 6,
1375
+ backgroundColor: isActive
1376
+ ? AppColors.purple
1377
+ : 'transparent',
1378
+ }}>
1379
+ <Text style={{
1380
+ fontFamily: AppFonts.interBold,
1381
+ fontSize: 11,
1382
+ color: isActive ? '#FFFFFF' : AppColors.grayText,
1383
+ }}>
1384
+ {opt}%
1385
+ </Text>
1386
+ </TouchableScale>);
1387
+ })}
1388
+ </View>
1389
+ </View>
1272
1390
  </View>
1273
1391
  </View>
1274
1392
  </ScrollView>
@@ -1403,11 +1521,13 @@ const NetworkInspector = ({ enabled = true, }) => {
1403
1521
  fontSize: 11,
1404
1522
  color: isActive ? '#FFFFFF' : AppColors.grayText,
1405
1523
  }}>
1406
- {typeof opt === 'number' &&
1407
- opt >= 500 &&
1408
- settingsPage === 'insights'
1409
- ? `${opt}ms`
1410
- : opt}
1524
+ {opts.picker.formatLabel
1525
+ ? opts.picker.formatLabel(opt)
1526
+ : typeof opt === 'number' &&
1527
+ opt >= 500 &&
1528
+ settingsPage === 'insights'
1529
+ ? `${opt}ms`
1530
+ : opt}
1411
1531
  </Text>
1412
1532
  </TouchableScale>);
1413
1533
  })}
@@ -1872,7 +1992,187 @@ const NetworkInspector = ({ enabled = true, }) => {
1872
1992
  e.name === 'page_view' ||
1873
1993
  e.name === 'firebase_screen_class').length;
1874
1994
  const webviewTotal = webViewNavHistory.length;
1995
+ // --- Richer insights metrics ---
1996
+ const slowestTime = durations.length > 0 ? Math.max(...durations) : null;
1997
+ const fastestTime = durations.length > 0 ? Math.min(...durations) : null;
1998
+ const slowCount = durations.filter(d => d >= slowRequestThreshold).length;
1999
+ const status2xx = logs.filter(l => l.status != null && l.status >= 200 && l.status < 300).length;
2000
+ const status3xx = logs.filter(l => l.status != null && l.status >= 300 && l.status < 400).length;
2001
+ const status4xx = logs.filter(l => l.status != null && l.status >= 400 && l.status < 500).length;
2002
+ const status5xx = logs.filter(l => l.status != null && l.status >= 500).length;
2003
+ const totalSignals = apiTotal + logTotal + analyticsTotal + webviewTotal;
2004
+ const totalIssues = apiErrors + logErrors;
2005
+ const activeModules = [
2006
+ tabVisibility.apis,
2007
+ tabVisibility.logs,
2008
+ tabVisibility.analytics,
2009
+ tabVisibility.webview,
2010
+ tabVisibility.redux,
2011
+ ].filter(Boolean).length;
2012
+ // Composite health score: success rate penalised by error volume and slow requests.
2013
+ const healthScore = totalSignals === 0
2014
+ ? 100
2015
+ : Math.max(0, Math.min(100, Math.round(apiSuccessRate -
2016
+ (logErrors > 0 ? Math.min(15, logErrors * 3) : 0) -
2017
+ (slowCount > 0 ? Math.min(10, slowCount * 2) : 0))));
2018
+ const healthColor = healthScore >= 90
2019
+ ? AppColors.greenColor
2020
+ : healthScore >= 70
2021
+ ? AppColors.warningIconGold
2022
+ : AppColors.errorColor;
2023
+ const healthLabel = healthScore >= 90
2024
+ ? 'Healthy'
2025
+ : healthScore >= 70
2026
+ ? 'Needs attention'
2027
+ : 'Degraded';
1875
2028
  return (<View style={styles.dashboardContainer}>
2029
+ {/* Overview hero card */}
2030
+ <View style={{
2031
+ backgroundColor: AppColors.primaryLight,
2032
+ borderRadius: 14,
2033
+ borderWidth: 1,
2034
+ borderColor: AppColors.grayBorderSecondary,
2035
+ padding: 16,
2036
+ marginBottom: 12,
2037
+ }}>
2038
+ <View style={{
2039
+ flexDirection: 'row',
2040
+ alignItems: 'center',
2041
+ gap: 14,
2042
+ }}>
2043
+ {/* Health ring stand-in */}
2044
+ <View style={{
2045
+ width: 64,
2046
+ height: 64,
2047
+ borderRadius: 32,
2048
+ borderWidth: 4,
2049
+ borderColor: healthColor,
2050
+ alignItems: 'center',
2051
+ justifyContent: 'center',
2052
+ backgroundColor: AppColors.purpleShade50,
2053
+ }}>
2054
+ <Text style={{
2055
+ fontFamily: AppFonts.interBold,
2056
+ fontSize: 18,
2057
+ color: healthColor,
2058
+ }}>
2059
+ {healthScore}
2060
+ </Text>
2061
+ <Text style={{
2062
+ fontFamily: AppFonts.interMedium,
2063
+ fontSize: 7.5,
2064
+ color: AppColors.grayTextWeak,
2065
+ letterSpacing: 0.4,
2066
+ }}>
2067
+ HEALTH
2068
+ </Text>
2069
+ </View>
2070
+ <View style={{ flex: 1 }}>
2071
+ <Text style={{
2072
+ fontFamily: AppFonts.interBold,
2073
+ fontSize: 15,
2074
+ color: AppColors.primaryBlack,
2075
+ }}>
2076
+ Session Overview
2077
+ </Text>
2078
+ <View style={{
2079
+ flexDirection: 'row',
2080
+ alignItems: 'center',
2081
+ gap: 6,
2082
+ marginTop: 3,
2083
+ }}>
2084
+ <View style={{
2085
+ width: 7,
2086
+ height: 7,
2087
+ borderRadius: 3.5,
2088
+ backgroundColor: healthColor,
2089
+ }}/>
2090
+ <Text style={{
2091
+ fontFamily: AppFonts.interMedium,
2092
+ fontSize: 11.5,
2093
+ color: healthColor,
2094
+ }}>
2095
+ {healthLabel}
2096
+ </Text>
2097
+ <Text style={{
2098
+ fontFamily: AppFonts.interRegular,
2099
+ fontSize: 11.5,
2100
+ color: AppColors.grayTextWeak,
2101
+ }}>
2102
+ • {activeModules} modules active
2103
+ </Text>
2104
+ </View>
2105
+ </View>
2106
+ </View>
2107
+
2108
+ {/* Quick totals strip */}
2109
+ <View style={{
2110
+ flexDirection: 'row',
2111
+ marginTop: 14,
2112
+ borderTopWidth: 1,
2113
+ borderTopColor: AppColors.dividerColor,
2114
+ paddingTop: 12,
2115
+ }}>
2116
+ <View style={{ flex: 1, alignItems: 'center' }}>
2117
+ <Text style={{
2118
+ fontFamily: AppFonts.interBold,
2119
+ fontSize: 16,
2120
+ color: AppColors.primaryBlack,
2121
+ }}>
2122
+ {totalSignals}
2123
+ </Text>
2124
+ <Text style={{
2125
+ fontFamily: AppFonts.interRegular,
2126
+ fontSize: 10,
2127
+ color: AppColors.grayTextWeak,
2128
+ marginTop: 1,
2129
+ }}>
2130
+ Signals
2131
+ </Text>
2132
+ </View>
2133
+ <View style={{ width: 1, backgroundColor: AppColors.dividerColor }}/>
2134
+ <View style={{ flex: 1, alignItems: 'center' }}>
2135
+ <Text style={{
2136
+ fontFamily: AppFonts.interBold,
2137
+ fontSize: 16,
2138
+ color: totalIssues > 0
2139
+ ? AppColors.errorColor
2140
+ : AppColors.primaryBlack,
2141
+ }}>
2142
+ {totalIssues}
2143
+ </Text>
2144
+ <Text style={{
2145
+ fontFamily: AppFonts.interRegular,
2146
+ fontSize: 10,
2147
+ color: AppColors.grayTextWeak,
2148
+ marginTop: 1,
2149
+ }}>
2150
+ Issues
2151
+ </Text>
2152
+ </View>
2153
+ <View style={{ width: 1, backgroundColor: AppColors.dividerColor }}/>
2154
+ <View style={{ flex: 1, alignItems: 'center' }}>
2155
+ <Text style={{
2156
+ fontFamily: AppFonts.interBold,
2157
+ fontSize: 16,
2158
+ color: slowCount > 0
2159
+ ? AppColors.warningIconGold
2160
+ : AppColors.primaryBlack,
2161
+ }}>
2162
+ {slowCount}
2163
+ </Text>
2164
+ <Text style={{
2165
+ fontFamily: AppFonts.interRegular,
2166
+ fontSize: 10,
2167
+ color: AppColors.grayTextWeak,
2168
+ marginTop: 1,
2169
+ }}>
2170
+ Slow ({slowRequestThreshold}ms+)
2171
+ </Text>
2172
+ </View>
2173
+ </View>
2174
+ </View>
2175
+
1876
2176
  {/* Module 1: APIs */}
1877
2177
  {tabVisibility.apis && (<TouchableScale style={styles.dashboardModuleCard} onPress={() => switchActiveTab('apis')}>
1878
2178
  <View style={styles.dashboardModuleHeader}>
@@ -1912,9 +2212,75 @@ const NetworkInspector = ({ enabled = true, }) => {
1912
2212
  <Text style={styles.dashboardGridLbl}>Avg Latency</Text>
1913
2213
  </View>
1914
2214
  </View>
1915
- </TouchableScale>)}
1916
2215
 
1917
- {/* Module 2: Logs */}
2216
+ {/* Status-class breakdown + latency range */}
2217
+ <View style={{
2218
+ marginTop: 10,
2219
+ paddingTop: 10,
2220
+ borderTopWidth: 1,
2221
+ borderTopColor: AppColors.dividerColor,
2222
+ flexDirection: 'row',
2223
+ alignItems: 'center',
2224
+ flexWrap: 'wrap',
2225
+ gap: 6,
2226
+ }}>
2227
+ {[
2228
+ { label: '2xx', value: status2xx, color: AppColors.greenColor },
2229
+ { label: '3xx', value: status3xx, color: AppColors.skyBlue },
2230
+ {
2231
+ label: '4xx',
2232
+ value: status4xx,
2233
+ color: AppColors.warningIconGold,
2234
+ },
2235
+ { label: '5xx', value: status5xx, color: AppColors.errorColor },
2236
+ ].map(s => (<View key={s.label} style={{
2237
+ flexDirection: 'row',
2238
+ alignItems: 'center',
2239
+ gap: 4,
2240
+ backgroundColor: AppColors.grayBackground,
2241
+ borderRadius: 6,
2242
+ borderWidth: 1,
2243
+ borderColor: AppColors.dividerColor,
2244
+ paddingHorizontal: 7,
2245
+ paddingVertical: 3,
2246
+ }}>
2247
+ <View style={{
2248
+ width: 6,
2249
+ height: 6,
2250
+ borderRadius: 3,
2251
+ backgroundColor: s.color,
2252
+ }}/>
2253
+ <Text style={{
2254
+ fontFamily: AppFonts.interBold,
2255
+ fontSize: 10,
2256
+ color: AppColors.grayTextStrong,
2257
+ }}>
2258
+ {s.label} {s.value}
2259
+ </Text>
2260
+ </View>))}
2261
+ {slowestTime != null && (<View style={{
2262
+ marginLeft: 'auto',
2263
+ flexDirection: 'row',
2264
+ alignItems: 'center',
2265
+ gap: 4,
2266
+ }}>
2267
+ <Text style={{
2268
+ fontFamily: AppFonts.interRegular,
2269
+ fontSize: 10,
2270
+ color: AppColors.grayTextWeak,
2271
+ }}>
2272
+ Range
2273
+ </Text>
2274
+ <Text style={{
2275
+ fontFamily: AppFonts.interBold,
2276
+ fontSize: 10,
2277
+ color: AppColors.grayTextStrong,
2278
+ }}>
2279
+ {fastestTime}–{slowestTime}ms
2280
+ </Text>
2281
+ </View>)}
2282
+ </View>
2283
+ </TouchableScale>)}
1918
2284
  {tabVisibility.logs && (<TouchableScale style={styles.dashboardModuleCard} onPress={() => switchActiveTab('logs')}>
1919
2285
  <View style={styles.dashboardModuleHeader}>
1920
2286
  <View style={{ flexDirection: 'row', alignItems: 'center', gap: 8 }}>
@@ -2118,9 +2484,10 @@ const NetworkInspector = ({ enabled = true, }) => {
2118
2484
  <Text style={styles.emptySub}>Connected store state is empty.</Text>
2119
2485
  </View>);
2120
2486
  }
2121
- // Build hierarchical tree: Store -> Reducers -> Action -> Data
2122
- const lastActionMap = getLastActionForReducer();
2123
- const actionHistory = getActionHistory();
2487
+ // Build hierarchical tree: Store -> Reducers -> Action -> Data.
2488
+ // These come from component state (refreshed on every dispatch) so the view stays live.
2489
+ const lastActionMap = reduxLastActionMap;
2490
+ const actionHistory = reduxActionHistory;
2124
2491
  return (<ScrollView style={styles.detailScroll} contentContainerStyle={{ paddingBottom: 24 }}>
2125
2492
  {/* Top Summary Card */}
2126
2493
  <View style={{
@@ -2190,15 +2557,25 @@ const NetworkInspector = ({ enabled = true, }) => {
2190
2557
  ? AppColors.purple
2191
2558
  : 'transparent',
2192
2559
  }}>
2193
- <Text style={{
2560
+ <View style={{
2561
+ flexDirection: 'row',
2562
+ alignItems: 'center',
2563
+ justifyContent: 'center',
2564
+ gap: 6,
2565
+ }}>
2566
+ <ReduxTimelineIcon color={reduxActiveSubTab === 'timeline'
2567
+ ? '#FFFFFF'
2568
+ : AppColors.grayText} size={13}/>
2569
+ <Text style={{
2194
2570
  fontFamily: AppFonts.interBold,
2195
2571
  fontSize: 11,
2196
2572
  color: reduxActiveSubTab === 'timeline'
2197
2573
  ? '#FFFFFF'
2198
2574
  : AppColors.grayText,
2199
2575
  }}>
2200
- Action Timeline
2201
- </Text>
2576
+ Action Timeline
2577
+ </Text>
2578
+ </View>
2202
2579
  </TouchableOpacity>
2203
2580
  <TouchableOpacity onPress={() => {
2204
2581
  animateNextLayout();
@@ -2211,13 +2588,23 @@ const NetworkInspector = ({ enabled = true, }) => {
2211
2588
  borderRadius: 8,
2212
2589
  backgroundColor: reduxActiveSubTab === 'tree' ? AppColors.purple : 'transparent',
2213
2590
  }}>
2214
- <Text style={{
2591
+ <View style={{
2592
+ flexDirection: 'row',
2593
+ alignItems: 'center',
2594
+ justifyContent: 'center',
2595
+ gap: 6,
2596
+ }}>
2597
+ <ReduxTreeIcon color={reduxActiveSubTab === 'tree' ? '#FFFFFF' : AppColors.grayText} size={13}/>
2598
+ <Text style={{
2215
2599
  fontFamily: AppFonts.interBold,
2216
2600
  fontSize: 11,
2217
- color: reduxActiveSubTab === 'tree' ? '#FFFFFF' : AppColors.grayText,
2601
+ color: reduxActiveSubTab === 'tree'
2602
+ ? '#FFFFFF'
2603
+ : AppColors.grayText,
2218
2604
  }}>
2219
- 🏪 Store Tree
2220
- </Text>
2605
+ Store Tree
2606
+ </Text>
2607
+ </View>
2221
2608
  </TouchableOpacity>
2222
2609
  </View>
2223
2610
 
@@ -2283,7 +2670,10 @@ const NetworkInspector = ({ enabled = true, }) => {
2283
2670
  {visible && (<ErrorBoundary onClose={closeModal}>
2284
2671
  <View style={styles.modalBackdrop}>
2285
2672
  <Pressable style={styles.modalBackdropPressable} onPress={closeModal}/>
2286
- <View style={styles.modalContentCard}>
2673
+ <View style={[
2674
+ styles.modalContentCard,
2675
+ { height: `${modalHeightPercent}%` },
2676
+ ]}>
2287
2677
  <StatusBar translucent backgroundColor="transparent" barStyle="light-content"/>
2288
2678
 
2289
2679
  <LinearGradient colors={[AppColors.purple, '#6B4EFF']} style={styles.headerGradient}>
@@ -2343,25 +2733,83 @@ const NetworkInspector = ({ enabled = true, }) => {
2343
2733
  <View style={{
2344
2734
  flexDirection: 'row',
2345
2735
  alignItems: 'center',
2346
- gap: 5,
2736
+ gap: 6,
2347
2737
  }}>
2348
- <Animated.View style={{
2349
- width: 6,
2350
- height: 6,
2351
- borderRadius: 3,
2352
- backgroundColor: '#4ADE80',
2353
- opacity: activePulseAnim,
2354
- }}/>
2355
- <Text style={{
2738
+ {/* OS chip */}
2739
+ <View style={{
2740
+ flexDirection: 'row',
2741
+ alignItems: 'center',
2742
+ borderRadius: 6,
2743
+ overflow: 'hidden',
2744
+ borderWidth: 1,
2745
+ borderColor: 'rgba(255,255,255,0.18)',
2746
+ }}>
2747
+ <View style={{
2748
+ paddingHorizontal: 5,
2749
+ paddingVertical: 2,
2750
+ backgroundColor: 'rgba(255,255,255,0.28)',
2751
+ }}>
2752
+ <Text style={{
2753
+ fontFamily: AppFonts.interBold,
2754
+ fontSize: 9,
2755
+ color: '#FFFFFF',
2756
+ letterSpacing: 0.3,
2757
+ }}>
2758
+ {Platform.OS === 'ios' ? 'iOS' : 'Android'}
2759
+ </Text>
2760
+ </View>
2761
+ <View style={{
2762
+ paddingHorizontal: 5,
2763
+ paddingVertical: 2,
2764
+ backgroundColor: 'rgba(255,255,255,0.12)',
2765
+ }}>
2766
+ <Text style={{
2356
2767
  fontFamily: AppFonts.interMedium,
2357
- fontSize: 10,
2358
- color: 'rgba(255,255,255,0.78)',
2768
+ fontSize: 9.5,
2769
+ color: 'rgba(255,255,255,0.92)',
2770
+ }}>
2771
+ {String(Platform.Version)}
2772
+ </Text>
2773
+ </View>
2774
+ </View>
2775
+
2776
+ {/* npm chip */}
2777
+ <View style={{
2778
+ flexDirection: 'row',
2779
+ alignItems: 'center',
2780
+ borderRadius: 6,
2781
+ overflow: 'hidden',
2782
+ borderWidth: 1,
2783
+ borderColor: 'rgba(255,255,255,0.18)',
2784
+ }}>
2785
+ <View style={{
2786
+ paddingHorizontal: 5,
2787
+ paddingVertical: 2,
2788
+ backgroundColor: 'rgba(255,255,255,0.28)',
2789
+ }}>
2790
+ <Text style={{
2791
+ fontFamily: AppFonts.interBold,
2792
+ fontSize: 9,
2793
+ color: '#FFFFFF',
2359
2794
  letterSpacing: 0.3,
2360
2795
  }}>
2361
- Active •{' '}
2362
- {Platform.OS === 'ios' ? 'iOS' : 'Android'}{' '}
2363
- (v1.0.13)
2364
- </Text>
2796
+ npm
2797
+ </Text>
2798
+ </View>
2799
+ <View style={{
2800
+ paddingHorizontal: 5,
2801
+ paddingVertical: 2,
2802
+ backgroundColor: 'rgba(255,255,255,0.12)',
2803
+ }}>
2804
+ <Text style={{
2805
+ fontFamily: AppFonts.interMedium,
2806
+ fontSize: 9.5,
2807
+ color: 'rgba(255,255,255,0.92)',
2808
+ }}>
2809
+ v{LIB_VERSION}
2810
+ </Text>
2811
+ </View>
2812
+ </View>
2365
2813
  </View>
2366
2814
  </View>
2367
2815
  </View>) : null}