react-native-inapp-inspector 1.1.34 → 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/ConsoleLogCard.js +57 -56
- package/dist/commonjs/components/CopyButton.js +10 -1
- package/dist/commonjs/components/ErrorBoundary.js +3 -0
- package/dist/commonjs/components/Inspector/AnalyticsTab.js +7 -3
- package/dist/commonjs/components/Inspector/BundleTab.js +20 -20
- package/dist/commonjs/components/Inspector/ConsoleTab.js +1 -1
- package/dist/commonjs/components/Inspector/CrashDetail.js +16 -12
- package/dist/commonjs/components/Inspector/CrashTab.js +97 -90
- package/dist/commonjs/components/Inspector/InspectorHeader.js +28 -24
- package/dist/commonjs/components/Inspector/MainScreen.js +20 -103
- package/dist/commonjs/components/Inspector/NetworkTab.js +143 -10
- package/dist/commonjs/components/Inspector/PerformanceTab.js +96 -3
- package/dist/commonjs/components/Inspector/ReduxDetail.js +24 -19
- package/dist/commonjs/components/Inspector/ReduxTab.js +30 -18
- package/dist/commonjs/components/Inspector/SettingsPanel.js +1578 -754
- package/dist/commonjs/components/Inspector/TabBar.js +6 -3
- package/dist/commonjs/components/LogCard.js +27 -9
- package/dist/commonjs/components/MetaAccordion.js +42 -0
- package/dist/commonjs/components/NetworkIcons.d.ts +10 -0
- package/dist/commonjs/components/NetworkIcons.js +53 -1
- package/dist/commonjs/components/Toast.js +3 -3
- package/dist/commonjs/components/TouchableScale.d.ts +5 -2
- 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 +6 -0
- package/dist/commonjs/customHooks/analyticsLogger.js +16 -5
- package/dist/commonjs/customHooks/bundleAnalyzer.d.ts +2 -0
- package/dist/commonjs/customHooks/bundleAnalyzer.js +26 -17
- package/dist/commonjs/customHooks/consoleLogger.d.ts +2 -0
- package/dist/commonjs/customHooks/consoleLogger.js +10 -1
- package/dist/commonjs/customHooks/crashHandler.d.ts +2 -0
- package/dist/commonjs/customHooks/crashHandler.js +17 -1
- package/dist/commonjs/customHooks/networkLogger.d.ts +2 -0
- package/dist/commonjs/customHooks/networkLogger.js +12 -1
- package/dist/commonjs/customHooks/performanceTracker.d.ts +3 -1
- package/dist/commonjs/customHooks/performanceTracker.js +18 -4
- package/dist/commonjs/customHooks/reduxLogger.d.ts +2 -0
- package/dist/commonjs/customHooks/reduxLogger.js +10 -1
- 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/i18n/locales/en.json +96 -28
- package/dist/commonjs/index.d.ts +1 -0
- package/dist/commonjs/index.js +307 -73
- 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/AppColors.d.ts +28 -0
- package/dist/commonjs/styles/AppColors.js +30 -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/ConsoleLogCard.js +58 -57
- package/dist/esm/components/CopyButton.js +10 -1
- package/dist/esm/components/ErrorBoundary.js +3 -0
- package/dist/esm/components/Inspector/AnalyticsTab.js +7 -3
- package/dist/esm/components/Inspector/BundleTab.js +20 -20
- package/dist/esm/components/Inspector/ConsoleTab.js +1 -1
- package/dist/esm/components/Inspector/CrashDetail.js +16 -12
- package/dist/esm/components/Inspector/CrashTab.js +97 -90
- package/dist/esm/components/Inspector/InspectorHeader.js +29 -25
- package/dist/esm/components/Inspector/MainScreen.js +21 -71
- package/dist/esm/components/Inspector/NetworkTab.js +145 -12
- package/dist/esm/components/Inspector/PerformanceTab.js +96 -3
- package/dist/esm/components/Inspector/ReduxDetail.js +24 -19
- package/dist/esm/components/Inspector/ReduxTab.js +30 -18
- package/dist/esm/components/Inspector/SettingsPanel.js +1582 -758
- package/dist/esm/components/Inspector/TabBar.js +7 -4
- package/dist/esm/components/LogCard.js +27 -9
- package/dist/esm/components/MetaAccordion.js +42 -0
- package/dist/esm/components/NetworkIcons.d.ts +10 -0
- package/dist/esm/components/NetworkIcons.js +42 -0
- package/dist/esm/components/Toast.js +3 -3
- package/dist/esm/components/TouchableScale.d.ts +5 -2
- 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 +6 -0
- package/dist/esm/customHooks/analyticsLogger.js +12 -4
- package/dist/esm/customHooks/bundleAnalyzer.d.ts +2 -0
- package/dist/esm/customHooks/bundleAnalyzer.js +23 -16
- package/dist/esm/customHooks/consoleLogger.d.ts +2 -0
- package/dist/esm/customHooks/consoleLogger.js +7 -0
- package/dist/esm/customHooks/crashHandler.d.ts +2 -0
- package/dist/esm/customHooks/crashHandler.js +14 -0
- package/dist/esm/customHooks/networkLogger.d.ts +2 -0
- package/dist/esm/customHooks/networkLogger.js +9 -0
- package/dist/esm/customHooks/performanceTracker.d.ts +3 -1
- package/dist/esm/customHooks/performanceTracker.js +15 -3
- package/dist/esm/customHooks/reduxLogger.d.ts +2 -0
- package/dist/esm/customHooks/reduxLogger.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/i18n/locales/en.json +96 -28
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +279 -59
- 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/AppColors.d.ts +28 -0
- package/dist/esm/styles/AppColors.js +30 -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 +15 -3
- 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
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { Alert, Platform, ScrollView, Text,
|
|
1
|
+
import React, { useMemo, useState, useEffect } from 'react';
|
|
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,36 +8,129 @@ 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';
|
|
15
|
-
import { clearCrashRecords
|
|
15
|
+
import { clearCrashRecords } from '../../customHooks/crashHandler';
|
|
16
|
+
import { clearCachedBundleAnalysis } from '../../customHooks/bundleAnalyzer';
|
|
17
|
+
import { clearPerformanceEvents } from '../../customHooks/performanceTracker';
|
|
16
18
|
import { isReduxConnected } from '../../customHooks/reduxLogger';
|
|
17
19
|
import { isAnalyticsConnected } from '../../customHooks/analyticsLogger';
|
|
18
20
|
import { useTranslation } from '../../i18n';
|
|
19
|
-
import { SignalIcon, TerminalIcon, AnalyticsIcon, SettingsIcon, SunIcon, MoonIcon, ScreenIcon, MotionIcon, LayersIcon, EyeIcon, CheckIcon, TrashIcon, WhiteBackNavigation, PackageIcon, ReduxIcon, PerformanceIcon, CrashIcon, ShieldAlertIcon, } from '../NetworkIcons';
|
|
21
|
+
import { SignalIcon, TerminalIcon, AnalyticsIcon, SettingsIcon, SunIcon, MoonIcon, ScreenIcon, MotionIcon, LayersIcon, EyeIcon, CheckIcon, TrashIcon, WhiteBackNavigation, PackageIcon, ReduxIcon, PerformanceIcon, CrashIcon, ShieldAlertIcon, ForwardChevronIcon, } from '../NetworkIcons';
|
|
20
22
|
const SettingsPanel = () => {
|
|
21
23
|
const { t } = useTranslation();
|
|
22
|
-
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);
|
|
23
26
|
const isPersistent = isPersistentStorageAvailable();
|
|
24
|
-
|
|
27
|
+
// Safe Area & Status Bar Padding for All Device Form Factors
|
|
28
|
+
const statusBarHeight = Platform.OS === 'android' ? StatusBar.currentHeight || 24 : 44;
|
|
29
|
+
const headerTopPadding = modalHeightPercent >= 95 ? statusBarHeight : 0;
|
|
30
|
+
const allModules = [
|
|
31
|
+
{
|
|
32
|
+
key: 'apis',
|
|
33
|
+
label: 'APIs (Network)',
|
|
34
|
+
category: 'core',
|
|
35
|
+
icon: 'apis',
|
|
36
|
+
desc: 'HTTP/HTTPS requests, GraphQL, Axios & WebSocket inspector',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
key: 'logs',
|
|
40
|
+
label: 'Console Logs',
|
|
41
|
+
category: 'core',
|
|
42
|
+
icon: 'logs',
|
|
43
|
+
desc: 'Terminal console logs, warnings, errors & stack traces',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
key: 'performance',
|
|
47
|
+
label: 'Performance Tracker',
|
|
48
|
+
category: 'diagnostic',
|
|
49
|
+
icon: 'performance',
|
|
50
|
+
desc: '60 FPS monitor, Hermes memory telemetry & re-render profiler',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
key: 'bundle',
|
|
54
|
+
label: 'Bundle Analyzer',
|
|
55
|
+
category: 'diagnostic',
|
|
56
|
+
icon: 'bundle',
|
|
57
|
+
desc: 'Metro packager dependencies, source maps & asset breakdown',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
key: 'crash',
|
|
61
|
+
label: 'Crash Protection',
|
|
62
|
+
category: 'diagnostic',
|
|
63
|
+
icon: 'crash',
|
|
64
|
+
desc: 'Runtime exception guard, breadcrumbs & memory snapshot',
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
key: 'analytics',
|
|
68
|
+
label: 'Analytics Logger',
|
|
69
|
+
category: 'telemetry',
|
|
70
|
+
icon: 'analytics',
|
|
71
|
+
desc: 'Firebase & custom analytics events, user properties & params',
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
key: 'redux',
|
|
75
|
+
label: 'Redux Inspector',
|
|
76
|
+
category: 'telemetry',
|
|
77
|
+
icon: 'redux',
|
|
78
|
+
desc: 'Store state diffing, action history & reducer timeline',
|
|
79
|
+
},
|
|
80
|
+
];
|
|
81
|
+
// Staged selection state for checkboxes before clicking "Save Changes"
|
|
82
|
+
const [stagedTabVisibility, setStagedTabVisibility] = useState(() => ({
|
|
83
|
+
apis: true,
|
|
84
|
+
logs: Boolean(tabVisibility?.logs),
|
|
85
|
+
analytics: Boolean(tabVisibility?.analytics),
|
|
86
|
+
redux: Boolean(tabVisibility?.redux),
|
|
87
|
+
bundle: Boolean(tabVisibility?.bundle),
|
|
88
|
+
performance: Boolean(tabVisibility?.performance),
|
|
89
|
+
crash: Boolean(tabVisibility?.crash),
|
|
90
|
+
}));
|
|
91
|
+
// Synchronize staged state with tabVisibility when tabVisibility updates
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
setStagedTabVisibility({
|
|
94
|
+
apis: true,
|
|
95
|
+
logs: Boolean(tabVisibility?.logs),
|
|
96
|
+
analytics: Boolean(tabVisibility?.analytics),
|
|
97
|
+
redux: Boolean(tabVisibility?.redux),
|
|
98
|
+
bundle: Boolean(tabVisibility?.bundle),
|
|
99
|
+
performance: Boolean(tabVisibility?.performance),
|
|
100
|
+
crash: Boolean(tabVisibility?.crash),
|
|
101
|
+
});
|
|
102
|
+
}, [tabVisibility]);
|
|
103
|
+
const hasUnsavedChanges = useMemo(() => {
|
|
104
|
+
return allModules.some(m => Boolean(stagedTabVisibility[m.key]) !==
|
|
105
|
+
Boolean(tabVisibility?.[m.key]));
|
|
106
|
+
}, [stagedTabVisibility, tabVisibility, allModules]);
|
|
107
|
+
const stagedActiveCount = allModules.filter(m => m.key === 'apis' || Boolean(stagedTabVisibility[m.key])).length;
|
|
108
|
+
const handleSaveChanges = () => {
|
|
109
|
+
animateNextLayout();
|
|
110
|
+
allModules.forEach(m => {
|
|
111
|
+
if (m.key !== 'apis') {
|
|
112
|
+
const isStagedOn = Boolean(stagedTabVisibility[m.key]);
|
|
113
|
+
const isCurrentOn = Boolean(tabVisibility?.[m.key]);
|
|
114
|
+
if (isStagedOn !== isCurrentOn) {
|
|
115
|
+
toggleTabVisibility(m.key);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
Alert.alert(t('settings.settingsSaved'), t('settings.settingsSavedDesc'));
|
|
120
|
+
};
|
|
25
121
|
if (settingsPage === 'main') {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
{ key: 'bundle', label: 'Bundle', icon: 'bundle' },
|
|
32
|
-
{ key: 'performance', label: 'Performance', icon: 'performance' },
|
|
33
|
-
{ key: 'crash', label: 'Crash', icon: 'crash' },
|
|
34
|
-
];
|
|
35
|
-
return (<View style={{ flex: 1, backgroundColor: AppColors.grayBackground }}>
|
|
36
|
-
{/* Settings Header with back button */}
|
|
122
|
+
return (<View style={{
|
|
123
|
+
flex: 1,
|
|
124
|
+
backgroundColor: AppColors.grayBackground,
|
|
125
|
+
}}>
|
|
126
|
+
{/* Modern Floating Gradient Header */}
|
|
37
127
|
<LinearGradient colors={[AppColors.purple, AppColors.brandPurple]} start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }} style={styles.headerGradient}>
|
|
38
128
|
<View style={{ paddingTop: headerTopPadding, width: '100%' }}>
|
|
39
|
-
<View style={[
|
|
40
|
-
|
|
129
|
+
<View style={[
|
|
130
|
+
styles.header,
|
|
131
|
+
{ paddingHorizontal: 16, paddingVertical: 12, gap: 12 },
|
|
132
|
+
]}>
|
|
133
|
+
<TouchableScale accessible={true} accessibilityRole="button" accessibilityLabel={t('settings.back')} onPress={() => {
|
|
41
134
|
animateNextLayout();
|
|
42
135
|
setSettingsPage(null);
|
|
43
136
|
switchActiveTab('apis');
|
|
@@ -46,223 +139,360 @@ const SettingsPanel = () => {
|
|
|
46
139
|
borderRadius: 10,
|
|
47
140
|
backgroundColor: `${AppColors.white}26`,
|
|
48
141
|
borderWidth: 1,
|
|
49
|
-
borderColor: `${AppColors.white}
|
|
142
|
+
borderColor: `${AppColors.white}18`,
|
|
50
143
|
}}>
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
<
|
|
144
|
+
<WhiteBackNavigation color={AppColors.white} size={16}/>
|
|
145
|
+
</TouchableScale>
|
|
146
|
+
|
|
147
|
+
<View style={{ flex: 1 }}>
|
|
148
|
+
<View style={{
|
|
149
|
+
flexDirection: 'row',
|
|
150
|
+
alignItems: 'center',
|
|
151
|
+
gap: 8,
|
|
152
|
+
}}>
|
|
153
|
+
<Text style={{
|
|
55
154
|
fontFamily: AppFonts.interBold,
|
|
56
155
|
fontSize: 17,
|
|
57
156
|
color: AppColors.white,
|
|
157
|
+
letterSpacing: -0.3,
|
|
158
|
+
lineHeight: 22,
|
|
58
159
|
}}>
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
160
|
+
{t('settings.mainTitle')}
|
|
161
|
+
</Text>
|
|
162
|
+
<View style={{
|
|
163
|
+
backgroundColor: `${AppColors.white}26`,
|
|
164
|
+
paddingHorizontal: 7,
|
|
165
|
+
paddingVertical: 2,
|
|
166
|
+
borderRadius: 12,
|
|
167
|
+
}}>
|
|
168
|
+
<Text style={{
|
|
169
|
+
fontFamily: AppFonts.interBold,
|
|
170
|
+
fontSize: 10,
|
|
171
|
+
color: AppColors.white,
|
|
172
|
+
lineHeight: 13,
|
|
173
|
+
}}>
|
|
174
|
+
{stagedActiveCount}/{allModules.length} Active
|
|
175
|
+
</Text>
|
|
176
|
+
</View>
|
|
177
|
+
</View>
|
|
178
|
+
<Text style={{
|
|
62
179
|
fontFamily: AppFonts.interRegular,
|
|
63
180
|
fontSize: 11,
|
|
64
|
-
color: `${AppColors.white}
|
|
65
|
-
marginTop:
|
|
181
|
+
color: `${AppColors.white}CC`,
|
|
182
|
+
marginTop: 2,
|
|
183
|
+
lineHeight: 15,
|
|
66
184
|
}}>
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
185
|
+
{t('settings.mainSubtitle')}
|
|
186
|
+
</Text>
|
|
187
|
+
</View>
|
|
188
|
+
|
|
189
|
+
<View style={{
|
|
190
|
+
backgroundColor: `${AppColors.white}22`,
|
|
72
191
|
paddingHorizontal: 8,
|
|
73
192
|
paddingVertical: 4,
|
|
74
193
|
borderRadius: 8,
|
|
75
194
|
borderWidth: 1,
|
|
76
195
|
borderColor: `${AppColors.white}1A`,
|
|
77
196
|
}}>
|
|
78
|
-
|
|
197
|
+
<Text style={{
|
|
79
198
|
fontFamily: AppFonts.interBold,
|
|
80
199
|
fontSize: 10.5,
|
|
81
200
|
color: AppColors.white,
|
|
201
|
+
lineHeight: 14,
|
|
82
202
|
}}>
|
|
83
|
-
|
|
84
|
-
|
|
203
|
+
v{LIB_VERSION}
|
|
204
|
+
</Text>
|
|
205
|
+
</View>
|
|
85
206
|
</View>
|
|
86
207
|
</View>
|
|
87
|
-
</
|
|
88
|
-
</LinearGradient>
|
|
208
|
+
</LinearGradient>
|
|
89
209
|
|
|
90
|
-
<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16, gap:
|
|
91
|
-
{/* Sub
|
|
210
|
+
<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16, gap: 14 }} showsVerticalScrollIndicator={false}>
|
|
211
|
+
{/* Segmented Top Navigation Sub-Tabs */}
|
|
92
212
|
<View style={{
|
|
93
213
|
flexDirection: 'row',
|
|
94
214
|
backgroundColor: AppColors.primaryLight,
|
|
95
|
-
borderRadius:
|
|
96
|
-
padding:
|
|
215
|
+
borderRadius: 12,
|
|
216
|
+
padding: 4,
|
|
97
217
|
borderWidth: 1,
|
|
98
218
|
borderColor: AppColors.grayBorderSecondary,
|
|
99
|
-
|
|
219
|
+
shadowColor: AppColors.black,
|
|
220
|
+
shadowOpacity: 0.04,
|
|
221
|
+
shadowRadius: 4,
|
|
222
|
+
shadowOffset: { width: 0, height: 2 },
|
|
100
223
|
}}>
|
|
101
|
-
<
|
|
224
|
+
<TouchableScale accessible={true} accessibilityRole="tab" accessibilityLabel={t('settings.modulesAndTools')} accessibilityState={{ selected: settingsActiveSubTab === 'module' }} onPress={() => {
|
|
102
225
|
animateNextLayout();
|
|
103
226
|
setSettingsActiveSubTab('module');
|
|
104
227
|
}} style={{
|
|
105
228
|
flex: 1,
|
|
106
|
-
paddingVertical:
|
|
229
|
+
paddingVertical: 9,
|
|
230
|
+
flexDirection: 'row',
|
|
107
231
|
alignItems: 'center',
|
|
108
232
|
justifyContent: 'center',
|
|
109
|
-
|
|
233
|
+
gap: 6,
|
|
234
|
+
borderRadius: 9,
|
|
110
235
|
backgroundColor: settingsActiveSubTab === 'module'
|
|
111
236
|
? AppColors.purple
|
|
112
237
|
: 'transparent',
|
|
113
238
|
}}>
|
|
239
|
+
<LayersIcon color={settingsActiveSubTab === 'module'
|
|
240
|
+
? AppColors.white
|
|
241
|
+
: AppColors.grayText} size={13}/>
|
|
114
242
|
<Text style={{
|
|
115
243
|
fontFamily: AppFonts.interBold,
|
|
116
|
-
fontSize: 12,
|
|
244
|
+
fontSize: 12.5,
|
|
245
|
+
lineHeight: 16,
|
|
117
246
|
color: settingsActiveSubTab === 'module'
|
|
118
247
|
? AppColors.white
|
|
119
248
|
: AppColors.grayText,
|
|
120
249
|
}}>
|
|
121
|
-
|
|
250
|
+
{t('settings.modulesAndTools')}
|
|
122
251
|
</Text>
|
|
123
|
-
</
|
|
124
|
-
|
|
252
|
+
</TouchableScale>
|
|
253
|
+
|
|
254
|
+
<TouchableScale accessible={true} accessibilityRole="tab" accessibilityLabel={t('settings.uiPreferences')} accessibilityState={{ selected: settingsActiveSubTab === 'ui' }} onPress={() => {
|
|
125
255
|
animateNextLayout();
|
|
126
256
|
setSettingsActiveSubTab('ui');
|
|
127
257
|
}} style={{
|
|
128
258
|
flex: 1,
|
|
129
|
-
paddingVertical:
|
|
259
|
+
paddingVertical: 9,
|
|
260
|
+
flexDirection: 'row',
|
|
130
261
|
alignItems: 'center',
|
|
131
262
|
justifyContent: 'center',
|
|
132
|
-
|
|
263
|
+
gap: 6,
|
|
264
|
+
borderRadius: 9,
|
|
133
265
|
backgroundColor: settingsActiveSubTab === 'ui'
|
|
134
266
|
? AppColors.purple
|
|
135
267
|
: 'transparent',
|
|
136
268
|
}}>
|
|
269
|
+
<ScreenIcon color={settingsActiveSubTab === 'ui'
|
|
270
|
+
? AppColors.white
|
|
271
|
+
: AppColors.grayText} size={13}/>
|
|
137
272
|
<Text style={{
|
|
138
273
|
fontFamily: AppFonts.interBold,
|
|
139
|
-
fontSize: 12,
|
|
274
|
+
fontSize: 12.5,
|
|
275
|
+
lineHeight: 16,
|
|
140
276
|
color: settingsActiveSubTab === 'ui'
|
|
141
277
|
? AppColors.white
|
|
142
278
|
: AppColors.grayText,
|
|
143
279
|
}}>
|
|
144
|
-
|
|
280
|
+
{t('settings.uiPreferences')}
|
|
145
281
|
</Text>
|
|
146
|
-
</
|
|
282
|
+
</TouchableScale>
|
|
147
283
|
</View>
|
|
148
284
|
|
|
149
|
-
{settingsActiveSubTab === 'module' ? (
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
backgroundColor: AppColors.
|
|
285
|
+
{settingsActiveSubTab === 'module' ? (<View style={{ gap: 12 }}>
|
|
286
|
+
{/* Performance Advisory Banner */}
|
|
287
|
+
<View style={{
|
|
288
|
+
backgroundColor: `${AppColors.purple}0A`,
|
|
153
289
|
borderRadius: 12,
|
|
290
|
+
padding: 12,
|
|
154
291
|
borderWidth: 1,
|
|
155
|
-
borderColor: AppColors.
|
|
156
|
-
overflow: 'hidden',
|
|
157
|
-
}}>
|
|
158
|
-
{/* Table Header */}
|
|
159
|
-
<View style={{
|
|
292
|
+
borderColor: `${AppColors.purple}20`,
|
|
160
293
|
flexDirection: 'row',
|
|
161
294
|
alignItems: 'center',
|
|
162
|
-
|
|
163
|
-
paddingHorizontal: 14,
|
|
164
|
-
backgroundColor: AppColors.grayBackground,
|
|
165
|
-
borderBottomWidth: 1,
|
|
166
|
-
borderBottomColor: AppColors.dividerColor,
|
|
167
|
-
gap: 12,
|
|
295
|
+
gap: 10,
|
|
168
296
|
}}>
|
|
169
|
-
<
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
297
|
+
<View style={{
|
|
298
|
+
width: 32,
|
|
299
|
+
height: 32,
|
|
300
|
+
borderRadius: 8,
|
|
301
|
+
backgroundColor: `${AppColors.purple}14`,
|
|
302
|
+
alignItems: 'center',
|
|
303
|
+
justifyContent: 'center',
|
|
175
304
|
}}>
|
|
176
|
-
|
|
177
|
-
</
|
|
178
|
-
<
|
|
305
|
+
<SignalIcon color={AppColors.purple} size={15}/>
|
|
306
|
+
</View>
|
|
307
|
+
<View style={{ flex: 1 }}>
|
|
308
|
+
<Text style={{
|
|
179
309
|
fontFamily: AppFonts.interBold,
|
|
180
|
-
fontSize:
|
|
181
|
-
color: AppColors.
|
|
182
|
-
|
|
183
|
-
width: 90,
|
|
184
|
-
textAlign: 'right',
|
|
185
|
-
paddingRight: 4,
|
|
310
|
+
fontSize: 12,
|
|
311
|
+
color: AppColors.primaryBlack,
|
|
312
|
+
lineHeight: 16,
|
|
186
313
|
}}>
|
|
187
|
-
|
|
188
|
-
|
|
314
|
+
{t('settings.zeroOverheadTitle')}
|
|
315
|
+
</Text>
|
|
316
|
+
<Text style={{
|
|
317
|
+
fontFamily: AppFonts.interRegular,
|
|
318
|
+
fontSize: 10.5,
|
|
319
|
+
color: AppColors.grayText,
|
|
320
|
+
marginTop: 2,
|
|
321
|
+
lineHeight: 14,
|
|
322
|
+
}}>
|
|
323
|
+
{t('settings.zeroOverheadDesc')}
|
|
324
|
+
</Text>
|
|
325
|
+
</View>
|
|
189
326
|
</View>
|
|
190
327
|
|
|
191
|
-
{
|
|
328
|
+
{/* Enhanced Individual Module Cards with Decorative Checkboxes */}
|
|
329
|
+
<View style={{ gap: 10 }}>
|
|
330
|
+
{allModules.map(moduleItem => {
|
|
192
331
|
const isReduxAvail = isReduxConnected();
|
|
193
332
|
const isAnalyticsAvail = isAnalyticsConnected();
|
|
194
|
-
const isUnavailable = (
|
|
195
|
-
(
|
|
196
|
-
const isLocked =
|
|
197
|
-
const
|
|
198
|
-
(Boolean(
|
|
199
|
-
|
|
200
|
-
|
|
333
|
+
const isUnavailable = (moduleItem.key === 'redux' && !isReduxAvail) ||
|
|
334
|
+
(moduleItem.key === 'analytics' && !isAnalyticsAvail);
|
|
335
|
+
const isLocked = moduleItem.key === 'apis' || isUnavailable;
|
|
336
|
+
const isChecked = moduleItem.key === 'apis' ||
|
|
337
|
+
(Boolean(stagedTabVisibility?.[moduleItem.key]) &&
|
|
338
|
+
!isUnavailable);
|
|
339
|
+
const liveStats = moduleItem.key === 'apis'
|
|
340
|
+
? `${logs.length} requests • Limit: ${maxNetworkLogs}`
|
|
341
|
+
: moduleItem.key === 'logs'
|
|
342
|
+
? `${consoleLogs.length} logs • Limit: ${maxConsoleLogs}`
|
|
343
|
+
: moduleItem.key === 'performance'
|
|
344
|
+
? '60 FPS Target • Memory Telemetry'
|
|
345
|
+
: moduleItem.key === 'bundle'
|
|
346
|
+
? 'Metro Packager • Dependency Map'
|
|
347
|
+
: moduleItem.key === 'crash'
|
|
348
|
+
? `${crashRecords?.length || 0} crashes recorded • Crash Guard`
|
|
349
|
+
: moduleItem.key === 'analytics'
|
|
350
|
+
? `${analyticsEvents.length} events logged`
|
|
351
|
+
: moduleItem.key === 'redux'
|
|
352
|
+
? `${Object.keys(reduxState || {}).length} slices • Depth: ${reduxExpandDepth}`
|
|
353
|
+
: '';
|
|
354
|
+
return (<View key={moduleItem.key} style={{
|
|
355
|
+
backgroundColor: AppColors.primaryLight,
|
|
356
|
+
borderRadius: 14,
|
|
357
|
+
borderWidth: 1.5,
|
|
358
|
+
borderColor: isChecked
|
|
359
|
+
? `${AppColors.purple}38`
|
|
360
|
+
: AppColors.grayBorderSecondary,
|
|
361
|
+
padding: 14,
|
|
362
|
+
gap: 10,
|
|
363
|
+
shadowColor: AppColors.black,
|
|
364
|
+
shadowOpacity: isChecked ? 0.04 : 0.02,
|
|
365
|
+
shadowRadius: 5,
|
|
366
|
+
shadowOffset: { width: 0, height: 2 },
|
|
367
|
+
}}>
|
|
368
|
+
{/* Top Row: Icon + Title & Badges + Checkbox */}
|
|
369
|
+
<View style={{
|
|
201
370
|
flexDirection: 'row',
|
|
202
|
-
alignItems: '
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
borderBottomWidth: isLast ? 0 : 1,
|
|
206
|
-
borderBottomColor: AppColors.dividerColor,
|
|
207
|
-
gap: 12,
|
|
371
|
+
alignItems: 'flex-start',
|
|
372
|
+
justifyContent: 'space-between',
|
|
373
|
+
gap: 10,
|
|
208
374
|
}}>
|
|
209
|
-
|
|
210
|
-
|
|
375
|
+
{/* Tap Zone for Details/Settings */}
|
|
376
|
+
<TouchableScale accessible={true} accessibilityRole="button" accessibilityLabel={`${moduleItem.label} settings`} disabled={isUnavailable} onPress={() => {
|
|
377
|
+
animateNextLayout();
|
|
378
|
+
setSettingsPage(moduleItem.key);
|
|
379
|
+
}} style={{
|
|
211
380
|
flex: 1,
|
|
212
381
|
flexDirection: 'row',
|
|
213
|
-
alignItems: '
|
|
214
|
-
gap:
|
|
215
|
-
flexWrap: 'wrap',
|
|
382
|
+
alignItems: 'flex-start',
|
|
383
|
+
gap: 10,
|
|
216
384
|
}}>
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
width:
|
|
220
|
-
height:
|
|
221
|
-
borderRadius:
|
|
385
|
+
{/* Icon Tile */}
|
|
386
|
+
<View style={{
|
|
387
|
+
width: 36,
|
|
388
|
+
height: 36,
|
|
389
|
+
borderRadius: 10,
|
|
222
390
|
backgroundColor: isLocked
|
|
223
|
-
? AppColors.grayBorderSecondary
|
|
224
|
-
:
|
|
391
|
+
? `${AppColors.grayBorderSecondary}4D`
|
|
392
|
+
: isChecked
|
|
393
|
+
? `${AppColors.purple}14`
|
|
394
|
+
: AppColors.grayBackground,
|
|
225
395
|
borderWidth: 1,
|
|
226
396
|
borderColor: isLocked
|
|
227
397
|
? AppColors.dividerColor
|
|
228
|
-
:
|
|
398
|
+
: isChecked
|
|
399
|
+
? `${AppColors.purple}33`
|
|
400
|
+
: AppColors.grayBorderSecondary,
|
|
229
401
|
alignItems: 'center',
|
|
230
402
|
justifyContent: 'center',
|
|
403
|
+
marginTop: 1,
|
|
231
404
|
}}>
|
|
232
|
-
|
|
233
|
-
? AppColors.
|
|
234
|
-
: AppColors.
|
|
235
|
-
|
|
236
|
-
? AppColors.
|
|
237
|
-
: AppColors.
|
|
238
|
-
|
|
239
|
-
? AppColors.
|
|
240
|
-
: AppColors.
|
|
241
|
-
|
|
242
|
-
? AppColors.
|
|
243
|
-
: AppColors.
|
|
244
|
-
|
|
245
|
-
? AppColors.
|
|
246
|
-
: AppColors.
|
|
247
|
-
|
|
248
|
-
? AppColors.
|
|
249
|
-
: AppColors.
|
|
250
|
-
|
|
251
|
-
? AppColors.
|
|
252
|
-
: AppColors.
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
405
|
+
{moduleItem.icon === 'apis' && (<SignalIcon color={isChecked
|
|
406
|
+
? AppColors.purple
|
|
407
|
+
: AppColors.grayTextWeak} size={16}/>)}
|
|
408
|
+
{moduleItem.icon === 'logs' && (<TerminalIcon color={isChecked
|
|
409
|
+
? AppColors.purple
|
|
410
|
+
: AppColors.grayTextWeak} size={16}/>)}
|
|
411
|
+
{moduleItem.icon === 'performance' && (<PerformanceIcon color={isChecked
|
|
412
|
+
? AppColors.purple
|
|
413
|
+
: AppColors.grayTextWeak} size={16}/>)}
|
|
414
|
+
{moduleItem.icon === 'bundle' && (<PackageIcon color={isChecked
|
|
415
|
+
? AppColors.purple
|
|
416
|
+
: AppColors.grayTextWeak} size={16}/>)}
|
|
417
|
+
{moduleItem.icon === 'crash' && (<CrashIcon color={isChecked
|
|
418
|
+
? AppColors.purple
|
|
419
|
+
: AppColors.grayTextWeak} size={16}/>)}
|
|
420
|
+
{moduleItem.icon === 'analytics' && (<AnalyticsIcon color={isChecked
|
|
421
|
+
? AppColors.purple
|
|
422
|
+
: AppColors.grayTextWeak} size={16}/>)}
|
|
423
|
+
{moduleItem.icon === 'redux' && (<ReduxIcon color={isChecked
|
|
424
|
+
? AppColors.purple
|
|
425
|
+
: AppColors.grayTextWeak} size={16}/>)}
|
|
426
|
+
</View>
|
|
427
|
+
|
|
428
|
+
{/* Titles & Status Pill */}
|
|
429
|
+
<View style={{ flex: 1, gap: 2 }}>
|
|
430
|
+
<View style={{
|
|
431
|
+
flexDirection: 'row',
|
|
432
|
+
alignItems: 'center',
|
|
433
|
+
gap: 6,
|
|
434
|
+
flexWrap: 'wrap',
|
|
435
|
+
}}>
|
|
436
|
+
<Text style={{
|
|
256
437
|
fontFamily: AppFonts.interBold,
|
|
257
|
-
fontSize:
|
|
438
|
+
fontSize: 14,
|
|
439
|
+
lineHeight: 18,
|
|
258
440
|
color: isLocked
|
|
259
441
|
? AppColors.grayText
|
|
260
442
|
: AppColors.primaryBlack,
|
|
261
443
|
}}>
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
444
|
+
{moduleItem.label}
|
|
445
|
+
</Text>
|
|
446
|
+
|
|
447
|
+
{/* Default Startup Tab Badge */}
|
|
448
|
+
{moduleItem.key === defaultTab &&
|
|
449
|
+
!isUnavailable && (<View style={{
|
|
450
|
+
flexDirection: 'row',
|
|
451
|
+
alignItems: 'center',
|
|
452
|
+
backgroundColor: `${AppColors.purple}14`,
|
|
453
|
+
borderRadius: 12,
|
|
454
|
+
paddingHorizontal: 5,
|
|
455
|
+
paddingVertical: 1.5,
|
|
456
|
+
borderWidth: 1,
|
|
457
|
+
borderColor: `${AppColors.purple}2E`,
|
|
458
|
+
gap: 3,
|
|
459
|
+
}}>
|
|
460
|
+
<View style={{
|
|
461
|
+
width: 4,
|
|
462
|
+
height: 4,
|
|
463
|
+
borderRadius: 2,
|
|
464
|
+
backgroundColor: AppColors.purple,
|
|
465
|
+
}}/>
|
|
466
|
+
<Text style={{
|
|
467
|
+
fontFamily: AppFonts.interBold,
|
|
468
|
+
fontSize: 8,
|
|
469
|
+
lineHeight: 11,
|
|
470
|
+
color: AppColors.purple,
|
|
471
|
+
letterSpacing: 0.4,
|
|
472
|
+
}}>
|
|
473
|
+
{t('settings.defaultBadge')}
|
|
474
|
+
</Text>
|
|
475
|
+
</View>)}
|
|
476
|
+
|
|
477
|
+
{/* Status Pill */}
|
|
478
|
+
{moduleItem.key === 'apis' ? (<View style={{
|
|
479
|
+
backgroundColor: `${AppColors.blue500}14`,
|
|
480
|
+
borderRadius: 4,
|
|
481
|
+
paddingHorizontal: 5,
|
|
482
|
+
paddingVertical: 1.5,
|
|
483
|
+
borderWidth: 1,
|
|
484
|
+
borderColor: `${AppColors.blue500}33`,
|
|
485
|
+
}}>
|
|
486
|
+
<Text style={{
|
|
487
|
+
fontFamily: AppFonts.interBold,
|
|
488
|
+
fontSize: 8,
|
|
489
|
+
lineHeight: 11,
|
|
490
|
+
color: AppColors.blue500,
|
|
491
|
+
letterSpacing: 0.3,
|
|
492
|
+
}}>
|
|
493
|
+
{t('settings.coreBadge')}
|
|
494
|
+
</Text>
|
|
495
|
+
</View>) : isUnavailable ? (<View style={{
|
|
266
496
|
backgroundColor: `${AppColors.amber500}18`,
|
|
267
497
|
borderRadius: 4,
|
|
268
498
|
paddingHorizontal: 5,
|
|
@@ -270,181 +500,439 @@ const SettingsPanel = () => {
|
|
|
270
500
|
borderWidth: 1,
|
|
271
501
|
borderColor: `${AppColors.amber500}35`,
|
|
272
502
|
}}>
|
|
273
|
-
|
|
503
|
+
<Text style={{
|
|
274
504
|
fontFamily: AppFonts.interBold,
|
|
275
505
|
fontSize: 8,
|
|
506
|
+
lineHeight: 11,
|
|
276
507
|
color: AppColors.amber700,
|
|
277
508
|
letterSpacing: 0.3,
|
|
278
509
|
}}>
|
|
279
|
-
|
|
510
|
+
{moduleItem.key === 'redux'
|
|
280
511
|
? t('settings.notConnectedBadge')
|
|
281
512
|
: t('settings.notDetectedBadge')}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
backgroundColor: `${AppColors.purple}14`,
|
|
289
|
-
borderRadius: 20,
|
|
290
|
-
paddingHorizontal: 6,
|
|
291
|
-
paddingVertical: 2,
|
|
513
|
+
</Text>
|
|
514
|
+
</View>) : isChecked ? (<View style={{
|
|
515
|
+
backgroundColor: `${AppColors.liveGreen}18`,
|
|
516
|
+
borderRadius: 4,
|
|
517
|
+
paddingHorizontal: 5,
|
|
518
|
+
paddingVertical: 1.5,
|
|
292
519
|
borderWidth: 1,
|
|
293
|
-
borderColor: `${AppColors.
|
|
294
|
-
gap: 3,
|
|
520
|
+
borderColor: `${AppColors.liveGreen}38`,
|
|
295
521
|
}}>
|
|
296
|
-
|
|
297
|
-
width: 4,
|
|
298
|
-
height: 4,
|
|
299
|
-
borderRadius: 2,
|
|
300
|
-
backgroundColor: AppColors.purple,
|
|
301
|
-
opacity: 0.7,
|
|
302
|
-
}}/>
|
|
303
|
-
<Text style={{
|
|
522
|
+
<Text style={{
|
|
304
523
|
fontFamily: AppFonts.interBold,
|
|
305
|
-
fontSize: 8
|
|
306
|
-
|
|
307
|
-
|
|
524
|
+
fontSize: 8,
|
|
525
|
+
lineHeight: 11,
|
|
526
|
+
color: AppColors.green700,
|
|
527
|
+
letterSpacing: 0.3,
|
|
308
528
|
}}>
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
setSettingsPage(tab.key);
|
|
317
|
-
}} hitSlop={8} style={{
|
|
318
|
-
marginLeft: 4,
|
|
319
|
-
padding: 4,
|
|
320
|
-
borderRadius: 6,
|
|
321
|
-
backgroundColor: AppColors.purpleShade50,
|
|
529
|
+
{t('settings.activeBadge')}
|
|
530
|
+
</Text>
|
|
531
|
+
</View>) : (<View style={{
|
|
532
|
+
backgroundColor: `${AppColors.grayTextWeak}18`,
|
|
533
|
+
borderRadius: 4,
|
|
534
|
+
paddingHorizontal: 5,
|
|
535
|
+
paddingVertical: 1.5,
|
|
322
536
|
borderWidth: 1,
|
|
323
|
-
borderColor: `${AppColors.
|
|
324
|
-
alignItems: 'center',
|
|
325
|
-
justifyContent: 'center',
|
|
537
|
+
borderColor: `${AppColors.grayTextWeak}2E`,
|
|
326
538
|
}}>
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
539
|
+
<Text style={{
|
|
540
|
+
fontFamily: AppFonts.interBold,
|
|
541
|
+
fontSize: 8,
|
|
542
|
+
lineHeight: 11,
|
|
543
|
+
color: AppColors.grayTextWeak,
|
|
544
|
+
letterSpacing: 0.3,
|
|
545
|
+
}}>
|
|
546
|
+
{t('settings.dormantBadge')}
|
|
547
|
+
</Text>
|
|
548
|
+
</View>)}
|
|
549
|
+
</View>
|
|
330
550
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
551
|
+
<Text style={{
|
|
552
|
+
fontFamily: AppFonts.interRegular,
|
|
553
|
+
fontSize: 11,
|
|
554
|
+
color: AppColors.grayText,
|
|
555
|
+
lineHeight: 15,
|
|
556
|
+
marginTop: 1,
|
|
336
557
|
}}>
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
558
|
+
{moduleItem.desc}
|
|
559
|
+
</Text>
|
|
560
|
+
</View>
|
|
561
|
+
</TouchableScale>
|
|
562
|
+
|
|
563
|
+
{/* Decorative Custom Checkbox */}
|
|
564
|
+
<TouchableScale accessible={true} accessibilityRole="checkbox" accessibilityLabel={`Select ${moduleItem.label}`} accessibilityState={{
|
|
565
|
+
checked: isChecked,
|
|
566
|
+
disabled: isLocked,
|
|
567
|
+
}} disabled={isLocked} onPress={() => {
|
|
568
|
+
if (isLocked)
|
|
569
|
+
return;
|
|
570
|
+
setStagedTabVisibility(prev => ({
|
|
571
|
+
...prev,
|
|
572
|
+
[moduleItem.key]: !prev[moduleItem.key],
|
|
573
|
+
}));
|
|
574
|
+
}} style={{
|
|
575
|
+
width: 26,
|
|
576
|
+
height: 26,
|
|
577
|
+
borderRadius: 8,
|
|
578
|
+
borderWidth: isChecked ? 0 : 2,
|
|
347
579
|
borderColor: isLocked
|
|
348
|
-
? AppColors.
|
|
349
|
-
:
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
}}>
|
|
356
|
-
<View style={{
|
|
357
|
-
width: 18,
|
|
358
|
-
height: 18,
|
|
359
|
-
borderRadius: 9,
|
|
360
|
-
backgroundColor: isLocked
|
|
361
|
-
? AppColors.grayBorderSecondary
|
|
362
|
-
: AppColors.white,
|
|
580
|
+
? AppColors.dividerColor
|
|
581
|
+
: AppColors.grayBorderSecondary,
|
|
582
|
+
backgroundColor: moduleItem.key === 'apis'
|
|
583
|
+
? `${AppColors.blue500}22`
|
|
584
|
+
: isChecked
|
|
585
|
+
? AppColors.purple
|
|
586
|
+
: AppColors.grayBackground,
|
|
363
587
|
alignItems: 'center',
|
|
364
588
|
justifyContent: 'center',
|
|
365
|
-
shadowColor:
|
|
366
|
-
|
|
367
|
-
|
|
589
|
+
shadowColor: isChecked
|
|
590
|
+
? AppColors.purple
|
|
591
|
+
: 'transparent',
|
|
592
|
+
shadowOpacity: isChecked ? 0.3 : 0,
|
|
593
|
+
shadowRadius: 3,
|
|
368
594
|
shadowOffset: { width: 0, height: 1 },
|
|
595
|
+
elevation: isChecked ? 2 : 0,
|
|
369
596
|
}}>
|
|
370
|
-
{isLocked
|
|
597
|
+
{moduleItem.key === 'apis' ? (<CheckIcon size={14} color={AppColors.blue500}/>) : isChecked ? (<CheckIcon size={14} color={AppColors.white}/>) : isLocked ? (<Svg width={10} height={10} viewBox="0 0 24 24" fill="none">
|
|
371
598
|
<Path d="M7 10V7a5 5 0 0 1 10 0v3" stroke={AppColors.grayText} strokeWidth="2.2" strokeLinecap="round"/>
|
|
372
599
|
<Path d="M5 10h14v9a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1z" fill={AppColors.grayText}/>
|
|
373
|
-
</Svg>)}
|
|
374
|
-
</
|
|
375
|
-
</
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
600
|
+
</Svg>) : null}
|
|
601
|
+
</TouchableScale>
|
|
602
|
+
</View>
|
|
603
|
+
|
|
604
|
+
{/* Card Footer: Live Stats + Configure Button */}
|
|
605
|
+
{!isUnavailable && (<View style={{
|
|
606
|
+
flexDirection: 'row',
|
|
607
|
+
alignItems: 'center',
|
|
608
|
+
justifyContent: 'space-between',
|
|
609
|
+
paddingTop: 8,
|
|
610
|
+
borderTopWidth: 1,
|
|
611
|
+
borderTopColor: AppColors.dividerColor,
|
|
612
|
+
}}>
|
|
613
|
+
{/* Live Info Pill */}
|
|
614
|
+
<View style={{
|
|
615
|
+
flexDirection: 'row',
|
|
616
|
+
alignItems: 'center',
|
|
617
|
+
gap: 6,
|
|
618
|
+
flex: 1,
|
|
619
|
+
}}>
|
|
620
|
+
<View style={{
|
|
621
|
+
width: 6,
|
|
622
|
+
height: 6,
|
|
623
|
+
borderRadius: 3,
|
|
624
|
+
backgroundColor: isChecked
|
|
625
|
+
? AppColors.liveGreen
|
|
381
626
|
: AppColors.grayTextWeak,
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
627
|
+
}}/>
|
|
628
|
+
<Text style={{
|
|
629
|
+
fontFamily: AppFonts.interMedium,
|
|
630
|
+
fontSize: 11,
|
|
631
|
+
color: AppColors.grayText,
|
|
632
|
+
lineHeight: 14,
|
|
385
633
|
}}>
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
634
|
+
{liveStats}
|
|
635
|
+
</Text>
|
|
636
|
+
</View>
|
|
637
|
+
|
|
638
|
+
{/* Sleek Configure Button */}
|
|
639
|
+
<TouchableScale accessible={true} accessibilityRole="button" accessibilityLabel={`Configure ${moduleItem.label} settings`} onPress={() => {
|
|
640
|
+
animateNextLayout();
|
|
641
|
+
setSettingsPage(moduleItem.key);
|
|
642
|
+
}} style={{
|
|
643
|
+
flexDirection: 'row',
|
|
644
|
+
alignItems: 'center',
|
|
645
|
+
gap: 5,
|
|
646
|
+
backgroundColor: `${AppColors.purple}12`,
|
|
647
|
+
paddingHorizontal: 10,
|
|
648
|
+
paddingVertical: 5,
|
|
649
|
+
borderRadius: 8,
|
|
650
|
+
borderWidth: 1,
|
|
651
|
+
borderColor: `${AppColors.purple}26`,
|
|
652
|
+
}}>
|
|
653
|
+
<SettingsIcon color={AppColors.purple} size={11}/>
|
|
654
|
+
<Text style={{
|
|
655
|
+
fontFamily: AppFonts.interBold,
|
|
656
|
+
fontSize: 11,
|
|
657
|
+
lineHeight: 14,
|
|
658
|
+
color: AppColors.purple,
|
|
659
|
+
}}>
|
|
660
|
+
{t('settings.configure')}
|
|
661
|
+
</Text>
|
|
662
|
+
<ForwardChevronIcon color={AppColors.purple} size={9}/>
|
|
663
|
+
</TouchableScale>
|
|
664
|
+
</View>)}
|
|
665
|
+
</View>);
|
|
392
666
|
})}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
667
|
+
</View>
|
|
668
|
+
|
|
669
|
+
{/* Section 3.5: RAM-Based Auto Limits */}
|
|
670
|
+
<View style={{
|
|
396
671
|
backgroundColor: AppColors.primaryLight,
|
|
397
|
-
borderRadius:
|
|
672
|
+
borderRadius: 14,
|
|
398
673
|
borderWidth: 1,
|
|
399
674
|
borderColor: AppColors.grayBorderSecondary,
|
|
400
675
|
overflow: 'hidden',
|
|
401
|
-
|
|
402
|
-
<View style={{
|
|
403
|
-
flexDirection: 'row',
|
|
404
|
-
alignItems: 'center',
|
|
405
|
-
paddingVertical: 12,
|
|
406
|
-
paddingHorizontal: 14,
|
|
676
|
+
padding: 14,
|
|
407
677
|
gap: 12,
|
|
408
678
|
}}>
|
|
409
|
-
{
|
|
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 */}
|
|
410
690
|
<View style={{
|
|
411
|
-
flex: 1,
|
|
412
691
|
flexDirection: 'row',
|
|
413
692
|
alignItems: 'center',
|
|
414
|
-
|
|
693
|
+
justifyContent: 'space-between',
|
|
415
694
|
}}>
|
|
416
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={{
|
|
417
744
|
width: 20,
|
|
418
745
|
height: 20,
|
|
419
|
-
borderRadius:
|
|
420
|
-
backgroundColor: AppColors.
|
|
421
|
-
|
|
422
|
-
|
|
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,
|
|
423
767
|
alignItems: 'center',
|
|
424
768
|
justifyContent: 'center',
|
|
425
769
|
}}>
|
|
426
|
-
|
|
770
|
+
<SignalIcon color={isAutoRamLimitEnabled ? AppColors.purple : AppColors.grayTextWeak} size={15}/>
|
|
427
771
|
</View>
|
|
428
772
|
<View style={{ flex: 1 }}>
|
|
429
773
|
<Text style={{
|
|
430
774
|
fontFamily: AppFonts.interBold,
|
|
431
|
-
fontSize: 13,
|
|
432
|
-
|
|
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,
|
|
433
789
|
}}>
|
|
434
|
-
|
|
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
|
|
435
814
|
</Text>
|
|
436
815
|
</View>
|
|
437
816
|
</View>
|
|
438
817
|
|
|
439
|
-
{/*
|
|
440
|
-
<
|
|
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 }}>
|
|
866
|
+
{/* Section 1: Appearance */}
|
|
867
|
+
<View style={{
|
|
868
|
+
backgroundColor: AppColors.primaryLight,
|
|
869
|
+
borderRadius: 14,
|
|
870
|
+
borderWidth: 1,
|
|
871
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
872
|
+
overflow: 'hidden',
|
|
873
|
+
padding: 14,
|
|
874
|
+
gap: 12,
|
|
875
|
+
}}>
|
|
876
|
+
<Text style={{
|
|
877
|
+
fontFamily: AppFonts.interBold,
|
|
878
|
+
fontSize: 11,
|
|
879
|
+
lineHeight: 14,
|
|
880
|
+
color: AppColors.grayTextWeak,
|
|
881
|
+
letterSpacing: 0.8,
|
|
882
|
+
}}>
|
|
883
|
+
{t('settings.appearanceTheme')}
|
|
884
|
+
</Text>
|
|
885
|
+
|
|
886
|
+
<View style={{
|
|
887
|
+
flexDirection: 'row',
|
|
888
|
+
alignItems: 'center',
|
|
889
|
+
justifyContent: 'space-between',
|
|
890
|
+
}}>
|
|
891
|
+
<View style={{
|
|
892
|
+
flexDirection: 'row',
|
|
893
|
+
alignItems: 'center',
|
|
894
|
+
gap: 10,
|
|
895
|
+
flex: 1,
|
|
896
|
+
}}>
|
|
897
|
+
<View style={{
|
|
898
|
+
width: 32,
|
|
899
|
+
height: 32,
|
|
900
|
+
borderRadius: 8,
|
|
901
|
+
backgroundColor: AppColors.purpleShade50,
|
|
902
|
+
alignItems: 'center',
|
|
903
|
+
justifyContent: 'center',
|
|
904
|
+
}}>
|
|
905
|
+
{isDark ? (<SunIcon color={AppColors.purple} size={15}/>) : (<MoonIcon color={AppColors.purple} size={15}/>)}
|
|
906
|
+
</View>
|
|
907
|
+
<View style={{ flex: 1 }}>
|
|
908
|
+
<Text style={{
|
|
909
|
+
fontFamily: AppFonts.interBold,
|
|
910
|
+
fontSize: 13.5,
|
|
911
|
+
lineHeight: 18,
|
|
912
|
+
color: AppColors.primaryBlack,
|
|
913
|
+
}}>
|
|
914
|
+
{t('settings.general.darkMode')}
|
|
915
|
+
</Text>
|
|
916
|
+
<Text style={{
|
|
917
|
+
fontFamily: AppFonts.interRegular,
|
|
918
|
+
fontSize: 11,
|
|
919
|
+
lineHeight: 15,
|
|
920
|
+
color: AppColors.grayText,
|
|
921
|
+
marginTop: 1,
|
|
922
|
+
}}>
|
|
923
|
+
{t('settings.general.darkModeDescription')}
|
|
924
|
+
</Text>
|
|
925
|
+
</View>
|
|
926
|
+
</View>
|
|
927
|
+
|
|
928
|
+
<TouchableScale accessible={true} accessibilityRole="switch" accessibilityLabel="Toggle Dark Theme" accessibilityState={{ checked: isDark }} onPress={() => {
|
|
441
929
|
const newTheme = !isDark;
|
|
442
930
|
setIsDark(newTheme);
|
|
443
931
|
toggleGlobalTheme(newTheme);
|
|
444
932
|
}} style={{
|
|
445
|
-
width:
|
|
446
|
-
height:
|
|
447
|
-
borderRadius:
|
|
933
|
+
width: 42,
|
|
934
|
+
height: 24,
|
|
935
|
+
borderRadius: 12,
|
|
448
936
|
backgroundColor: isDark
|
|
449
937
|
? AppColors.purple
|
|
450
938
|
: AppColors.grayBorderSecondary,
|
|
@@ -452,226 +940,243 @@ const SettingsPanel = () => {
|
|
|
452
940
|
justifyContent: 'center',
|
|
453
941
|
alignItems: isDark ? 'flex-end' : 'flex-start',
|
|
454
942
|
}}>
|
|
455
|
-
|
|
456
|
-
width:
|
|
457
|
-
height:
|
|
458
|
-
borderRadius:
|
|
943
|
+
<View style={{
|
|
944
|
+
width: 20,
|
|
945
|
+
height: 20,
|
|
946
|
+
borderRadius: 10,
|
|
459
947
|
backgroundColor: AppColors.white,
|
|
460
948
|
shadowColor: AppColors.black,
|
|
461
|
-
shadowOpacity: 0.
|
|
462
|
-
shadowRadius:
|
|
949
|
+
shadowOpacity: 0.18,
|
|
950
|
+
shadowRadius: 2,
|
|
463
951
|
shadowOffset: { width: 0, height: 1 },
|
|
464
952
|
}}/>
|
|
465
|
-
|
|
953
|
+
</TouchableScale>
|
|
954
|
+
</View>
|
|
466
955
|
</View>
|
|
467
956
|
|
|
468
|
-
{/*
|
|
469
|
-
<View style={{
|
|
470
|
-
height: 1,
|
|
471
|
-
backgroundColor: AppColors.dividerColor,
|
|
472
|
-
}}/>
|
|
473
|
-
|
|
474
|
-
{/* Modal Height */}
|
|
957
|
+
{/* Section 2: Window & Layout */}
|
|
475
958
|
<View style={{
|
|
476
|
-
|
|
477
|
-
|
|
959
|
+
backgroundColor: AppColors.primaryLight,
|
|
960
|
+
borderRadius: 14,
|
|
961
|
+
borderWidth: 1,
|
|
962
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
963
|
+
overflow: 'hidden',
|
|
964
|
+
padding: 14,
|
|
965
|
+
gap: 14,
|
|
478
966
|
}}>
|
|
479
|
-
<
|
|
967
|
+
<Text style={{
|
|
968
|
+
fontFamily: AppFonts.interBold,
|
|
969
|
+
fontSize: 11,
|
|
970
|
+
lineHeight: 14,
|
|
971
|
+
color: AppColors.grayTextWeak,
|
|
972
|
+
letterSpacing: 0.8,
|
|
973
|
+
}}>
|
|
974
|
+
{t('settings.windowLayout')}
|
|
975
|
+
</Text>
|
|
976
|
+
|
|
977
|
+
{/* Modal Height */}
|
|
978
|
+
<View style={{ gap: 8 }}>
|
|
979
|
+
<View style={{
|
|
480
980
|
flexDirection: 'row',
|
|
481
981
|
alignItems: 'center',
|
|
482
|
-
gap:
|
|
982
|
+
gap: 10,
|
|
483
983
|
}}>
|
|
484
|
-
|
|
485
|
-
width:
|
|
486
|
-
height:
|
|
487
|
-
borderRadius:
|
|
984
|
+
<View style={{
|
|
985
|
+
width: 32,
|
|
986
|
+
height: 32,
|
|
987
|
+
borderRadius: 8,
|
|
488
988
|
backgroundColor: AppColors.purpleShade50,
|
|
489
|
-
borderWidth: 1,
|
|
490
|
-
borderColor: `${AppColors.purple}33`,
|
|
491
989
|
alignItems: 'center',
|
|
492
990
|
justifyContent: 'center',
|
|
493
991
|
}}>
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
992
|
+
<ScreenIcon color={AppColors.purple} size={15}/>
|
|
993
|
+
</View>
|
|
994
|
+
<View style={{ flex: 1 }}>
|
|
995
|
+
<Text style={{
|
|
498
996
|
fontFamily: AppFonts.interBold,
|
|
499
|
-
fontSize: 13,
|
|
997
|
+
fontSize: 13.5,
|
|
998
|
+
lineHeight: 18,
|
|
500
999
|
color: AppColors.primaryBlack,
|
|
501
1000
|
}}>
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
1001
|
+
{t('settings.general.modalHeight')}
|
|
1002
|
+
</Text>
|
|
1003
|
+
<Text style={{
|
|
505
1004
|
fontFamily: AppFonts.interRegular,
|
|
506
1005
|
fontSize: 11,
|
|
1006
|
+
lineHeight: 15,
|
|
507
1007
|
color: AppColors.grayText,
|
|
508
1008
|
marginTop: 1,
|
|
509
1009
|
}}>
|
|
510
|
-
|
|
511
|
-
|
|
1010
|
+
{t('settings.general.modalHeightDescription')}
|
|
1011
|
+
</Text>
|
|
1012
|
+
</View>
|
|
512
1013
|
</View>
|
|
513
|
-
</View>
|
|
514
1014
|
|
|
515
|
-
|
|
516
|
-
<View style={{
|
|
1015
|
+
<View style={{
|
|
517
1016
|
flexDirection: 'row',
|
|
518
1017
|
backgroundColor: AppColors.grayBackground,
|
|
519
|
-
borderRadius:
|
|
520
|
-
padding:
|
|
521
|
-
marginTop: 10,
|
|
1018
|
+
borderRadius: 10,
|
|
1019
|
+
padding: 3,
|
|
522
1020
|
borderWidth: 1,
|
|
523
1021
|
borderColor: AppColors.dividerColor,
|
|
524
1022
|
}}>
|
|
525
|
-
|
|
1023
|
+
{[50, 70, 90, 100].map(opt => {
|
|
526
1024
|
const isActive = modalHeightPercent === opt;
|
|
527
|
-
return (<TouchableScale key={opt} onPress={() => setModalHeightPercent(opt)} style={{
|
|
1025
|
+
return (<TouchableScale key={opt} accessible={true} accessibilityRole="button" accessibilityLabel={`Set window height to ${opt} percent`} accessibilityState={{ selected: isActive }} onPress={() => setModalHeightPercent(opt)} style={{
|
|
528
1026
|
flex: 1,
|
|
529
|
-
paddingVertical:
|
|
1027
|
+
paddingVertical: 7,
|
|
530
1028
|
alignItems: 'center',
|
|
531
|
-
borderRadius:
|
|
1029
|
+
borderRadius: 8,
|
|
532
1030
|
backgroundColor: isActive
|
|
533
1031
|
? AppColors.purple
|
|
534
1032
|
: 'transparent',
|
|
535
1033
|
}}>
|
|
536
|
-
|
|
1034
|
+
<Text style={{
|
|
537
1035
|
fontFamily: AppFonts.interBold,
|
|
538
|
-
fontSize: 11,
|
|
539
|
-
|
|
1036
|
+
fontSize: 11.5,
|
|
1037
|
+
lineHeight: 15,
|
|
1038
|
+
color: isActive
|
|
1039
|
+
? AppColors.white
|
|
1040
|
+
: AppColors.grayText,
|
|
540
1041
|
}}>
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
1042
|
+
{opt}%
|
|
1043
|
+
</Text>
|
|
1044
|
+
</TouchableScale>);
|
|
544
1045
|
})}
|
|
1046
|
+
</View>
|
|
545
1047
|
</View>
|
|
546
|
-
</View>
|
|
547
1048
|
|
|
548
|
-
|
|
549
|
-
<View style={{
|
|
550
|
-
height: 1,
|
|
551
|
-
backgroundColor: AppColors.dividerColor,
|
|
552
|
-
}}/>
|
|
1049
|
+
<View style={{ height: 1, backgroundColor: AppColors.dividerColor }}/>
|
|
553
1050
|
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
paddingHorizontal: 14,
|
|
558
|
-
}}>
|
|
559
|
-
<View style={{
|
|
1051
|
+
{/* Modal Animation */}
|
|
1052
|
+
<View style={{ gap: 8 }}>
|
|
1053
|
+
<View style={{
|
|
560
1054
|
flexDirection: 'row',
|
|
561
1055
|
alignItems: 'center',
|
|
562
|
-
gap:
|
|
1056
|
+
gap: 10,
|
|
563
1057
|
}}>
|
|
564
|
-
|
|
565
|
-
width:
|
|
566
|
-
height:
|
|
567
|
-
borderRadius:
|
|
1058
|
+
<View style={{
|
|
1059
|
+
width: 32,
|
|
1060
|
+
height: 32,
|
|
1061
|
+
borderRadius: 8,
|
|
568
1062
|
backgroundColor: AppColors.purpleShade50,
|
|
569
|
-
borderWidth: 1,
|
|
570
|
-
borderColor: `${AppColors.purple}33`,
|
|
571
1063
|
alignItems: 'center',
|
|
572
1064
|
justifyContent: 'center',
|
|
573
1065
|
}}>
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
1066
|
+
<MotionIcon color={AppColors.purple} size={15}/>
|
|
1067
|
+
</View>
|
|
1068
|
+
<View style={{ flex: 1 }}>
|
|
1069
|
+
<Text style={{
|
|
578
1070
|
fontFamily: AppFonts.interBold,
|
|
579
|
-
fontSize: 13,
|
|
1071
|
+
fontSize: 13.5,
|
|
1072
|
+
lineHeight: 18,
|
|
580
1073
|
color: AppColors.primaryBlack,
|
|
581
1074
|
}}>
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
1075
|
+
{t('settings.general.modalAnimation')}
|
|
1076
|
+
</Text>
|
|
1077
|
+
<Text style={{
|
|
585
1078
|
fontFamily: AppFonts.interRegular,
|
|
586
1079
|
fontSize: 11,
|
|
1080
|
+
lineHeight: 15,
|
|
587
1081
|
color: AppColors.grayText,
|
|
588
1082
|
marginTop: 1,
|
|
589
1083
|
}}>
|
|
590
|
-
|
|
591
|
-
|
|
1084
|
+
{t('settings.general.modalAnimationDescription')}
|
|
1085
|
+
</Text>
|
|
1086
|
+
</View>
|
|
592
1087
|
</View>
|
|
593
|
-
</View>
|
|
594
1088
|
|
|
595
|
-
|
|
596
|
-
<View style={{
|
|
1089
|
+
<View style={{
|
|
597
1090
|
flexDirection: 'row',
|
|
598
1091
|
backgroundColor: AppColors.grayBackground,
|
|
599
|
-
borderRadius:
|
|
600
|
-
padding:
|
|
601
|
-
marginTop: 10,
|
|
1092
|
+
borderRadius: 10,
|
|
1093
|
+
padding: 3,
|
|
602
1094
|
borderWidth: 1,
|
|
603
1095
|
borderColor: AppColors.dividerColor,
|
|
604
1096
|
}}>
|
|
605
|
-
|
|
1097
|
+
{[
|
|
606
1098
|
{ key: 'slide', label: 'Slide Up' },
|
|
607
1099
|
{ key: 'fade', label: 'Fade' },
|
|
608
1100
|
{ key: 'none', label: 'None' },
|
|
609
|
-
]
|
|
1101
|
+
].map(opt => {
|
|
610
1102
|
const isActive = modalAnimationType === opt.key;
|
|
611
|
-
return (<TouchableScale key={opt.key} onPress={() => setModalAnimationType(opt.key)} style={{
|
|
1103
|
+
return (<TouchableScale key={opt.key} accessible={true} accessibilityRole="button" accessibilityLabel={`Set transition animation to ${opt.label}`} accessibilityState={{ selected: isActive }} onPress={() => setModalAnimationType(opt.key)} style={{
|
|
612
1104
|
flex: 1,
|
|
613
|
-
paddingVertical:
|
|
1105
|
+
paddingVertical: 7,
|
|
614
1106
|
alignItems: 'center',
|
|
615
|
-
borderRadius:
|
|
1107
|
+
borderRadius: 8,
|
|
616
1108
|
backgroundColor: isActive
|
|
617
1109
|
? AppColors.purple
|
|
618
1110
|
: 'transparent',
|
|
619
1111
|
}}>
|
|
620
|
-
|
|
1112
|
+
<Text style={{
|
|
621
1113
|
fontFamily: AppFonts.interBold,
|
|
622
|
-
fontSize: 11,
|
|
623
|
-
|
|
1114
|
+
fontSize: 11.5,
|
|
1115
|
+
lineHeight: 15,
|
|
1116
|
+
color: isActive
|
|
1117
|
+
? AppColors.white
|
|
1118
|
+
: AppColors.grayText,
|
|
624
1119
|
}}>
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
1120
|
+
{opt.label}
|
|
1121
|
+
</Text>
|
|
1122
|
+
</TouchableScale>);
|
|
628
1123
|
})}
|
|
1124
|
+
</View>
|
|
629
1125
|
</View>
|
|
630
1126
|
</View>
|
|
631
1127
|
|
|
632
|
-
{/*
|
|
633
|
-
<View style={{
|
|
634
|
-
height: 1,
|
|
635
|
-
backgroundColor: AppColors.dividerColor,
|
|
636
|
-
}}/>
|
|
637
|
-
|
|
638
|
-
{/* #6 — Default Tab */}
|
|
1128
|
+
{/* Section 3: Default Startup Tab */}
|
|
639
1129
|
<View style={{
|
|
640
|
-
|
|
641
|
-
|
|
1130
|
+
backgroundColor: AppColors.primaryLight,
|
|
1131
|
+
borderRadius: 14,
|
|
1132
|
+
borderWidth: 1,
|
|
1133
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
1134
|
+
overflow: 'hidden',
|
|
1135
|
+
padding: 14,
|
|
1136
|
+
gap: 12,
|
|
1137
|
+
}}>
|
|
1138
|
+
<Text style={{
|
|
1139
|
+
fontFamily: AppFonts.interBold,
|
|
1140
|
+
fontSize: 11,
|
|
1141
|
+
lineHeight: 14,
|
|
1142
|
+
color: AppColors.grayTextWeak,
|
|
1143
|
+
letterSpacing: 0.8,
|
|
642
1144
|
}}>
|
|
1145
|
+
{t('settings.startupDefault')}
|
|
1146
|
+
</Text>
|
|
1147
|
+
|
|
643
1148
|
<View style={{
|
|
644
1149
|
flexDirection: 'row',
|
|
645
1150
|
alignItems: 'center',
|
|
646
|
-
gap:
|
|
1151
|
+
gap: 10,
|
|
647
1152
|
}}>
|
|
648
1153
|
<View style={{
|
|
649
|
-
width:
|
|
650
|
-
height:
|
|
651
|
-
borderRadius:
|
|
1154
|
+
width: 32,
|
|
1155
|
+
height: 32,
|
|
1156
|
+
borderRadius: 8,
|
|
652
1157
|
backgroundColor: AppColors.purpleShade50,
|
|
653
|
-
borderWidth: 1,
|
|
654
|
-
borderColor: `${AppColors.purple}33`,
|
|
655
1158
|
alignItems: 'center',
|
|
656
1159
|
justifyContent: 'center',
|
|
657
1160
|
}}>
|
|
658
|
-
<LayersIcon color={AppColors.purple} size={
|
|
1161
|
+
<LayersIcon color={AppColors.purple} size={15}/>
|
|
659
1162
|
</View>
|
|
660
1163
|
<View style={{ flex: 1 }}>
|
|
661
1164
|
<Text style={{
|
|
662
1165
|
fontFamily: AppFonts.interBold,
|
|
663
|
-
fontSize: 13,
|
|
1166
|
+
fontSize: 13.5,
|
|
1167
|
+
lineHeight: 18,
|
|
664
1168
|
color: AppColors.primaryBlack,
|
|
665
1169
|
}}>
|
|
666
|
-
|
|
1170
|
+
{t('settings.general.defaultOpeningTab')}
|
|
667
1171
|
</Text>
|
|
668
1172
|
<Text style={{
|
|
669
1173
|
fontFamily: AppFonts.interRegular,
|
|
670
1174
|
fontSize: 11,
|
|
1175
|
+
lineHeight: 15,
|
|
671
1176
|
color: AppColors.grayText,
|
|
672
1177
|
marginTop: 1,
|
|
673
1178
|
}}>
|
|
674
|
-
|
|
1179
|
+
{t('settings.general.defaultOpeningTabDesc')}
|
|
675
1180
|
</Text>
|
|
676
1181
|
</View>
|
|
677
1182
|
</View>
|
|
@@ -681,13 +1186,15 @@ const SettingsPanel = () => {
|
|
|
681
1186
|
flexDirection: 'row',
|
|
682
1187
|
flexWrap: 'wrap',
|
|
683
1188
|
gap: 8,
|
|
684
|
-
marginTop:
|
|
1189
|
+
marginTop: 4,
|
|
685
1190
|
}}>
|
|
686
|
-
{
|
|
687
|
-
.filter(tab => tab.key === 'apis' ||
|
|
1191
|
+
{allModules
|
|
1192
|
+
.filter(tab => tab.key === 'apis' ||
|
|
1193
|
+
stagedTabVisibility?.[tab.key] ||
|
|
1194
|
+
tabVisibility?.[tab.key])
|
|
688
1195
|
.map(tab => {
|
|
689
1196
|
const isActive = defaultTab === tab.key;
|
|
690
|
-
return (<TouchableScale key={tab.key} onPress={() => setDefaultTab(tab.key)} style={{
|
|
1197
|
+
return (<TouchableScale key={tab.key} accessible={true} accessibilityRole="button" accessibilityLabel={`Set ${tab.label} as default tab`} accessibilityState={{ selected: isActive }} onPress={() => setDefaultTab(tab.key)} style={{
|
|
691
1198
|
flexDirection: 'row',
|
|
692
1199
|
alignItems: 'center',
|
|
693
1200
|
gap: 8,
|
|
@@ -695,186 +1202,190 @@ const SettingsPanel = () => {
|
|
|
695
1202
|
paddingHorizontal: 12,
|
|
696
1203
|
borderRadius: 10,
|
|
697
1204
|
borderWidth: 1.5,
|
|
698
|
-
borderColor: isActive
|
|
699
|
-
|
|
1205
|
+
borderColor: isActive
|
|
1206
|
+
? AppColors.purple
|
|
1207
|
+
: AppColors.grayBorderSecondary,
|
|
1208
|
+
backgroundColor: isActive
|
|
1209
|
+
? `${AppColors.purple}0F`
|
|
1210
|
+
: AppColors.primaryLight,
|
|
700
1211
|
minWidth: '47%',
|
|
701
1212
|
flex: 1,
|
|
702
1213
|
}}>
|
|
703
|
-
<View style={{
|
|
704
|
-
width: 22,
|
|
705
|
-
height: 22,
|
|
706
|
-
borderRadius: 6,
|
|
707
|
-
backgroundColor: isActive ? AppColors.purple : AppColors.purpleShade50,
|
|
708
|
-
alignItems: 'center',
|
|
709
|
-
justifyContent: 'center',
|
|
710
|
-
}}>
|
|
711
|
-
{tab.icon === 'apis' && (<SignalIcon color={isActive ? AppColors.white : AppColors.purple} size={11}/>)}
|
|
712
|
-
{tab.icon === 'logs' && (<TerminalIcon color={isActive ? AppColors.white : AppColors.purple} size={11}/>)}
|
|
713
|
-
{tab.icon === 'analytics' && (<AnalyticsIcon color={isActive ? AppColors.white : AppColors.purple} size={11}/>)}
|
|
714
|
-
{tab.icon === 'redux' && (<ReduxIcon color={isActive ? AppColors.white : AppColors.purple} size={11}/>)}
|
|
715
|
-
{tab.icon === 'bundle' && (<PackageIcon color={isActive ? AppColors.white : AppColors.purple} size={11}/>)}
|
|
716
|
-
{tab.icon === 'performance' && (<PerformanceIcon color={isActive ? AppColors.white : AppColors.purple} size={11}/>)}
|
|
717
|
-
{tab.icon === 'crash' && (<CrashIcon color={isActive ? AppColors.white : AppColors.purple} size={11}/>)}
|
|
718
|
-
</View>
|
|
719
1214
|
<Text style={{
|
|
720
1215
|
fontFamily: AppFonts.interBold,
|
|
721
|
-
fontSize:
|
|
722
|
-
|
|
1216
|
+
fontSize: 12.5,
|
|
1217
|
+
lineHeight: 16,
|
|
1218
|
+
color: isActive
|
|
1219
|
+
? AppColors.purple
|
|
1220
|
+
: AppColors.primaryBlack,
|
|
723
1221
|
flex: 1,
|
|
724
1222
|
}}>
|
|
725
|
-
|
|
1223
|
+
{tab.label}
|
|
726
1224
|
</Text>
|
|
727
1225
|
{isActive && (<View style={{
|
|
728
|
-
width:
|
|
729
|
-
height:
|
|
730
|
-
borderRadius:
|
|
1226
|
+
width: 16,
|
|
1227
|
+
height: 16,
|
|
1228
|
+
borderRadius: 8,
|
|
731
1229
|
backgroundColor: AppColors.purple,
|
|
732
1230
|
alignItems: 'center',
|
|
733
1231
|
justifyContent: 'center',
|
|
734
1232
|
}}>
|
|
735
|
-
<CheckIcon size={
|
|
1233
|
+
<CheckIcon size={9} color={AppColors.white}/>
|
|
736
1234
|
</View>)}
|
|
737
1235
|
</TouchableScale>);
|
|
738
1236
|
})}
|
|
739
1237
|
</View>
|
|
740
1238
|
</View>
|
|
741
1239
|
|
|
742
|
-
{/*
|
|
1240
|
+
{/* Section 4: Log Deduplication & Levels */}
|
|
743
1241
|
<View style={{
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
1242
|
+
backgroundColor: AppColors.primaryLight,
|
|
1243
|
+
borderRadius: 14,
|
|
1244
|
+
borderWidth: 1,
|
|
1245
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
1246
|
+
overflow: 'hidden',
|
|
1247
|
+
padding: 14,
|
|
1248
|
+
gap: 14,
|
|
1249
|
+
}}>
|
|
1250
|
+
<Text style={{
|
|
1251
|
+
fontFamily: AppFonts.interBold,
|
|
1252
|
+
fontSize: 11,
|
|
1253
|
+
lineHeight: 14,
|
|
1254
|
+
color: AppColors.grayTextWeak,
|
|
1255
|
+
letterSpacing: 0.8,
|
|
1256
|
+
}}>
|
|
1257
|
+
{t('settings.logFiltersDeduplication')}
|
|
1258
|
+
</Text>
|
|
747
1259
|
|
|
748
|
-
|
|
749
|
-
|
|
1260
|
+
{/* Show Duplicate Logs */}
|
|
1261
|
+
<View style={{
|
|
750
1262
|
flexDirection: 'row',
|
|
751
1263
|
alignItems: 'center',
|
|
752
|
-
|
|
753
|
-
paddingHorizontal: 14,
|
|
754
|
-
gap: 12,
|
|
1264
|
+
justifyContent: 'space-between',
|
|
755
1265
|
}}>
|
|
756
|
-
|
|
757
|
-
flex: 1,
|
|
1266
|
+
<View style={{
|
|
758
1267
|
flexDirection: 'row',
|
|
759
1268
|
alignItems: 'center',
|
|
760
|
-
gap:
|
|
1269
|
+
gap: 10,
|
|
1270
|
+
flex: 1,
|
|
761
1271
|
}}>
|
|
762
|
-
|
|
763
|
-
width:
|
|
764
|
-
height:
|
|
765
|
-
borderRadius:
|
|
1272
|
+
<View style={{
|
|
1273
|
+
width: 32,
|
|
1274
|
+
height: 32,
|
|
1275
|
+
borderRadius: 8,
|
|
766
1276
|
backgroundColor: AppColors.purpleShade50,
|
|
767
|
-
borderWidth: 1,
|
|
768
|
-
borderColor: `${AppColors.purple}33`,
|
|
769
1277
|
alignItems: 'center',
|
|
770
1278
|
justifyContent: 'center',
|
|
771
1279
|
}}>
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
1280
|
+
<EyeIcon color={AppColors.purple} size={15}/>
|
|
1281
|
+
</View>
|
|
1282
|
+
<View style={{ flex: 1 }}>
|
|
1283
|
+
<Text style={{
|
|
776
1284
|
fontFamily: AppFonts.interBold,
|
|
777
|
-
fontSize: 13,
|
|
1285
|
+
fontSize: 13.5,
|
|
1286
|
+
lineHeight: 18,
|
|
778
1287
|
color: AppColors.primaryBlack,
|
|
779
1288
|
}}>
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
1289
|
+
{t('settings.general.duplicateLogs')}
|
|
1290
|
+
</Text>
|
|
1291
|
+
<Text style={{
|
|
783
1292
|
fontFamily: AppFonts.interRegular,
|
|
784
1293
|
fontSize: 11,
|
|
1294
|
+
lineHeight: 15,
|
|
785
1295
|
color: AppColors.grayText,
|
|
786
1296
|
marginTop: 1,
|
|
787
1297
|
}}>
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
</
|
|
1298
|
+
{t('settings.general.duplicateLogsDescription')}
|
|
1299
|
+
</Text>
|
|
1300
|
+
</View>
|
|
791
1301
|
</View>
|
|
792
|
-
</View>
|
|
793
1302
|
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
borderRadius: 11,
|
|
1303
|
+
<TouchableScale accessible={true} accessibilityRole="switch" accessibilityLabel="Toggle show duplicate logs" accessibilityState={{ checked: showDuplicateLogs }} onPress={() => setShowDuplicateLogs(prev => !prev)} style={{
|
|
1304
|
+
width: 42,
|
|
1305
|
+
height: 24,
|
|
1306
|
+
borderRadius: 12,
|
|
799
1307
|
backgroundColor: showDuplicateLogs
|
|
800
1308
|
? AppColors.purple
|
|
801
1309
|
: AppColors.grayBorderSecondary,
|
|
802
1310
|
padding: 2,
|
|
803
1311
|
justifyContent: 'center',
|
|
804
|
-
alignItems: showDuplicateLogs
|
|
1312
|
+
alignItems: showDuplicateLogs
|
|
1313
|
+
? 'flex-end'
|
|
1314
|
+
: 'flex-start',
|
|
805
1315
|
}}>
|
|
806
|
-
|
|
807
|
-
width:
|
|
808
|
-
height:
|
|
809
|
-
borderRadius:
|
|
1316
|
+
<View style={{
|
|
1317
|
+
width: 20,
|
|
1318
|
+
height: 20,
|
|
1319
|
+
borderRadius: 10,
|
|
810
1320
|
backgroundColor: AppColors.white,
|
|
811
1321
|
shadowColor: AppColors.black,
|
|
812
|
-
shadowOpacity: 0.
|
|
813
|
-
shadowRadius:
|
|
1322
|
+
shadowOpacity: 0.18,
|
|
1323
|
+
shadowRadius: 2,
|
|
814
1324
|
shadowOffset: { width: 0, height: 1 },
|
|
815
1325
|
}}/>
|
|
816
|
-
|
|
817
|
-
|
|
1326
|
+
</TouchableScale>
|
|
1327
|
+
</View>
|
|
818
1328
|
|
|
819
|
-
|
|
820
|
-
<View style={{
|
|
821
|
-
height: 1,
|
|
822
|
-
backgroundColor: AppColors.dividerColor,
|
|
823
|
-
}}/>
|
|
1329
|
+
<View style={{ height: 1, backgroundColor: AppColors.dividerColor }}/>
|
|
824
1330
|
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
paddingHorizontal: 14,
|
|
829
|
-
}}>
|
|
830
|
-
<View style={{
|
|
1331
|
+
{/* Console Log Levels */}
|
|
1332
|
+
<View style={{ gap: 8 }}>
|
|
1333
|
+
<View style={{
|
|
831
1334
|
flexDirection: 'row',
|
|
832
1335
|
alignItems: 'center',
|
|
833
|
-
gap:
|
|
1336
|
+
gap: 10,
|
|
834
1337
|
}}>
|
|
835
|
-
|
|
836
|
-
width:
|
|
837
|
-
height:
|
|
838
|
-
borderRadius:
|
|
1338
|
+
<View style={{
|
|
1339
|
+
width: 32,
|
|
1340
|
+
height: 32,
|
|
1341
|
+
borderRadius: 8,
|
|
839
1342
|
backgroundColor: AppColors.purpleShade50,
|
|
840
|
-
borderWidth: 1,
|
|
841
|
-
borderColor: `${AppColors.purple}33`,
|
|
842
1343
|
alignItems: 'center',
|
|
843
1344
|
justifyContent: 'center',
|
|
844
1345
|
}}>
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
1346
|
+
<TerminalIcon color={AppColors.purple} size={15}/>
|
|
1347
|
+
</View>
|
|
1348
|
+
<View style={{ flex: 1 }}>
|
|
1349
|
+
<Text style={{
|
|
849
1350
|
fontFamily: AppFonts.interBold,
|
|
850
|
-
fontSize: 13,
|
|
1351
|
+
fontSize: 13.5,
|
|
1352
|
+
lineHeight: 18,
|
|
851
1353
|
color: AppColors.primaryBlack,
|
|
852
1354
|
}}>
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
1355
|
+
{t('settings.general.activeConsoleLogLevels')}
|
|
1356
|
+
</Text>
|
|
1357
|
+
<Text style={{
|
|
856
1358
|
fontFamily: AppFonts.interRegular,
|
|
857
1359
|
fontSize: 11,
|
|
1360
|
+
lineHeight: 15,
|
|
858
1361
|
color: AppColors.grayText,
|
|
859
1362
|
marginTop: 1,
|
|
860
1363
|
}}>
|
|
861
|
-
|
|
862
|
-
|
|
1364
|
+
{t('settings.general.activeConsoleLogLevelsDesc')}
|
|
1365
|
+
</Text>
|
|
1366
|
+
</View>
|
|
863
1367
|
</View>
|
|
864
|
-
</View>
|
|
865
1368
|
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
{
|
|
874
|
-
|
|
875
|
-
|
|
1369
|
+
<View style={{ flexDirection: 'row', gap: 8, marginTop: 4 }}>
|
|
1370
|
+
{[
|
|
1371
|
+
{
|
|
1372
|
+
key: 'info',
|
|
1373
|
+
label: 'Info',
|
|
1374
|
+
color: AppColors.blue500,
|
|
1375
|
+
},
|
|
1376
|
+
{
|
|
1377
|
+
key: 'warn',
|
|
1378
|
+
label: 'Warning',
|
|
1379
|
+
color: AppColors.amber500,
|
|
1380
|
+
},
|
|
1381
|
+
{
|
|
1382
|
+
key: 'error',
|
|
1383
|
+
label: 'Error',
|
|
1384
|
+
color: AppColors.errorColor,
|
|
1385
|
+
},
|
|
1386
|
+
].map(level => {
|
|
876
1387
|
const isActive = showConsoleLevels[level.key];
|
|
877
|
-
return (<TouchableScale key={level.key} onPress={() => setShowConsoleLevels(prev => ({
|
|
1388
|
+
return (<TouchableScale key={level.key} accessible={true} accessibilityRole="checkbox" accessibilityLabel={`Toggle ${level.label} logs`} accessibilityState={{ checked: isActive }} onPress={() => setShowConsoleLevels(prev => ({
|
|
878
1389
|
...prev,
|
|
879
1390
|
[level.key]: !prev[level.key],
|
|
880
1391
|
}))} style={{
|
|
@@ -884,112 +1395,113 @@ const SettingsPanel = () => {
|
|
|
884
1395
|
justifyContent: 'center',
|
|
885
1396
|
gap: 6,
|
|
886
1397
|
paddingVertical: 8,
|
|
887
|
-
borderRadius:
|
|
1398
|
+
borderRadius: 9,
|
|
888
1399
|
borderWidth: 1.5,
|
|
889
|
-
borderColor: isActive
|
|
890
|
-
|
|
1400
|
+
borderColor: isActive
|
|
1401
|
+
? level.color
|
|
1402
|
+
: AppColors.grayBorderSecondary,
|
|
1403
|
+
backgroundColor: isActive
|
|
1404
|
+
? `${level.color}0D`
|
|
1405
|
+
: AppColors.primaryLight,
|
|
891
1406
|
}}>
|
|
892
|
-
|
|
1407
|
+
<View style={{
|
|
893
1408
|
width: 8,
|
|
894
1409
|
height: 8,
|
|
895
1410
|
borderRadius: 4,
|
|
896
|
-
backgroundColor: isActive
|
|
1411
|
+
backgroundColor: isActive
|
|
1412
|
+
? level.color
|
|
1413
|
+
: AppColors.grayBorderSecondary,
|
|
897
1414
|
}}/>
|
|
898
|
-
|
|
1415
|
+
<Text style={{
|
|
899
1416
|
fontFamily: AppFonts.interBold,
|
|
900
|
-
fontSize: 11,
|
|
901
|
-
|
|
1417
|
+
fontSize: 11.5,
|
|
1418
|
+
lineHeight: 15,
|
|
1419
|
+
color: isActive
|
|
1420
|
+
? level.color
|
|
1421
|
+
: AppColors.grayText,
|
|
902
1422
|
}}>
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
1423
|
+
{level.label}
|
|
1424
|
+
</Text>
|
|
1425
|
+
</TouchableScale>);
|
|
906
1426
|
})}
|
|
1427
|
+
</View>
|
|
907
1428
|
</View>
|
|
908
1429
|
</View>
|
|
909
1430
|
|
|
910
|
-
{/*
|
|
911
|
-
<View style={{
|
|
912
|
-
height: 1,
|
|
913
|
-
backgroundColor: AppColors.dividerColor,
|
|
914
|
-
}}/>
|
|
915
|
-
|
|
916
|
-
{/* Reset Settings */}
|
|
1431
|
+
{/* Section 5: Reset Settings */}
|
|
917
1432
|
<View style={{
|
|
1433
|
+
backgroundColor: AppColors.primaryLight,
|
|
1434
|
+
borderRadius: 14,
|
|
1435
|
+
borderWidth: 1,
|
|
1436
|
+
borderColor: `${AppColors.errorColor}33`,
|
|
1437
|
+
overflow: 'hidden',
|
|
1438
|
+
padding: 14,
|
|
918
1439
|
flexDirection: 'row',
|
|
919
1440
|
alignItems: 'center',
|
|
920
|
-
paddingVertical: 12,
|
|
921
|
-
paddingHorizontal: 14,
|
|
922
1441
|
gap: 12,
|
|
923
1442
|
}}>
|
|
924
1443
|
<View style={{
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
gap: 8,
|
|
929
|
-
}}>
|
|
930
|
-
<View style={{
|
|
931
|
-
width: 20,
|
|
932
|
-
height: 20,
|
|
933
|
-
borderRadius: 6,
|
|
1444
|
+
width: 34,
|
|
1445
|
+
height: 34,
|
|
1446
|
+
borderRadius: 9,
|
|
934
1447
|
backgroundColor: `${AppColors.errorColor}14`,
|
|
935
|
-
borderWidth: 1,
|
|
936
|
-
borderColor: `${AppColors.errorColor}33`,
|
|
937
1448
|
alignItems: 'center',
|
|
938
1449
|
justifyContent: 'center',
|
|
939
1450
|
}}>
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
1451
|
+
<TrashIcon color={AppColors.errorColor} size={15}/>
|
|
1452
|
+
</View>
|
|
1453
|
+
<View style={{ flex: 1 }}>
|
|
1454
|
+
<Text style={{
|
|
944
1455
|
fontFamily: AppFonts.interBold,
|
|
945
|
-
fontSize: 13,
|
|
1456
|
+
fontSize: 13.5,
|
|
1457
|
+
lineHeight: 18,
|
|
946
1458
|
color: AppColors.primaryBlack,
|
|
947
1459
|
}}>
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
1460
|
+
{t('settings.resetSettings')}
|
|
1461
|
+
</Text>
|
|
1462
|
+
<Text style={{
|
|
951
1463
|
fontFamily: AppFonts.interRegular,
|
|
952
1464
|
fontSize: 11,
|
|
1465
|
+
lineHeight: 15,
|
|
953
1466
|
color: AppColors.grayText,
|
|
954
1467
|
marginTop: 1,
|
|
955
1468
|
}}>
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
</View>
|
|
1469
|
+
{t('settings.resetSettingsDesc')}
|
|
1470
|
+
</Text>
|
|
959
1471
|
</View>
|
|
960
1472
|
|
|
961
|
-
<TouchableScale onPress={resetToDefaults} style={{
|
|
962
|
-
paddingHorizontal:
|
|
963
|
-
paddingVertical:
|
|
964
|
-
borderRadius:
|
|
1473
|
+
<TouchableScale accessible={true} accessibilityRole="button" accessibilityLabel="Reset all settings to default" onPress={resetToDefaults} style={{
|
|
1474
|
+
paddingHorizontal: 12,
|
|
1475
|
+
paddingVertical: 7,
|
|
1476
|
+
borderRadius: 8,
|
|
965
1477
|
backgroundColor: `${AppColors.errorColor}14`,
|
|
966
1478
|
borderWidth: 1,
|
|
967
|
-
borderColor: `${AppColors.errorColor}
|
|
1479
|
+
borderColor: `${AppColors.errorColor}38`,
|
|
968
1480
|
}}>
|
|
969
1481
|
<Text style={{
|
|
970
1482
|
fontFamily: AppFonts.interBold,
|
|
971
|
-
fontSize: 11,
|
|
1483
|
+
fontSize: 11.5,
|
|
1484
|
+
lineHeight: 15,
|
|
972
1485
|
color: AppColors.errorColor,
|
|
973
1486
|
}}>
|
|
974
|
-
|
|
1487
|
+
{t('settings.reset')}
|
|
975
1488
|
</Text>
|
|
976
1489
|
</TouchableScale>
|
|
977
1490
|
</View>
|
|
978
1491
|
</View>)}
|
|
979
1492
|
|
|
980
|
-
|
|
981
|
-
{/* Storage Status */}
|
|
1493
|
+
{/* Storage & Engine Status Card */}
|
|
982
1494
|
<View style={{
|
|
983
|
-
backgroundColor:
|
|
984
|
-
? `${AppColors.liveGreen}
|
|
985
|
-
: `${AppColors.amber600}
|
|
1495
|
+
backgroundColor: isPersistent
|
|
1496
|
+
? `${AppColors.liveGreen}12`
|
|
1497
|
+
: `${AppColors.amber600}12`,
|
|
986
1498
|
borderRadius: 12,
|
|
987
1499
|
borderWidth: 1,
|
|
988
|
-
borderColor:
|
|
1500
|
+
borderColor: isPersistent
|
|
989
1501
|
? `${AppColors.liveGreen}33`
|
|
990
1502
|
: `${AppColors.amber600}33`,
|
|
991
1503
|
padding: 12,
|
|
992
|
-
|
|
1504
|
+
marginBottom: 10,
|
|
993
1505
|
flexDirection: 'row',
|
|
994
1506
|
alignItems: 'center',
|
|
995
1507
|
gap: 10,
|
|
@@ -998,32 +1510,106 @@ const SettingsPanel = () => {
|
|
|
998
1510
|
width: 8,
|
|
999
1511
|
height: 8,
|
|
1000
1512
|
borderRadius: 4,
|
|
1001
|
-
backgroundColor:
|
|
1513
|
+
backgroundColor: isPersistent
|
|
1514
|
+
? AppColors.green500
|
|
1515
|
+
: AppColors.amber600,
|
|
1002
1516
|
}}/>
|
|
1003
1517
|
<View style={{ flex: 1 }}>
|
|
1004
1518
|
<Text style={{
|
|
1005
1519
|
fontFamily: AppFonts.interBold,
|
|
1006
1520
|
fontSize: 12,
|
|
1007
|
-
|
|
1521
|
+
lineHeight: 16,
|
|
1522
|
+
color: isPersistent
|
|
1523
|
+
? AppColors.green700
|
|
1524
|
+
: AppColors.amber800,
|
|
1008
1525
|
}}>
|
|
1009
|
-
{
|
|
1010
|
-
?
|
|
1011
|
-
|
|
1526
|
+
{isPersistent
|
|
1527
|
+
? t('settings.general.storageStatusEnabled', {
|
|
1528
|
+
type: storage ? 'Custom Storage' : 'iOS NSUserDefaults',
|
|
1529
|
+
})
|
|
1530
|
+
: t('settings.general.storageStatusDisabled')}
|
|
1012
1531
|
</Text>
|
|
1013
1532
|
<Text style={{
|
|
1014
1533
|
fontFamily: AppFonts.interRegular,
|
|
1015
1534
|
fontSize: 10.5,
|
|
1016
|
-
|
|
1535
|
+
lineHeight: 14,
|
|
1536
|
+
color: isPersistent
|
|
1537
|
+
? AppColors.green800
|
|
1538
|
+
: AppColors.amber800,
|
|
1017
1539
|
marginTop: 2,
|
|
1018
|
-
opacity: 0.
|
|
1540
|
+
opacity: 0.85,
|
|
1019
1541
|
}}>
|
|
1020
|
-
{
|
|
1021
|
-
? '
|
|
1022
|
-
: '
|
|
1542
|
+
{isPersistent
|
|
1543
|
+
? t('settings.general.storageStatusEnabledDesc')
|
|
1544
|
+
: t('settings.general.storageStatusDisabledDesc')}
|
|
1545
|
+
</Text>
|
|
1546
|
+
</View>
|
|
1547
|
+
</View>
|
|
1548
|
+
</ScrollView>
|
|
1549
|
+
|
|
1550
|
+
{/* Bottom Sticky Action Bar for Save Changes */}
|
|
1551
|
+
{settingsActiveSubTab === 'module' && (<View style={{
|
|
1552
|
+
paddingHorizontal: 16,
|
|
1553
|
+
paddingTop: 12,
|
|
1554
|
+
paddingBottom: Platform.OS === 'ios' ? 26 : 14,
|
|
1555
|
+
backgroundColor: AppColors.primaryLight,
|
|
1556
|
+
borderTopWidth: 1,
|
|
1557
|
+
borderTopColor: AppColors.dividerColor,
|
|
1558
|
+
flexDirection: 'row',
|
|
1559
|
+
alignItems: 'center',
|
|
1560
|
+
gap: 12,
|
|
1561
|
+
shadowColor: AppColors.black,
|
|
1562
|
+
shadowOpacity: 0.08,
|
|
1563
|
+
shadowRadius: 8,
|
|
1564
|
+
shadowOffset: { width: 0, height: -3 },
|
|
1565
|
+
elevation: 8,
|
|
1566
|
+
}}>
|
|
1567
|
+
<View style={{ flex: 1 }}>
|
|
1568
|
+
<Text style={{
|
|
1569
|
+
fontFamily: AppFonts.interBold,
|
|
1570
|
+
fontSize: 13,
|
|
1571
|
+
lineHeight: 17,
|
|
1572
|
+
color: AppColors.primaryBlack,
|
|
1573
|
+
}}>
|
|
1574
|
+
{stagedActiveCount} of {allModules.length} Modules Active
|
|
1575
|
+
</Text>
|
|
1576
|
+
<Text style={{
|
|
1577
|
+
fontFamily: AppFonts.interRegular,
|
|
1578
|
+
fontSize: 11,
|
|
1579
|
+
lineHeight: 15,
|
|
1580
|
+
color: hasUnsavedChanges
|
|
1581
|
+
? AppColors.purple
|
|
1582
|
+
: AppColors.grayText,
|
|
1583
|
+
marginTop: 1,
|
|
1584
|
+
}}>
|
|
1585
|
+
{hasUnsavedChanges
|
|
1586
|
+
? t('settings.unsavedPending')
|
|
1587
|
+
: t('settings.allSynchronized')}
|
|
1588
|
+
</Text>
|
|
1589
|
+
</View>
|
|
1590
|
+
|
|
1591
|
+
<TouchableScale accessible={true} accessibilityRole="button" accessibilityLabel="Save Changes" onPress={handleSaveChanges} style={{
|
|
1592
|
+
flexDirection: 'row',
|
|
1593
|
+
alignItems: 'center',
|
|
1594
|
+
gap: 6,
|
|
1595
|
+
backgroundColor: hasUnsavedChanges
|
|
1596
|
+
? AppColors.purple
|
|
1597
|
+
: `${AppColors.purple}22`,
|
|
1598
|
+
paddingHorizontal: 18,
|
|
1599
|
+
paddingVertical: 10,
|
|
1600
|
+
borderRadius: 10,
|
|
1601
|
+
}}>
|
|
1602
|
+
<CheckIcon size={14} color={hasUnsavedChanges ? AppColors.white : AppColors.purple}/>
|
|
1603
|
+
<Text style={{
|
|
1604
|
+
fontFamily: AppFonts.interBold,
|
|
1605
|
+
fontSize: 13,
|
|
1606
|
+
lineHeight: 17,
|
|
1607
|
+
color: hasUnsavedChanges ? AppColors.white : AppColors.purple,
|
|
1608
|
+
}}>
|
|
1609
|
+
{t('settings.saveChanges')}
|
|
1023
1610
|
</Text>
|
|
1024
|
-
</
|
|
1025
|
-
</View>
|
|
1026
|
-
</ScrollView>
|
|
1611
|
+
</TouchableScale>
|
|
1612
|
+
</View>)}
|
|
1027
1613
|
</View>);
|
|
1028
1614
|
}
|
|
1029
1615
|
const goBackToMain = () => {
|
|
@@ -1031,105 +1617,154 @@ const SettingsPanel = () => {
|
|
|
1031
1617
|
setSettingsPage('main');
|
|
1032
1618
|
};
|
|
1033
1619
|
// Helper: settings row with icon + label + optional description
|
|
1034
|
-
const renderSettingRow = (opts) =>
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
<TouchableScale disabled={!opts.onPress} onPress={opts.onPress} style={{
|
|
1040
|
-
flexDirection: 'row',
|
|
1041
|
-
alignItems: 'center',
|
|
1042
|
-
gap: 12,
|
|
1043
|
-
}}>
|
|
1044
|
-
<View style={{
|
|
1045
|
-
width: 36,
|
|
1046
|
-
height: 36,
|
|
1047
|
-
borderRadius: 10,
|
|
1048
|
-
backgroundColor: AppColors.purpleShade50,
|
|
1049
|
-
borderWidth: 1,
|
|
1050
|
-
borderColor: `${AppColors.purple}2E`,
|
|
1051
|
-
alignItems: 'center',
|
|
1052
|
-
justifyContent: 'center',
|
|
1053
|
-
}}>
|
|
1054
|
-
{opts.icon}
|
|
1055
|
-
</View>
|
|
1056
|
-
<View style={{ flex: 1 }}>
|
|
1057
|
-
<Text style={{
|
|
1058
|
-
fontFamily: AppFonts.interBold,
|
|
1059
|
-
fontSize: 14,
|
|
1060
|
-
color: AppColors.primaryBlack,
|
|
1061
|
-
}}>
|
|
1062
|
-
{opts.label}
|
|
1063
|
-
</Text>
|
|
1064
|
-
{opts.description ? (<Text style={{
|
|
1065
|
-
fontFamily: AppFonts.interRegular,
|
|
1066
|
-
fontSize: 11,
|
|
1067
|
-
color: AppColors.grayText,
|
|
1068
|
-
marginTop: 1,
|
|
1620
|
+
const renderSettingRow = (opts) => {
|
|
1621
|
+
return (<View style={{
|
|
1622
|
+
paddingVertical: 12,
|
|
1623
|
+
borderBottomWidth: opts.isLast ? 0 : 1,
|
|
1624
|
+
borderBottomColor: AppColors.dividerColor,
|
|
1069
1625
|
}}>
|
|
1070
|
-
|
|
1071
|
-
</Text>) : null}
|
|
1072
|
-
</View>
|
|
1073
|
-
{opts.right || null}
|
|
1074
|
-
</TouchableScale>
|
|
1075
|
-
{opts.picker && (<View style={{
|
|
1626
|
+
<TouchableScale disabled={!opts.onPress} onPress={opts.onPress} style={{
|
|
1076
1627
|
flexDirection: 'row',
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1628
|
+
alignItems: 'center',
|
|
1629
|
+
gap: 12,
|
|
1630
|
+
}}>
|
|
1631
|
+
<View style={{
|
|
1632
|
+
width: 36,
|
|
1633
|
+
height: 36,
|
|
1634
|
+
borderRadius: 10,
|
|
1635
|
+
backgroundColor: AppColors.purpleShade50,
|
|
1081
1636
|
borderWidth: 1,
|
|
1082
|
-
borderColor: AppColors.
|
|
1637
|
+
borderColor: `${AppColors.purple}2E`,
|
|
1638
|
+
alignItems: 'center',
|
|
1639
|
+
justifyContent: 'center',
|
|
1083
1640
|
}}>
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
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,
|
|
1099
1703
|
}}>
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
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
|
+
};
|
|
1108
1742
|
let content = null;
|
|
1109
1743
|
let title = '';
|
|
1110
1744
|
let icon = null;
|
|
1111
1745
|
let rightInfo = '';
|
|
1112
1746
|
if (settingsPage === 'apis') {
|
|
1113
|
-
title = '
|
|
1747
|
+
title = t('settings.apis.title');
|
|
1114
1748
|
icon = <SignalIcon color={AppColors.white} size={16}/>;
|
|
1115
|
-
rightInfo =
|
|
1116
|
-
content = (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16 }}>
|
|
1749
|
+
rightInfo = t('settings.apis.total', { count: logs.length });
|
|
1750
|
+
content = (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16, gap: 12 }}>
|
|
1117
1751
|
<View style={{
|
|
1118
1752
|
backgroundColor: AppColors.primaryLight,
|
|
1119
1753
|
padding: 16,
|
|
1120
|
-
borderRadius:
|
|
1754
|
+
borderRadius: 14,
|
|
1121
1755
|
borderWidth: 1,
|
|
1122
1756
|
borderColor: AppColors.grayBorderSecondary,
|
|
1123
|
-
gap: 4,
|
|
1124
1757
|
}}>
|
|
1125
1758
|
{renderSettingRow({
|
|
1126
1759
|
icon: <SignalIcon color={AppColors.purple} size={16}/>,
|
|
1127
|
-
label: '
|
|
1128
|
-
description: '
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1760
|
+
label: t('settings.apis.maxRequestLogs'),
|
|
1761
|
+
description: t('settings.apis.maxRequestLogsDescription'),
|
|
1762
|
+
numericInput: {
|
|
1763
|
+
value: maxNetworkLogs,
|
|
1764
|
+
onChange: setMaxNetworkLogs,
|
|
1765
|
+
min: 10,
|
|
1766
|
+
max: 5000,
|
|
1767
|
+
placeholder: 'Enter max requests (10-5000)',
|
|
1133
1768
|
},
|
|
1134
1769
|
isLast: true,
|
|
1135
1770
|
})}
|
|
@@ -1137,26 +1772,25 @@ const SettingsPanel = () => {
|
|
|
1137
1772
|
|
|
1138
1773
|
<View style={{
|
|
1139
1774
|
backgroundColor: AppColors.primaryLight,
|
|
1140
|
-
borderRadius:
|
|
1775
|
+
borderRadius: 14,
|
|
1141
1776
|
borderWidth: 1,
|
|
1142
1777
|
borderColor: AppColors.grayBorderSecondary,
|
|
1143
1778
|
padding: 16,
|
|
1144
|
-
marginTop: 12,
|
|
1145
1779
|
}}>
|
|
1146
1780
|
{renderSettingRow({
|
|
1147
1781
|
icon: <TrashIcon color={AppColors.errorColor} size={16}/>,
|
|
1148
|
-
label: '
|
|
1149
|
-
description:
|
|
1782
|
+
label: t('settings.apis.clearNetworkLogs'),
|
|
1783
|
+
description: t('settings.apis.clearNetworkLogsDescription', { count: logs.length }),
|
|
1150
1784
|
isLast: true,
|
|
1151
1785
|
onPress: () => {
|
|
1152
1786
|
clearNetworkLogs();
|
|
1153
1787
|
setSelected(null);
|
|
1154
|
-
Alert.alert('
|
|
1788
|
+
Alert.alert(t('common.success'), t('settings.apis.networkLogsCleared'));
|
|
1155
1789
|
},
|
|
1156
1790
|
right: (<View style={{
|
|
1157
|
-
paddingHorizontal:
|
|
1158
|
-
paddingVertical:
|
|
1159
|
-
borderRadius:
|
|
1791
|
+
paddingHorizontal: 12,
|
|
1792
|
+
paddingVertical: 6,
|
|
1793
|
+
borderRadius: 8,
|
|
1160
1794
|
backgroundColor: `${AppColors.errorColor}14`,
|
|
1161
1795
|
borderWidth: 1,
|
|
1162
1796
|
borderColor: `${AppColors.errorColor}33`,
|
|
@@ -1164,9 +1798,10 @@ const SettingsPanel = () => {
|
|
|
1164
1798
|
<Text style={{
|
|
1165
1799
|
fontFamily: AppFonts.interBold,
|
|
1166
1800
|
fontSize: 11,
|
|
1801
|
+
lineHeight: 14,
|
|
1167
1802
|
color: AppColors.errorColor,
|
|
1168
1803
|
}}>
|
|
1169
|
-
|
|
1804
|
+
{t('common.clear')}
|
|
1170
1805
|
</Text>
|
|
1171
1806
|
</View>),
|
|
1172
1807
|
})}
|
|
@@ -1174,36 +1809,39 @@ const SettingsPanel = () => {
|
|
|
1174
1809
|
</ScrollView>);
|
|
1175
1810
|
}
|
|
1176
1811
|
else if (settingsPage === 'logs') {
|
|
1177
|
-
title = '
|
|
1812
|
+
title = t('settings.logs.title');
|
|
1178
1813
|
icon = <TerminalIcon color={AppColors.white} size={16}/>;
|
|
1179
|
-
rightInfo =
|
|
1180
|
-
content = (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16 }}>
|
|
1814
|
+
rightInfo = t('settings.logs.total', { count: consoleLogs.length });
|
|
1815
|
+
content = (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16, gap: 12 }}>
|
|
1181
1816
|
<View style={{
|
|
1182
1817
|
backgroundColor: AppColors.primaryLight,
|
|
1183
1818
|
padding: 16,
|
|
1184
|
-
borderRadius:
|
|
1819
|
+
borderRadius: 14,
|
|
1185
1820
|
borderWidth: 1,
|
|
1186
1821
|
borderColor: AppColors.grayBorderSecondary,
|
|
1187
1822
|
gap: 4,
|
|
1188
1823
|
}}>
|
|
1189
1824
|
{renderSettingRow({
|
|
1190
1825
|
icon: <TerminalIcon color={AppColors.purple} size={16}/>,
|
|
1191
|
-
label: '
|
|
1192
|
-
description: '
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1826
|
+
label: t('settings.logs.maxConsoleLogs'),
|
|
1827
|
+
description: t('settings.logs.maxConsoleLogsDescription'),
|
|
1828
|
+
numericInput: {
|
|
1829
|
+
value: maxConsoleLogs,
|
|
1830
|
+
onChange: setMaxConsoleLogs,
|
|
1831
|
+
min: 10,
|
|
1832
|
+
max: 10000,
|
|
1833
|
+
placeholder: 'Enter max logs (10-10000)',
|
|
1197
1834
|
},
|
|
1198
1835
|
})}
|
|
1199
1836
|
<View style={{ height: 1, backgroundColor: AppColors.dividerColor }}/>
|
|
1200
1837
|
<Text style={{
|
|
1201
1838
|
fontFamily: AppFonts.interBold,
|
|
1202
1839
|
fontSize: 13,
|
|
1840
|
+
lineHeight: 17,
|
|
1203
1841
|
color: AppColors.primaryBlack,
|
|
1204
|
-
paddingTop:
|
|
1842
|
+
paddingTop: 6,
|
|
1205
1843
|
}}>
|
|
1206
|
-
|
|
1844
|
+
{t('settings.logs.logLevels')}
|
|
1207
1845
|
</Text>
|
|
1208
1846
|
{['info', 'warn', 'error'].map(level => {
|
|
1209
1847
|
const isLvlActive = showConsoleLevels?.[level];
|
|
@@ -1212,19 +1850,25 @@ const SettingsPanel = () => {
|
|
|
1212
1850
|
: level === 'warn'
|
|
1213
1851
|
? AppColors.warningIconGold
|
|
1214
1852
|
: AppColors.skyBlue;
|
|
1853
|
+
const label = level === 'info'
|
|
1854
|
+
? t('settings.logs.showInfo')
|
|
1855
|
+
: level === 'warn'
|
|
1856
|
+
? t('settings.logs.showWarn')
|
|
1857
|
+
: t('settings.logs.showError');
|
|
1858
|
+
const desc = level === 'info'
|
|
1859
|
+
? t('settings.logs.showInfoDesc')
|
|
1860
|
+
: level === 'warn'
|
|
1861
|
+
? t('settings.logs.showWarnDesc')
|
|
1862
|
+
: t('settings.logs.showErrorDesc');
|
|
1215
1863
|
return renderSettingRow({
|
|
1216
1864
|
icon: (<View style={{
|
|
1217
|
-
width:
|
|
1218
|
-
height:
|
|
1219
|
-
borderRadius:
|
|
1865
|
+
width: 12,
|
|
1866
|
+
height: 12,
|
|
1867
|
+
borderRadius: 6,
|
|
1220
1868
|
backgroundColor: levelColor,
|
|
1221
1869
|
}}/>),
|
|
1222
|
-
label
|
|
1223
|
-
description:
|
|
1224
|
-
? 'Informational messages'
|
|
1225
|
-
: level === 'warn'
|
|
1226
|
-
? 'Warning messages'
|
|
1227
|
-
: 'Error messages',
|
|
1870
|
+
label,
|
|
1871
|
+
description: desc,
|
|
1228
1872
|
isLast: level === 'error',
|
|
1229
1873
|
onPress: () => setShowConsoleLevels(prev => ({
|
|
1230
1874
|
...prev,
|
|
@@ -1252,25 +1896,24 @@ const SettingsPanel = () => {
|
|
|
1252
1896
|
|
|
1253
1897
|
<View style={{
|
|
1254
1898
|
backgroundColor: AppColors.primaryLight,
|
|
1255
|
-
borderRadius:
|
|
1899
|
+
borderRadius: 14,
|
|
1256
1900
|
borderWidth: 1,
|
|
1257
1901
|
borderColor: AppColors.grayBorderSecondary,
|
|
1258
1902
|
padding: 16,
|
|
1259
|
-
marginTop: 12,
|
|
1260
1903
|
}}>
|
|
1261
1904
|
{renderSettingRow({
|
|
1262
1905
|
icon: <TrashIcon color={AppColors.errorColor} size={16}/>,
|
|
1263
|
-
label: '
|
|
1264
|
-
description:
|
|
1906
|
+
label: t('settings.logs.clearConsoleLogs'),
|
|
1907
|
+
description: t('settings.logs.clearConsoleLogsDescription', { count: consoleLogs.length }),
|
|
1265
1908
|
isLast: true,
|
|
1266
1909
|
onPress: () => {
|
|
1267
1910
|
clearConsoleLogs();
|
|
1268
|
-
Alert.alert('
|
|
1911
|
+
Alert.alert(t('common.success'), t('settings.logs.consoleLogsCleared'));
|
|
1269
1912
|
},
|
|
1270
1913
|
right: (<View style={{
|
|
1271
|
-
paddingHorizontal:
|
|
1272
|
-
paddingVertical:
|
|
1273
|
-
borderRadius:
|
|
1914
|
+
paddingHorizontal: 12,
|
|
1915
|
+
paddingVertical: 6,
|
|
1916
|
+
borderRadius: 8,
|
|
1274
1917
|
backgroundColor: `${AppColors.errorColor}14`,
|
|
1275
1918
|
borderWidth: 1,
|
|
1276
1919
|
borderColor: `${AppColors.errorColor}33`,
|
|
@@ -1278,9 +1921,10 @@ const SettingsPanel = () => {
|
|
|
1278
1921
|
<Text style={{
|
|
1279
1922
|
fontFamily: AppFonts.interBold,
|
|
1280
1923
|
fontSize: 11,
|
|
1924
|
+
lineHeight: 14,
|
|
1281
1925
|
color: AppColors.errorColor,
|
|
1282
1926
|
}}>
|
|
1283
|
-
|
|
1927
|
+
{t('common.clear')}
|
|
1284
1928
|
</Text>
|
|
1285
1929
|
</View>),
|
|
1286
1930
|
})}
|
|
@@ -1288,47 +1932,52 @@ const SettingsPanel = () => {
|
|
|
1288
1932
|
</ScrollView>);
|
|
1289
1933
|
}
|
|
1290
1934
|
else if (settingsPage === 'analytics') {
|
|
1291
|
-
title = '
|
|
1935
|
+
title = t('settings.analytics.title');
|
|
1292
1936
|
icon = <AnalyticsIcon color={AppColors.white} size={16}/>;
|
|
1293
|
-
rightInfo =
|
|
1294
|
-
content = (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16 }}>
|
|
1937
|
+
rightInfo = t('settings.analytics.total', { count: analyticsEvents.length });
|
|
1938
|
+
content = (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16, gap: 12 }}>
|
|
1295
1939
|
<View style={{
|
|
1296
1940
|
backgroundColor: AppColors.primaryLight,
|
|
1297
1941
|
padding: 16,
|
|
1298
|
-
borderRadius:
|
|
1942
|
+
borderRadius: 14,
|
|
1299
1943
|
borderWidth: 1,
|
|
1300
1944
|
borderColor: AppColors.grayBorderSecondary,
|
|
1301
|
-
gap: 4,
|
|
1302
1945
|
}}>
|
|
1303
1946
|
{renderSettingRow({
|
|
1304
1947
|
icon: <AnalyticsIcon color={AppColors.purple} size={16}/>,
|
|
1305
|
-
label: '
|
|
1306
|
-
description:
|
|
1948
|
+
label: t('settings.analytics.maxAnalyticsEvents'),
|
|
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
|
+
},
|
|
1307
1957
|
isLast: true,
|
|
1308
1958
|
})}
|
|
1309
1959
|
</View>
|
|
1310
1960
|
<View style={{
|
|
1311
1961
|
backgroundColor: AppColors.primaryLight,
|
|
1312
|
-
borderRadius:
|
|
1962
|
+
borderRadius: 14,
|
|
1313
1963
|
borderWidth: 1,
|
|
1314
1964
|
borderColor: AppColors.grayBorderSecondary,
|
|
1315
1965
|
padding: 16,
|
|
1316
|
-
marginTop: 12,
|
|
1317
1966
|
}}>
|
|
1318
1967
|
{renderSettingRow({
|
|
1319
1968
|
icon: <TrashIcon color={AppColors.errorColor} size={16}/>,
|
|
1320
|
-
label: '
|
|
1321
|
-
description: '
|
|
1969
|
+
label: t('settings.analytics.clearAnalyticsEvents'),
|
|
1970
|
+
description: t('settings.analytics.clearAnalyticsEventsDescription'),
|
|
1322
1971
|
isLast: true,
|
|
1323
1972
|
onPress: () => {
|
|
1324
1973
|
clearAnalyticsEvents();
|
|
1325
1974
|
setSelectedEvent(null);
|
|
1326
|
-
Alert.alert('
|
|
1975
|
+
Alert.alert(t('common.success'), t('settings.analytics.analyticsEventsCleared'));
|
|
1327
1976
|
},
|
|
1328
1977
|
right: (<View style={{
|
|
1329
|
-
paddingHorizontal:
|
|
1330
|
-
paddingVertical:
|
|
1331
|
-
borderRadius:
|
|
1978
|
+
paddingHorizontal: 12,
|
|
1979
|
+
paddingVertical: 6,
|
|
1980
|
+
borderRadius: 8,
|
|
1332
1981
|
backgroundColor: `${AppColors.errorColor}14`,
|
|
1333
1982
|
borderWidth: 1,
|
|
1334
1983
|
borderColor: `${AppColors.errorColor}33`,
|
|
@@ -1336,9 +1985,10 @@ const SettingsPanel = () => {
|
|
|
1336
1985
|
<Text style={{
|
|
1337
1986
|
fontFamily: AppFonts.interBold,
|
|
1338
1987
|
fontSize: 11,
|
|
1988
|
+
lineHeight: 14,
|
|
1339
1989
|
color: AppColors.errorColor,
|
|
1340
1990
|
}}>
|
|
1341
|
-
|
|
1991
|
+
{t('common.clear')}
|
|
1342
1992
|
</Text>
|
|
1343
1993
|
</View>),
|
|
1344
1994
|
})}
|
|
@@ -1346,22 +1996,22 @@ const SettingsPanel = () => {
|
|
|
1346
1996
|
</ScrollView>);
|
|
1347
1997
|
}
|
|
1348
1998
|
else if (settingsPage === 'redux') {
|
|
1349
|
-
title = '
|
|
1350
|
-
icon = <
|
|
1351
|
-
rightInfo =
|
|
1352
|
-
content = (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16 }}>
|
|
1999
|
+
title = t('settings.redux.title');
|
|
2000
|
+
icon = <ReduxIcon color={AppColors.white} size={16}/>;
|
|
2001
|
+
rightInfo = t('settings.redux.reducers', { count: Object.keys(reduxState || {}).length });
|
|
2002
|
+
content = (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16, gap: 12 }}>
|
|
1353
2003
|
<View style={{
|
|
1354
2004
|
backgroundColor: AppColors.primaryLight,
|
|
1355
2005
|
padding: 16,
|
|
1356
|
-
borderRadius:
|
|
2006
|
+
borderRadius: 14,
|
|
1357
2007
|
borderWidth: 1,
|
|
1358
2008
|
borderColor: AppColors.grayBorderSecondary,
|
|
1359
2009
|
gap: 4,
|
|
1360
2010
|
}}>
|
|
1361
2011
|
{renderSettingRow({
|
|
1362
|
-
icon: <
|
|
1363
|
-
label: '
|
|
1364
|
-
description: '
|
|
2012
|
+
icon: <ReduxIcon color={AppColors.purple} size={16}/>,
|
|
2013
|
+
label: t('settings.redux.autoRefresh'),
|
|
2014
|
+
description: t('settings.redux.autoRefreshDescription'),
|
|
1365
2015
|
onPress: () => setReduxAutoRefreshState(prev => !prev),
|
|
1366
2016
|
right: (<View style={{
|
|
1367
2017
|
width: 22,
|
|
@@ -1383,8 +2033,8 @@ const SettingsPanel = () => {
|
|
|
1383
2033
|
<View style={{ height: 1, backgroundColor: AppColors.dividerColor }}/>
|
|
1384
2034
|
{renderSettingRow({
|
|
1385
2035
|
icon: <LayersIcon color={AppColors.purple} size={16}/>,
|
|
1386
|
-
label: '
|
|
1387
|
-
description: '
|
|
2036
|
+
label: t('settings.redux.defaultJsonExpandDepth'),
|
|
2037
|
+
description: t('settings.redux.defaultJsonExpandDepthDescription'),
|
|
1388
2038
|
picker: {
|
|
1389
2039
|
options: [1, 2, 3, 5],
|
|
1390
2040
|
selectedValue: reduxExpandDepth,
|
|
@@ -1396,27 +2046,26 @@ const SettingsPanel = () => {
|
|
|
1396
2046
|
|
|
1397
2047
|
<View style={{
|
|
1398
2048
|
backgroundColor: AppColors.primaryLight,
|
|
1399
|
-
borderRadius:
|
|
2049
|
+
borderRadius: 14,
|
|
1400
2050
|
borderWidth: 1,
|
|
1401
2051
|
borderColor: AppColors.grayBorderSecondary,
|
|
1402
2052
|
padding: 16,
|
|
1403
|
-
marginTop: 12,
|
|
1404
2053
|
}}>
|
|
1405
2054
|
{renderSettingRow({
|
|
1406
2055
|
icon: <TrashIcon color={AppColors.errorColor} size={16}/>,
|
|
1407
|
-
label: '
|
|
2056
|
+
label: t('settings.redux.clearReduxState'),
|
|
1408
2057
|
description: reduxState
|
|
1409
|
-
? '
|
|
1410
|
-
: '
|
|
2058
|
+
? t('settings.redux.clearReduxStateDescription')
|
|
2059
|
+
: t('settings.redux.clearReduxStateEmpty'),
|
|
1411
2060
|
isLast: true,
|
|
1412
2061
|
onPress: () => {
|
|
1413
2062
|
setReduxState(null);
|
|
1414
|
-
Alert.alert('
|
|
2063
|
+
Alert.alert(t('common.success'), t('settings.redux.reduxStateCleared'));
|
|
1415
2064
|
},
|
|
1416
2065
|
right: (<View style={{
|
|
1417
|
-
paddingHorizontal:
|
|
1418
|
-
paddingVertical:
|
|
1419
|
-
borderRadius:
|
|
2066
|
+
paddingHorizontal: 12,
|
|
2067
|
+
paddingVertical: 6,
|
|
2068
|
+
borderRadius: 8,
|
|
1420
2069
|
backgroundColor: `${AppColors.errorColor}14`,
|
|
1421
2070
|
borderWidth: 1,
|
|
1422
2071
|
borderColor: `${AppColors.errorColor}33`,
|
|
@@ -1424,9 +2073,10 @@ const SettingsPanel = () => {
|
|
|
1424
2073
|
<Text style={{
|
|
1425
2074
|
fontFamily: AppFonts.interBold,
|
|
1426
2075
|
fontSize: 11,
|
|
2076
|
+
lineHeight: 14,
|
|
1427
2077
|
color: AppColors.errorColor,
|
|
1428
2078
|
}}>
|
|
1429
|
-
|
|
2079
|
+
{t('common.clear')}
|
|
1430
2080
|
</Text>
|
|
1431
2081
|
</View>),
|
|
1432
2082
|
})}
|
|
@@ -1434,33 +2084,35 @@ const SettingsPanel = () => {
|
|
|
1434
2084
|
</ScrollView>);
|
|
1435
2085
|
}
|
|
1436
2086
|
else if (settingsPage === 'crash') {
|
|
1437
|
-
title = '
|
|
2087
|
+
title = t('settings.crash.title');
|
|
1438
2088
|
icon = <CrashIcon color={AppColors.white} size={16}/>;
|
|
1439
2089
|
rightInfo = `Total: ${crashRecords?.length || 0}`;
|
|
1440
|
-
content = (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16 }}>
|
|
2090
|
+
content = (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16, gap: 12 }}>
|
|
1441
2091
|
<View style={{
|
|
1442
2092
|
backgroundColor: AppColors.primaryLight,
|
|
1443
2093
|
padding: 16,
|
|
1444
|
-
borderRadius:
|
|
2094
|
+
borderRadius: 14,
|
|
1445
2095
|
borderWidth: 1,
|
|
1446
2096
|
borderColor: AppColors.grayBorderSecondary,
|
|
1447
2097
|
gap: 4,
|
|
1448
2098
|
}}>
|
|
1449
2099
|
{renderSettingRow({
|
|
1450
2100
|
icon: <LayersIcon color={AppColors.purple} size={16}/>,
|
|
1451
|
-
label: '
|
|
1452
|
-
description: '
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
2101
|
+
label: t('settings.crash.maxCrashLogs'),
|
|
2102
|
+
description: t('settings.crash.maxCrashLogsDesc'),
|
|
2103
|
+
numericInput: {
|
|
2104
|
+
value: maxCrashLogs,
|
|
2105
|
+
onChange: setMaxCrashLogs,
|
|
2106
|
+
min: 5,
|
|
2107
|
+
max: 500,
|
|
2108
|
+
placeholder: 'Enter max crashes (5-500)',
|
|
1457
2109
|
},
|
|
1458
2110
|
})}
|
|
1459
2111
|
<View style={{ height: 1, backgroundColor: AppColors.dividerColor }}/>
|
|
1460
2112
|
{renderSettingRow({
|
|
1461
2113
|
icon: <ShieldAlertIcon color={AppColors.greenColor} size={16}/>,
|
|
1462
|
-
label: '
|
|
1463
|
-
description: '
|
|
2114
|
+
label: t('settings.crash.globalGuard'),
|
|
2115
|
+
description: t('settings.crash.globalGuardDesc'),
|
|
1464
2116
|
isLast: true,
|
|
1465
2117
|
right: (<View style={{
|
|
1466
2118
|
paddingHorizontal: 8,
|
|
@@ -1471,9 +2123,10 @@ const SettingsPanel = () => {
|
|
|
1471
2123
|
<Text style={{
|
|
1472
2124
|
fontFamily: AppFonts.interBold,
|
|
1473
2125
|
fontSize: 10,
|
|
2126
|
+
lineHeight: 13,
|
|
1474
2127
|
color: AppColors.greenColor,
|
|
1475
2128
|
}}>
|
|
1476
|
-
|
|
2129
|
+
{t('settings.protectedBadge')}
|
|
1477
2130
|
</Text>
|
|
1478
2131
|
</View>),
|
|
1479
2132
|
})}
|
|
@@ -1481,25 +2134,190 @@ const SettingsPanel = () => {
|
|
|
1481
2134
|
|
|
1482
2135
|
<View style={{
|
|
1483
2136
|
backgroundColor: AppColors.primaryLight,
|
|
1484
|
-
borderRadius:
|
|
2137
|
+
borderRadius: 14,
|
|
1485
2138
|
borderWidth: 1,
|
|
1486
2139
|
borderColor: AppColors.grayBorderSecondary,
|
|
1487
2140
|
padding: 16,
|
|
1488
|
-
marginTop: 12,
|
|
1489
2141
|
}}>
|
|
1490
2142
|
{renderSettingRow({
|
|
1491
2143
|
icon: <TrashIcon color={AppColors.errorColor} size={16}/>,
|
|
1492
|
-
label: '
|
|
1493
|
-
description:
|
|
2144
|
+
label: t('settings.crash.clearHistory'),
|
|
2145
|
+
description: t('settings.crash.clearHistoryDesc', { count: crashRecords?.length || 0 }),
|
|
1494
2146
|
isLast: true,
|
|
1495
2147
|
onPress: () => {
|
|
1496
2148
|
clearCrashRecords();
|
|
1497
|
-
Alert.alert('
|
|
2149
|
+
Alert.alert(t('common.success'), t('settings.crash.historyCleared'));
|
|
2150
|
+
},
|
|
2151
|
+
right: (<View style={{
|
|
2152
|
+
paddingHorizontal: 12,
|
|
2153
|
+
paddingVertical: 6,
|
|
2154
|
+
borderRadius: 8,
|
|
2155
|
+
backgroundColor: `${AppColors.errorColor}14`,
|
|
2156
|
+
borderWidth: 1,
|
|
2157
|
+
borderColor: `${AppColors.errorColor}33`,
|
|
2158
|
+
}}>
|
|
2159
|
+
<Text style={{
|
|
2160
|
+
fontFamily: AppFonts.interBold,
|
|
2161
|
+
fontSize: 11,
|
|
2162
|
+
lineHeight: 14,
|
|
2163
|
+
color: AppColors.errorColor,
|
|
2164
|
+
}}>
|
|
2165
|
+
{t('common.clear')}
|
|
2166
|
+
</Text>
|
|
2167
|
+
</View>),
|
|
2168
|
+
})}
|
|
2169
|
+
</View>
|
|
2170
|
+
</ScrollView>);
|
|
2171
|
+
}
|
|
2172
|
+
else if (settingsPage === 'bundle') {
|
|
2173
|
+
title = t('settings.bundle.title');
|
|
2174
|
+
icon = <PackageIcon color={AppColors.white} size={16}/>;
|
|
2175
|
+
rightInfo = 'Metro';
|
|
2176
|
+
content = (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16, gap: 12 }}>
|
|
2177
|
+
<View style={{
|
|
2178
|
+
backgroundColor: AppColors.primaryLight,
|
|
2179
|
+
padding: 16,
|
|
2180
|
+
borderRadius: 14,
|
|
2181
|
+
borderWidth: 1,
|
|
2182
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
2183
|
+
gap: 8,
|
|
2184
|
+
}}>
|
|
2185
|
+
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 10 }}>
|
|
2186
|
+
<View style={{
|
|
2187
|
+
width: 36,
|
|
2188
|
+
height: 36,
|
|
2189
|
+
borderRadius: 10,
|
|
2190
|
+
backgroundColor: AppColors.purpleShade50,
|
|
2191
|
+
alignItems: 'center',
|
|
2192
|
+
justifyContent: 'center',
|
|
2193
|
+
}}>
|
|
2194
|
+
<PackageIcon color={AppColors.purple} size={16}/>
|
|
2195
|
+
</View>
|
|
2196
|
+
<View style={{ flex: 1 }}>
|
|
2197
|
+
<Text style={{
|
|
2198
|
+
fontFamily: AppFonts.interBold,
|
|
2199
|
+
fontSize: 14,
|
|
2200
|
+
lineHeight: 18,
|
|
2201
|
+
color: AppColors.primaryBlack,
|
|
2202
|
+
}}>
|
|
2203
|
+
{t('settings.bundle.sourceBundler')}
|
|
2204
|
+
</Text>
|
|
2205
|
+
<Text style={{
|
|
2206
|
+
fontFamily: AppFonts.interRegular,
|
|
2207
|
+
fontSize: 11,
|
|
2208
|
+
lineHeight: 15,
|
|
2209
|
+
color: AppColors.grayText,
|
|
2210
|
+
marginTop: 1,
|
|
2211
|
+
}}>
|
|
2212
|
+
{t('settings.bundle.sourceBundlerDesc')}
|
|
2213
|
+
</Text>
|
|
2214
|
+
</View>
|
|
2215
|
+
</View>
|
|
2216
|
+
</View>
|
|
2217
|
+
|
|
2218
|
+
<View style={{
|
|
2219
|
+
backgroundColor: AppColors.primaryLight,
|
|
2220
|
+
borderRadius: 14,
|
|
2221
|
+
borderWidth: 1,
|
|
2222
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
2223
|
+
padding: 16,
|
|
2224
|
+
}}>
|
|
2225
|
+
{renderSettingRow({
|
|
2226
|
+
icon: <TrashIcon color={AppColors.errorColor} size={16}/>,
|
|
2227
|
+
label: t('settings.bundle.clearCache'),
|
|
2228
|
+
description: t('settings.bundle.clearCacheDesc'),
|
|
2229
|
+
isLast: true,
|
|
2230
|
+
onPress: () => {
|
|
2231
|
+
clearCachedBundleAnalysis();
|
|
2232
|
+
Alert.alert(t('common.success'), t('settings.bundle.cacheCleared'));
|
|
2233
|
+
},
|
|
2234
|
+
right: (<View style={{
|
|
2235
|
+
paddingHorizontal: 12,
|
|
2236
|
+
paddingVertical: 6,
|
|
2237
|
+
borderRadius: 8,
|
|
2238
|
+
backgroundColor: `${AppColors.errorColor}14`,
|
|
2239
|
+
borderWidth: 1,
|
|
2240
|
+
borderColor: `${AppColors.errorColor}33`,
|
|
2241
|
+
}}>
|
|
2242
|
+
<Text style={{
|
|
2243
|
+
fontFamily: AppFonts.interBold,
|
|
2244
|
+
fontSize: 11,
|
|
2245
|
+
lineHeight: 14,
|
|
2246
|
+
color: AppColors.errorColor,
|
|
2247
|
+
}}>
|
|
2248
|
+
{t('common.clear')}
|
|
2249
|
+
</Text>
|
|
2250
|
+
</View>),
|
|
2251
|
+
})}
|
|
2252
|
+
</View>
|
|
2253
|
+
</ScrollView>);
|
|
2254
|
+
}
|
|
2255
|
+
else if (settingsPage === 'performance') {
|
|
2256
|
+
title = t('settings.performance.title');
|
|
2257
|
+
icon = <PerformanceIcon color={AppColors.white} size={16}/>;
|
|
2258
|
+
rightInfo = '60 FPS Target';
|
|
2259
|
+
content = (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16, gap: 12 }}>
|
|
2260
|
+
<View style={{
|
|
2261
|
+
backgroundColor: AppColors.primaryLight,
|
|
2262
|
+
padding: 16,
|
|
2263
|
+
borderRadius: 14,
|
|
2264
|
+
borderWidth: 1,
|
|
2265
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
2266
|
+
gap: 8,
|
|
2267
|
+
}}>
|
|
2268
|
+
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 10 }}>
|
|
2269
|
+
<View style={{
|
|
2270
|
+
width: 36,
|
|
2271
|
+
height: 36,
|
|
2272
|
+
borderRadius: 10,
|
|
2273
|
+
backgroundColor: AppColors.purpleShade50,
|
|
2274
|
+
alignItems: 'center',
|
|
2275
|
+
justifyContent: 'center',
|
|
2276
|
+
}}>
|
|
2277
|
+
<PerformanceIcon color={AppColors.purple} size={16}/>
|
|
2278
|
+
</View>
|
|
2279
|
+
<View style={{ flex: 1 }}>
|
|
2280
|
+
<Text style={{
|
|
2281
|
+
fontFamily: AppFonts.interBold,
|
|
2282
|
+
fontSize: 14,
|
|
2283
|
+
lineHeight: 18,
|
|
2284
|
+
color: AppColors.primaryBlack,
|
|
2285
|
+
}}>
|
|
2286
|
+
{t('settings.performance.frameMeasurement')}
|
|
2287
|
+
</Text>
|
|
2288
|
+
<Text style={{
|
|
2289
|
+
fontFamily: AppFonts.interRegular,
|
|
2290
|
+
fontSize: 11,
|
|
2291
|
+
lineHeight: 15,
|
|
2292
|
+
color: AppColors.grayText,
|
|
2293
|
+
marginTop: 1,
|
|
2294
|
+
}}>
|
|
2295
|
+
{t('settings.performance.frameMeasurementDesc')}
|
|
2296
|
+
</Text>
|
|
2297
|
+
</View>
|
|
2298
|
+
</View>
|
|
2299
|
+
</View>
|
|
2300
|
+
|
|
2301
|
+
<View style={{
|
|
2302
|
+
backgroundColor: AppColors.primaryLight,
|
|
2303
|
+
borderRadius: 14,
|
|
2304
|
+
borderWidth: 1,
|
|
2305
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
2306
|
+
padding: 16,
|
|
2307
|
+
}}>
|
|
2308
|
+
{renderSettingRow({
|
|
2309
|
+
icon: <TrashIcon color={AppColors.errorColor} size={16}/>,
|
|
2310
|
+
label: t('settings.performance.clearEvents'),
|
|
2311
|
+
description: t('settings.performance.clearEventsDesc'),
|
|
2312
|
+
isLast: true,
|
|
2313
|
+
onPress: () => {
|
|
2314
|
+
clearPerformanceEvents();
|
|
2315
|
+
Alert.alert(t('common.success'), t('settings.performance.eventsCleared'));
|
|
1498
2316
|
},
|
|
1499
2317
|
right: (<View style={{
|
|
1500
|
-
paddingHorizontal:
|
|
1501
|
-
paddingVertical:
|
|
1502
|
-
borderRadius:
|
|
2318
|
+
paddingHorizontal: 12,
|
|
2319
|
+
paddingVertical: 6,
|
|
2320
|
+
borderRadius: 8,
|
|
1503
2321
|
backgroundColor: `${AppColors.errorColor}14`,
|
|
1504
2322
|
borderWidth: 1,
|
|
1505
2323
|
borderColor: `${AppColors.errorColor}33`,
|
|
@@ -1507,29 +2325,33 @@ const SettingsPanel = () => {
|
|
|
1507
2325
|
<Text style={{
|
|
1508
2326
|
fontFamily: AppFonts.interBold,
|
|
1509
2327
|
fontSize: 11,
|
|
2328
|
+
lineHeight: 14,
|
|
1510
2329
|
color: AppColors.errorColor,
|
|
1511
2330
|
}}>
|
|
1512
|
-
|
|
2331
|
+
{t('common.clear')}
|
|
1513
2332
|
</Text>
|
|
1514
2333
|
</View>),
|
|
1515
2334
|
})}
|
|
1516
2335
|
</View>
|
|
1517
2336
|
</ScrollView>);
|
|
1518
2337
|
}
|
|
1519
|
-
return (<View style={{
|
|
2338
|
+
return (<View style={{
|
|
2339
|
+
flex: 1,
|
|
2340
|
+
backgroundColor: AppColors.grayBackground,
|
|
2341
|
+
}}>
|
|
1520
2342
|
<LinearGradient colors={[AppColors.purple, AppColors.brandPurple]} start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }} style={styles.headerGradient}>
|
|
1521
2343
|
<View style={{ paddingTop: headerTopPadding, width: '100%' }}>
|
|
1522
2344
|
<View style={[styles.header, { paddingHorizontal: 16, gap: 12 }]}>
|
|
1523
|
-
|
|
2345
|
+
<TouchableScale accessible={true} accessibilityRole="button" accessibilityLabel={t('settings.back')} onPress={goBackToMain} hitSlop={12} style={{
|
|
1524
2346
|
padding: 8,
|
|
1525
2347
|
borderRadius: 10,
|
|
1526
2348
|
backgroundColor: `${AppColors.white}26`,
|
|
1527
2349
|
borderWidth: 1,
|
|
1528
2350
|
borderColor: `${AppColors.white}14`,
|
|
1529
2351
|
}}>
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
2352
|
+
<WhiteBackNavigation color={AppColors.white} size={16}/>
|
|
2353
|
+
</TouchableScale>
|
|
2354
|
+
{icon && (<View style={{
|
|
1533
2355
|
width: 30,
|
|
1534
2356
|
height: 30,
|
|
1535
2357
|
borderRadius: 8,
|
|
@@ -1537,18 +2359,19 @@ const SettingsPanel = () => {
|
|
|
1537
2359
|
alignItems: 'center',
|
|
1538
2360
|
justifyContent: 'center',
|
|
1539
2361
|
}}>
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
2362
|
+
{icon}
|
|
2363
|
+
</View>)}
|
|
2364
|
+
<View style={{ flex: 1 }}>
|
|
2365
|
+
<Text style={{
|
|
1544
2366
|
fontFamily: AppFonts.interBold,
|
|
1545
2367
|
fontSize: 17,
|
|
2368
|
+
lineHeight: 22,
|
|
1546
2369
|
color: AppColors.white,
|
|
1547
2370
|
}}>
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
2371
|
+
{title}
|
|
2372
|
+
</Text>
|
|
2373
|
+
</View>
|
|
2374
|
+
{rightInfo ? (<View style={{
|
|
1552
2375
|
backgroundColor: `${AppColors.white}26`,
|
|
1553
2376
|
paddingHorizontal: 8,
|
|
1554
2377
|
paddingVertical: 4,
|
|
@@ -1556,17 +2379,18 @@ const SettingsPanel = () => {
|
|
|
1556
2379
|
borderWidth: 1,
|
|
1557
2380
|
borderColor: `${AppColors.white}1A`,
|
|
1558
2381
|
}}>
|
|
1559
|
-
|
|
2382
|
+
<Text style={{
|
|
1560
2383
|
fontFamily: AppFonts.interBold,
|
|
1561
2384
|
fontSize: 11,
|
|
2385
|
+
lineHeight: 14,
|
|
1562
2386
|
color: AppColors.white,
|
|
1563
2387
|
}}>
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
2388
|
+
{rightInfo}
|
|
2389
|
+
</Text>
|
|
2390
|
+
</View>) : null}
|
|
2391
|
+
</View>
|
|
1567
2392
|
</View>
|
|
1568
|
-
</
|
|
1569
|
-
</LinearGradient>
|
|
2393
|
+
</LinearGradient>
|
|
1570
2394
|
{content}
|
|
1571
2395
|
</View>);
|
|
1572
2396
|
};
|