react-native-inapp-inspector 1.1.35 → 2.0.0
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/README.md +123 -101
- package/android/build.gradle +13 -1
- package/android/src/main/java/com/inappinspector/NetworkInspectorModule.kt +904 -0
- package/android/src/main/java/com/inappinspector/NetworkInspectorPackage.kt +17 -0
- package/dist/commonjs/components/CopyButton.js +3 -0
- package/dist/commonjs/components/ErrorBoundary.js +3 -0
- package/dist/commonjs/components/Inspector/AnalyticsTab.js +7 -3
- package/dist/commonjs/components/Inspector/BundleTab.js +1 -1
- package/dist/commonjs/components/Inspector/ConsoleTab.js +1 -1
- package/dist/commonjs/components/Inspector/CrashTab.js +97 -90
- package/dist/commonjs/components/Inspector/InspectorHeader.js +12 -8
- package/dist/commonjs/components/Inspector/MainScreen.js +14 -101
- package/dist/commonjs/components/Inspector/NetworkTab.js +47 -10
- package/dist/commonjs/components/Inspector/PerformanceTab.js +96 -3
- package/dist/commonjs/components/Inspector/ReduxTab.js +18 -10
- package/dist/commonjs/components/Inspector/SettingsPanel.js +342 -88
- package/dist/commonjs/components/Inspector/TabBar.js +6 -3
- package/dist/commonjs/components/NetworkIcons.d.ts +1 -0
- package/dist/commonjs/components/NetworkIcons.js +6 -1
- package/dist/commonjs/components/TouchableScale.d.ts +1 -0
- package/dist/commonjs/components/TouchableScale.js +30 -32
- package/dist/commonjs/constants/index.d.ts +1 -2
- package/dist/commonjs/constants/index.js +4 -0
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/commonjs/customHooks/analyticsLogger.d.ts +4 -0
- package/dist/commonjs/customHooks/analyticsLogger.js +7 -5
- package/dist/commonjs/customHooks/crashHandler.js +7 -0
- package/dist/commonjs/helpers/index.js +10 -1
- package/dist/commonjs/helpers/settingsStore.d.ts +9 -0
- package/dist/commonjs/helpers/settingsStore.js +59 -3
- package/dist/commonjs/index.d.ts +1 -0
- package/dist/commonjs/index.js +229 -39
- package/dist/commonjs/native/NativeInspector.d.ts +125 -0
- package/dist/commonjs/native/NativeInspector.js +313 -0
- package/dist/commonjs/native/NativeNetworkInspector.d.ts +22 -0
- package/dist/commonjs/native/NativeNetworkInspector.js +4 -0
- package/dist/commonjs/styles/index.js +6 -6
- package/dist/commonjs/types/enums.d.ts +1 -1
- package/dist/commonjs/types/interfaces.d.ts +9 -0
- package/dist/esm/components/CopyButton.js +3 -0
- package/dist/esm/components/ErrorBoundary.js +3 -0
- package/dist/esm/components/Inspector/AnalyticsTab.js +7 -3
- package/dist/esm/components/Inspector/BundleTab.js +1 -1
- package/dist/esm/components/Inspector/ConsoleTab.js +1 -1
- package/dist/esm/components/Inspector/CrashTab.js +97 -90
- package/dist/esm/components/Inspector/InspectorHeader.js +13 -9
- package/dist/esm/components/Inspector/MainScreen.js +15 -69
- package/dist/esm/components/Inspector/NetworkTab.js +47 -10
- package/dist/esm/components/Inspector/PerformanceTab.js +96 -3
- package/dist/esm/components/Inspector/ReduxTab.js +18 -10
- package/dist/esm/components/Inspector/SettingsPanel.js +344 -90
- package/dist/esm/components/Inspector/TabBar.js +7 -4
- package/dist/esm/components/NetworkIcons.d.ts +1 -0
- package/dist/esm/components/NetworkIcons.js +4 -0
- package/dist/esm/components/TouchableScale.d.ts +1 -0
- package/dist/esm/components/TouchableScale.js +31 -33
- package/dist/esm/constants/index.d.ts +1 -2
- package/dist/esm/constants/index.js +4 -0
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/customHooks/analyticsLogger.d.ts +4 -0
- package/dist/esm/customHooks/analyticsLogger.js +5 -4
- package/dist/esm/customHooks/crashHandler.js +7 -0
- package/dist/esm/helpers/index.js +10 -1
- package/dist/esm/helpers/settingsStore.d.ts +9 -0
- package/dist/esm/helpers/settingsStore.js +58 -3
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +215 -39
- package/dist/esm/native/NativeInspector.d.ts +125 -0
- package/dist/esm/native/NativeInspector.js +289 -0
- package/dist/esm/native/NativeNetworkInspector.d.ts +22 -0
- package/dist/esm/native/NativeNetworkInspector.js +2 -0
- package/dist/esm/styles/index.js +6 -6
- package/dist/esm/types/enums.d.ts +1 -1
- package/dist/esm/types/interfaces.d.ts +9 -0
- package/ios/NetworkInspectorModule.h +6 -0
- package/ios/NetworkInspectorModule.m +720 -5
- package/package.json +13 -2
- package/react-native-inapp-inspector.podspec +7 -2
- package/android/src/main/java/com/inappinspector/NetworkInspectorModule.java +0 -97
- package/android/src/main/java/com/inappinspector/NetworkInspectorPackage.java +0 -28
|
@@ -176,10 +176,21 @@ const ReduxTab = React.memo(() => {
|
|
|
176
176
|
// Filter & Sort slices: by default, the most recently updated item is at the FIRST position
|
|
177
177
|
const filteredSlices = useMemo(() => {
|
|
178
178
|
let list = sliceItems;
|
|
179
|
-
if (reduxSearch.trim().length > 0) {
|
|
180
|
-
const
|
|
181
|
-
list = list.filter(item =>
|
|
182
|
-
|
|
179
|
+
if (reduxSearch && reduxSearch.trim().length > 0) {
|
|
180
|
+
const queryTokens = reduxSearch.trim().toLowerCase().split(/\s+/).filter(Boolean);
|
|
181
|
+
list = list.filter(item => {
|
|
182
|
+
const sliceVal = reduxState ? reduxState[item.name] : null;
|
|
183
|
+
const searchTarget = [
|
|
184
|
+
item.name || '',
|
|
185
|
+
item.lastAction?.type || '',
|
|
186
|
+
item.lastAction?.payloadPreview || '',
|
|
187
|
+
item.lastAction?.originType || '',
|
|
188
|
+
item.status || '',
|
|
189
|
+
item.statusMessage || '',
|
|
190
|
+
sliceVal ? (typeof sliceVal === 'string' ? sliceVal : JSON.stringify(sliceVal)) : '',
|
|
191
|
+
].join(' ').toLowerCase();
|
|
192
|
+
return queryTokens.every(tok => searchTarget.includes(tok));
|
|
193
|
+
});
|
|
183
194
|
}
|
|
184
195
|
return [...list].sort((a, b) => {
|
|
185
196
|
if (sortMode === 'latest') {
|
|
@@ -189,12 +200,9 @@ const ReduxTab = React.memo(() => {
|
|
|
189
200
|
}
|
|
190
201
|
return a.name.localeCompare(b.name);
|
|
191
202
|
}
|
|
192
|
-
|
|
193
|
-
// Alphabetical A-Z
|
|
194
|
-
return a.name.localeCompare(b.name);
|
|
195
|
-
}
|
|
203
|
+
return a.name.localeCompare(b.name);
|
|
196
204
|
});
|
|
197
|
-
}, [sliceItems, reduxSearch, sortMode]);
|
|
205
|
+
}, [sliceItems, reduxSearch, sortMode, reduxState]);
|
|
198
206
|
const lastGlobalAction = useMemo(() => {
|
|
199
207
|
const actions = Object.values(reduxLastActionMap);
|
|
200
208
|
if (actions.length === 0)
|
|
@@ -438,7 +446,7 @@ const ReduxTab = React.memo(() => {
|
|
|
438
446
|
</View>
|
|
439
447
|
|
|
440
448
|
{/* ─── FlatList of Slices ─── */}
|
|
441
|
-
<FlatList data={filteredSlices} keyExtractor={item => item.id} renderItem={renderSliceItem} initialNumToRender={
|
|
449
|
+
<FlatList data={filteredSlices} keyExtractor={item => item.id} renderItem={renderSliceItem} initialNumToRender={12} maxToRenderPerBatch={8} windowSize={5} removeClippedSubviews={true} renderToHardwareTextureAndroid={true} ListEmptyComponent={<EmptyState isSearch={reduxSearch.length > 0}/>} ListFooterComponent={filteredSlices.length > 0 ? (<EndOfListFooter count={filteredSlices.length} label="slices"/>) : null} contentContainerStyle={[
|
|
442
450
|
reduxTabStyles.listContent,
|
|
443
451
|
filteredSlices.length === 0 && { flexGrow: 1 },
|
|
444
452
|
]} keyboardShouldPersistTaps="handled"/>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useMemo, useState, useEffect } from 'react';
|
|
2
|
-
import { Alert, Platform, ScrollView, StatusBar, Text, View, } from 'react-native';
|
|
2
|
+
import { Alert, Platform, ScrollView, StatusBar, Text, TextInput, View, } from 'react-native';
|
|
3
3
|
import Svg, { Path } from 'react-native-svg';
|
|
4
4
|
import LinearGradient from 'react-native-linear-gradient';
|
|
5
5
|
import { animateNextLayout, useInspector } from './InspectorContext';
|
|
@@ -8,7 +8,7 @@ import styles, { toggleGlobalTheme } from '../../styles';
|
|
|
8
8
|
import { AppColors } from '../../styles/AppColors';
|
|
9
9
|
import { AppFonts } from '../../styles/AppFonts';
|
|
10
10
|
import { LIB_VERSION } from '../../constants';
|
|
11
|
-
import { isPersistentStorageAvailable } from '../../helpers/settingsStore';
|
|
11
|
+
import { isPersistentStorageAvailable, calculateRamBasedLimits, } from '../../helpers/settingsStore';
|
|
12
12
|
import { clearNetworkLogs } from '../../customHooks/networkLogger';
|
|
13
13
|
import { clearConsoleLogs } from '../../customHooks/consoleLogger';
|
|
14
14
|
import { clearAnalyticsEvents } from '../../customHooks/analyticsLogger';
|
|
@@ -21,7 +21,8 @@ import { useTranslation } from '../../i18n';
|
|
|
21
21
|
import { SignalIcon, TerminalIcon, AnalyticsIcon, SettingsIcon, SunIcon, MoonIcon, ScreenIcon, MotionIcon, LayersIcon, EyeIcon, CheckIcon, TrashIcon, WhiteBackNavigation, PackageIcon, ReduxIcon, PerformanceIcon, CrashIcon, ShieldAlertIcon, ForwardChevronIcon, } from '../NetworkIcons';
|
|
22
22
|
const SettingsPanel = () => {
|
|
23
23
|
const { t } = useTranslation();
|
|
24
|
-
const { settingsPage, setSettingsPage, settingsActiveSubTab, setSettingsActiveSubTab, tabVisibility, toggleTabVisibility, defaultTab, setDefaultTab, isDark, setIsDark, modalHeightPercent, setModalHeightPercent, modalAnimationType, setModalAnimationType, showDuplicateLogs, setShowDuplicateLogs, showConsoleLevels, setShowConsoleLevels, resetToDefaults, storage, logs, consoleLogs, analyticsEvents, reduxState, maxNetworkLogs, setMaxNetworkLogs, maxConsoleLogs, setMaxConsoleLogs, reduxAutoRefresh, setReduxAutoRefreshState, reduxExpandDepth, setReduxExpandDepth, switchActiveTab, setSelected, setSelectedEvent, setReduxState, crashRecords, maxCrashLogs, setMaxCrashLogs, } = useInspector();
|
|
24
|
+
const { settingsPage, setSettingsPage, settingsActiveSubTab, setSettingsActiveSubTab, tabVisibility, toggleTabVisibility, defaultTab, setDefaultTab, isDark, setIsDark, modalHeightPercent, setModalHeightPercent, modalAnimationType, setModalAnimationType, showDuplicateLogs, setShowDuplicateLogs, showConsoleLevels, setShowConsoleLevels, resetToDefaults, storage, logs, consoleLogs, analyticsEvents, reduxState, maxNetworkLogs, setMaxNetworkLogs, maxConsoleLogs, setMaxConsoleLogs, maxAnalyticsEventsLimit, setMaxAnalyticsEventsLimit, isAutoRamLimitEnabled, setIsAutoRamLimitEnabled, deviceFreeRamMb, reduxAutoRefresh, setReduxAutoRefreshState, reduxExpandDepth, setReduxExpandDepth, switchActiveTab, setSelected, setSelectedEvent, setReduxState, crashRecords, maxCrashLogs, setMaxCrashLogs, } = useInspector();
|
|
25
|
+
const autoRamProfile = calculateRamBasedLimits(deviceFreeRamMb);
|
|
25
26
|
const isPersistent = isPersistentStorageAvailable();
|
|
26
27
|
// Safe Area & Status Bar Padding for All Device Form Factors
|
|
27
28
|
const statusBarHeight = Platform.OS === 'android' ? StatusBar.currentHeight || 24 : 44;
|
|
@@ -664,9 +665,204 @@ const SettingsPanel = () => {
|
|
|
664
665
|
</View>);
|
|
665
666
|
})}
|
|
666
667
|
</View>
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
668
|
+
|
|
669
|
+
{/* Section 3.5: RAM-Based Auto Limits */}
|
|
670
|
+
<View style={{
|
|
671
|
+
backgroundColor: AppColors.primaryLight,
|
|
672
|
+
borderRadius: 14,
|
|
673
|
+
borderWidth: 1,
|
|
674
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
675
|
+
overflow: 'hidden',
|
|
676
|
+
padding: 14,
|
|
677
|
+
gap: 12,
|
|
678
|
+
}}>
|
|
679
|
+
<Text style={{
|
|
680
|
+
fontFamily: AppFonts.interBold,
|
|
681
|
+
fontSize: 11,
|
|
682
|
+
lineHeight: 14,
|
|
683
|
+
color: AppColors.grayTextWeak,
|
|
684
|
+
letterSpacing: 0.8,
|
|
685
|
+
}}>
|
|
686
|
+
RAM-Based Auto Limits
|
|
687
|
+
</Text>
|
|
688
|
+
|
|
689
|
+
{/* Auto RAM Limit Toggle */}
|
|
690
|
+
<View style={{
|
|
691
|
+
flexDirection: 'row',
|
|
692
|
+
alignItems: 'center',
|
|
693
|
+
justifyContent: 'space-between',
|
|
694
|
+
}}>
|
|
695
|
+
<View style={{
|
|
696
|
+
flexDirection: 'row',
|
|
697
|
+
alignItems: 'center',
|
|
698
|
+
gap: 10,
|
|
699
|
+
flex: 1,
|
|
700
|
+
}}>
|
|
701
|
+
<View style={{
|
|
702
|
+
width: 32,
|
|
703
|
+
height: 32,
|
|
704
|
+
borderRadius: 8,
|
|
705
|
+
backgroundColor: AppColors.purpleShade50,
|
|
706
|
+
alignItems: 'center',
|
|
707
|
+
justifyContent: 'center',
|
|
708
|
+
}}>
|
|
709
|
+
<PerformanceIcon color={AppColors.purple} size={15}/>
|
|
710
|
+
</View>
|
|
711
|
+
<View style={{ flex: 1 }}>
|
|
712
|
+
<Text style={{
|
|
713
|
+
fontFamily: AppFonts.interBold,
|
|
714
|
+
fontSize: 13.5,
|
|
715
|
+
lineHeight: 18,
|
|
716
|
+
color: AppColors.primaryBlack,
|
|
717
|
+
}}>
|
|
718
|
+
Auto-Calculate Limits from Device RAM
|
|
719
|
+
</Text>
|
|
720
|
+
<Text style={{
|
|
721
|
+
fontFamily: AppFonts.interRegular,
|
|
722
|
+
fontSize: 11,
|
|
723
|
+
lineHeight: 15,
|
|
724
|
+
color: AppColors.grayText,
|
|
725
|
+
marginTop: 1,
|
|
726
|
+
}}>
|
|
727
|
+
Automatically set API, Logs, Analytics & Crash limits based on available memory
|
|
728
|
+
</Text>
|
|
729
|
+
</View>
|
|
730
|
+
</View>
|
|
731
|
+
|
|
732
|
+
<TouchableScale accessible={true} accessibilityRole="switch" accessibilityLabel="Toggle auto RAM limit calculation" accessibilityState={{ checked: isAutoRamLimitEnabled }} onPress={() => setIsAutoRamLimitEnabled(prev => !prev)} style={{
|
|
733
|
+
width: 42,
|
|
734
|
+
height: 24,
|
|
735
|
+
borderRadius: 12,
|
|
736
|
+
backgroundColor: isAutoRamLimitEnabled
|
|
737
|
+
? AppColors.purple
|
|
738
|
+
: AppColors.grayBorderSecondary,
|
|
739
|
+
padding: 2,
|
|
740
|
+
justifyContent: 'center',
|
|
741
|
+
alignItems: isAutoRamLimitEnabled ? 'flex-end' : 'flex-start',
|
|
742
|
+
}}>
|
|
743
|
+
<View style={{
|
|
744
|
+
width: 20,
|
|
745
|
+
height: 20,
|
|
746
|
+
borderRadius: 10,
|
|
747
|
+
backgroundColor: AppColors.white,
|
|
748
|
+
shadowColor: AppColors.black,
|
|
749
|
+
shadowOpacity: 0.18,
|
|
750
|
+
shadowRadius: 2,
|
|
751
|
+
shadowOffset: { width: 0, height: 1 },
|
|
752
|
+
}}/>
|
|
753
|
+
</TouchableScale>
|
|
754
|
+
</View>
|
|
755
|
+
|
|
756
|
+
<View style={{ height: 1, backgroundColor: AppColors.dividerColor }}/>
|
|
757
|
+
|
|
758
|
+
{/* Device Free RAM Display */}
|
|
759
|
+
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 10 }}>
|
|
760
|
+
<View style={{
|
|
761
|
+
width: 32,
|
|
762
|
+
height: 32,
|
|
763
|
+
borderRadius: 8,
|
|
764
|
+
backgroundColor: isAutoRamLimitEnabled
|
|
765
|
+
? `${AppColors.purple}14`
|
|
766
|
+
: AppColors.grayBackground,
|
|
767
|
+
alignItems: 'center',
|
|
768
|
+
justifyContent: 'center',
|
|
769
|
+
}}>
|
|
770
|
+
<SignalIcon color={isAutoRamLimitEnabled ? AppColors.purple : AppColors.grayTextWeak} size={15}/>
|
|
771
|
+
</View>
|
|
772
|
+
<View style={{ flex: 1 }}>
|
|
773
|
+
<Text style={{
|
|
774
|
+
fontFamily: AppFonts.interBold,
|
|
775
|
+
fontSize: 13.5,
|
|
776
|
+
lineHeight: 18,
|
|
777
|
+
color: isAutoRamLimitEnabled
|
|
778
|
+
? AppColors.primaryBlack
|
|
779
|
+
: AppColors.grayText,
|
|
780
|
+
}}>
|
|
781
|
+
Detected Free RAM
|
|
782
|
+
</Text>
|
|
783
|
+
<Text style={{
|
|
784
|
+
fontFamily: AppFonts.interRegular,
|
|
785
|
+
fontSize: 11,
|
|
786
|
+
lineHeight: 15,
|
|
787
|
+
color: AppColors.grayText,
|
|
788
|
+
marginTop: 1,
|
|
789
|
+
}}>
|
|
790
|
+
{deviceFreeRamMb} MB available
|
|
791
|
+
</Text>
|
|
792
|
+
</View>
|
|
793
|
+
<View style={{
|
|
794
|
+
paddingHorizontal: 10,
|
|
795
|
+
paddingVertical: 5,
|
|
796
|
+
borderRadius: 8,
|
|
797
|
+
backgroundColor: isAutoRamLimitEnabled
|
|
798
|
+
? `${AppColors.purple}12`
|
|
799
|
+
: AppColors.grayBackground,
|
|
800
|
+
borderWidth: 1,
|
|
801
|
+
borderColor: isAutoRamLimitEnabled
|
|
802
|
+
? `${AppColors.purple}26`
|
|
803
|
+
: AppColors.dividerColor,
|
|
804
|
+
}}>
|
|
805
|
+
<Text style={{
|
|
806
|
+
fontFamily: AppFonts.interBold,
|
|
807
|
+
fontSize: 12,
|
|
808
|
+
lineHeight: 15,
|
|
809
|
+
color: isAutoRamLimitEnabled
|
|
810
|
+
? AppColors.purple
|
|
811
|
+
: AppColors.grayText,
|
|
812
|
+
}}>
|
|
813
|
+
{deviceFreeRamMb} MB
|
|
814
|
+
</Text>
|
|
815
|
+
</View>
|
|
816
|
+
</View>
|
|
817
|
+
|
|
818
|
+
{/* Current Auto-Calculated Limits Preview */}
|
|
819
|
+
{isAutoRamLimitEnabled && (<View style={{ marginTop: 8, paddingTop: 8, borderTopWidth: 1, borderTopColor: AppColors.dividerColor, gap: 6 }}>
|
|
820
|
+
<Text style={{
|
|
821
|
+
fontFamily: AppFonts.interBold,
|
|
822
|
+
fontSize: 11.5,
|
|
823
|
+
lineHeight: 15,
|
|
824
|
+
color: AppColors.purple,
|
|
825
|
+
}}>
|
|
826
|
+
Auto Profile: {autoRamProfile.profileName}
|
|
827
|
+
</Text>
|
|
828
|
+
<View style={{ flexDirection: 'row', flexWrap: 'wrap', gap: 8 }}>
|
|
829
|
+
{[
|
|
830
|
+
{ label: 'APIs', value: autoRamProfile.maxNetworkLogs, color: AppColors.blue500 },
|
|
831
|
+
{ label: 'Logs', value: autoRamProfile.maxConsoleLogs, color: AppColors.sky500 },
|
|
832
|
+
{ label: 'Analytics', value: autoRamProfile.maxAnalyticsEvents, color: AppColors.purple },
|
|
833
|
+
{ label: 'Crash', value: autoRamProfile.maxCrashRecords, color: AppColors.errorColor },
|
|
834
|
+
].map(item => (<View key={item.label} style={{
|
|
835
|
+
flexDirection: 'row',
|
|
836
|
+
alignItems: 'center',
|
|
837
|
+
gap: 4,
|
|
838
|
+
paddingHorizontal: 8,
|
|
839
|
+
paddingVertical: 4,
|
|
840
|
+
borderRadius: 6,
|
|
841
|
+
backgroundColor: `${item.color}14`,
|
|
842
|
+
borderWidth: 1,
|
|
843
|
+
borderColor: `${item.color}33`,
|
|
844
|
+
}}>
|
|
845
|
+
<Text style={{
|
|
846
|
+
fontFamily: AppFonts.interBold,
|
|
847
|
+
fontSize: 10.5,
|
|
848
|
+
lineHeight: 14,
|
|
849
|
+
color: item.color,
|
|
850
|
+
}}>
|
|
851
|
+
{item.label}
|
|
852
|
+
</Text>
|
|
853
|
+
<Text style={{
|
|
854
|
+
fontFamily: AppFonts.interBold,
|
|
855
|
+
fontSize: 10.5,
|
|
856
|
+
lineHeight: 14,
|
|
857
|
+
color: item.color,
|
|
858
|
+
}}>
|
|
859
|
+
{item.value}
|
|
860
|
+
</Text>
|
|
861
|
+
</View>))}
|
|
862
|
+
</View>
|
|
863
|
+
</View>)}
|
|
864
|
+
</View>
|
|
865
|
+
</View>) : (<View style={{ gap: 14 }}>
|
|
670
866
|
{/* Section 1: Appearance */}
|
|
671
867
|
<View style={{
|
|
672
868
|
backgroundColor: AppColors.primaryLight,
|
|
@@ -1421,83 +1617,128 @@ const SettingsPanel = () => {
|
|
|
1421
1617
|
setSettingsPage('main');
|
|
1422
1618
|
};
|
|
1423
1619
|
// Helper: settings row with icon + label + optional description
|
|
1424
|
-
const renderSettingRow = (opts) =>
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
<TouchableScale disabled={!opts.onPress} onPress={opts.onPress} style={{
|
|
1430
|
-
flexDirection: 'row',
|
|
1431
|
-
alignItems: 'center',
|
|
1432
|
-
gap: 12,
|
|
1433
|
-
}}>
|
|
1434
|
-
<View style={{
|
|
1435
|
-
width: 36,
|
|
1436
|
-
height: 36,
|
|
1437
|
-
borderRadius: 10,
|
|
1438
|
-
backgroundColor: AppColors.purpleShade50,
|
|
1439
|
-
borderWidth: 1,
|
|
1440
|
-
borderColor: `${AppColors.purple}2E`,
|
|
1441
|
-
alignItems: 'center',
|
|
1442
|
-
justifyContent: 'center',
|
|
1443
|
-
}}>
|
|
1444
|
-
{opts.icon}
|
|
1445
|
-
</View>
|
|
1446
|
-
<View style={{ flex: 1 }}>
|
|
1447
|
-
<Text style={{
|
|
1448
|
-
fontFamily: AppFonts.interBold,
|
|
1449
|
-
fontSize: 14,
|
|
1450
|
-
lineHeight: 18,
|
|
1451
|
-
color: AppColors.primaryBlack,
|
|
1452
|
-
}}>
|
|
1453
|
-
{opts.label}
|
|
1454
|
-
</Text>
|
|
1455
|
-
{opts.description ? (<Text style={{
|
|
1456
|
-
fontFamily: AppFonts.interRegular,
|
|
1457
|
-
fontSize: 11,
|
|
1458
|
-
lineHeight: 15,
|
|
1459
|
-
color: AppColors.grayText,
|
|
1460
|
-
marginTop: 1,
|
|
1620
|
+
const renderSettingRow = (opts) => {
|
|
1621
|
+
return (<View style={{
|
|
1622
|
+
paddingVertical: 12,
|
|
1623
|
+
borderBottomWidth: opts.isLast ? 0 : 1,
|
|
1624
|
+
borderBottomColor: AppColors.dividerColor,
|
|
1461
1625
|
}}>
|
|
1462
|
-
|
|
1463
|
-
</Text>) : null}
|
|
1464
|
-
</View>
|
|
1465
|
-
{opts.right || null}
|
|
1466
|
-
</TouchableScale>
|
|
1467
|
-
{opts.picker && (<View style={{
|
|
1626
|
+
<TouchableScale disabled={!opts.onPress} onPress={opts.onPress} style={{
|
|
1468
1627
|
flexDirection: 'row',
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1628
|
+
alignItems: 'center',
|
|
1629
|
+
gap: 12,
|
|
1630
|
+
}}>
|
|
1631
|
+
<View style={{
|
|
1632
|
+
width: 36,
|
|
1633
|
+
height: 36,
|
|
1634
|
+
borderRadius: 10,
|
|
1635
|
+
backgroundColor: AppColors.purpleShade50,
|
|
1473
1636
|
borderWidth: 1,
|
|
1474
|
-
borderColor: AppColors.
|
|
1637
|
+
borderColor: `${AppColors.purple}2E`,
|
|
1638
|
+
alignItems: 'center',
|
|
1639
|
+
justifyContent: 'center',
|
|
1475
1640
|
}}>
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1641
|
+
{opts.icon}
|
|
1642
|
+
</View>
|
|
1643
|
+
<View style={{ flex: 1 }}>
|
|
1644
|
+
<Text style={{
|
|
1645
|
+
fontFamily: AppFonts.interBold,
|
|
1646
|
+
fontSize: 14,
|
|
1647
|
+
lineHeight: 18,
|
|
1648
|
+
color: AppColors.primaryBlack,
|
|
1649
|
+
}}>
|
|
1650
|
+
{opts.label}
|
|
1651
|
+
</Text>
|
|
1652
|
+
{opts.description ? (<Text style={{
|
|
1653
|
+
fontFamily: AppFonts.interRegular,
|
|
1654
|
+
fontSize: 11,
|
|
1655
|
+
lineHeight: 15,
|
|
1656
|
+
color: AppColors.grayText,
|
|
1657
|
+
marginTop: 1,
|
|
1658
|
+
}}>
|
|
1659
|
+
{opts.description}
|
|
1660
|
+
</Text>) : null}
|
|
1661
|
+
</View>
|
|
1662
|
+
{opts.right || null}
|
|
1663
|
+
</TouchableScale>
|
|
1664
|
+
{opts.numericInput && (<View style={{ marginTop: 10, gap: 6 }}>
|
|
1665
|
+
<View style={{
|
|
1666
|
+
flexDirection: 'row',
|
|
1667
|
+
alignItems: 'center',
|
|
1668
|
+
backgroundColor: AppColors.grayBackground,
|
|
1669
|
+
borderRadius: 8,
|
|
1670
|
+
borderWidth: 1,
|
|
1671
|
+
borderColor: AppColors.dividerColor,
|
|
1672
|
+
paddingHorizontal: 12,
|
|
1673
|
+
paddingVertical: 4,
|
|
1674
|
+
}}>
|
|
1675
|
+
<TextInput style={{
|
|
1676
|
+
flex: 1,
|
|
1677
|
+
fontFamily: AppFonts.interMedium,
|
|
1678
|
+
fontSize: 14,
|
|
1679
|
+
lineHeight: 18,
|
|
1680
|
+
color: AppColors.primaryBlack,
|
|
1681
|
+
paddingVertical: 6,
|
|
1682
|
+
}} value={String(opts.numericInput.value || '')} onChangeText={text => {
|
|
1683
|
+
const num = parseInt(text.replace(/[^0-9]/g, ''), 10);
|
|
1684
|
+
if (!isNaN(num)) {
|
|
1685
|
+
const clamped = Math.max(opts.numericInput?.min ?? 1, Math.min(opts.numericInput?.max ?? 10000, num));
|
|
1686
|
+
opts.numericInput?.onChange(clamped);
|
|
1687
|
+
}
|
|
1688
|
+
}} keyboardType={opts.numericInput.keyboardType ?? 'number-pad'} placeholder={opts.numericInput.placeholder} placeholderTextColor={AppColors.grayTextWeak} maxLength={6} selectTextOnFocus/>
|
|
1689
|
+
<Text style={{
|
|
1690
|
+
fontFamily: AppFonts.interBold,
|
|
1691
|
+
fontSize: 11,
|
|
1692
|
+
color: AppColors.purple,
|
|
1693
|
+
marginLeft: 6,
|
|
1694
|
+
}}>
|
|
1695
|
+
MAX
|
|
1696
|
+
</Text>
|
|
1697
|
+
</View>
|
|
1698
|
+
{opts.numericInput.min !== undefined || opts.numericInput.max !== undefined ? (<Text style={{
|
|
1699
|
+
fontFamily: AppFonts.interRegular,
|
|
1700
|
+
fontSize: 10,
|
|
1701
|
+
lineHeight: 13,
|
|
1702
|
+
color: AppColors.grayTextWeak,
|
|
1492
1703
|
}}>
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1704
|
+
Range: {opts.numericInput.min ?? 1} - {opts.numericInput.max ?? '∞'}
|
|
1705
|
+
</Text>) : null}
|
|
1706
|
+
</View>)}
|
|
1707
|
+
{opts.picker && (<View style={{
|
|
1708
|
+
flexDirection: 'row',
|
|
1709
|
+
backgroundColor: AppColors.grayBackground,
|
|
1710
|
+
borderRadius: 8,
|
|
1711
|
+
padding: 2.5,
|
|
1712
|
+
marginTop: 10,
|
|
1713
|
+
borderWidth: 1,
|
|
1714
|
+
borderColor: AppColors.dividerColor,
|
|
1715
|
+
}}>
|
|
1716
|
+
{opts.picker.options.map(opt => {
|
|
1717
|
+
const isActive = opts.picker.selectedValue === opt;
|
|
1718
|
+
return (<TouchableScale key={String(opt)} onPress={() => opts.picker.onSelect(opt)} style={{
|
|
1719
|
+
flex: 1,
|
|
1720
|
+
paddingVertical: 6,
|
|
1721
|
+
alignItems: 'center',
|
|
1722
|
+
borderRadius: 6,
|
|
1723
|
+
backgroundColor: isActive
|
|
1724
|
+
? AppColors.purple
|
|
1725
|
+
: 'transparent',
|
|
1726
|
+
}}>
|
|
1727
|
+
<Text style={{
|
|
1728
|
+
fontFamily: AppFonts.interBold,
|
|
1729
|
+
fontSize: 11,
|
|
1730
|
+
lineHeight: 14,
|
|
1731
|
+
color: isActive ? AppColors.white : AppColors.grayText,
|
|
1732
|
+
}}>
|
|
1733
|
+
{opts.picker.formatLabel
|
|
1734
|
+
? opts.picker.formatLabel(opt)
|
|
1735
|
+
: opt}
|
|
1736
|
+
</Text>
|
|
1737
|
+
</TouchableScale>);
|
|
1738
|
+
})}
|
|
1739
|
+
</View>)}
|
|
1740
|
+
</View>);
|
|
1741
|
+
};
|
|
1501
1742
|
let content = null;
|
|
1502
1743
|
let title = '';
|
|
1503
1744
|
let icon = null;
|
|
@@ -1518,10 +1759,12 @@ const SettingsPanel = () => {
|
|
|
1518
1759
|
icon: <SignalIcon color={AppColors.purple} size={16}/>,
|
|
1519
1760
|
label: t('settings.apis.maxRequestLogs'),
|
|
1520
1761
|
description: t('settings.apis.maxRequestLogsDescription'),
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1762
|
+
numericInput: {
|
|
1763
|
+
value: maxNetworkLogs,
|
|
1764
|
+
onChange: setMaxNetworkLogs,
|
|
1765
|
+
min: 10,
|
|
1766
|
+
max: 5000,
|
|
1767
|
+
placeholder: 'Enter max requests (10-5000)',
|
|
1525
1768
|
},
|
|
1526
1769
|
isLast: true,
|
|
1527
1770
|
})}
|
|
@@ -1582,10 +1825,12 @@ const SettingsPanel = () => {
|
|
|
1582
1825
|
icon: <TerminalIcon color={AppColors.purple} size={16}/>,
|
|
1583
1826
|
label: t('settings.logs.maxConsoleLogs'),
|
|
1584
1827
|
description: t('settings.logs.maxConsoleLogsDescription'),
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1828
|
+
numericInput: {
|
|
1829
|
+
value: maxConsoleLogs,
|
|
1830
|
+
onChange: setMaxConsoleLogs,
|
|
1831
|
+
min: 10,
|
|
1832
|
+
max: 10000,
|
|
1833
|
+
placeholder: 'Enter max logs (10-10000)',
|
|
1589
1834
|
},
|
|
1590
1835
|
})}
|
|
1591
1836
|
<View style={{ height: 1, backgroundColor: AppColors.dividerColor }}/>
|
|
@@ -1702,6 +1947,13 @@ const SettingsPanel = () => {
|
|
|
1702
1947
|
icon: <AnalyticsIcon color={AppColors.purple} size={16}/>,
|
|
1703
1948
|
label: t('settings.analytics.maxAnalyticsEvents'),
|
|
1704
1949
|
description: t('settings.analytics.maxAnalyticsEventsDescription', { count: analyticsEvents.length }),
|
|
1950
|
+
numericInput: {
|
|
1951
|
+
value: maxAnalyticsEventsLimit,
|
|
1952
|
+
onChange: setMaxAnalyticsEventsLimit,
|
|
1953
|
+
min: 10,
|
|
1954
|
+
max: 5000,
|
|
1955
|
+
placeholder: 'Enter max events (10-5000)',
|
|
1956
|
+
},
|
|
1705
1957
|
isLast: true,
|
|
1706
1958
|
})}
|
|
1707
1959
|
</View>
|
|
@@ -1848,10 +2100,12 @@ const SettingsPanel = () => {
|
|
|
1848
2100
|
icon: <LayersIcon color={AppColors.purple} size={16}/>,
|
|
1849
2101
|
label: t('settings.crash.maxCrashLogs'),
|
|
1850
2102
|
description: t('settings.crash.maxCrashLogsDesc'),
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
2103
|
+
numericInput: {
|
|
2104
|
+
value: maxCrashLogs,
|
|
2105
|
+
onChange: setMaxCrashLogs,
|
|
2106
|
+
min: 5,
|
|
2107
|
+
max: 500,
|
|
2108
|
+
placeholder: 'Enter max crashes (5-500)',
|
|
1855
2109
|
},
|
|
1856
2110
|
})}
|
|
1857
2111
|
<View style={{ height: 1, backgroundColor: AppColors.dividerColor }}/>
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { Animated, ScrollView, Text, View } from 'react-native';
|
|
2
|
+
import { Animated, ScrollView, Text, TouchableOpacity, View } from 'react-native';
|
|
3
3
|
import { useInspector } from './InspectorContext';
|
|
4
|
-
import TouchableScale from '../TouchableScale';
|
|
5
4
|
import styles from '../../styles';
|
|
6
5
|
import { AppColors } from '../../styles/AppColors';
|
|
7
6
|
import { SignalIcon, TerminalIcon, AnalyticsIcon, PackageIcon, ReduxIcon, PerformanceIcon, CrashIcon, } from '../NetworkIcons';
|
|
8
7
|
import { isReduxConnected } from '../../customHooks/reduxLogger';
|
|
9
8
|
import { isAnalyticsConnected } from '../../customHooks/analyticsLogger';
|
|
9
|
+
import { triggerNativeHaptic } from '../../native/NativeInspector';
|
|
10
10
|
const TabBar = React.memo(() => {
|
|
11
11
|
const { activeTab, switchActiveTab, tabVisibility, logs, consoleLogs, analyticsEvents, crashRecords, lastReadApisCount, lastReadLogsCount, lastReadCrashesCount, unreadPulseAnim, } = useInspector();
|
|
12
12
|
const isReduxAvail = isReduxConnected();
|
|
@@ -80,7 +80,10 @@ const TabBar = React.memo(() => {
|
|
|
80
80
|
consoleLogs.length > lastReadLogsCount;
|
|
81
81
|
const hasUnreadCrashes = activeTab !== 'crash' &&
|
|
82
82
|
(crashRecords?.length || 0) > (lastReadCrashesCount || 0);
|
|
83
|
-
return (<
|
|
83
|
+
return (<TouchableOpacity key={tab.key} activeOpacity={0.7} onPress={() => {
|
|
84
|
+
switchActiveTab(tab.key);
|
|
85
|
+
triggerNativeHaptic('light');
|
|
86
|
+
}} style={[
|
|
84
87
|
styles.contentTabButton,
|
|
85
88
|
isActive && styles.contentTabButtonActive,
|
|
86
89
|
]}>
|
|
@@ -116,7 +119,7 @@ const TabBar = React.memo(() => {
|
|
|
116
119
|
transform: [{ scale: unreadPulseAnim }],
|
|
117
120
|
}}/>)}
|
|
118
121
|
</View>
|
|
119
|
-
</
|
|
122
|
+
</TouchableOpacity>);
|
|
120
123
|
})}
|
|
121
124
|
</ScrollView>
|
|
122
125
|
</View>);
|
|
@@ -124,3 +124,4 @@ export declare const SmartphoneIcon: ({ color, size }: IconProps) => React.JSX.E
|
|
|
124
124
|
export declare const AlertTriangleIcon: ({ color, size }: IconProps) => React.JSX.Element;
|
|
125
125
|
export declare const BugIcon: ({ color, size }: IconProps) => React.JSX.Element;
|
|
126
126
|
export declare const TagIcon: ({ color, size }: IconProps) => React.JSX.Element;
|
|
127
|
+
export declare const NpmIcon: ({ color, size }: IconProps) => React.JSX.Element;
|
|
@@ -700,3 +700,7 @@ export const TagIcon = ({ color = AppColors.grayTextWeak, size = 14 }) => (<Svg
|
|
|
700
700
|
<Path d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8 8a2 2 0 0 0 2.828 0l7.172-7.172a2 2 0 0 0 0-2.828l-8-8z" stroke={color} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
|
|
701
701
|
<Circle cx="7.5" cy="7.5" r="1.5" fill={color}/>
|
|
702
702
|
</Svg>);
|
|
703
|
+
export const NpmIcon = ({ color = '#CB3837', size = 14 }) => (<Svg width={size} height={size} viewBox="0 0 256 256" fill="none">
|
|
704
|
+
<Rect width="256" height="256" rx="32" fill={color}/>
|
|
705
|
+
<Path d="M48 48h160v160h-32V96h-32v112H48V48z" fill="#FFFFFF"/>
|
|
706
|
+
</Svg>);
|
|
@@ -7,6 +7,7 @@ export interface TouchableScaleProps extends PressableProps {
|
|
|
7
7
|
children?: React.ReactNode;
|
|
8
8
|
hitSlop?: any;
|
|
9
9
|
disabled?: boolean;
|
|
10
|
+
enableHaptics?: boolean;
|
|
10
11
|
}
|
|
11
12
|
declare const TouchableScale: React.NamedExoticComponent<TouchableScaleProps>;
|
|
12
13
|
export default TouchableScale;
|