react-native-inapp-inspector 2.3.14 → 2.3.15

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 (65) hide show
  1. package/dist/commonjs/components/AnimatedEntrance.js +3 -3
  2. package/dist/commonjs/components/ConsoleLogCard.js +174 -100
  3. package/dist/commonjs/components/Inspector/ConsoleTab.js +25 -16
  4. package/dist/commonjs/components/Inspector/CrashTab.js +19 -5
  5. package/dist/commonjs/components/Inspector/DeviceInfoTab.js +198 -98
  6. package/dist/commonjs/components/Inspector/InspectorHeader.js +2 -2
  7. package/dist/commonjs/components/Inspector/MainScreen.js +56 -56
  8. package/dist/commonjs/components/Inspector/NetworkTab.js +1 -335
  9. package/dist/commonjs/components/Inspector/PerformanceTab.js +32 -6
  10. package/dist/commonjs/components/Inspector/ReduxTab.js +3 -1
  11. package/dist/commonjs/components/Inspector/StorageTab.js +23 -5
  12. package/dist/commonjs/components/JsonViewer.js +14 -2
  13. package/dist/commonjs/components/LogCard.js +428 -227
  14. package/dist/commonjs/constants/version.d.ts +1 -1
  15. package/dist/commonjs/constants/version.js +1 -1
  16. package/dist/commonjs/customHooks/analyticsLogger.js +1 -1
  17. package/dist/commonjs/customHooks/consoleLogger.js +34 -2
  18. package/dist/commonjs/customHooks/crashHandler.js +1 -1
  19. package/dist/commonjs/customHooks/networkLogger.js +184 -26
  20. package/dist/commonjs/helpers/searchQueryParser.d.ts +1 -1
  21. package/dist/commonjs/helpers/searchQueryParser.js +37 -291
  22. package/dist/commonjs/index.js +141 -27
  23. package/dist/esm/components/AnimatedEntrance.js +3 -3
  24. package/dist/esm/components/ConsoleLogCard.js +141 -100
  25. package/dist/esm/components/Inspector/ConsoleTab.js +25 -16
  26. package/dist/esm/components/Inspector/CrashTab.js +19 -5
  27. package/dist/esm/components/Inspector/DeviceInfoTab.js +198 -98
  28. package/dist/esm/components/Inspector/InspectorHeader.js +3 -3
  29. package/dist/esm/components/Inspector/MainScreen.js +56 -56
  30. package/dist/esm/components/Inspector/NetworkTab.js +2 -336
  31. package/dist/esm/components/Inspector/PerformanceTab.js +32 -6
  32. package/dist/esm/components/Inspector/ReduxTab.js +3 -1
  33. package/dist/esm/components/Inspector/StorageTab.js +23 -5
  34. package/dist/esm/components/JsonViewer.js +14 -2
  35. package/dist/esm/components/LogCard.js +422 -221
  36. package/dist/esm/constants/version.d.ts +1 -1
  37. package/dist/esm/constants/version.js +1 -1
  38. package/dist/esm/customHooks/analyticsLogger.js +1 -1
  39. package/dist/esm/customHooks/consoleLogger.js +34 -2
  40. package/dist/esm/customHooks/crashHandler.js +1 -1
  41. package/dist/esm/customHooks/networkLogger.js +184 -26
  42. package/dist/esm/helpers/searchQueryParser.d.ts +1 -1
  43. package/dist/esm/helpers/searchQueryParser.js +37 -291
  44. package/dist/esm/index.js +141 -27
  45. package/package.json +1 -1
  46. package/src/components/AnimatedEntrance.tsx +3 -3
  47. package/src/components/ConsoleLogCard.tsx +154 -103
  48. package/src/components/Inspector/ConsoleTab.tsx +27 -18
  49. package/src/components/Inspector/CrashTab.tsx +19 -5
  50. package/src/components/Inspector/DeviceInfoTab.tsx +224 -102
  51. package/src/components/Inspector/InspectorHeader.tsx +5 -3
  52. package/src/components/Inspector/MainScreen.tsx +2 -3
  53. package/src/components/Inspector/NetworkTab.tsx +1 -402
  54. package/src/components/Inspector/PerformanceTab.tsx +36 -7
  55. package/src/components/Inspector/ReduxTab.tsx +9 -1
  56. package/src/components/Inspector/StorageTab.tsx +27 -7
  57. package/src/components/JsonViewer.tsx +15 -2
  58. package/src/components/LogCard.tsx +528 -339
  59. package/src/constants/version.ts +1 -1
  60. package/src/customHooks/analyticsLogger.ts +1 -1
  61. package/src/customHooks/consoleLogger.ts +36 -3
  62. package/src/customHooks/crashHandler.ts +1 -1
  63. package/src/customHooks/networkLogger.ts +214 -26
  64. package/src/helpers/searchQueryParser.ts +40 -285
  65. package/src/index.tsx +332 -211
@@ -338,19 +338,119 @@ export const DeviceInfoTab = React.memo(() => {
338
338
  copyToClipboard(md, 'Device Markdown Report');
339
339
  showToast('Copied Markdown Report to Clipboard!');
340
340
  };
341
- const isMatch = (text) => {
341
+ const isMatch = useCallback((label, value, subtext) => {
342
342
  if (!search.trim())
343
343
  return true;
344
- return text.toLowerCase().includes(search.toLowerCase().trim());
345
- };
344
+ const query = search.toLowerCase().trim();
345
+ const strVal = value != null
346
+ ? typeof value === 'object'
347
+ ? JSON.stringify(value)
348
+ : String(value)
349
+ : '';
350
+ const strSub = subtext != null ? String(subtext) : '';
351
+ return (label.toLowerCase().includes(query) ||
352
+ strVal.toLowerCase().includes(query) ||
353
+ strSub.toLowerCase().includes(query));
354
+ }, [search]);
355
+ const hasHeroMatch = useMemo(() => {
356
+ if (!search.trim())
357
+ return true;
358
+ return (isMatch('Model', deviceMetrics?.deviceModel || Platform.constants?.Model) ||
359
+ isMatch('OS', Platform.OS) ||
360
+ isMatch('IP Address', ipAddress) ||
361
+ isMatch('RAM', `${usedRamMb}/${totalRamMb}`) ||
362
+ isMatch('Uptime', deviceUptime));
363
+ }, [search, isMatch, deviceMetrics, ipAddress, usedRamMb, totalRamMb, deviceUptime]);
364
+ const hasOverviewMatch = useMemo(() => {
365
+ if (!search.trim())
366
+ return true;
367
+ return (isMatch('Device Model', fullDeviceData.hardware.model) ||
368
+ isMatch('Manufacturer', fullDeviceData.hardware.brand) ||
369
+ isMatch('Operating System', fullDeviceData.hardware.osVersion) ||
370
+ isMatch('IP Address', ipAddress) ||
371
+ isMatch('RAM Memory', `${usedRamMb} MB / ${totalRamMb} MB (${ramUsagePct}%)`, `Free Memory: ${freeRamMb} MB`) ||
372
+ isMatch('Storage Capacity', `${freeStorageGb} GB Free / ${totalStorageGb} GB Total`) ||
373
+ isMatch('App Version', `v${fullDeviceData.runtime.appVersion} (${fullDeviceData.runtime.appBuild})`) ||
374
+ isMatch('JavaScript Engine', isHermes ? 'Hermes Bytecode Engine' : 'JavaScriptCore (JSC)') ||
375
+ isMatch('UDID Identifier', pseudoUDID));
376
+ }, [search, isMatch, fullDeviceData, ipAddress, usedRamMb, totalRamMb, ramUsagePct, freeRamMb, freeStorageGb, totalStorageGb, isHermes, pseudoUDID]);
377
+ const hasHardwareMatch = useMemo(() => {
378
+ if (!search.trim())
379
+ return true;
380
+ return (isMatch('CPU Architecture', fullDeviceData.hardware.cpuAbi) ||
381
+ isMatch('Total RAM', `${totalRamMb} MB`) ||
382
+ isMatch('Free RAM', `${freeRamMb} MB`) ||
383
+ isMatch('Storage Capacity', `${totalStorageGb} GB`) ||
384
+ isMatch('Available Storage', `${freeStorageGb} GB`) ||
385
+ isMatch('Battery', `${deviceMetrics?.batteryPercent ?? 100}%`) ||
386
+ isMatch('API Level', `API ${deviceMetrics?.apiLevel || Platform.Version}`) ||
387
+ isMatch('Thermal State', 'Nominal (Cool)'));
388
+ }, [search, isMatch, fullDeviceData, totalRamMb, freeRamMb, totalStorageGb, freeStorageGb, deviceMetrics]);
389
+ const hasNetworkMatch = useMemo(() => {
390
+ if (!search.trim())
391
+ return true;
392
+ return (isMatch('IP Address', ipAddress) ||
393
+ isMatch('Internet Reachability', 'Connected') ||
394
+ isMatch('Connection Type', 'Wi-Fi / Local Area Network') ||
395
+ isMatch('Metro Dev Server', NativeModules?.PlatformConstants?.serverHost || NativeModules?.AndroidConstants?.serverHost || 'localhost:8081') ||
396
+ isMatch('WebSocket Protocol', 'Active & Enabled') ||
397
+ isMatch('Network Inspector Interceptor', 'Intercepting XHR & Fetch'));
398
+ }, [search, isMatch, ipAddress]);
399
+ const hasDisplayMatch = useMemo(() => {
400
+ if (!search.trim())
401
+ return true;
402
+ return (isMatch('Window Resolution', `${windowDims.width.toFixed(0)} × ${windowDims.height.toFixed(0)} pt`) ||
403
+ isMatch('Screen Physical Size', `${(screenDims.width * pixelRatio).toFixed(0)} × ${(screenDims.height * pixelRatio).toFixed(0)} px`) ||
404
+ isMatch('Pixel Density', `@${pixelRatio}x (${Math.round(pixelRatio * 160)} dpi)`) ||
405
+ isMatch('Font Scale', `${fontScale}x`) ||
406
+ isMatch('Form Factor', isTablet ? 'Tablet' : 'Smartphone') ||
407
+ isMatch('Orientation', isLandscape ? 'Landscape' : 'Portrait') ||
408
+ isMatch('Status Bar Height', `${statusBarHeight} pt`));
409
+ }, [search, isMatch, windowDims, screenDims, pixelRatio, fontScale, isTablet, isLandscape, statusBarHeight]);
410
+ const hasRuntimeMatch = useMemo(() => {
411
+ if (!search.trim())
412
+ return true;
413
+ return (isMatch('App Name', fullDeviceData.runtime.appName) ||
414
+ isMatch('Bundle ID', fullDeviceData.identifiers.bundleId) ||
415
+ isMatch('App Version', `v${fullDeviceData.runtime.appVersion} (${fullDeviceData.runtime.appBuild})`) ||
416
+ isMatch('React Native', `v${reactNativeVersion}`) ||
417
+ isMatch('In-App Inspector Version', `v${LIB_VERSION}`) ||
418
+ isMatch('Hermes Engine', isHermes ? 'Enabled (AOT Bytecode)' : 'Disabled (JSC)') ||
419
+ isMatch('New Architecture', isTurboModule ? 'Enabled' : 'Legacy Bridge') ||
420
+ isMatch('Build Type', __DEV__ ? 'Debug (__DEV__ = true)' : 'Release / Production') ||
421
+ isMatch('Timezone', fullDeviceData.runtime.timezone) ||
422
+ isMatch('Locale', fullDeviceData.runtime.locale) ||
423
+ isMatch('Session Uptime', deviceUptime));
424
+ }, [search, isMatch, fullDeviceData, reactNativeVersion, isHermes, isTurboModule, deviceUptime]);
425
+ const hasSecurityMatch = useMemo(() => {
426
+ if (!search.trim())
427
+ return true;
428
+ return (isMatch('Pseudo-UDID', pseudoUDID) ||
429
+ isMatch('Bundle ID', fullDeviceData.identifiers.bundleId) ||
430
+ isMatch('Root / Jailbreak', 'Clean (Standard Sandbox)') ||
431
+ isMatch('Simulator / Emulator', Platform.constants?.Model?.includes?.('sdk') || Platform.constants?.Model?.includes?.('Emulator') || Platform.constants?.Model?.includes?.('Simulator') ? 'Virtual Simulator' : 'Physical Device') ||
432
+ isMatch('Sandbox Integrity', 'Enforced by OS Kernel'));
433
+ }, [search, isMatch, pseudoUDID, fullDeviceData]);
346
434
  const hasAnyMatch = useMemo(() => {
347
435
  if (!search.trim())
348
436
  return true;
349
- const query = search.toLowerCase().trim();
350
- return (JSON.stringify(fullDeviceData).toLowerCase().includes(query) ||
351
- ipAddress.toLowerCase().includes(query) ||
352
- pseudoUDID.toLowerCase().includes(query));
353
- }, [search, fullDeviceData, ipAddress, pseudoUDID]);
437
+ return (hasHeroMatch ||
438
+ hasOverviewMatch ||
439
+ hasHardwareMatch ||
440
+ hasNetworkMatch ||
441
+ hasDisplayMatch ||
442
+ hasRuntimeMatch ||
443
+ hasSecurityMatch);
444
+ }, [
445
+ search,
446
+ hasHeroMatch,
447
+ hasOverviewMatch,
448
+ hasHardwareMatch,
449
+ hasNetworkMatch,
450
+ hasDisplayMatch,
451
+ hasRuntimeMatch,
452
+ hasSecurityMatch,
453
+ ]);
354
454
  return (<View style={styles.container}>
355
455
 
356
456
  <View style={styles.subTabsWrapper}>
@@ -395,154 +495,154 @@ export const DeviceInfoTab = React.memo(() => {
395
495
 
396
496
  <ScrollView style={styles.scrollArea} contentContainerStyle={styles.scrollContent} showsVerticalScrollIndicator={false}>
397
497
 
398
- <View style={styles.heroCard}>
399
- <View style={styles.heroHeader}>
400
- <View style={styles.heroIconWrap}>
401
- {Platform.OS === 'ios' ? (<AppleIcon size={20} color={AppColors.white}/>) : (<AndroidIcon size={20} color={AppColors.white}/>)}
402
- </View>
403
- <View style={{ flex: 1, minWidth: 0 }}>
404
- <Text style={styles.heroTitle} numberOfLines={1} ellipsizeMode="tail">
405
- {deviceMetrics?.deviceModel || Platform.constants?.Model || (Platform.OS === 'ios' ? 'Apple iPhone' : 'Android Device')}
406
- </Text>
407
- <Text style={styles.heroSubtitle} numberOfLines={1} ellipsizeMode="tail">
408
- {Platform.OS === 'ios' ? `iOS ${Platform.Version}` : `Android ${Platform.Version} (API ${deviceMetrics?.apiLevel || Platform.Version})`}
409
- </Text>
410
- </View>
411
- <View style={styles.heroBadge}>
412
- <View style={styles.pulseDot}/>
413
- <Text style={styles.heroBadgeText}>LIVE</Text>
498
+ {(!search.trim() || hasHeroMatch) && (<View style={styles.heroCard}>
499
+ <View style={styles.heroHeader}>
500
+ <View style={styles.heroIconWrap}>
501
+ {Platform.OS === 'ios' ? (<AppleIcon size={20} color={AppColors.white}/>) : (<AndroidIcon size={20} color={AppColors.white}/>)}
502
+ </View>
503
+ <View style={{ flex: 1, minWidth: 0 }}>
504
+ <Text style={styles.heroTitle} numberOfLines={1} ellipsizeMode="tail">
505
+ {deviceMetrics?.deviceModel || Platform.constants?.Model || (Platform.OS === 'ios' ? 'Apple iPhone' : 'Android Device')}
506
+ </Text>
507
+ <Text style={styles.heroSubtitle} numberOfLines={1} ellipsizeMode="tail">
508
+ {Platform.OS === 'ios' ? `iOS ${Platform.Version}` : `Android ${Platform.Version} (API ${deviceMetrics?.apiLevel || Platform.Version})`}
509
+ </Text>
510
+ </View>
511
+ <View style={styles.heroBadge}>
512
+ <View style={styles.pulseDot}/>
513
+ <Text style={styles.heroBadgeText}>LIVE</Text>
514
+ </View>
414
515
  </View>
415
- </View>
416
516
 
417
-
418
- <View style={styles.heroMetricsStrip}>
419
- <View style={styles.heroMetricItem}>
420
- <Text style={styles.heroMetricLabel} numberOfLines={1} ellipsizeMode="tail">IP ADDRESS</Text>
421
- <Text style={styles.heroMetricValue} numberOfLines={1} ellipsizeMode="tail">
422
- {ipAddress}
423
- </Text>
424
- </View>
425
- <View style={styles.heroMetricDivider}/>
426
- <View style={styles.heroMetricItem}>
427
- <Text style={styles.heroMetricLabel} numberOfLines={1} ellipsizeMode="tail">RAM (USED/TOTAL)</Text>
428
- <Text style={styles.heroMetricValue} numberOfLines={1} ellipsizeMode="tail">
429
- {usedRamMb}/{totalRamMb} MB
430
- </Text>
431
- </View>
432
- <View style={styles.heroMetricDivider}/>
433
- <View style={styles.heroMetricItem}>
434
- <Text style={styles.heroMetricLabel} numberOfLines={1} ellipsizeMode="tail">UPTIME</Text>
435
- <Text style={styles.heroMetricValue} numberOfLines={1} ellipsizeMode="tail">{deviceUptime}</Text>
517
+
518
+ <View style={styles.heroMetricsStrip}>
519
+ <View style={styles.heroMetricItem}>
520
+ <Text style={styles.heroMetricLabel} numberOfLines={1} ellipsizeMode="tail">IP ADDRESS</Text>
521
+ <Text style={styles.heroMetricValue} numberOfLines={1} ellipsizeMode="tail">
522
+ {ipAddress}
523
+ </Text>
524
+ </View>
525
+ <View style={styles.heroMetricDivider}/>
526
+ <View style={styles.heroMetricItem}>
527
+ <Text style={styles.heroMetricLabel} numberOfLines={1} ellipsizeMode="tail">RAM (USED/TOTAL)</Text>
528
+ <Text style={styles.heroMetricValue} numberOfLines={1} ellipsizeMode="tail">
529
+ {usedRamMb}/{totalRamMb} MB
530
+ </Text>
531
+ </View>
532
+ <View style={styles.heroMetricDivider}/>
533
+ <View style={styles.heroMetricItem}>
534
+ <Text style={styles.heroMetricLabel} numberOfLines={1} ellipsizeMode="tail">UPTIME</Text>
535
+ <Text style={styles.heroMetricValue} numberOfLines={1} ellipsizeMode="tail">{deviceUptime}</Text>
536
+ </View>
436
537
  </View>
437
- </View>
438
- </View>
538
+ </View>)}
439
539
 
440
540
 
441
- {(activeSubTab === 'overview' || search.length > 0) && (<View style={styles.sectionCard}>
541
+ {(activeSubTab === 'overview' || search.length > 0) && hasOverviewMatch && (<View style={styles.sectionCard}>
442
542
  <Text style={styles.sectionTitle}>DEVICE OVERVIEW</Text>
443
- {isMatch('Device Model') && (<InfoRow label="Device Model" value={fullDeviceData.hardware.model}/>)}
444
- {isMatch('Manufacturer') && (<InfoRow label="Manufacturer / Brand" value={fullDeviceData.hardware.brand}/>)}
445
- {isMatch('Operating System') && (<InfoRow label="Operating System" value={fullDeviceData.hardware.osVersion} badge={{ text: Platform.OS.toUpperCase(), color: AppColors.blue500, bg: `${AppColors.blue500}18` }}/>)}
446
- {isMatch('IP Address') && (<InfoRow label="Local IP Address" value={ipAddress} badge={{ text: 'ONLINE', color: AppColors.emerald500, bg: `${AppColors.emerald500}18` }}/>)}
447
- {isMatch('RAM Memory') && (<InfoRow label="RAM Memory" value={`${usedRamMb} MB / ${totalRamMb} MB (${ramUsagePct}%)`} subtext={`Free Memory: ${freeRamMb} MB`}/>)}
448
- {isMatch('Storage Capacity') && (<InfoRow label="Internal Storage" value={`${freeStorageGb} GB Free / ${totalStorageGb} GB Total`}/>)}
449
- {isMatch('App Version') && (<InfoRow label="Host App Version" value={`v${fullDeviceData.runtime.appVersion} (${fullDeviceData.runtime.appBuild})`}/>)}
450
- {isMatch('JavaScript Engine') && (<InfoRow label="JS Runtime Engine" value={isHermes ? 'Hermes Bytecode Engine' : 'JavaScriptCore (JSC)'} badge={isHermes
543
+ {isMatch('Device Model', fullDeviceData.hardware.model) && (<InfoRow label="Device Model" value={fullDeviceData.hardware.model}/>)}
544
+ {isMatch('Manufacturer', fullDeviceData.hardware.brand) && (<InfoRow label="Manufacturer / Brand" value={fullDeviceData.hardware.brand}/>)}
545
+ {isMatch('Operating System', fullDeviceData.hardware.osVersion) && (<InfoRow label="Operating System" value={fullDeviceData.hardware.osVersion} badge={{ text: Platform.OS.toUpperCase(), color: AppColors.blue500, bg: `${AppColors.blue500}18` }}/>)}
546
+ {isMatch('IP Address', ipAddress) && (<InfoRow label="Local IP Address" value={ipAddress} badge={{ text: 'ONLINE', color: AppColors.emerald500, bg: `${AppColors.emerald500}18` }}/>)}
547
+ {isMatch('RAM Memory', `${usedRamMb} MB / ${totalRamMb} MB (${ramUsagePct}%)`, `Free Memory: ${freeRamMb} MB`) && (<InfoRow label="RAM Memory" value={`${usedRamMb} MB / ${totalRamMb} MB (${ramUsagePct}%)`} subtext={`Free Memory: ${freeRamMb} MB`}/>)}
548
+ {isMatch('Storage Capacity', `${freeStorageGb} GB Free / ${totalStorageGb} GB Total`) && (<InfoRow label="Internal Storage" value={`${freeStorageGb} GB Free / ${totalStorageGb} GB Total`}/>)}
549
+ {isMatch('App Version', `v${fullDeviceData.runtime.appVersion} (${fullDeviceData.runtime.appBuild})`) && (<InfoRow label="Host App Version" value={`v${fullDeviceData.runtime.appVersion} (${fullDeviceData.runtime.appBuild})`}/>)}
550
+ {isMatch('JavaScript Engine', isHermes ? 'Hermes Bytecode Engine' : 'JavaScriptCore (JSC)') && (<InfoRow label="JS Runtime Engine" value={isHermes ? 'Hermes Bytecode Engine' : 'JavaScriptCore (JSC)'} badge={isHermes
451
551
  ? { text: 'HERMES', color: AppColors.purple, bg: `${AppColors.purple}18` }
452
552
  : { text: 'JSC', color: AppColors.sky500, bg: `${AppColors.sky500}18` }}/>)}
453
- {isMatch('UDID Identifier') && (<InfoRow label="Pseudo-UDID" value={pseudoUDID} isLast/>)}
553
+ {isMatch('UDID Identifier', pseudoUDID) && (<InfoRow label="Pseudo-UDID" value={pseudoUDID} isLast/>)}
454
554
  </View>)}
455
555
 
456
556
 
457
- {(activeSubTab === 'hardware' || search.length > 0) && (<View style={styles.sectionCard}>
557
+ {(activeSubTab === 'hardware' || search.length > 0) && hasHardwareMatch && (<View style={styles.sectionCard}>
458
558
  <Text style={styles.sectionTitle}>HARDWARE & SYSTEM SPECIFICATIONS</Text>
459
- {isMatch('CPU Architecture') && (<InfoRow label="CPU Architecture / ABI" value={fullDeviceData.hardware.cpuAbi} badge={{ text: '64-BIT', color: AppColors.purple, bg: `${AppColors.purple}18` }}/>)}
460
- {isMatch('Total RAM') && (<InfoRow label="Total Physical RAM" value={`${totalRamMb} MB`}/>)}
461
- {isMatch('Free RAM') && (<InfoRow label="Available Free RAM" value={`${freeRamMb} MB`} badge={{
559
+ {isMatch('CPU Architecture', fullDeviceData.hardware.cpuAbi) && (<InfoRow label="CPU Architecture / ABI" value={fullDeviceData.hardware.cpuAbi} badge={{ text: '64-BIT', color: AppColors.purple, bg: `${AppColors.purple}18` }}/>)}
560
+ {isMatch('Total RAM', `${totalRamMb} MB`) && (<InfoRow label="Total Physical RAM" value={`${totalRamMb} MB`}/>)}
561
+ {isMatch('Free RAM', `${freeRamMb} MB`) && (<InfoRow label="Available Free RAM" value={`${freeRamMb} MB`} badge={{
462
562
  text: freeRamMb < 500 ? 'LOW' : 'HEALTHY',
463
563
  color: freeRamMb < 500 ? AppColors.errorColor : AppColors.emerald500,
464
564
  bg: freeRamMb < 500 ? `${AppColors.errorColor}18` : `${AppColors.emerald500}18`,
465
565
  }}/>)}
466
- {isMatch('Storage Capacity') && (<InfoRow label="Disk Storage Total" value={`${totalStorageGb} GB`}/>)}
467
- {isMatch('Available Storage') && (<InfoRow label="Disk Storage Available" value={`${freeStorageGb} GB`}/>)}
468
- {isMatch('Battery') && (<InfoRow label="Battery Level" value={`${deviceMetrics?.batteryPercent ?? 100}%`} badge={{
566
+ {isMatch('Storage Capacity', `${totalStorageGb} GB`) && (<InfoRow label="Disk Storage Total" value={`${totalStorageGb} GB`}/>)}
567
+ {isMatch('Available Storage', `${freeStorageGb} GB`) && (<InfoRow label="Disk Storage Available" value={`${freeStorageGb} GB`}/>)}
568
+ {isMatch('Battery', `${deviceMetrics?.batteryPercent ?? 100}%`) && (<InfoRow label="Battery Level" value={`${deviceMetrics?.batteryPercent ?? 100}%`} badge={{
469
569
  text: deviceMetrics?.isCharging ? 'CHARGING' : 'DISCHARGING',
470
570
  color: deviceMetrics?.isCharging ? AppColors.emerald500 : AppColors.grayText,
471
571
  bg: deviceMetrics?.isCharging ? `${AppColors.emerald500}18` : `${AppColors.grayText}18`,
472
572
  }}/>)}
473
- {isMatch('API Level') && Platform.OS === 'android' && (<InfoRow label="Android API SDK Level" value={`API ${deviceMetrics?.apiLevel || Platform.Version}`}/>)}
474
- {isMatch('Thermal State') && (<InfoRow label="Thermal State" value="Nominal (Cool)" badge={{ text: 'OPTIMAL', color: AppColors.emerald500, bg: `${AppColors.emerald500}18` }} isLast/>)}
573
+ {isMatch('API Level', `API ${deviceMetrics?.apiLevel || Platform.Version}`) && Platform.OS === 'android' && (<InfoRow label="Android API SDK Level" value={`API ${deviceMetrics?.apiLevel || Platform.Version}`}/>)}
574
+ {isMatch('Thermal State', 'Nominal (Cool)') && (<InfoRow label="Thermal State" value="Nominal (Cool)" badge={{ text: 'OPTIMAL', color: AppColors.emerald500, bg: `${AppColors.emerald500}18` }} isLast/>)}
475
575
  </View>)}
476
576
 
477
577
 
478
- {(activeSubTab === 'network' || search.length > 0) && (<View style={styles.sectionCard}>
578
+ {(activeSubTab === 'network' || search.length > 0) && hasNetworkMatch && (<View style={styles.sectionCard}>
479
579
  <Text style={styles.sectionTitle}>NETWORK & CONNECTIVITY</Text>
480
- {isMatch('IP Address') && (<InfoRow label="Local Device IP" value={ipAddress} badge={{ text: 'IPV4', color: AppColors.blue500, bg: `${AppColors.blue500}18` }}/>)}
481
- {isMatch('Internet Reachability') && (<InfoRow label="Internet Reachability" value="Connected" badge={{ text: 'ONLINE', color: AppColors.emerald500, bg: `${AppColors.emerald500}18` }}/>)}
482
- {isMatch('Connection Type') && (<InfoRow label="Active Connection Type" value="Wi-Fi / Local Area Network"/>)}
483
- {isMatch('Metro Dev Server') && (<InfoRow label="Metro Packager Host" value={NativeModules?.PlatformConstants?.serverHost ||
580
+ {isMatch('IP Address', ipAddress) && (<InfoRow label="Local Device IP" value={ipAddress} badge={{ text: 'IPV4', color: AppColors.blue500, bg: `${AppColors.blue500}18` }}/>)}
581
+ {isMatch('Internet Reachability', 'Connected') && (<InfoRow label="Internet Reachability" value="Connected" badge={{ text: 'ONLINE', color: AppColors.emerald500, bg: `${AppColors.emerald500}18` }}/>)}
582
+ {isMatch('Connection Type', 'Wi-Fi / Local Area Network') && (<InfoRow label="Active Connection Type" value="Wi-Fi / Local Area Network"/>)}
583
+ {isMatch('Metro Dev Server', NativeModules?.PlatformConstants?.serverHost || NativeModules?.AndroidConstants?.serverHost || 'localhost:8081') && (<InfoRow label="Metro Packager Host" value={NativeModules?.PlatformConstants?.serverHost ||
484
584
  NativeModules?.AndroidConstants?.serverHost ||
485
585
  'localhost:8081'}/>)}
486
- {isMatch('WebSocket Protocol') && (<InfoRow label="WebSocket (WSS) Support" value="Active & Enabled"/>)}
487
- {isMatch('Network Inspector Interceptor') && (<InfoRow label="Network Interceptor Status" value="Intercepting XHR & Fetch" badge={{ text: 'MONITORING', color: AppColors.purple, bg: `${AppColors.purple}18` }} isLast/>)}
586
+ {isMatch('WebSocket Protocol', 'Active & Enabled') && (<InfoRow label="WebSocket (WSS) Support" value="Active & Enabled"/>)}
587
+ {isMatch('Network Inspector Interceptor', 'Intercepting XHR & Fetch') && (<InfoRow label="Network Interceptor Status" value="Intercepting XHR & Fetch" badge={{ text: 'MONITORING', color: AppColors.purple, bg: `${AppColors.purple}18` }} isLast/>)}
488
588
  </View>)}
489
589
 
490
590
 
491
- {(activeSubTab === 'display' || search.length > 0) && (<View style={styles.sectionCard}>
591
+ {(activeSubTab === 'display' || search.length > 0) && hasDisplayMatch && (<View style={styles.sectionCard}>
492
592
  <Text style={styles.sectionTitle}>DISPLAY & SCREEN GEOMETRY</Text>
493
- {isMatch('Window Resolution') && (<InfoRow label="Window Logical Size" value={`${windowDims.width.toFixed(0)} × ${windowDims.height.toFixed(0)} pt`}/>)}
494
- {isMatch('Screen Physical Size') && (<InfoRow label="Physical Screen Size" value={`${(screenDims.width * pixelRatio).toFixed(0)} × ${(screenDims.height * pixelRatio).toFixed(0)} px`}/>)}
495
- {isMatch('Pixel Density') && (<InfoRow label="Pixel Ratio (DPI Scale)" value={`@${pixelRatio}x (${Math.round(pixelRatio * 160)} dpi)`} badge={{ text: `@${pixelRatio}x`, color: AppColors.purple, bg: `${AppColors.purple}18` }}/>)}
496
- {isMatch('Font Scale') && (<InfoRow label="User Font Scale" value={`${fontScale}x (${fontScale === 1 ? 'Default' : fontScale > 1 ? 'Enlarged' : 'Compact'})`}/>)}
497
- {isMatch('Form Factor') && (<InfoRow label="Device Form Factor" value={isTablet ? 'Tablet' : 'Smartphone'} badge={{
593
+ {isMatch('Window Resolution', `${windowDims.width.toFixed(0)} × ${windowDims.height.toFixed(0)} pt`) && (<InfoRow label="Window Logical Size" value={`${windowDims.width.toFixed(0)} × ${windowDims.height.toFixed(0)} pt`}/>)}
594
+ {isMatch('Screen Physical Size', `${(screenDims.width * pixelRatio).toFixed(0)} × ${(screenDims.height * pixelRatio).toFixed(0)} px`) && (<InfoRow label="Physical Screen Size" value={`${(screenDims.width * pixelRatio).toFixed(0)} × ${(screenDims.height * pixelRatio).toFixed(0)} px`}/>)}
595
+ {isMatch('Pixel Density', `@${pixelRatio}x (${Math.round(pixelRatio * 160)} dpi)`) && (<InfoRow label="Pixel Ratio (DPI Scale)" value={`@${pixelRatio}x (${Math.round(pixelRatio * 160)} dpi)`} badge={{ text: `@${pixelRatio}x`, color: AppColors.purple, bg: `${AppColors.purple}18` }}/>)}
596
+ {isMatch('Font Scale', `${fontScale}x`) && (<InfoRow label="User Font Scale" value={`${fontScale}x (${fontScale === 1 ? 'Default' : fontScale > 1 ? 'Enlarged' : 'Compact'})`}/>)}
597
+ {isMatch('Form Factor', isTablet ? 'Tablet' : 'Smartphone') && (<InfoRow label="Device Form Factor" value={isTablet ? 'Tablet' : 'Smartphone'} badge={{
498
598
  text: isTablet ? 'TABLET' : 'PHONE',
499
599
  color: isTablet ? AppColors.blue500 : AppColors.purple,
500
600
  bg: isTablet ? `${AppColors.blue500}18` : `${AppColors.purple}18`,
501
601
  }}/>)}
502
- {isMatch('Orientation') && (<InfoRow label="Screen Orientation" value={isLandscape ? 'Landscape' : 'Portrait'}/>)}
503
- {isMatch('Status Bar Height') && (<InfoRow label="Status Bar Inset" value={`${statusBarHeight} pt`} isLast/>)}
602
+ {isMatch('Orientation', isLandscape ? 'Landscape' : 'Portrait') && (<InfoRow label="Screen Orientation" value={isLandscape ? 'Landscape' : 'Portrait'}/>)}
603
+ {isMatch('Status Bar Height', `${statusBarHeight} pt`) && (<InfoRow label="Status Bar Inset" value={`${statusBarHeight} pt`} isLast/>)}
504
604
  </View>)}
505
605
 
506
606
 
507
- {(activeSubTab === 'runtime' || search.length > 0) && (<View style={styles.sectionCard}>
607
+ {(activeSubTab === 'runtime' || search.length > 0) && hasRuntimeMatch && (<View style={styles.sectionCard}>
508
608
  <Text style={styles.sectionTitle}>RUNTIME & APPLICATION</Text>
509
- {isMatch('App Name') && (<InfoRow label="Application Name" value={fullDeviceData.runtime.appName}/>)}
510
- {isMatch('Bundle ID') && (<InfoRow label="Bundle Identifier / Package" value={fullDeviceData.identifiers.bundleId}/>)}
511
- {isMatch('App Version') && (<InfoRow label="Application Version" value={`v${fullDeviceData.runtime.appVersion} (${fullDeviceData.runtime.appBuild})`}/>)}
512
- {isMatch('React Native') && (<InfoRow label="React Native Framework" value={`v${reactNativeVersion}`} badge={{ text: 'RN', color: AppColors.sky500, bg: `${AppColors.sky500}18` }}/>)}
513
- {isMatch('In-App Inspector Version') && (<InfoRow label="In-App Inspector Library" value={`v${LIB_VERSION}`} badge={{ text: 'LATEST', color: AppColors.purple, bg: `${AppColors.purple}18` }}/>)}
514
- {isMatch('Hermes Engine') && (<InfoRow label="Hermes JavaScript Engine" value={isHermes ? 'Enabled (AOT Bytecode)' : 'Disabled (JSC)'} badge={{
609
+ {isMatch('App Name', fullDeviceData.runtime.appName) && (<InfoRow label="Application Name" value={fullDeviceData.runtime.appName}/>)}
610
+ {isMatch('Bundle ID', fullDeviceData.identifiers.bundleId) && (<InfoRow label="Bundle Identifier / Package" value={fullDeviceData.identifiers.bundleId}/>)}
611
+ {isMatch('App Version', `v${fullDeviceData.runtime.appVersion} (${fullDeviceData.runtime.appBuild})`) && (<InfoRow label="Application Version" value={`v${fullDeviceData.runtime.appVersion} (${fullDeviceData.runtime.appBuild})`}/>)}
612
+ {isMatch('React Native', `v${reactNativeVersion}`) && (<InfoRow label="React Native Framework" value={`v${reactNativeVersion}`} badge={{ text: 'RN', color: AppColors.sky500, bg: `${AppColors.sky500}18` }}/>)}
613
+ {isMatch('In-App Inspector Version', `v${LIB_VERSION}`) && (<InfoRow label="In-App Inspector Library" value={`v${LIB_VERSION}`} badge={{ text: 'LATEST', color: AppColors.purple, bg: `${AppColors.purple}18` }}/>)}
614
+ {isMatch('Hermes Engine', isHermes ? 'Enabled (AOT Bytecode)' : 'Disabled (JSC)') && (<InfoRow label="Hermes JavaScript Engine" value={isHermes ? 'Enabled (AOT Bytecode)' : 'Disabled (JSC)'} badge={{
515
615
  text: isHermes ? 'HERMES' : 'JSC',
516
616
  color: isHermes ? AppColors.purple : AppColors.grayText,
517
617
  bg: isHermes ? `${AppColors.purple}18` : `${AppColors.grayText}18`,
518
618
  }}/>)}
519
- {isMatch('New Architecture') && (<InfoRow label="Bridgeless TurboModules (New Arch)" value={isTurboModule ? 'Enabled' : 'Legacy Bridge'} badge={{
619
+ {isMatch('New Architecture', isTurboModule ? 'Enabled' : 'Legacy Bridge') && (<InfoRow label="Bridgeless TurboModules (New Arch)" value={isTurboModule ? 'Enabled' : 'Legacy Bridge'} badge={{
520
620
  text: isTurboModule ? 'NEW ARCH' : 'LEGACY',
521
621
  color: isTurboModule ? AppColors.emerald500 : AppColors.blue500,
522
622
  bg: isTurboModule ? `${AppColors.emerald500}18` : `${AppColors.blue500}18`,
523
623
  }}/>)}
524
- {isMatch('Build Type') && (<InfoRow label="Build Configuration" value={__DEV__ ? 'Debug (__DEV__ = true)' : 'Release / Production'} badge={{
624
+ {isMatch('Build Type', __DEV__ ? 'Debug (__DEV__ = true)' : 'Release / Production') && (<InfoRow label="Build Configuration" value={__DEV__ ? 'Debug (__DEV__ = true)' : 'Release / Production'} badge={{
525
625
  text: __DEV__ ? 'DEBUG' : 'RELEASE',
526
626
  color: __DEV__ ? AppColors.warningIconGold : AppColors.emerald500,
527
627
  bg: __DEV__ ? `${AppColors.warningIconGold}18` : `${AppColors.emerald500}18`,
528
628
  }}/>)}
529
- {isMatch('Timezone') && (<InfoRow label="System Timezone" value={fullDeviceData.runtime.timezone}/>)}
530
- {isMatch('Locale') && (<InfoRow label="System Language & Locale" value={fullDeviceData.runtime.locale}/>)}
531
- {isMatch('Session Uptime') && (<InfoRow label="Inspector Session Uptime" value={deviceUptime} isLast/>)}
629
+ {isMatch('Timezone', fullDeviceData.runtime.timezone) && (<InfoRow label="System Timezone" value={fullDeviceData.runtime.timezone}/>)}
630
+ {isMatch('Locale', fullDeviceData.runtime.locale) && (<InfoRow label="System Language & Locale" value={fullDeviceData.runtime.locale}/>)}
631
+ {isMatch('Session Uptime', deviceUptime) && (<InfoRow label="Inspector Session Uptime" value={deviceUptime} isLast/>)}
532
632
  </View>)}
533
633
 
534
634
 
535
- {(activeSubTab === 'security' || search.length > 0) && (<View style={styles.sectionCard}>
635
+ {(activeSubTab === 'security' || search.length > 0) && hasSecurityMatch && (<View style={styles.sectionCard}>
536
636
  <Text style={styles.sectionTitle}>DEVICE IDENTIFIERS & SECURITY</Text>
537
- {isMatch('Pseudo-UDID') && (<InfoRow label="Deterministic Pseudo-UDID" value={pseudoUDID} subtext="Stable hardware signature hash for testing & diagnostics" badge={{ text: 'PERSISTENT', color: AppColors.purple, bg: `${AppColors.purple}18` }}/>)}
538
- {isMatch('Bundle ID') && (<InfoRow label="Application Bundle ID" value={fullDeviceData.identifiers.bundleId}/>)}
539
- {isMatch('Root / Jailbreak') && (<InfoRow label="Root / Jailbreak Heuristic" value="Clean (Standard Sandbox)" badge={{ text: 'SECURE', color: AppColors.emerald500, bg: `${AppColors.emerald500}18` }}/>)}
540
- {isMatch('Simulator / Emulator') && (<InfoRow label="Emulator / Physical Device" value={Platform.constants?.Model?.includes?.('sdk') ||
637
+ {isMatch('Pseudo-UDID', pseudoUDID) && (<InfoRow label="Deterministic Pseudo-UDID" value={pseudoUDID} subtext="Stable hardware signature hash for testing & diagnostics" badge={{ text: 'PERSISTENT', color: AppColors.purple, bg: `${AppColors.purple}18` }}/>)}
638
+ {isMatch('Bundle ID', fullDeviceData.identifiers.bundleId) && (<InfoRow label="Application Bundle ID" value={fullDeviceData.identifiers.bundleId}/>)}
639
+ {isMatch('Root / Jailbreak', 'Clean (Standard Sandbox)') && (<InfoRow label="Root / Jailbreak Heuristic" value="Clean (Standard Sandbox)" badge={{ text: 'SECURE', color: AppColors.emerald500, bg: `${AppColors.emerald500}18` }}/>)}
640
+ {isMatch('Simulator / Emulator', Platform.constants?.Model?.includes?.('sdk') || Platform.constants?.Model?.includes?.('Emulator') || Platform.constants?.Model?.includes?.('Simulator') ? 'Virtual Simulator' : 'Physical Device') && (<InfoRow label="Emulator / Physical Device" value={Platform.constants?.Model?.includes?.('sdk') ||
541
641
  Platform.constants?.Model?.includes?.('Emulator') ||
542
642
  Platform.constants?.Model?.includes?.('Simulator')
543
643
  ? 'Virtual Simulator'
544
644
  : 'Physical Device'}/>)}
545
- {isMatch('Sandbox Integrity') && (<InfoRow label="App Sandbox File Isolation" value="Enforced by OS Kernel" isLast/>)}
645
+ {isMatch('Sandbox Integrity', 'Enforced by OS Kernel') && (<InfoRow label="App Sandbox File Isolation" value="Enforced by OS Kernel" isLast/>)}
546
646
  </View>)}
547
647
 
548
648
 
@@ -1,5 +1,5 @@
1
1
  import React, { useMemo } from 'react';
2
- import { Alert, Animated, Linking, Platform, Pressable, ScrollView, Text, useWindowDimensions, View, } from 'react-native';
2
+ import { Alert, Animated, Linking, Platform, Pressable, ScrollView, Text, TouchableOpacity, useWindowDimensions, View, } from 'react-native';
3
3
  import LinearGradient from 'react-native-linear-gradient';
4
4
  import { useInspector } from './InspectorContext';
5
5
  import TouchableScale from '../TouchableScale';
@@ -764,7 +764,7 @@ const InspectorHeader = React.memo(() => {
764
764
  <SettingsIcon color={AppColors.white} size={isNarrow ? 12 : 14}/>
765
765
  </TouchableScale>)}
766
766
 
767
- <TouchableScale onPress={closeModal} hitSlop={15} style={[
767
+ <TouchableOpacity onPress={closeModal} hitSlop={{ top: 12, bottom: 12, left: 12, right: 12 }} activeOpacity={0.6} style={[
768
768
  styles.closeButtonSquare,
769
769
  {
770
770
  width: buttonSize,
@@ -773,7 +773,7 @@ const InspectorHeader = React.memo(() => {
773
773
  },
774
774
  ]}>
775
775
  <CloseWhite size={isNarrow ? 12 : 14}/>
776
- </TouchableScale>
776
+ </TouchableOpacity>
777
777
  </View>
778
778
  </View>
779
779
  </View>
@@ -72,18 +72,18 @@ const MainScreen = () => {
72
72
  enabled &&
73
73
  !visible &&
74
74
  !useNativeFab && <FabLauncher />}
75
- <Modal visible={visible} animationType={modalAnimationType} transparent statusBarTranslucent={true}>
76
- {visible && (<ErrorBoundary onClose={closeModal}>
75
+ <Modal visible={visible} animationType={modalAnimationType} transparent statusBarTranslucent={true} onRequestClose={closeModal}>
76
+ <ErrorBoundary onClose={closeModal}>
77
77
  <View style={styles.modalBackdrop}>
78
78
  <Pressable style={styles.modalBackdropPressable} onPress={closeModal}/>
79
79
  <View style={[
80
- styles.modalContentCard,
81
- {
82
- height: `${modalHeightPercent}%`,
83
- borderTopLeftRadius: modalHeightPercent >= 100 ? 0 : 20,
84
- borderTopRightRadius: modalHeightPercent >= 100 ? 0 : 20,
85
- },
86
- ]}>
80
+ styles.modalContentCard,
81
+ {
82
+ height: `${modalHeightPercent}%`,
83
+ borderTopLeftRadius: modalHeightPercent >= 100 ? 0 : 20,
84
+ borderTopRightRadius: modalHeightPercent >= 100 ? 0 : 20,
85
+ },
86
+ ]}>
87
87
  <StatusBar translucent backgroundColor="transparent" barStyle="light-content"/>
88
88
 
89
89
  <InspectorHeader />
@@ -95,22 +95,22 @@ const MainScreen = () => {
95
95
  {isReady ? (<View style={{ flex: 1 }}>
96
96
 
97
97
  <Animated.View style={[
98
- {
99
- flex: 1,
100
- opacity: tabAnim,
101
- transform: [
102
- {
103
- translateY: tabAnim.interpolate({
104
- inputRange: [0, 1],
105
- outputRange: [6, 0],
106
- }),
107
- },
108
- ],
109
- },
110
- (isDetailActive || settingsPage !== null) && {
111
- pointerEvents: 'none',
112
- },
113
- ]}>
98
+ {
99
+ flex: 1,
100
+ opacity: tabAnim,
101
+ transform: [
102
+ {
103
+ translateY: tabAnim.interpolate({
104
+ inputRange: [0, 1],
105
+ outputRange: [6, 0],
106
+ }),
107
+ },
108
+ ],
109
+ },
110
+ (isDetailActive || settingsPage !== null) && {
111
+ pointerEvents: 'none',
112
+ },
113
+ ]}>
114
114
  {activeTab === 'apis' && <NetworkTab />}
115
115
  {activeTab === 'logs' && <ConsoleTab />}
116
116
  {activeTab === 'analytics' && <AnalyticsTab />}
@@ -121,50 +121,50 @@ const MainScreen = () => {
121
121
  {activeTab === 'device' && <DeviceInfoTab />}
122
122
  {activeTab === 'storage' && <StorageTab />}
123
123
  {Platform.OS === 'android' &&
124
- isLocalDebugEnvironment() &&
125
- activeTab === 'debugging' && <DebuggingTab />}
124
+ isLocalDebugEnvironment() &&
125
+ activeTab === 'debugging' && <DebuggingTab />}
126
126
  </Animated.View>
127
127
 
128
128
 
129
129
  {isDetailActive && (<Animated.View style={[
130
- StyleSheet.absoluteFill,
131
- {
132
- backgroundColor: AppColors.contentBg,
133
- opacity: detailAnim,
134
- transform: [
135
- {
136
- translateX: detailAnim.interpolate({
137
- inputRange: [0, 1],
138
- outputRange: [32, 0],
139
- }),
140
- },
141
- ],
142
- },
143
- ]}>
144
- {activeTab === 'apis' && selected != null && (<NetworkDetail />)}
145
- {activeTab === 'analytics' && selectedEvent != null && (<AnalyticsDetail event={selectedEvent}/>)}
146
- {activeTab === 'logs' && selectedLog != null && (<LogDetail />)}
147
- {activeTab === 'redux' && <ReduxDetail />}
148
- {activeTab === 'crash' && selectedCrash != null && (<CrashDetail />)}
149
- </Animated.View>)}
150
- </View>) : (<MainScreenSkeleton />)}
151
-
152
-
153
- {settingsPage !== null && (<Animated.View style={[
154
130
  StyleSheet.absoluteFill,
155
131
  {
156
- backgroundColor: AppColors.grayBackground,
157
- opacity: settingsAnim,
132
+ backgroundColor: AppColors.contentBg,
133
+ opacity: detailAnim,
158
134
  transform: [
159
135
  {
160
- translateY: settingsAnim.interpolate({
136
+ translateX: detailAnim.interpolate({
161
137
  inputRange: [0, 1],
162
- outputRange: [24, 0],
138
+ outputRange: [32, 0],
163
139
  }),
164
140
  },
165
141
  ],
166
142
  },
167
143
  ]}>
144
+ {activeTab === 'apis' && selected != null && (<NetworkDetail />)}
145
+ {activeTab === 'analytics' && selectedEvent != null && (<AnalyticsDetail event={selectedEvent}/>)}
146
+ {activeTab === 'logs' && selectedLog != null && (<LogDetail />)}
147
+ {activeTab === 'redux' && <ReduxDetail />}
148
+ {activeTab === 'crash' && selectedCrash != null && (<CrashDetail />)}
149
+ </Animated.View>)}
150
+ </View>) : (<MainScreenSkeleton />)}
151
+
152
+
153
+ {settingsPage !== null && (<Animated.View style={[
154
+ StyleSheet.absoluteFill,
155
+ {
156
+ backgroundColor: AppColors.grayBackground,
157
+ opacity: settingsAnim,
158
+ transform: [
159
+ {
160
+ translateY: settingsAnim.interpolate({
161
+ inputRange: [0, 1],
162
+ outputRange: [24, 0],
163
+ }),
164
+ },
165
+ ],
166
+ },
167
+ ]}>
168
168
  <SettingsPanel />
169
169
  </Animated.View>)}
170
170
  </View>
@@ -176,7 +176,7 @@ const MainScreen = () => {
176
176
  <NpmUpdateToast />
177
177
  </View>
178
178
  </View>
179
- </ErrorBoundary>)}
179
+ </ErrorBoundary>
180
180
  {hasNavigationContext && (<NavigationTracker onStateChange={setNavState}/>)}
181
181
  </Modal>
182
182
  </>);