react-native-inapp-inspector 2.0.0 → 2.0.2
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 +10 -0
- package/android/.gradle/8.9/checksums/checksums.lock +0 -0
- package/android/.gradle/8.9/checksums/md5-checksums.bin +0 -0
- package/android/.gradle/8.9/checksums/sha1-checksums.bin +0 -0
- package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
- package/android/.gradle/8.9/executionHistory/executionHistory.lock +0 -0
- package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
- package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/8.9/gc.properties +0 -0
- package/android/.gradle/9.2.0/checksums/checksums.lock +0 -0
- package/android/.gradle/9.2.0/fileChanges/last-build.bin +0 -0
- package/android/.gradle/9.2.0/fileHashes/fileHashes.bin +0 -0
- package/android/.gradle/9.2.0/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/9.2.0/gc.properties +0 -0
- package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
- package/android/.gradle/vcs-1/gc.properties +0 -0
- package/android/build/reports/problems/problems-report.html +659 -0
- package/android/src/main/java/com/inappinspector/NetworkInspectorModule.kt +33 -24
- package/dist/commonjs/components/ConsoleLogCard.js +5 -5
- package/dist/commonjs/components/EndOfListFooter.js +1 -1
- package/dist/commonjs/components/Inspector/AnalyticsTab.js +19 -71
- package/dist/commonjs/components/Inspector/BundleTab.js +670 -188
- package/dist/commonjs/components/Inspector/ConsoleTab.js +109 -98
- package/dist/commonjs/components/Inspector/CrashTab.js +2 -1
- package/dist/commonjs/components/Inspector/InspectorHeader.js +102 -19
- package/dist/commonjs/components/Inspector/MainScreen.js +151 -17
- package/dist/commonjs/components/Inspector/NetworkTab.js +104 -20
- package/dist/commonjs/components/Inspector/SettingsPanel.js +1111 -1385
- package/dist/commonjs/components/Inspector/TabBar.js +3 -4
- package/dist/commonjs/components/Inspector/TelemetryConsentModal.d.ts +3 -0
- package/dist/commonjs/components/Inspector/TelemetryConsentModal.js +212 -0
- package/dist/commonjs/components/JsonViewer.js +9 -4
- package/dist/commonjs/components/LogCard.js +31 -1
- package/dist/commonjs/components/LogSyntaxHighlighter.d.ts +16 -0
- package/dist/commonjs/components/LogSyntaxHighlighter.js +130 -0
- package/dist/commonjs/components/NetworkIcons.d.ts +2 -0
- package/dist/commonjs/components/NetworkIcons.js +10 -1
- package/dist/commonjs/components/Slider.d.ts +13 -0
- package/dist/commonjs/components/Slider.js +261 -0
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/commonjs/customHooks/analyticsLogger.js +1 -1
- package/dist/commonjs/customHooks/crashHandler.js +1 -1
- package/dist/commonjs/helpers/index.d.ts +2 -0
- package/dist/commonjs/helpers/index.js +16 -0
- package/dist/commonjs/helpers/searchQueryParser.d.ts +6 -0
- package/dist/commonjs/helpers/searchQueryParser.js +236 -0
- package/dist/commonjs/helpers/settingsStore.js +13 -13
- package/dist/commonjs/helpers/telemetry.d.ts +99 -0
- package/dist/commonjs/helpers/telemetry.js +398 -0
- package/dist/commonjs/index.d.ts +2 -0
- package/dist/commonjs/index.js +30 -21
- package/dist/commonjs/native/NativeInspector.d.ts +5 -0
- package/dist/commonjs/native/NativeInspector.js +3 -2
- package/dist/commonjs/styles/index.js +35 -35
- package/dist/esm/components/ConsoleLogCard.js +5 -5
- package/dist/esm/components/EndOfListFooter.js +2 -2
- package/dist/esm/components/Inspector/AnalyticsTab.js +21 -73
- package/dist/esm/components/Inspector/BundleTab.js +670 -188
- package/dist/esm/components/Inspector/ConsoleTab.js +110 -99
- package/dist/esm/components/Inspector/CrashTab.js +2 -1
- package/dist/esm/components/Inspector/InspectorHeader.js +103 -20
- package/dist/esm/components/Inspector/MainScreen.js +119 -18
- package/dist/esm/components/Inspector/NetworkTab.js +105 -21
- package/dist/esm/components/Inspector/SettingsPanel.js +1114 -1388
- package/dist/esm/components/Inspector/TabBar.js +4 -5
- package/dist/esm/components/Inspector/TelemetryConsentModal.d.ts +3 -0
- package/dist/esm/components/Inspector/TelemetryConsentModal.js +175 -0
- package/dist/esm/components/JsonViewer.js +9 -4
- package/dist/esm/components/LogCard.js +32 -2
- package/dist/esm/components/LogSyntaxHighlighter.d.ts +16 -0
- package/dist/esm/components/LogSyntaxHighlighter.js +123 -0
- package/dist/esm/components/NetworkIcons.d.ts +2 -0
- package/dist/esm/components/NetworkIcons.js +7 -0
- package/dist/esm/components/Slider.d.ts +13 -0
- package/dist/esm/components/Slider.js +222 -0
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/customHooks/analyticsLogger.js +1 -1
- package/dist/esm/customHooks/crashHandler.js +1 -1
- package/dist/esm/helpers/index.d.ts +2 -0
- package/dist/esm/helpers/index.js +2 -0
- package/dist/esm/helpers/searchQueryParser.d.ts +6 -0
- package/dist/esm/helpers/searchQueryParser.js +233 -0
- package/dist/esm/helpers/settingsStore.js +13 -13
- package/dist/esm/helpers/telemetry.d.ts +99 -0
- package/dist/esm/helpers/telemetry.js +380 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +20 -21
- package/dist/esm/native/NativeInspector.d.ts +5 -0
- package/dist/esm/native/NativeInspector.js +3 -2
- package/dist/esm/styles/index.js +35 -35
- package/ios/{NetworkInspectorModule.m → NetworkInspectorModule.mm} +193 -97
- package/package.json +2 -2
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import React, { useMemo, useState, useEffect } from 'react';
|
|
2
|
-
import { Alert, Platform, ScrollView, StatusBar, Text, TextInput, View, } from 'react-native';
|
|
1
|
+
import React, { useMemo, useState, useEffect, useRef } from 'react';
|
|
2
|
+
import { Alert, Animated, Platform, ScrollView, StatusBar, StyleSheet, Text, TextInput, View, } from 'react-native';
|
|
3
3
|
import Svg, { Path } from 'react-native-svg';
|
|
4
|
-
import LinearGradient from 'react-native-linear-gradient';
|
|
5
4
|
import { animateNextLayout, useInspector } from './InspectorContext';
|
|
6
5
|
import TouchableScale from '../TouchableScale';
|
|
7
|
-
import
|
|
6
|
+
import Slider from '../Slider';
|
|
7
|
+
import { toggleGlobalTheme } from '../../styles';
|
|
8
8
|
import { AppColors } from '../../styles/AppColors';
|
|
9
9
|
import { AppFonts } from '../../styles/AppFonts';
|
|
10
|
-
import { LIB_VERSION } from '../../constants';
|
|
11
10
|
import { isPersistentStorageAvailable, calculateRamBasedLimits, } from '../../helpers/settingsStore';
|
|
12
11
|
import { clearNetworkLogs } from '../../customHooks/networkLogger';
|
|
13
12
|
import { clearConsoleLogs } from '../../customHooks/consoleLogger';
|
|
@@ -18,10 +17,14 @@ import { clearPerformanceEvents } from '../../customHooks/performanceTracker';
|
|
|
18
17
|
import { isReduxConnected } from '../../customHooks/reduxLogger';
|
|
19
18
|
import { isAnalyticsConnected } from '../../customHooks/analyticsLogger';
|
|
20
19
|
import { useTranslation } from '../../i18n';
|
|
21
|
-
import { SignalIcon, TerminalIcon, AnalyticsIcon, SettingsIcon, SunIcon, MoonIcon, ScreenIcon, MotionIcon, LayersIcon, EyeIcon, CheckIcon, TrashIcon,
|
|
20
|
+
import { SignalIcon, TerminalIcon, AnalyticsIcon, SettingsIcon, SunIcon, MoonIcon, ScreenIcon, MotionIcon, LayersIcon, EyeIcon, CheckIcon, TrashIcon, PackageIcon, ReduxIcon, PerformanceIcon, CrashIcon, ShieldAlertIcon, ForwardChevronIcon, ChevronDownIcon, } from '../NetworkIcons';
|
|
22
21
|
const SettingsPanel = () => {
|
|
23
22
|
const { t } = useTranslation();
|
|
24
23
|
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();
|
|
24
|
+
const [stagedHeight, setStagedHeight] = useState(modalHeightPercent);
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
setStagedHeight(modalHeightPercent);
|
|
27
|
+
}, [modalHeightPercent]);
|
|
25
28
|
const autoRamProfile = calculateRamBasedLimits(deviceFreeRamMb);
|
|
26
29
|
const isPersistent = isPersistentStorageAvailable();
|
|
27
30
|
// Safe Area & Status Bar Padding for All Device Form Factors
|
|
@@ -118,638 +121,638 @@ const SettingsPanel = () => {
|
|
|
118
121
|
});
|
|
119
122
|
Alert.alert(t('settings.settingsSaved'), t('settings.settingsSavedDesc'));
|
|
120
123
|
};
|
|
121
|
-
|
|
124
|
+
const [isDefaultTabDropdownOpen, setIsDefaultTabDropdownOpen] = useState(false);
|
|
125
|
+
const goBackToMain = () => {
|
|
126
|
+
animateNextLayout();
|
|
127
|
+
setSettingsPage('main');
|
|
128
|
+
};
|
|
129
|
+
// Helper: settings row with icon + label + optional description
|
|
130
|
+
const renderSettingRow = (opts) => {
|
|
122
131
|
return (<View style={{
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
{/* Modern Floating Gradient Header */}
|
|
127
|
-
<LinearGradient colors={[AppColors.purple, AppColors.brandPurple]} start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }} style={styles.headerGradient}>
|
|
128
|
-
<View style={{ paddingTop: headerTopPadding, width: '100%' }}>
|
|
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={() => {
|
|
134
|
-
animateNextLayout();
|
|
135
|
-
setSettingsPage(null);
|
|
136
|
-
switchActiveTab('apis');
|
|
137
|
-
}} hitSlop={12} style={{
|
|
138
|
-
padding: 8,
|
|
139
|
-
borderRadius: 10,
|
|
140
|
-
backgroundColor: `${AppColors.white}26`,
|
|
141
|
-
borderWidth: 1,
|
|
142
|
-
borderColor: `${AppColors.white}18`,
|
|
132
|
+
paddingVertical: 12,
|
|
133
|
+
borderBottomWidth: opts.isLast ? 0 : 1,
|
|
134
|
+
borderBottomColor: AppColors.dividerColor,
|
|
143
135
|
}}>
|
|
144
|
-
|
|
145
|
-
</TouchableScale>
|
|
146
|
-
|
|
147
|
-
<View style={{ flex: 1 }}>
|
|
148
|
-
<View style={{
|
|
136
|
+
<TouchableScale disabled={!opts.onPress} onPress={opts.onPress} style={{
|
|
149
137
|
flexDirection: 'row',
|
|
150
138
|
alignItems: 'center',
|
|
151
|
-
gap:
|
|
152
|
-
}}>
|
|
153
|
-
<Text style={{
|
|
154
|
-
fontFamily: AppFonts.interBold,
|
|
155
|
-
fontSize: 17,
|
|
156
|
-
color: AppColors.white,
|
|
157
|
-
letterSpacing: -0.3,
|
|
158
|
-
lineHeight: 22,
|
|
159
|
-
}}>
|
|
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={{
|
|
179
|
-
fontFamily: AppFonts.interRegular,
|
|
180
|
-
fontSize: 11,
|
|
181
|
-
color: `${AppColors.white}CC`,
|
|
182
|
-
marginTop: 2,
|
|
183
|
-
lineHeight: 15,
|
|
139
|
+
gap: 12,
|
|
184
140
|
}}>
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
backgroundColor: `${AppColors.white}22`,
|
|
191
|
-
paddingHorizontal: 8,
|
|
192
|
-
paddingVertical: 4,
|
|
193
|
-
borderRadius: 8,
|
|
141
|
+
<View style={{
|
|
142
|
+
width: 36,
|
|
143
|
+
height: 36,
|
|
144
|
+
borderRadius: 10,
|
|
145
|
+
backgroundColor: AppColors.purpleShade50,
|
|
194
146
|
borderWidth: 1,
|
|
195
|
-
borderColor: `${AppColors.
|
|
147
|
+
borderColor: `${AppColors.purple}2E`,
|
|
148
|
+
alignItems: 'center',
|
|
149
|
+
justifyContent: 'center',
|
|
196
150
|
}}>
|
|
197
|
-
|
|
151
|
+
{opts.icon}
|
|
152
|
+
</View>
|
|
153
|
+
<View style={{ flex: 1 }}>
|
|
154
|
+
<Text style={{
|
|
198
155
|
fontFamily: AppFonts.interBold,
|
|
199
|
-
fontSize:
|
|
200
|
-
|
|
201
|
-
|
|
156
|
+
fontSize: 14,
|
|
157
|
+
lineHeight: 18,
|
|
158
|
+
color: AppColors.primaryBlack,
|
|
202
159
|
}}>
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
160
|
+
{opts.label}
|
|
161
|
+
</Text>
|
|
162
|
+
{opts.description ? (<Text style={{
|
|
163
|
+
fontFamily: AppFonts.interRegular,
|
|
164
|
+
fontSize: 11,
|
|
165
|
+
lineHeight: 15,
|
|
166
|
+
color: AppColors.grayText,
|
|
167
|
+
marginTop: 1,
|
|
168
|
+
}}>
|
|
169
|
+
{opts.description}
|
|
170
|
+
</Text>) : null}
|
|
207
171
|
</View>
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
172
|
+
{opts.right || null}
|
|
173
|
+
</TouchableScale>
|
|
174
|
+
{opts.numericInput && (<View style={{ marginTop: 10, gap: 6 }}>
|
|
175
|
+
<View style={{
|
|
176
|
+
flexDirection: 'row',
|
|
177
|
+
alignItems: 'center',
|
|
178
|
+
backgroundColor: AppColors.grayBackground,
|
|
179
|
+
borderRadius: 8,
|
|
180
|
+
borderWidth: 1,
|
|
181
|
+
borderColor: AppColors.dividerColor,
|
|
182
|
+
paddingHorizontal: 12,
|
|
183
|
+
paddingVertical: 4,
|
|
184
|
+
}}>
|
|
185
|
+
<TextInput style={{
|
|
186
|
+
flex: 1,
|
|
187
|
+
fontFamily: AppFonts.interMedium,
|
|
188
|
+
fontSize: 14,
|
|
189
|
+
lineHeight: 18,
|
|
190
|
+
color: AppColors.primaryBlack,
|
|
191
|
+
paddingVertical: 6,
|
|
192
|
+
}} value={String(opts.numericInput.value || '')} onChangeText={text => {
|
|
193
|
+
const num = parseInt(text.replace(/[^0-9]/g, ''), 10);
|
|
194
|
+
if (!isNaN(num)) {
|
|
195
|
+
const clamped = Math.max(opts.numericInput?.min ?? 1, Math.min(opts.numericInput?.max ?? 10000, num));
|
|
196
|
+
opts.numericInput?.onChange(clamped);
|
|
197
|
+
}
|
|
198
|
+
}} keyboardType={opts.numericInput.keyboardType ?? 'number-pad'} placeholder={opts.numericInput.placeholder} placeholderTextColor={AppColors.grayTextWeak} maxLength={6} selectTextOnFocus/>
|
|
199
|
+
<Text style={{
|
|
200
|
+
fontFamily: AppFonts.interBold,
|
|
201
|
+
fontSize: 11,
|
|
202
|
+
color: AppColors.purple,
|
|
203
|
+
marginLeft: 6,
|
|
204
|
+
}}>
|
|
205
|
+
MAX
|
|
206
|
+
</Text>
|
|
207
|
+
</View>
|
|
208
|
+
{opts.numericInput.min !== undefined || opts.numericInput.max !== undefined ? (<Text style={{
|
|
209
|
+
fontFamily: AppFonts.interRegular,
|
|
210
|
+
fontSize: 10,
|
|
211
|
+
lineHeight: 13,
|
|
212
|
+
color: AppColors.grayTextWeak,
|
|
213
|
+
}}>
|
|
214
|
+
Range: {opts.numericInput.min ?? 1} - {opts.numericInput.max ?? '∞'}
|
|
215
|
+
</Text>) : null}
|
|
216
|
+
</View>)}
|
|
217
|
+
{opts.picker && (<View style={{
|
|
218
|
+
flexDirection: 'row',
|
|
219
|
+
backgroundColor: AppColors.grayBackground,
|
|
220
|
+
borderRadius: 8,
|
|
221
|
+
padding: 2.5,
|
|
222
|
+
marginTop: 10,
|
|
223
|
+
borderWidth: 1,
|
|
224
|
+
borderColor: AppColors.dividerColor,
|
|
225
|
+
}}>
|
|
226
|
+
{opts.picker.options.map(opt => {
|
|
227
|
+
const isActive = opts.picker.selectedValue === opt;
|
|
228
|
+
return (<TouchableScale key={String(opt)} onPress={() => opts.picker.onSelect(opt)} style={{
|
|
229
|
+
flex: 1,
|
|
230
|
+
paddingVertical: 6,
|
|
231
|
+
alignItems: 'center',
|
|
232
|
+
borderRadius: 6,
|
|
233
|
+
backgroundColor: isActive
|
|
234
|
+
? AppColors.purple
|
|
235
|
+
: 'transparent',
|
|
236
|
+
}}>
|
|
237
|
+
<Text style={{
|
|
238
|
+
fontFamily: AppFonts.interBold,
|
|
239
|
+
fontSize: 11,
|
|
240
|
+
lineHeight: 14,
|
|
241
|
+
color: isActive ? AppColors.white : AppColors.grayText,
|
|
242
|
+
}}>
|
|
243
|
+
{opts.picker.formatLabel
|
|
244
|
+
? opts.picker.formatLabel(opt)
|
|
245
|
+
: opt}
|
|
246
|
+
</Text>
|
|
247
|
+
</TouchableScale>);
|
|
248
|
+
})}
|
|
249
|
+
</View>)}
|
|
250
|
+
</View>);
|
|
251
|
+
};
|
|
252
|
+
const renderMainSettingsContent = () => (<View style={{
|
|
253
|
+
flex: 1,
|
|
254
|
+
backgroundColor: AppColors.grayBackground,
|
|
255
|
+
}}>
|
|
256
|
+
<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16, paddingBottom: 100, gap: 14 }} showsVerticalScrollIndicator={false}>
|
|
211
257
|
{/* Segmented Top Navigation Sub-Tabs */}
|
|
212
258
|
<View style={{
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
259
|
+
flexDirection: 'row',
|
|
260
|
+
backgroundColor: AppColors.primaryLight,
|
|
261
|
+
borderRadius: 12,
|
|
262
|
+
padding: 4,
|
|
263
|
+
borderWidth: 1,
|
|
264
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
265
|
+
shadowColor: AppColors.black,
|
|
266
|
+
shadowOpacity: 0.04,
|
|
267
|
+
shadowRadius: 4,
|
|
268
|
+
shadowOffset: { width: 0, height: 2 },
|
|
269
|
+
}}>
|
|
224
270
|
<TouchableScale accessible={true} accessibilityRole="tab" accessibilityLabel={t('settings.modulesAndTools')} accessibilityState={{ selected: settingsActiveSubTab === 'module' }} onPress={() => {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
271
|
+
animateNextLayout();
|
|
272
|
+
setSettingsActiveSubTab('module');
|
|
273
|
+
}} style={{
|
|
274
|
+
flex: 1,
|
|
275
|
+
paddingVertical: 9,
|
|
276
|
+
flexDirection: 'row',
|
|
277
|
+
alignItems: 'center',
|
|
278
|
+
justifyContent: 'center',
|
|
279
|
+
gap: 6,
|
|
280
|
+
borderRadius: 9,
|
|
281
|
+
backgroundColor: settingsActiveSubTab === 'module'
|
|
282
|
+
? AppColors.purple
|
|
283
|
+
: 'transparent',
|
|
284
|
+
}}>
|
|
239
285
|
<LayersIcon color={settingsActiveSubTab === 'module'
|
|
240
|
-
|
|
241
|
-
|
|
286
|
+
? AppColors.white
|
|
287
|
+
: AppColors.grayText} size={13}/>
|
|
242
288
|
<Text style={{
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
289
|
+
fontFamily: AppFonts.interBold,
|
|
290
|
+
fontSize: 12.5,
|
|
291
|
+
lineHeight: 16,
|
|
292
|
+
color: settingsActiveSubTab === 'module'
|
|
293
|
+
? AppColors.white
|
|
294
|
+
: AppColors.grayText,
|
|
295
|
+
}}>
|
|
250
296
|
{t('settings.modulesAndTools')}
|
|
251
297
|
</Text>
|
|
252
298
|
</TouchableScale>
|
|
253
299
|
|
|
254
300
|
<TouchableScale accessible={true} accessibilityRole="tab" accessibilityLabel={t('settings.uiPreferences')} accessibilityState={{ selected: settingsActiveSubTab === 'ui' }} onPress={() => {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
301
|
+
animateNextLayout();
|
|
302
|
+
setSettingsActiveSubTab('ui');
|
|
303
|
+
}} style={{
|
|
304
|
+
flex: 1,
|
|
305
|
+
paddingVertical: 9,
|
|
306
|
+
flexDirection: 'row',
|
|
307
|
+
alignItems: 'center',
|
|
308
|
+
justifyContent: 'center',
|
|
309
|
+
gap: 6,
|
|
310
|
+
borderRadius: 9,
|
|
311
|
+
backgroundColor: settingsActiveSubTab === 'ui'
|
|
312
|
+
? AppColors.purple
|
|
313
|
+
: 'transparent',
|
|
314
|
+
}}>
|
|
269
315
|
<ScreenIcon color={settingsActiveSubTab === 'ui'
|
|
270
|
-
|
|
271
|
-
|
|
316
|
+
? AppColors.white
|
|
317
|
+
: AppColors.grayText} size={13}/>
|
|
272
318
|
<Text style={{
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
319
|
+
fontFamily: AppFonts.interBold,
|
|
320
|
+
fontSize: 12.5,
|
|
321
|
+
lineHeight: 16,
|
|
322
|
+
color: settingsActiveSubTab === 'ui'
|
|
323
|
+
? AppColors.white
|
|
324
|
+
: AppColors.grayText,
|
|
325
|
+
}}>
|
|
280
326
|
{t('settings.uiPreferences')}
|
|
281
327
|
</Text>
|
|
282
328
|
</TouchableScale>
|
|
283
329
|
</View>
|
|
284
330
|
|
|
285
331
|
{settingsActiveSubTab === 'module' ? (<View style={{ gap: 12 }}>
|
|
286
|
-
{/*
|
|
287
|
-
<View style={{
|
|
288
|
-
backgroundColor: `${AppColors.purple}0A`,
|
|
289
|
-
borderRadius: 12,
|
|
290
|
-
padding: 12,
|
|
291
|
-
borderWidth: 1,
|
|
292
|
-
borderColor: `${AppColors.purple}20`,
|
|
293
|
-
flexDirection: 'row',
|
|
294
|
-
alignItems: 'center',
|
|
295
|
-
gap: 10,
|
|
296
|
-
}}>
|
|
297
|
-
<View style={{
|
|
298
|
-
width: 32,
|
|
299
|
-
height: 32,
|
|
300
|
-
borderRadius: 8,
|
|
301
|
-
backgroundColor: `${AppColors.purple}14`,
|
|
302
|
-
alignItems: 'center',
|
|
303
|
-
justifyContent: 'center',
|
|
304
|
-
}}>
|
|
305
|
-
<SignalIcon color={AppColors.purple} size={15}/>
|
|
306
|
-
</View>
|
|
307
|
-
<View style={{ flex: 1 }}>
|
|
308
|
-
<Text style={{
|
|
309
|
-
fontFamily: AppFonts.interBold,
|
|
310
|
-
fontSize: 12,
|
|
311
|
-
color: AppColors.primaryBlack,
|
|
312
|
-
lineHeight: 16,
|
|
313
|
-
}}>
|
|
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>
|
|
326
|
-
</View>
|
|
327
|
-
|
|
328
|
-
{/* Enhanced Individual Module Cards with Decorative Checkboxes */}
|
|
332
|
+
{/* Individual Module Cards with Left Checkboxes */}
|
|
329
333
|
<View style={{ gap: 10 }}>
|
|
330
334
|
{allModules.map(moduleItem => {
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
{/* Top Row: Icon
|
|
335
|
+
const isReduxAvail = isReduxConnected();
|
|
336
|
+
const isAnalyticsAvail = isAnalyticsConnected();
|
|
337
|
+
const isUnavailable = (moduleItem.key === 'redux' && !isReduxAvail) ||
|
|
338
|
+
(moduleItem.key === 'analytics' && !isAnalyticsAvail);
|
|
339
|
+
const isLocked = moduleItem.key === 'apis' || isUnavailable;
|
|
340
|
+
const isChecked = moduleItem.key === 'apis' ||
|
|
341
|
+
(Boolean(stagedTabVisibility?.[moduleItem.key]) &&
|
|
342
|
+
!isUnavailable);
|
|
343
|
+
const liveStats = moduleItem.key === 'apis'
|
|
344
|
+
? `${logs.length} requests • Limit: ${maxNetworkLogs}`
|
|
345
|
+
: moduleItem.key === 'logs'
|
|
346
|
+
? `${consoleLogs.length} logs • Limit: ${maxConsoleLogs}`
|
|
347
|
+
: moduleItem.key === 'performance'
|
|
348
|
+
? '60 FPS Target • Memory Telemetry'
|
|
349
|
+
: moduleItem.key === 'bundle'
|
|
350
|
+
? 'Metro Packager • Dependency Map'
|
|
351
|
+
: moduleItem.key === 'crash'
|
|
352
|
+
? `${crashRecords?.length || 0} crashes recorded • Crash Guard`
|
|
353
|
+
: moduleItem.key === 'analytics'
|
|
354
|
+
? `${analyticsEvents.length} events logged`
|
|
355
|
+
: moduleItem.key === 'redux'
|
|
356
|
+
? `${Object.keys(reduxState || {}).length} slices • Depth: ${reduxExpandDepth}`
|
|
357
|
+
: '';
|
|
358
|
+
return (<View key={moduleItem.key} style={{
|
|
359
|
+
backgroundColor: AppColors.primaryLight,
|
|
360
|
+
borderRadius: 14,
|
|
361
|
+
borderWidth: 1.5,
|
|
362
|
+
borderColor: isChecked
|
|
363
|
+
? `${AppColors.purple}38`
|
|
364
|
+
: AppColors.grayBorderSecondary,
|
|
365
|
+
padding: 14,
|
|
366
|
+
gap: 10,
|
|
367
|
+
shadowColor: AppColors.black,
|
|
368
|
+
shadowOpacity: isChecked ? 0.04 : 0.02,
|
|
369
|
+
shadowRadius: 5,
|
|
370
|
+
shadowOffset: { width: 0, height: 2 },
|
|
371
|
+
}}>
|
|
372
|
+
{/* Top Row: [Checkbox] -> [Icon Tile] -> [Title & Subtitle] */}
|
|
369
373
|
<View style={{
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
}
|
|
375
|
-
{
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
borderColor: isLocked
|
|
397
|
-
? AppColors.dividerColor
|
|
398
|
-
: isChecked
|
|
399
|
-
? `${AppColors.purple}33`
|
|
400
|
-
: AppColors.grayBorderSecondary,
|
|
401
|
-
alignItems: 'center',
|
|
402
|
-
justifyContent: 'center',
|
|
403
|
-
marginTop: 1,
|
|
404
|
-
}}>
|
|
405
|
-
{moduleItem.icon === 'apis' && (<SignalIcon color={isChecked
|
|
374
|
+
flexDirection: 'row',
|
|
375
|
+
alignItems: 'flex-start',
|
|
376
|
+
gap: 10,
|
|
377
|
+
}}>
|
|
378
|
+
{/* 1. Checkbox on the Left */}
|
|
379
|
+
<TouchableScale accessible={true} accessibilityRole="checkbox" accessibilityLabel={`Select ${moduleItem.label}`} accessibilityState={{
|
|
380
|
+
checked: isChecked,
|
|
381
|
+
disabled: isLocked,
|
|
382
|
+
}} disabled={isLocked} onPress={() => {
|
|
383
|
+
if (isLocked)
|
|
384
|
+
return;
|
|
385
|
+
setStagedTabVisibility(prev => ({
|
|
386
|
+
...prev,
|
|
387
|
+
[moduleItem.key]: !prev[moduleItem.key],
|
|
388
|
+
}));
|
|
389
|
+
}} hitSlop={8} style={{
|
|
390
|
+
width: 22,
|
|
391
|
+
height: 22,
|
|
392
|
+
borderRadius: 6,
|
|
393
|
+
borderWidth: isChecked ? 0 : 1.8,
|
|
394
|
+
borderColor: isLocked
|
|
395
|
+
? AppColors.dividerColor
|
|
396
|
+
: AppColors.grayBorderSecondary,
|
|
397
|
+
backgroundColor: moduleItem.key === 'apis'
|
|
398
|
+
? `${AppColors.blue500}22`
|
|
399
|
+
: isChecked
|
|
406
400
|
? AppColors.purple
|
|
407
|
-
: AppColors.
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
401
|
+
: AppColors.grayBackground,
|
|
402
|
+
alignItems: 'center',
|
|
403
|
+
justifyContent: 'center',
|
|
404
|
+
marginTop: 7,
|
|
405
|
+
shadowColor: isChecked
|
|
406
|
+
? AppColors.purple
|
|
407
|
+
: 'transparent',
|
|
408
|
+
shadowOpacity: isChecked ? 0.25 : 0,
|
|
409
|
+
shadowRadius: 2,
|
|
410
|
+
elevation: isChecked ? 2 : 0,
|
|
411
|
+
}}>
|
|
412
|
+
{moduleItem.key === 'apis' ? (<CheckIcon size={12} color={AppColors.blue500}/>) : isChecked ? (<CheckIcon size={12} color={AppColors.white}/>) : isLocked ? (<Svg width={10} height={10} viewBox="0 0 24 24" fill="none">
|
|
413
|
+
<Path d="M7 10V7a5 5 0 0 1 10 0v3" stroke={AppColors.grayText} strokeWidth="2.2" strokeLinecap="round"/>
|
|
414
|
+
<Path d="M5 10h14v9a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1z" fill={AppColors.grayText}/>
|
|
415
|
+
</Svg>) : null}
|
|
416
|
+
</TouchableScale>
|
|
417
|
+
|
|
418
|
+
{/* 2. Middle Tap Zone: Icon + Title & Desc */}
|
|
419
|
+
<TouchableScale accessible={true} accessibilityRole="button" accessibilityLabel={`${moduleItem.label} settings`} disabled={isUnavailable} onPress={() => {
|
|
420
|
+
animateNextLayout();
|
|
421
|
+
setSettingsPage(moduleItem.key);
|
|
422
|
+
}} style={{
|
|
423
|
+
flex: 1,
|
|
424
|
+
flexDirection: 'row',
|
|
425
|
+
alignItems: 'flex-start',
|
|
426
|
+
gap: 10,
|
|
427
|
+
}}>
|
|
428
|
+
{/* Icon Tile */}
|
|
429
|
+
<View style={{
|
|
430
|
+
width: 36,
|
|
431
|
+
height: 36,
|
|
432
|
+
borderRadius: 10,
|
|
433
|
+
backgroundColor: isLocked
|
|
434
|
+
? `${AppColors.grayBorderSecondary}4D`
|
|
435
|
+
: isChecked
|
|
436
|
+
? `${AppColors.purple}14`
|
|
437
|
+
: AppColors.grayBackground,
|
|
438
|
+
borderWidth: 1,
|
|
439
|
+
borderColor: isLocked
|
|
440
|
+
? AppColors.dividerColor
|
|
441
|
+
: isChecked
|
|
442
|
+
? `${AppColors.purple}33`
|
|
443
|
+
: AppColors.grayBorderSecondary,
|
|
444
|
+
alignItems: 'center',
|
|
445
|
+
justifyContent: 'center',
|
|
446
|
+
marginTop: 1,
|
|
447
|
+
}}>
|
|
448
|
+
{moduleItem.icon === 'apis' && (<SignalIcon color={isChecked
|
|
449
|
+
? AppColors.purple
|
|
450
|
+
: AppColors.grayTextWeak} size={16}/>)}
|
|
451
|
+
{moduleItem.icon === 'logs' && (<TerminalIcon color={isChecked
|
|
452
|
+
? AppColors.purple
|
|
453
|
+
: AppColors.grayTextWeak} size={16}/>)}
|
|
411
454
|
{moduleItem.icon === 'performance' && (<PerformanceIcon color={isChecked
|
|
412
|
-
|
|
413
|
-
|
|
455
|
+
? AppColors.purple
|
|
456
|
+
: AppColors.grayTextWeak} size={16}/>)}
|
|
414
457
|
{moduleItem.icon === 'bundle' && (<PackageIcon color={isChecked
|
|
415
|
-
|
|
416
|
-
|
|
458
|
+
? AppColors.purple
|
|
459
|
+
: AppColors.grayTextWeak} size={16}/>)}
|
|
417
460
|
{moduleItem.icon === 'crash' && (<CrashIcon color={isChecked
|
|
418
|
-
|
|
419
|
-
|
|
461
|
+
? AppColors.purple
|
|
462
|
+
: AppColors.grayTextWeak} size={16}/>)}
|
|
420
463
|
{moduleItem.icon === 'analytics' && (<AnalyticsIcon color={isChecked
|
|
421
|
-
|
|
422
|
-
|
|
464
|
+
? AppColors.purple
|
|
465
|
+
: AppColors.grayTextWeak} size={16}/>)}
|
|
423
466
|
{moduleItem.icon === 'redux' && (<ReduxIcon color={isChecked
|
|
424
|
-
|
|
425
|
-
|
|
467
|
+
? AppColors.purple
|
|
468
|
+
: AppColors.grayTextWeak} size={16}/>)}
|
|
426
469
|
</View>
|
|
427
470
|
|
|
428
471
|
{/* Titles & Status Pill */}
|
|
429
472
|
<View style={{ flex: 1, gap: 2 }}>
|
|
430
473
|
<View style={{
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
474
|
+
flexDirection: 'row',
|
|
475
|
+
alignItems: 'center',
|
|
476
|
+
gap: 6,
|
|
477
|
+
flexWrap: 'wrap',
|
|
478
|
+
}}>
|
|
436
479
|
<Text style={{
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
480
|
+
fontFamily: AppFonts.interBold,
|
|
481
|
+
fontSize: 14,
|
|
482
|
+
lineHeight: 18,
|
|
483
|
+
color: isLocked
|
|
484
|
+
? AppColors.grayText
|
|
485
|
+
: AppColors.primaryBlack,
|
|
486
|
+
}}>
|
|
444
487
|
{moduleItem.label}
|
|
445
488
|
</Text>
|
|
446
489
|
|
|
447
490
|
{/* Default Startup Tab Badge */}
|
|
448
491
|
{moduleItem.key === defaultTab &&
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
492
|
+
!isUnavailable && (<View style={{
|
|
493
|
+
flexDirection: 'row',
|
|
494
|
+
alignItems: 'center',
|
|
495
|
+
backgroundColor: `${AppColors.purple}14`,
|
|
496
|
+
borderRadius: 12,
|
|
497
|
+
paddingHorizontal: 5,
|
|
498
|
+
paddingVertical: 1.5,
|
|
499
|
+
borderWidth: 1,
|
|
500
|
+
borderColor: `${AppColors.purple}2E`,
|
|
501
|
+
gap: 3,
|
|
502
|
+
}}>
|
|
460
503
|
<View style={{
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
504
|
+
width: 4,
|
|
505
|
+
height: 4,
|
|
506
|
+
borderRadius: 2,
|
|
507
|
+
backgroundColor: AppColors.purple,
|
|
508
|
+
}}/>
|
|
466
509
|
<Text style={{
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
510
|
+
fontFamily: AppFonts.interBold,
|
|
511
|
+
fontSize: 8,
|
|
512
|
+
lineHeight: 11,
|
|
513
|
+
color: AppColors.purple,
|
|
514
|
+
letterSpacing: 0.4,
|
|
515
|
+
}}>
|
|
473
516
|
{t('settings.defaultBadge')}
|
|
474
517
|
</Text>
|
|
475
518
|
</View>)}
|
|
476
519
|
|
|
477
520
|
{/* Status Pill */}
|
|
478
521
|
{moduleItem.key === 'apis' ? (<View style={{
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
522
|
+
backgroundColor: `${AppColors.blue500}14`,
|
|
523
|
+
borderRadius: 4,
|
|
524
|
+
paddingHorizontal: 5,
|
|
525
|
+
paddingVertical: 1.5,
|
|
526
|
+
borderWidth: 1,
|
|
527
|
+
borderColor: `${AppColors.blue500}33`,
|
|
528
|
+
}}>
|
|
486
529
|
<Text style={{
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
530
|
+
fontFamily: AppFonts.interBold,
|
|
531
|
+
fontSize: 8,
|
|
532
|
+
lineHeight: 11,
|
|
533
|
+
color: AppColors.blue500,
|
|
534
|
+
letterSpacing: 0.3,
|
|
535
|
+
}}>
|
|
493
536
|
{t('settings.coreBadge')}
|
|
494
537
|
</Text>
|
|
495
538
|
</View>) : isUnavailable ? (<View style={{
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
539
|
+
backgroundColor: `${AppColors.amber500}18`,
|
|
540
|
+
borderRadius: 4,
|
|
541
|
+
paddingHorizontal: 5,
|
|
542
|
+
paddingVertical: 1.5,
|
|
543
|
+
borderWidth: 1,
|
|
544
|
+
borderColor: `${AppColors.amber500}35`,
|
|
545
|
+
}}>
|
|
503
546
|
<Text style={{
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
547
|
+
fontFamily: AppFonts.interBold,
|
|
548
|
+
fontSize: 8,
|
|
549
|
+
lineHeight: 11,
|
|
550
|
+
color: AppColors.amber700,
|
|
551
|
+
letterSpacing: 0.3,
|
|
552
|
+
}}>
|
|
510
553
|
{moduleItem.key === 'redux'
|
|
511
|
-
|
|
512
|
-
|
|
554
|
+
? t('settings.notConnectedBadge')
|
|
555
|
+
: t('settings.notDetectedBadge')}
|
|
513
556
|
</Text>
|
|
514
557
|
</View>) : isChecked ? (<View style={{
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
558
|
+
backgroundColor: `${AppColors.liveGreen}18`,
|
|
559
|
+
borderRadius: 4,
|
|
560
|
+
paddingHorizontal: 5,
|
|
561
|
+
paddingVertical: 1.5,
|
|
562
|
+
borderWidth: 1,
|
|
563
|
+
borderColor: `${AppColors.liveGreen}38`,
|
|
564
|
+
}}>
|
|
522
565
|
<Text style={{
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
566
|
+
fontFamily: AppFonts.interBold,
|
|
567
|
+
fontSize: 8,
|
|
568
|
+
lineHeight: 11,
|
|
569
|
+
color: AppColors.green700,
|
|
570
|
+
letterSpacing: 0.3,
|
|
571
|
+
}}>
|
|
529
572
|
{t('settings.activeBadge')}
|
|
530
573
|
</Text>
|
|
531
574
|
</View>) : (<View style={{
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
575
|
+
backgroundColor: `${AppColors.grayTextWeak}18`,
|
|
576
|
+
borderRadius: 4,
|
|
577
|
+
paddingHorizontal: 5,
|
|
578
|
+
paddingVertical: 1.5,
|
|
579
|
+
borderWidth: 1,
|
|
580
|
+
borderColor: `${AppColors.grayTextWeak}2E`,
|
|
581
|
+
}}>
|
|
539
582
|
<Text style={{
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
583
|
+
fontFamily: AppFonts.interBold,
|
|
584
|
+
fontSize: 8,
|
|
585
|
+
lineHeight: 11,
|
|
586
|
+
color: AppColors.grayTextWeak,
|
|
587
|
+
letterSpacing: 0.3,
|
|
588
|
+
}}>
|
|
546
589
|
{t('settings.dormantBadge')}
|
|
547
590
|
</Text>
|
|
548
591
|
</View>)}
|
|
549
592
|
</View>
|
|
550
593
|
|
|
551
594
|
<Text style={{
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
595
|
+
fontFamily: AppFonts.interRegular,
|
|
596
|
+
fontSize: 11,
|
|
597
|
+
color: AppColors.grayText,
|
|
598
|
+
lineHeight: 15,
|
|
599
|
+
marginTop: 1,
|
|
600
|
+
}}>
|
|
558
601
|
{moduleItem.desc}
|
|
559
602
|
</Text>
|
|
560
603
|
</View>
|
|
561
604
|
</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,
|
|
579
|
-
borderColor: isLocked
|
|
580
|
-
? AppColors.dividerColor
|
|
581
|
-
: AppColors.grayBorderSecondary,
|
|
582
|
-
backgroundColor: moduleItem.key === 'apis'
|
|
583
|
-
? `${AppColors.blue500}22`
|
|
584
|
-
: isChecked
|
|
585
|
-
? AppColors.purple
|
|
586
|
-
: AppColors.grayBackground,
|
|
587
|
-
alignItems: 'center',
|
|
588
|
-
justifyContent: 'center',
|
|
589
|
-
shadowColor: isChecked
|
|
590
|
-
? AppColors.purple
|
|
591
|
-
: 'transparent',
|
|
592
|
-
shadowOpacity: isChecked ? 0.3 : 0,
|
|
593
|
-
shadowRadius: 3,
|
|
594
|
-
shadowOffset: { width: 0, height: 1 },
|
|
595
|
-
elevation: isChecked ? 2 : 0,
|
|
596
|
-
}}>
|
|
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">
|
|
598
|
-
<Path d="M7 10V7a5 5 0 0 1 10 0v3" stroke={AppColors.grayText} strokeWidth="2.2" strokeLinecap="round"/>
|
|
599
|
-
<Path d="M5 10h14v9a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1z" fill={AppColors.grayText}/>
|
|
600
|
-
</Svg>) : null}
|
|
601
|
-
</TouchableScale>
|
|
602
605
|
</View>
|
|
603
606
|
|
|
604
607
|
{/* Card Footer: Live Stats + Configure Button */}
|
|
605
608
|
{!isUnavailable && (<View style={{
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
609
|
+
flexDirection: 'row',
|
|
610
|
+
alignItems: 'center',
|
|
611
|
+
justifyContent: 'space-between',
|
|
612
|
+
paddingTop: 8,
|
|
613
|
+
borderTopWidth: 1,
|
|
614
|
+
borderTopColor: AppColors.dividerColor,
|
|
615
|
+
}}>
|
|
613
616
|
{/* Live Info Pill */}
|
|
614
617
|
<View style={{
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
618
|
+
flexDirection: 'row',
|
|
619
|
+
alignItems: 'center',
|
|
620
|
+
gap: 6,
|
|
621
|
+
flex: 1,
|
|
622
|
+
}}>
|
|
620
623
|
<View style={{
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
624
|
+
width: 6,
|
|
625
|
+
height: 6,
|
|
626
|
+
borderRadius: 3,
|
|
627
|
+
backgroundColor: isChecked
|
|
628
|
+
? AppColors.liveGreen
|
|
629
|
+
: AppColors.grayTextWeak,
|
|
630
|
+
}}/>
|
|
628
631
|
<Text style={{
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
632
|
+
fontFamily: AppFonts.interMedium,
|
|
633
|
+
fontSize: 11,
|
|
634
|
+
color: AppColors.grayText,
|
|
635
|
+
lineHeight: 14,
|
|
636
|
+
}}>
|
|
634
637
|
{liveStats}
|
|
635
638
|
</Text>
|
|
636
639
|
</View>
|
|
637
640
|
|
|
638
641
|
{/* Sleek Configure Button */}
|
|
639
642
|
<TouchableScale accessible={true} accessibilityRole="button" accessibilityLabel={`Configure ${moduleItem.label} settings`} onPress={() => {
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
643
|
+
animateNextLayout();
|
|
644
|
+
setSettingsPage(moduleItem.key);
|
|
645
|
+
}} style={{
|
|
646
|
+
flexDirection: 'row',
|
|
647
|
+
alignItems: 'center',
|
|
648
|
+
gap: 5,
|
|
649
|
+
backgroundColor: `${AppColors.purple}12`,
|
|
650
|
+
paddingHorizontal: 10,
|
|
651
|
+
paddingVertical: 5,
|
|
652
|
+
borderRadius: 8,
|
|
653
|
+
borderWidth: 1,
|
|
654
|
+
borderColor: `${AppColors.purple}26`,
|
|
655
|
+
}}>
|
|
653
656
|
<SettingsIcon color={AppColors.purple} size={11}/>
|
|
654
657
|
<Text style={{
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
658
|
+
fontFamily: AppFonts.interBold,
|
|
659
|
+
fontSize: 11,
|
|
660
|
+
lineHeight: 14,
|
|
661
|
+
color: AppColors.purple,
|
|
662
|
+
}}>
|
|
660
663
|
{t('settings.configure')}
|
|
661
664
|
</Text>
|
|
662
665
|
<ForwardChevronIcon color={AppColors.purple} size={9}/>
|
|
663
666
|
</TouchableScale>
|
|
664
667
|
</View>)}
|
|
665
668
|
</View>);
|
|
666
|
-
|
|
669
|
+
})}
|
|
667
670
|
</View>
|
|
668
671
|
|
|
669
672
|
{/* Section 3.5: RAM-Based Auto Limits */}
|
|
670
673
|
<View style={{
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
674
|
+
backgroundColor: AppColors.primaryLight,
|
|
675
|
+
borderRadius: 14,
|
|
676
|
+
borderWidth: 1,
|
|
677
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
678
|
+
overflow: 'hidden',
|
|
679
|
+
padding: 14,
|
|
680
|
+
gap: 12,
|
|
681
|
+
}}>
|
|
679
682
|
<Text style={{
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
683
|
+
fontFamily: AppFonts.interBold,
|
|
684
|
+
fontSize: 11,
|
|
685
|
+
lineHeight: 14,
|
|
686
|
+
color: AppColors.grayTextWeak,
|
|
687
|
+
letterSpacing: 0.8,
|
|
688
|
+
}}>
|
|
686
689
|
RAM-Based Auto Limits
|
|
687
690
|
</Text>
|
|
688
691
|
|
|
689
692
|
{/* Auto RAM Limit Toggle */}
|
|
690
693
|
<View style={{
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
694
|
+
flexDirection: 'row',
|
|
695
|
+
alignItems: 'center',
|
|
696
|
+
justifyContent: 'space-between',
|
|
697
|
+
}}>
|
|
695
698
|
<View style={{
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
699
|
+
flexDirection: 'row',
|
|
700
|
+
alignItems: 'center',
|
|
701
|
+
gap: 10,
|
|
702
|
+
flex: 1,
|
|
703
|
+
}}>
|
|
701
704
|
<View style={{
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
705
|
+
width: 32,
|
|
706
|
+
height: 32,
|
|
707
|
+
borderRadius: 8,
|
|
708
|
+
backgroundColor: AppColors.purpleShade50,
|
|
709
|
+
alignItems: 'center',
|
|
710
|
+
justifyContent: 'center',
|
|
711
|
+
}}>
|
|
709
712
|
<PerformanceIcon color={AppColors.purple} size={15}/>
|
|
710
713
|
</View>
|
|
711
714
|
<View style={{ flex: 1 }}>
|
|
712
715
|
<Text style={{
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
716
|
+
fontFamily: AppFonts.interBold,
|
|
717
|
+
fontSize: 13.5,
|
|
718
|
+
lineHeight: 18,
|
|
719
|
+
color: AppColors.primaryBlack,
|
|
720
|
+
}}>
|
|
718
721
|
Auto-Calculate Limits from Device RAM
|
|
719
722
|
</Text>
|
|
720
723
|
<Text style={{
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
724
|
+
fontFamily: AppFonts.interRegular,
|
|
725
|
+
fontSize: 11,
|
|
726
|
+
lineHeight: 15,
|
|
727
|
+
color: AppColors.grayText,
|
|
728
|
+
marginTop: 1,
|
|
729
|
+
}}>
|
|
727
730
|
Automatically set API, Logs, Analytics & Crash limits based on available memory
|
|
728
731
|
</Text>
|
|
729
732
|
</View>
|
|
730
733
|
</View>
|
|
731
734
|
|
|
732
735
|
<TouchableScale accessible={true} accessibilityRole="switch" accessibilityLabel="Toggle auto RAM limit calculation" accessibilityState={{ checked: isAutoRamLimitEnabled }} onPress={() => setIsAutoRamLimitEnabled(prev => !prev)} style={{
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
736
|
+
width: 42,
|
|
737
|
+
height: 24,
|
|
738
|
+
borderRadius: 12,
|
|
739
|
+
backgroundColor: isAutoRamLimitEnabled
|
|
740
|
+
? AppColors.purple
|
|
741
|
+
: AppColors.grayBorderSecondary,
|
|
742
|
+
padding: 2,
|
|
743
|
+
justifyContent: 'center',
|
|
744
|
+
alignItems: isAutoRamLimitEnabled ? 'flex-end' : 'flex-start',
|
|
745
|
+
}}>
|
|
743
746
|
<View style={{
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
747
|
+
width: 20,
|
|
748
|
+
height: 20,
|
|
749
|
+
borderRadius: 10,
|
|
750
|
+
backgroundColor: AppColors.white,
|
|
751
|
+
shadowColor: AppColors.black,
|
|
752
|
+
shadowOpacity: 0.18,
|
|
753
|
+
shadowRadius: 2,
|
|
754
|
+
shadowOffset: { width: 0, height: 1 },
|
|
755
|
+
}}/>
|
|
753
756
|
</TouchableScale>
|
|
754
757
|
</View>
|
|
755
758
|
|
|
@@ -758,58 +761,58 @@ const SettingsPanel = () => {
|
|
|
758
761
|
{/* Device Free RAM Display */}
|
|
759
762
|
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 10 }}>
|
|
760
763
|
<View style={{
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
764
|
+
width: 32,
|
|
765
|
+
height: 32,
|
|
766
|
+
borderRadius: 8,
|
|
767
|
+
backgroundColor: isAutoRamLimitEnabled
|
|
768
|
+
? `${AppColors.purple}14`
|
|
769
|
+
: AppColors.grayBackground,
|
|
770
|
+
alignItems: 'center',
|
|
771
|
+
justifyContent: 'center',
|
|
772
|
+
}}>
|
|
770
773
|
<SignalIcon color={isAutoRamLimitEnabled ? AppColors.purple : AppColors.grayTextWeak} size={15}/>
|
|
771
774
|
</View>
|
|
772
775
|
<View style={{ flex: 1 }}>
|
|
773
776
|
<Text style={{
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
777
|
+
fontFamily: AppFonts.interBold,
|
|
778
|
+
fontSize: 13.5,
|
|
779
|
+
lineHeight: 18,
|
|
780
|
+
color: isAutoRamLimitEnabled
|
|
781
|
+
? AppColors.primaryBlack
|
|
782
|
+
: AppColors.grayText,
|
|
783
|
+
}}>
|
|
781
784
|
Detected Free RAM
|
|
782
785
|
</Text>
|
|
783
786
|
<Text style={{
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
787
|
+
fontFamily: AppFonts.interRegular,
|
|
788
|
+
fontSize: 11,
|
|
789
|
+
lineHeight: 15,
|
|
790
|
+
color: AppColors.grayText,
|
|
791
|
+
marginTop: 1,
|
|
792
|
+
}}>
|
|
790
793
|
{deviceFreeRamMb} MB available
|
|
791
794
|
</Text>
|
|
792
795
|
</View>
|
|
793
796
|
<View style={{
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
797
|
+
paddingHorizontal: 10,
|
|
798
|
+
paddingVertical: 5,
|
|
799
|
+
borderRadius: 8,
|
|
800
|
+
backgroundColor: isAutoRamLimitEnabled
|
|
801
|
+
? `${AppColors.purple}12`
|
|
802
|
+
: AppColors.grayBackground,
|
|
803
|
+
borderWidth: 1,
|
|
804
|
+
borderColor: isAutoRamLimitEnabled
|
|
805
|
+
? `${AppColors.purple}26`
|
|
806
|
+
: AppColors.dividerColor,
|
|
807
|
+
}}>
|
|
805
808
|
<Text style={{
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
809
|
+
fontFamily: AppFonts.interBold,
|
|
810
|
+
fontSize: 12,
|
|
811
|
+
lineHeight: 15,
|
|
812
|
+
color: isAutoRamLimitEnabled
|
|
813
|
+
? AppColors.purple
|
|
814
|
+
: AppColors.grayText,
|
|
815
|
+
}}>
|
|
813
816
|
{deviceFreeRamMb} MB
|
|
814
817
|
</Text>
|
|
815
818
|
</View>
|
|
@@ -818,44 +821,44 @@ const SettingsPanel = () => {
|
|
|
818
821
|
{/* Current Auto-Calculated Limits Preview */}
|
|
819
822
|
{isAutoRamLimitEnabled && (<View style={{ marginTop: 8, paddingTop: 8, borderTopWidth: 1, borderTopColor: AppColors.dividerColor, gap: 6 }}>
|
|
820
823
|
<Text style={{
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
824
|
+
fontFamily: AppFonts.interBold,
|
|
825
|
+
fontSize: 11.5,
|
|
826
|
+
lineHeight: 15,
|
|
827
|
+
color: AppColors.purple,
|
|
828
|
+
}}>
|
|
826
829
|
Auto Profile: {autoRamProfile.profileName}
|
|
827
830
|
</Text>
|
|
828
831
|
<View style={{ flexDirection: 'row', flexWrap: 'wrap', gap: 8 }}>
|
|
829
832
|
{[
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
<Text style={{
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
833
|
+
{ label: 'APIs', value: autoRamProfile.maxNetworkLogs, color: AppColors.blue500 },
|
|
834
|
+
{ label: 'Logs', value: autoRamProfile.maxConsoleLogs, color: AppColors.sky500 },
|
|
835
|
+
{ label: 'Analytics', value: autoRamProfile.maxAnalyticsEvents, color: AppColors.purple },
|
|
836
|
+
{ label: 'Crash', value: autoRamProfile.maxCrashRecords, color: AppColors.errorColor },
|
|
837
|
+
].map(item => (<View key={item.label} style={{
|
|
838
|
+
flexDirection: 'row',
|
|
839
|
+
alignItems: 'center',
|
|
840
|
+
gap: 4,
|
|
841
|
+
paddingHorizontal: 8,
|
|
842
|
+
paddingVertical: 4,
|
|
843
|
+
borderRadius: 6,
|
|
844
|
+
backgroundColor: `${item.color}14`,
|
|
845
|
+
borderWidth: 1,
|
|
846
|
+
borderColor: `${item.color}33`,
|
|
847
|
+
}}>
|
|
848
|
+
<Text style={{
|
|
849
|
+
fontFamily: AppFonts.interBold,
|
|
850
|
+
fontSize: 10.5,
|
|
851
|
+
lineHeight: 14,
|
|
852
|
+
color: item.color,
|
|
853
|
+
}}>
|
|
851
854
|
{item.label}
|
|
852
855
|
</Text>
|
|
853
856
|
<Text style={{
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
857
|
+
fontFamily: AppFonts.interBold,
|
|
858
|
+
fontSize: 10.5,
|
|
859
|
+
lineHeight: 14,
|
|
860
|
+
color: item.color,
|
|
861
|
+
}}>
|
|
859
862
|
{item.value}
|
|
860
863
|
</Text>
|
|
861
864
|
</View>))}
|
|
@@ -865,184 +868,189 @@ const SettingsPanel = () => {
|
|
|
865
868
|
</View>) : (<View style={{ gap: 14 }}>
|
|
866
869
|
{/* Section 1: Appearance */}
|
|
867
870
|
<View style={{
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
871
|
+
backgroundColor: AppColors.primaryLight,
|
|
872
|
+
borderRadius: 14,
|
|
873
|
+
borderWidth: 1,
|
|
874
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
875
|
+
overflow: 'hidden',
|
|
876
|
+
padding: 14,
|
|
877
|
+
gap: 12,
|
|
878
|
+
}}>
|
|
876
879
|
<Text style={{
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
880
|
+
fontFamily: AppFonts.interBold,
|
|
881
|
+
fontSize: 11,
|
|
882
|
+
lineHeight: 14,
|
|
883
|
+
color: AppColors.grayTextWeak,
|
|
884
|
+
letterSpacing: 0.8,
|
|
885
|
+
}}>
|
|
883
886
|
{t('settings.appearanceTheme')}
|
|
884
887
|
</Text>
|
|
885
888
|
|
|
886
889
|
<View style={{
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
890
|
+
flexDirection: 'row',
|
|
891
|
+
alignItems: 'center',
|
|
892
|
+
justifyContent: 'space-between',
|
|
893
|
+
}}>
|
|
891
894
|
<View style={{
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
895
|
+
flexDirection: 'row',
|
|
896
|
+
alignItems: 'center',
|
|
897
|
+
gap: 10,
|
|
898
|
+
flex: 1,
|
|
899
|
+
}}>
|
|
897
900
|
<View style={{
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
901
|
+
width: 32,
|
|
902
|
+
height: 32,
|
|
903
|
+
borderRadius: 8,
|
|
904
|
+
backgroundColor: AppColors.purpleShade50,
|
|
905
|
+
alignItems: 'center',
|
|
906
|
+
justifyContent: 'center',
|
|
907
|
+
}}>
|
|
905
908
|
{isDark ? (<SunIcon color={AppColors.purple} size={15}/>) : (<MoonIcon color={AppColors.purple} size={15}/>)}
|
|
906
909
|
</View>
|
|
907
910
|
<View style={{ flex: 1 }}>
|
|
908
911
|
<Text style={{
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
912
|
+
fontFamily: AppFonts.interBold,
|
|
913
|
+
fontSize: 13.5,
|
|
914
|
+
lineHeight: 18,
|
|
915
|
+
color: AppColors.primaryBlack,
|
|
916
|
+
}}>
|
|
914
917
|
{t('settings.general.darkMode')}
|
|
915
918
|
</Text>
|
|
916
919
|
<Text style={{
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
920
|
+
fontFamily: AppFonts.interRegular,
|
|
921
|
+
fontSize: 11,
|
|
922
|
+
lineHeight: 15,
|
|
923
|
+
color: AppColors.grayText,
|
|
924
|
+
marginTop: 1,
|
|
925
|
+
}}>
|
|
923
926
|
{t('settings.general.darkModeDescription')}
|
|
924
927
|
</Text>
|
|
925
928
|
</View>
|
|
926
929
|
</View>
|
|
927
930
|
|
|
928
931
|
<TouchableScale accessible={true} accessibilityRole="switch" accessibilityLabel="Toggle Dark Theme" accessibilityState={{ checked: isDark }} onPress={() => {
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
932
|
+
const newTheme = !isDark;
|
|
933
|
+
setIsDark(newTheme);
|
|
934
|
+
toggleGlobalTheme(newTheme);
|
|
935
|
+
}} style={{
|
|
936
|
+
width: 42,
|
|
937
|
+
height: 24,
|
|
938
|
+
borderRadius: 12,
|
|
939
|
+
backgroundColor: isDark
|
|
940
|
+
? AppColors.purple
|
|
941
|
+
: AppColors.grayBorderSecondary,
|
|
942
|
+
padding: 2,
|
|
943
|
+
justifyContent: 'center',
|
|
944
|
+
alignItems: isDark ? 'flex-end' : 'flex-start',
|
|
945
|
+
}}>
|
|
943
946
|
<View style={{
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
947
|
+
width: 20,
|
|
948
|
+
height: 20,
|
|
949
|
+
borderRadius: 10,
|
|
950
|
+
backgroundColor: AppColors.white,
|
|
951
|
+
shadowColor: AppColors.black,
|
|
952
|
+
shadowOpacity: 0.18,
|
|
953
|
+
shadowRadius: 2,
|
|
954
|
+
shadowOffset: { width: 0, height: 1 },
|
|
955
|
+
}}/>
|
|
953
956
|
</TouchableScale>
|
|
954
957
|
</View>
|
|
955
958
|
</View>
|
|
956
959
|
|
|
957
960
|
{/* Section 2: Window & Layout */}
|
|
958
961
|
<View style={{
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
962
|
+
backgroundColor: AppColors.primaryLight,
|
|
963
|
+
borderRadius: 14,
|
|
964
|
+
borderWidth: 1,
|
|
965
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
966
|
+
overflow: 'hidden',
|
|
967
|
+
padding: 14,
|
|
968
|
+
gap: 14,
|
|
969
|
+
}}>
|
|
967
970
|
<Text style={{
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
971
|
+
fontFamily: AppFonts.interBold,
|
|
972
|
+
fontSize: 11,
|
|
973
|
+
lineHeight: 14,
|
|
974
|
+
color: AppColors.grayTextWeak,
|
|
975
|
+
letterSpacing: 0.8,
|
|
976
|
+
}}>
|
|
974
977
|
{t('settings.windowLayout')}
|
|
975
978
|
</Text>
|
|
976
979
|
|
|
977
980
|
{/* Modal Height */}
|
|
978
981
|
<View style={{ gap: 8 }}>
|
|
979
982
|
<View style={{
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
983
|
+
flexDirection: 'row',
|
|
984
|
+
alignItems: 'center',
|
|
985
|
+
justifyContent: 'space-between',
|
|
986
|
+
gap: 10,
|
|
987
|
+
}}>
|
|
984
988
|
<View style={{
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
+
flexDirection: 'row',
|
|
990
|
+
alignItems: 'center',
|
|
991
|
+
gap: 10,
|
|
992
|
+
flex: 1,
|
|
993
|
+
}}>
|
|
994
|
+
<View style={{
|
|
995
|
+
width: 32,
|
|
996
|
+
height: 32,
|
|
997
|
+
borderRadius: 8,
|
|
998
|
+
backgroundColor: AppColors.purpleShade50,
|
|
999
|
+
alignItems: 'center',
|
|
1000
|
+
justifyContent: 'center',
|
|
1001
|
+
}}>
|
|
1002
|
+
<ScreenIcon color={AppColors.purple} size={15}/>
|
|
1003
|
+
</View>
|
|
1004
|
+
<View style={{ flex: 1 }}>
|
|
1005
|
+
<Text style={{
|
|
1006
|
+
fontFamily: AppFonts.interBold,
|
|
1007
|
+
fontSize: 13.5,
|
|
1008
|
+
lineHeight: 18,
|
|
1009
|
+
color: AppColors.primaryBlack,
|
|
1010
|
+
}}>
|
|
1011
|
+
{t('settings.general.modalHeight')}
|
|
1012
|
+
</Text>
|
|
1013
|
+
<Text style={{
|
|
1014
|
+
fontFamily: AppFonts.interRegular,
|
|
1015
|
+
fontSize: 11,
|
|
1016
|
+
lineHeight: 15,
|
|
1017
|
+
color: AppColors.grayText,
|
|
1018
|
+
marginTop: 1,
|
|
1019
|
+
}}>
|
|
1020
|
+
{t('settings.general.modalHeightDescription')}
|
|
1021
|
+
</Text>
|
|
1022
|
+
</View>
|
|
1023
|
+
</View>
|
|
1024
|
+
|
|
1025
|
+
{stagedHeight !== modalHeightPercent && (<TouchableScale onPress={() => {
|
|
1026
|
+
setModalHeightPercent(stagedHeight);
|
|
1027
|
+
}} style={{
|
|
1028
|
+
flexDirection: 'row',
|
|
989
1029
|
alignItems: 'center',
|
|
990
|
-
|
|
1030
|
+
gap: 5,
|
|
1031
|
+
backgroundColor: AppColors.purple,
|
|
1032
|
+
paddingHorizontal: 10,
|
|
1033
|
+
paddingVertical: 5,
|
|
1034
|
+
borderRadius: 7,
|
|
1035
|
+
shadowColor: AppColors.purple,
|
|
1036
|
+
shadowOffset: { width: 0, height: 1 },
|
|
1037
|
+
shadowOpacity: 0.28,
|
|
1038
|
+
shadowRadius: 2,
|
|
1039
|
+
elevation: 2,
|
|
991
1040
|
}}>
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
<View style={{ flex: 1 }}>
|
|
995
|
-
<Text style={{
|
|
1041
|
+
<CheckIcon size={11} color={AppColors.white}/>
|
|
1042
|
+
<Text style={{
|
|
996
1043
|
fontFamily: AppFonts.interBold,
|
|
997
|
-
fontSize: 13.5,
|
|
998
|
-
lineHeight: 18,
|
|
999
|
-
color: AppColors.primaryBlack,
|
|
1000
|
-
}}>
|
|
1001
|
-
{t('settings.general.modalHeight')}
|
|
1002
|
-
</Text>
|
|
1003
|
-
<Text style={{
|
|
1004
|
-
fontFamily: AppFonts.interRegular,
|
|
1005
1044
|
fontSize: 11,
|
|
1006
|
-
|
|
1007
|
-
color: AppColors.grayText,
|
|
1008
|
-
marginTop: 1,
|
|
1045
|
+
color: AppColors.white,
|
|
1009
1046
|
}}>
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1047
|
+
Save ({stagedHeight}%)
|
|
1048
|
+
</Text>
|
|
1049
|
+
</TouchableScale>)}
|
|
1013
1050
|
</View>
|
|
1014
1051
|
|
|
1015
|
-
<View style={{
|
|
1016
|
-
|
|
1017
|
-
backgroundColor: AppColors.grayBackground,
|
|
1018
|
-
borderRadius: 10,
|
|
1019
|
-
padding: 3,
|
|
1020
|
-
borderWidth: 1,
|
|
1021
|
-
borderColor: AppColors.dividerColor,
|
|
1022
|
-
}}>
|
|
1023
|
-
{[50, 70, 90, 100].map(opt => {
|
|
1024
|
-
const isActive = modalHeightPercent === opt;
|
|
1025
|
-
return (<TouchableScale key={opt} accessible={true} accessibilityRole="button" accessibilityLabel={`Set window height to ${opt} percent`} accessibilityState={{ selected: isActive }} onPress={() => setModalHeightPercent(opt)} style={{
|
|
1026
|
-
flex: 1,
|
|
1027
|
-
paddingVertical: 7,
|
|
1028
|
-
alignItems: 'center',
|
|
1029
|
-
borderRadius: 8,
|
|
1030
|
-
backgroundColor: isActive
|
|
1031
|
-
? AppColors.purple
|
|
1032
|
-
: 'transparent',
|
|
1033
|
-
}}>
|
|
1034
|
-
<Text style={{
|
|
1035
|
-
fontFamily: AppFonts.interBold,
|
|
1036
|
-
fontSize: 11.5,
|
|
1037
|
-
lineHeight: 15,
|
|
1038
|
-
color: isActive
|
|
1039
|
-
? AppColors.white
|
|
1040
|
-
: AppColors.grayText,
|
|
1041
|
-
}}>
|
|
1042
|
-
{opt}%
|
|
1043
|
-
</Text>
|
|
1044
|
-
</TouchableScale>);
|
|
1045
|
-
})}
|
|
1052
|
+
<View style={{ marginTop: 6 }}>
|
|
1053
|
+
<Slider value={stagedHeight} onValueChange={setStagedHeight} min={50} max={90} step={5} quickPresets={[50, 60, 70, 80, 90]} formatLabel={val => `${Math.round(val)}%`}/>
|
|
1046
1054
|
</View>
|
|
1047
1055
|
</View>
|
|
1048
1056
|
|
|
@@ -1051,694 +1059,330 @@ const SettingsPanel = () => {
|
|
|
1051
1059
|
{/* Modal Animation */}
|
|
1052
1060
|
<View style={{ gap: 8 }}>
|
|
1053
1061
|
<View style={{
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1062
|
+
flexDirection: 'row',
|
|
1063
|
+
alignItems: 'center',
|
|
1064
|
+
gap: 10,
|
|
1065
|
+
}}>
|
|
1058
1066
|
<View style={{
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1067
|
+
width: 32,
|
|
1068
|
+
height: 32,
|
|
1069
|
+
borderRadius: 8,
|
|
1070
|
+
backgroundColor: AppColors.purpleShade50,
|
|
1071
|
+
alignItems: 'center',
|
|
1072
|
+
justifyContent: 'center',
|
|
1073
|
+
}}>
|
|
1066
1074
|
<MotionIcon color={AppColors.purple} size={15}/>
|
|
1067
1075
|
</View>
|
|
1068
1076
|
<View style={{ flex: 1 }}>
|
|
1069
1077
|
<Text style={{
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1078
|
+
fontFamily: AppFonts.interBold,
|
|
1079
|
+
fontSize: 13.5,
|
|
1080
|
+
lineHeight: 18,
|
|
1081
|
+
color: AppColors.primaryBlack,
|
|
1082
|
+
}}>
|
|
1075
1083
|
{t('settings.general.modalAnimation')}
|
|
1076
1084
|
</Text>
|
|
1077
1085
|
<Text style={{
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1086
|
+
fontFamily: AppFonts.interRegular,
|
|
1087
|
+
fontSize: 11,
|
|
1088
|
+
lineHeight: 15,
|
|
1089
|
+
color: AppColors.grayText,
|
|
1090
|
+
marginTop: 1,
|
|
1091
|
+
}}>
|
|
1084
1092
|
{t('settings.general.modalAnimationDescription')}
|
|
1085
1093
|
</Text>
|
|
1086
1094
|
</View>
|
|
1087
1095
|
</View>
|
|
1088
1096
|
|
|
1089
1097
|
<View style={{
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1098
|
+
flexDirection: 'row',
|
|
1099
|
+
backgroundColor: AppColors.grayBackground,
|
|
1100
|
+
borderRadius: 10,
|
|
1101
|
+
padding: 3,
|
|
1102
|
+
borderWidth: 1,
|
|
1103
|
+
borderColor: AppColors.dividerColor,
|
|
1104
|
+
}}>
|
|
1097
1105
|
{[
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1106
|
+
{ key: 'slide', label: 'Slide Up' },
|
|
1107
|
+
{ key: 'fade', label: 'Fade' },
|
|
1108
|
+
{ key: 'none', label: 'None' },
|
|
1109
|
+
].map(opt => {
|
|
1110
|
+
const isActive = modalAnimationType === opt.key;
|
|
1111
|
+
return (<TouchableScale key={opt.key} accessible={true} accessibilityRole="button" accessibilityLabel={`Set transition animation to ${opt.label}`} accessibilityState={{ selected: isActive }} onPress={() => setModalAnimationType(opt.key)} style={{
|
|
1112
|
+
flex: 1,
|
|
1113
|
+
paddingVertical: 7,
|
|
1114
|
+
alignItems: 'center',
|
|
1115
|
+
borderRadius: 8,
|
|
1116
|
+
backgroundColor: isActive
|
|
1117
|
+
? AppColors.purple
|
|
1118
|
+
: 'transparent',
|
|
1119
|
+
}}>
|
|
1112
1120
|
<Text style={{
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1121
|
+
fontFamily: AppFonts.interBold,
|
|
1122
|
+
fontSize: 11.5,
|
|
1123
|
+
lineHeight: 15,
|
|
1124
|
+
color: isActive
|
|
1125
|
+
? AppColors.white
|
|
1126
|
+
: AppColors.grayText,
|
|
1127
|
+
}}>
|
|
1120
1128
|
{opt.label}
|
|
1121
1129
|
</Text>
|
|
1122
1130
|
</TouchableScale>);
|
|
1123
|
-
|
|
1131
|
+
})}
|
|
1124
1132
|
</View>
|
|
1125
1133
|
</View>
|
|
1126
1134
|
</View>
|
|
1127
1135
|
|
|
1128
1136
|
{/* Section 3: Default Startup Tab */}
|
|
1129
1137
|
<View style={{
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
<Text style={{
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1138
|
+
backgroundColor: AppColors.primaryLight,
|
|
1139
|
+
borderRadius: 14,
|
|
1140
|
+
borderWidth: 1,
|
|
1141
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
1142
|
+
overflow: 'hidden',
|
|
1143
|
+
padding: 14,
|
|
1144
|
+
gap: 12,
|
|
1145
|
+
}}>
|
|
1146
|
+
<Text style={{
|
|
1147
|
+
fontFamily: AppFonts.interBold,
|
|
1148
|
+
fontSize: 11,
|
|
1149
|
+
lineHeight: 14,
|
|
1150
|
+
color: AppColors.grayTextWeak,
|
|
1151
|
+
letterSpacing: 0.8,
|
|
1152
|
+
}}>
|
|
1145
1153
|
{t('settings.startupDefault')}
|
|
1146
1154
|
</Text>
|
|
1147
1155
|
|
|
1148
1156
|
<View style={{
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1157
|
+
flexDirection: 'row',
|
|
1158
|
+
alignItems: 'center',
|
|
1159
|
+
gap: 10,
|
|
1160
|
+
}}>
|
|
1153
1161
|
<View style={{
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1162
|
+
width: 32,
|
|
1163
|
+
height: 32,
|
|
1164
|
+
borderRadius: 8,
|
|
1165
|
+
backgroundColor: AppColors.purpleShade50,
|
|
1166
|
+
alignItems: 'center',
|
|
1167
|
+
justifyContent: 'center',
|
|
1168
|
+
}}>
|
|
1161
1169
|
<LayersIcon color={AppColors.purple} size={15}/>
|
|
1162
1170
|
</View>
|
|
1163
1171
|
<View style={{ flex: 1 }}>
|
|
1164
1172
|
<Text style={{
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1173
|
+
fontFamily: AppFonts.interBold,
|
|
1174
|
+
fontSize: 13.5,
|
|
1175
|
+
lineHeight: 18,
|
|
1176
|
+
color: AppColors.primaryBlack,
|
|
1177
|
+
}}>
|
|
1170
1178
|
{t('settings.general.defaultOpeningTab')}
|
|
1171
1179
|
</Text>
|
|
1172
1180
|
<Text style={{
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1181
|
+
fontFamily: AppFonts.interRegular,
|
|
1182
|
+
fontSize: 11,
|
|
1183
|
+
lineHeight: 15,
|
|
1184
|
+
color: AppColors.grayText,
|
|
1185
|
+
marginTop: 1,
|
|
1186
|
+
}}>
|
|
1179
1187
|
{t('settings.general.defaultOpeningTabDesc')}
|
|
1180
1188
|
</Text>
|
|
1181
1189
|
</View>
|
|
1182
1190
|
</View>
|
|
1183
1191
|
|
|
1184
|
-
{/*
|
|
1185
|
-
<View style={{
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
.
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
alignItems: 'center',
|
|
1200
|
-
gap: 8,
|
|
1201
|
-
paddingVertical: 10,
|
|
1202
|
-
paddingHorizontal: 12,
|
|
1203
|
-
borderRadius: 10,
|
|
1204
|
-
borderWidth: 1.5,
|
|
1205
|
-
borderColor: isActive
|
|
1206
|
-
? AppColors.purple
|
|
1207
|
-
: AppColors.grayBorderSecondary,
|
|
1208
|
-
backgroundColor: isActive
|
|
1209
|
-
? `${AppColors.purple}0F`
|
|
1210
|
-
: AppColors.primaryLight,
|
|
1211
|
-
minWidth: '47%',
|
|
1212
|
-
flex: 1,
|
|
1213
|
-
}}>
|
|
1214
|
-
<Text style={{
|
|
1215
|
-
fontFamily: AppFonts.interBold,
|
|
1216
|
-
fontSize: 12.5,
|
|
1217
|
-
lineHeight: 16,
|
|
1218
|
-
color: isActive
|
|
1219
|
-
? AppColors.purple
|
|
1220
|
-
: AppColors.primaryBlack,
|
|
1221
|
-
flex: 1,
|
|
1222
|
-
}}>
|
|
1223
|
-
{tab.label}
|
|
1224
|
-
</Text>
|
|
1225
|
-
{isActive && (<View style={{
|
|
1226
|
-
width: 16,
|
|
1227
|
-
height: 16,
|
|
1228
|
-
borderRadius: 8,
|
|
1229
|
-
backgroundColor: AppColors.purple,
|
|
1230
|
-
alignItems: 'center',
|
|
1231
|
-
justifyContent: 'center',
|
|
1232
|
-
}}>
|
|
1233
|
-
<CheckIcon size={9} color={AppColors.white}/>
|
|
1234
|
-
</View>)}
|
|
1235
|
-
</TouchableScale>);
|
|
1236
|
-
})}
|
|
1237
|
-
</View>
|
|
1238
|
-
</View>
|
|
1239
|
-
|
|
1240
|
-
{/* Section 4: Log Deduplication & Levels */}
|
|
1241
|
-
<View style={{
|
|
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>
|
|
1259
|
-
|
|
1260
|
-
{/* Show Duplicate Logs */}
|
|
1261
|
-
<View style={{
|
|
1262
|
-
flexDirection: 'row',
|
|
1263
|
-
alignItems: 'center',
|
|
1264
|
-
justifyContent: 'space-between',
|
|
1265
|
-
}}>
|
|
1266
|
-
<View style={{
|
|
1267
|
-
flexDirection: 'row',
|
|
1268
|
-
alignItems: 'center',
|
|
1269
|
-
gap: 10,
|
|
1270
|
-
flex: 1,
|
|
1271
|
-
}}>
|
|
1192
|
+
{/* Sleek Interactive Dropdown Picker */}
|
|
1193
|
+
<View style={{ marginTop: 6, gap: 6 }}>
|
|
1194
|
+
<TouchableScale accessible={true} accessibilityRole="button" accessibilityLabel={`Default opening tab: ${allModules.find(m => m.key === defaultTab)?.label || 'APIs'}`} onPress={() => setIsDefaultTabDropdownOpen(prev => !prev)} style={{
|
|
1195
|
+
flexDirection: 'row',
|
|
1196
|
+
alignItems: 'center',
|
|
1197
|
+
justifyContent: 'space-between',
|
|
1198
|
+
backgroundColor: AppColors.grayBackground,
|
|
1199
|
+
borderRadius: 10,
|
|
1200
|
+
borderWidth: 1.5,
|
|
1201
|
+
borderColor: isDefaultTabDropdownOpen
|
|
1202
|
+
? AppColors.purple
|
|
1203
|
+
: AppColors.grayBorderSecondary,
|
|
1204
|
+
paddingHorizontal: 14,
|
|
1205
|
+
paddingVertical: 11,
|
|
1206
|
+
}}>
|
|
1272
1207
|
<View style={{
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
fontFamily: AppFonts.interBold,
|
|
1285
|
-
fontSize: 13.5,
|
|
1286
|
-
lineHeight: 18,
|
|
1287
|
-
color: AppColors.primaryBlack,
|
|
1288
|
-
}}>
|
|
1289
|
-
{t('settings.general.duplicateLogs')}
|
|
1290
|
-
</Text>
|
|
1208
|
+
flexDirection: 'row',
|
|
1209
|
+
alignItems: 'center',
|
|
1210
|
+
gap: 10,
|
|
1211
|
+
flex: 1,
|
|
1212
|
+
}}>
|
|
1213
|
+
<View style={{
|
|
1214
|
+
width: 8,
|
|
1215
|
+
height: 8,
|
|
1216
|
+
borderRadius: 4,
|
|
1217
|
+
backgroundColor: AppColors.purple,
|
|
1218
|
+
}}/>
|
|
1291
1219
|
<Text style={{
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
{t('settings.general.duplicateLogsDescription')}
|
|
1220
|
+
fontFamily: AppFonts.interBold,
|
|
1221
|
+
fontSize: 13.5,
|
|
1222
|
+
lineHeight: 18,
|
|
1223
|
+
color: AppColors.primaryBlack,
|
|
1224
|
+
}}>
|
|
1225
|
+
{allModules.find(m => m.key === defaultTab)?.label || 'APIs (Network)'}
|
|
1299
1226
|
</Text>
|
|
1227
|
+
<View style={{
|
|
1228
|
+
backgroundColor: `${AppColors.purple}14`,
|
|
1229
|
+
paddingHorizontal: 6,
|
|
1230
|
+
paddingVertical: 1.5,
|
|
1231
|
+
borderRadius: 6,
|
|
1232
|
+
}}>
|
|
1233
|
+
<Text style={{
|
|
1234
|
+
fontFamily: AppFonts.interBold,
|
|
1235
|
+
fontSize: 8.5,
|
|
1236
|
+
color: AppColors.purple,
|
|
1237
|
+
}}>
|
|
1238
|
+
DEFAULT
|
|
1239
|
+
</Text>
|
|
1240
|
+
</View>
|
|
1300
1241
|
</View>
|
|
1301
|
-
</View>
|
|
1302
1242
|
|
|
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,
|
|
1307
|
-
backgroundColor: showDuplicateLogs
|
|
1308
|
-
? AppColors.purple
|
|
1309
|
-
: AppColors.grayBorderSecondary,
|
|
1310
|
-
padding: 2,
|
|
1311
|
-
justifyContent: 'center',
|
|
1312
|
-
alignItems: showDuplicateLogs
|
|
1313
|
-
? 'flex-end'
|
|
1314
|
-
: 'flex-start',
|
|
1315
|
-
}}>
|
|
1316
1243
|
<View style={{
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
shadowRadius: 2,
|
|
1324
|
-
shadowOffset: { width: 0, height: 1 },
|
|
1325
|
-
}}/>
|
|
1244
|
+
transform: [
|
|
1245
|
+
{ rotate: isDefaultTabDropdownOpen ? '180deg' : '0deg' },
|
|
1246
|
+
],
|
|
1247
|
+
}}>
|
|
1248
|
+
<ChevronDownIcon color={AppColors.grayText} size={15}/>
|
|
1249
|
+
</View>
|
|
1326
1250
|
</TouchableScale>
|
|
1327
|
-
</View>
|
|
1328
|
-
|
|
1329
|
-
<View style={{ height: 1, backgroundColor: AppColors.dividerColor }}/>
|
|
1330
1251
|
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
alignItems: 'center',
|
|
1344
|
-
justifyContent: 'center',
|
|
1345
|
-
}}>
|
|
1346
|
-
<TerminalIcon color={AppColors.purple} size={15}/>
|
|
1347
|
-
</View>
|
|
1348
|
-
<View style={{ flex: 1 }}>
|
|
1349
|
-
<Text style={{
|
|
1350
|
-
fontFamily: AppFonts.interBold,
|
|
1351
|
-
fontSize: 13.5,
|
|
1352
|
-
lineHeight: 18,
|
|
1353
|
-
color: AppColors.primaryBlack,
|
|
1354
|
-
}}>
|
|
1355
|
-
{t('settings.general.activeConsoleLogLevels')}
|
|
1356
|
-
</Text>
|
|
1357
|
-
<Text style={{
|
|
1358
|
-
fontFamily: AppFonts.interRegular,
|
|
1359
|
-
fontSize: 11,
|
|
1360
|
-
lineHeight: 15,
|
|
1361
|
-
color: AppColors.grayText,
|
|
1362
|
-
marginTop: 1,
|
|
1252
|
+
{/* Dropdown Options List */}
|
|
1253
|
+
{isDefaultTabDropdownOpen && (<View style={{
|
|
1254
|
+
backgroundColor: AppColors.primaryLight,
|
|
1255
|
+
borderRadius: 10,
|
|
1256
|
+
borderWidth: 1,
|
|
1257
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
1258
|
+
overflow: 'hidden',
|
|
1259
|
+
shadowColor: AppColors.black,
|
|
1260
|
+
shadowOpacity: 0.08,
|
|
1261
|
+
shadowRadius: 6,
|
|
1262
|
+
shadowOffset: { width: 0, height: 3 },
|
|
1263
|
+
elevation: 4,
|
|
1363
1264
|
}}>
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
{
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
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 => {
|
|
1387
|
-
const isActive = showConsoleLevels[level.key];
|
|
1388
|
-
return (<TouchableScale key={level.key} accessible={true} accessibilityRole="checkbox" accessibilityLabel={`Toggle ${level.label} logs`} accessibilityState={{ checked: isActive }} onPress={() => setShowConsoleLevels(prev => ({
|
|
1389
|
-
...prev,
|
|
1390
|
-
[level.key]: !prev[level.key],
|
|
1391
|
-
}))} style={{
|
|
1392
|
-
flex: 1,
|
|
1265
|
+
{allModules
|
|
1266
|
+
.filter(tab => tab.key === 'apis' ||
|
|
1267
|
+
stagedTabVisibility?.[tab.key] ||
|
|
1268
|
+
tabVisibility?.[tab.key])
|
|
1269
|
+
.map((tab, idx, arr) => {
|
|
1270
|
+
const isActive = defaultTab === tab.key;
|
|
1271
|
+
const isLast = idx === arr.length - 1;
|
|
1272
|
+
return (<TouchableScale key={tab.key} accessible={true} accessibilityRole="button" accessibilityLabel={`Select ${tab.label} as default tab`} onPress={() => {
|
|
1273
|
+
setDefaultTab(tab.key);
|
|
1274
|
+
setIsDefaultTabDropdownOpen(false);
|
|
1275
|
+
}} style={{
|
|
1393
1276
|
flexDirection: 'row',
|
|
1394
1277
|
alignItems: 'center',
|
|
1395
|
-
justifyContent: '
|
|
1396
|
-
|
|
1397
|
-
paddingVertical:
|
|
1398
|
-
borderRadius: 9,
|
|
1399
|
-
borderWidth: 1.5,
|
|
1400
|
-
borderColor: isActive
|
|
1401
|
-
? level.color
|
|
1402
|
-
: AppColors.grayBorderSecondary,
|
|
1278
|
+
justifyContent: 'space-between',
|
|
1279
|
+
paddingHorizontal: 14,
|
|
1280
|
+
paddingVertical: 11,
|
|
1403
1281
|
backgroundColor: isActive
|
|
1404
|
-
? `${
|
|
1405
|
-
:
|
|
1282
|
+
? `${AppColors.purple}0F`
|
|
1283
|
+
: 'transparent',
|
|
1284
|
+
borderBottomWidth: isLast ? 0 : 1,
|
|
1285
|
+
borderBottomColor: AppColors.dividerColor,
|
|
1406
1286
|
}}>
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1287
|
+
<View style={{
|
|
1288
|
+
flexDirection: 'row',
|
|
1289
|
+
alignItems: 'center',
|
|
1290
|
+
gap: 10,
|
|
1291
|
+
}}>
|
|
1292
|
+
<View style={{
|
|
1293
|
+
width: 6,
|
|
1294
|
+
height: 6,
|
|
1295
|
+
borderRadius: 3,
|
|
1411
1296
|
backgroundColor: isActive
|
|
1412
|
-
?
|
|
1413
|
-
: AppColors.
|
|
1297
|
+
? AppColors.purple
|
|
1298
|
+
: AppColors.grayTextWeak,
|
|
1414
1299
|
}}/>
|
|
1415
|
-
|
|
1416
|
-
fontFamily:
|
|
1417
|
-
|
|
1418
|
-
|
|
1300
|
+
<Text style={{
|
|
1301
|
+
fontFamily: isActive
|
|
1302
|
+
? AppFonts.interBold
|
|
1303
|
+
: AppFonts.interMedium,
|
|
1304
|
+
fontSize: 13,
|
|
1419
1305
|
color: isActive
|
|
1420
|
-
?
|
|
1421
|
-
: AppColors.
|
|
1306
|
+
? AppColors.purple
|
|
1307
|
+
: AppColors.primaryBlack,
|
|
1422
1308
|
}}>
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1309
|
+
{tab.label}
|
|
1310
|
+
</Text>
|
|
1311
|
+
</View>
|
|
1312
|
+
{isActive && (<CheckIcon size={14} color={AppColors.purple}/>)}
|
|
1313
|
+
</TouchableScale>);
|
|
1426
1314
|
})}
|
|
1427
|
-
|
|
1315
|
+
</View>)}
|
|
1428
1316
|
</View>
|
|
1429
1317
|
</View>
|
|
1430
|
-
|
|
1431
|
-
{/* Section 5: Reset Settings */}
|
|
1432
|
-
<View style={{
|
|
1433
|
-
backgroundColor: AppColors.primaryLight,
|
|
1434
|
-
borderRadius: 14,
|
|
1435
|
-
borderWidth: 1,
|
|
1436
|
-
borderColor: `${AppColors.errorColor}33`,
|
|
1437
|
-
overflow: 'hidden',
|
|
1438
|
-
padding: 14,
|
|
1439
|
-
flexDirection: 'row',
|
|
1440
|
-
alignItems: 'center',
|
|
1441
|
-
gap: 12,
|
|
1442
|
-
}}>
|
|
1443
|
-
<View style={{
|
|
1444
|
-
width: 34,
|
|
1445
|
-
height: 34,
|
|
1446
|
-
borderRadius: 9,
|
|
1447
|
-
backgroundColor: `${AppColors.errorColor}14`,
|
|
1448
|
-
alignItems: 'center',
|
|
1449
|
-
justifyContent: 'center',
|
|
1450
|
-
}}>
|
|
1451
|
-
<TrashIcon color={AppColors.errorColor} size={15}/>
|
|
1452
|
-
</View>
|
|
1453
|
-
<View style={{ flex: 1 }}>
|
|
1454
|
-
<Text style={{
|
|
1455
|
-
fontFamily: AppFonts.interBold,
|
|
1456
|
-
fontSize: 13.5,
|
|
1457
|
-
lineHeight: 18,
|
|
1458
|
-
color: AppColors.primaryBlack,
|
|
1459
|
-
}}>
|
|
1460
|
-
{t('settings.resetSettings')}
|
|
1461
|
-
</Text>
|
|
1462
|
-
<Text style={{
|
|
1463
|
-
fontFamily: AppFonts.interRegular,
|
|
1464
|
-
fontSize: 11,
|
|
1465
|
-
lineHeight: 15,
|
|
1466
|
-
color: AppColors.grayText,
|
|
1467
|
-
marginTop: 1,
|
|
1468
|
-
}}>
|
|
1469
|
-
{t('settings.resetSettingsDesc')}
|
|
1470
|
-
</Text>
|
|
1471
|
-
</View>
|
|
1472
|
-
|
|
1473
|
-
<TouchableScale accessible={true} accessibilityRole="button" accessibilityLabel="Reset all settings to default" onPress={resetToDefaults} style={{
|
|
1474
|
-
paddingHorizontal: 12,
|
|
1475
|
-
paddingVertical: 7,
|
|
1476
|
-
borderRadius: 8,
|
|
1477
|
-
backgroundColor: `${AppColors.errorColor}14`,
|
|
1478
|
-
borderWidth: 1,
|
|
1479
|
-
borderColor: `${AppColors.errorColor}38`,
|
|
1480
|
-
}}>
|
|
1481
|
-
<Text style={{
|
|
1482
|
-
fontFamily: AppFonts.interBold,
|
|
1483
|
-
fontSize: 11.5,
|
|
1484
|
-
lineHeight: 15,
|
|
1485
|
-
color: AppColors.errorColor,
|
|
1486
|
-
}}>
|
|
1487
|
-
{t('settings.reset')}
|
|
1488
|
-
</Text>
|
|
1489
|
-
</TouchableScale>
|
|
1490
|
-
</View>
|
|
1491
1318
|
</View>)}
|
|
1492
|
-
|
|
1493
|
-
{/* Storage & Engine Status Card */}
|
|
1494
|
-
<View style={{
|
|
1495
|
-
backgroundColor: isPersistent
|
|
1496
|
-
? `${AppColors.liveGreen}12`
|
|
1497
|
-
: `${AppColors.amber600}12`,
|
|
1498
|
-
borderRadius: 12,
|
|
1499
|
-
borderWidth: 1,
|
|
1500
|
-
borderColor: isPersistent
|
|
1501
|
-
? `${AppColors.liveGreen}33`
|
|
1502
|
-
: `${AppColors.amber600}33`,
|
|
1503
|
-
padding: 12,
|
|
1504
|
-
marginBottom: 10,
|
|
1505
|
-
flexDirection: 'row',
|
|
1506
|
-
alignItems: 'center',
|
|
1507
|
-
gap: 10,
|
|
1508
|
-
}}>
|
|
1509
|
-
<View style={{
|
|
1510
|
-
width: 8,
|
|
1511
|
-
height: 8,
|
|
1512
|
-
borderRadius: 4,
|
|
1513
|
-
backgroundColor: isPersistent
|
|
1514
|
-
? AppColors.green500
|
|
1515
|
-
: AppColors.amber600,
|
|
1516
|
-
}}/>
|
|
1517
|
-
<View style={{ flex: 1 }}>
|
|
1518
|
-
<Text style={{
|
|
1519
|
-
fontFamily: AppFonts.interBold,
|
|
1520
|
-
fontSize: 12,
|
|
1521
|
-
lineHeight: 16,
|
|
1522
|
-
color: isPersistent
|
|
1523
|
-
? AppColors.green700
|
|
1524
|
-
: AppColors.amber800,
|
|
1525
|
-
}}>
|
|
1526
|
-
{isPersistent
|
|
1527
|
-
? t('settings.general.storageStatusEnabled', {
|
|
1528
|
-
type: storage ? 'Custom Storage' : 'iOS NSUserDefaults',
|
|
1529
|
-
})
|
|
1530
|
-
: t('settings.general.storageStatusDisabled')}
|
|
1531
|
-
</Text>
|
|
1532
|
-
<Text style={{
|
|
1533
|
-
fontFamily: AppFonts.interRegular,
|
|
1534
|
-
fontSize: 10.5,
|
|
1535
|
-
lineHeight: 14,
|
|
1536
|
-
color: isPersistent
|
|
1537
|
-
? AppColors.green800
|
|
1538
|
-
: AppColors.amber800,
|
|
1539
|
-
marginTop: 2,
|
|
1540
|
-
opacity: 0.85,
|
|
1541
|
-
}}>
|
|
1542
|
-
{isPersistent
|
|
1543
|
-
? t('settings.general.storageStatusEnabledDesc')
|
|
1544
|
-
: t('settings.general.storageStatusDisabledDesc')}
|
|
1545
|
-
</Text>
|
|
1546
|
-
</View>
|
|
1547
|
-
</View>
|
|
1319
|
+
<View style={{ height: 48 }}/>
|
|
1548
1320
|
</ScrollView>
|
|
1549
1321
|
|
|
1550
1322
|
{/* Bottom Sticky Action Bar for Save Changes */}
|
|
1551
1323
|
{settingsActiveSubTab === 'module' && (<View style={{
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1324
|
+
paddingHorizontal: 16,
|
|
1325
|
+
paddingTop: 12,
|
|
1326
|
+
paddingBottom: Platform.OS === 'ios' ? 36 : 24,
|
|
1327
|
+
backgroundColor: AppColors.primaryLight,
|
|
1328
|
+
borderTopWidth: 1,
|
|
1329
|
+
borderTopColor: AppColors.dividerColor,
|
|
1330
|
+
flexDirection: 'row',
|
|
1331
|
+
alignItems: 'center',
|
|
1332
|
+
gap: 12,
|
|
1333
|
+
shadowColor: AppColors.black,
|
|
1334
|
+
shadowOpacity: 0.08,
|
|
1335
|
+
shadowRadius: 8,
|
|
1336
|
+
shadowOffset: { width: 0, height: -3 },
|
|
1337
|
+
elevation: 8,
|
|
1338
|
+
}}>
|
|
1567
1339
|
<View style={{ flex: 1 }}>
|
|
1568
1340
|
<Text style={{
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1341
|
+
fontFamily: AppFonts.interBold,
|
|
1342
|
+
fontSize: 13,
|
|
1343
|
+
lineHeight: 17,
|
|
1344
|
+
color: AppColors.primaryBlack,
|
|
1345
|
+
}}>
|
|
1574
1346
|
{stagedActiveCount} of {allModules.length} Modules Active
|
|
1575
1347
|
</Text>
|
|
1576
1348
|
<Text style={{
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1349
|
+
fontFamily: AppFonts.interRegular,
|
|
1350
|
+
fontSize: 11,
|
|
1351
|
+
lineHeight: 15,
|
|
1352
|
+
color: hasUnsavedChanges
|
|
1353
|
+
? AppColors.purple
|
|
1354
|
+
: AppColors.grayText,
|
|
1355
|
+
marginTop: 1,
|
|
1356
|
+
}}>
|
|
1585
1357
|
{hasUnsavedChanges
|
|
1586
|
-
|
|
1587
|
-
|
|
1358
|
+
? t('settings.unsavedPending')
|
|
1359
|
+
: t('settings.allSynchronized')}
|
|
1588
1360
|
</Text>
|
|
1589
1361
|
</View>
|
|
1590
1362
|
|
|
1591
1363
|
<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')}
|
|
1610
|
-
</Text>
|
|
1611
|
-
</TouchableScale>
|
|
1612
|
-
</View>)}
|
|
1613
|
-
</View>);
|
|
1614
|
-
}
|
|
1615
|
-
const goBackToMain = () => {
|
|
1616
|
-
animateNextLayout();
|
|
1617
|
-
setSettingsPage('main');
|
|
1618
|
-
};
|
|
1619
|
-
// Helper: settings row with icon + label + optional description
|
|
1620
|
-
const renderSettingRow = (opts) => {
|
|
1621
|
-
return (<View style={{
|
|
1622
|
-
paddingVertical: 12,
|
|
1623
|
-
borderBottomWidth: opts.isLast ? 0 : 1,
|
|
1624
|
-
borderBottomColor: AppColors.dividerColor,
|
|
1625
|
-
}}>
|
|
1626
|
-
<TouchableScale disabled={!opts.onPress} onPress={opts.onPress} style={{
|
|
1627
1364
|
flexDirection: 'row',
|
|
1628
1365
|
alignItems: 'center',
|
|
1629
|
-
gap:
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1366
|
+
gap: 6,
|
|
1367
|
+
backgroundColor: hasUnsavedChanges
|
|
1368
|
+
? AppColors.purple
|
|
1369
|
+
: `${AppColors.purple}22`,
|
|
1370
|
+
paddingHorizontal: 18,
|
|
1371
|
+
paddingVertical: 10,
|
|
1634
1372
|
borderRadius: 10,
|
|
1635
|
-
backgroundColor: AppColors.purpleShade50,
|
|
1636
|
-
borderWidth: 1,
|
|
1637
|
-
borderColor: `${AppColors.purple}2E`,
|
|
1638
|
-
alignItems: 'center',
|
|
1639
|
-
justifyContent: 'center',
|
|
1640
1373
|
}}>
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
<View style={{ flex: 1 }}>
|
|
1644
|
-
<Text style={{
|
|
1374
|
+
<CheckIcon size={14} color={hasUnsavedChanges ? AppColors.white : AppColors.purple}/>
|
|
1375
|
+
<Text style={{
|
|
1645
1376
|
fontFamily: AppFonts.interBold,
|
|
1646
|
-
fontSize:
|
|
1647
|
-
lineHeight:
|
|
1648
|
-
color: AppColors.
|
|
1377
|
+
fontSize: 13,
|
|
1378
|
+
lineHeight: 17,
|
|
1379
|
+
color: hasUnsavedChanges ? AppColors.white : AppColors.purple,
|
|
1649
1380
|
}}>
|
|
1650
|
-
|
|
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
|
|
1381
|
+
{t('settings.saveChanges')}
|
|
1696
1382
|
</Text>
|
|
1697
|
-
</
|
|
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,
|
|
1703
|
-
}}>
|
|
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
|
-
})}
|
|
1383
|
+
</TouchableScale>
|
|
1739
1384
|
</View>)}
|
|
1740
1385
|
</View>);
|
|
1741
|
-
};
|
|
1742
1386
|
let content = null;
|
|
1743
1387
|
let title = '';
|
|
1744
1388
|
let icon = null;
|
|
@@ -1747,7 +1391,7 @@ const SettingsPanel = () => {
|
|
|
1747
1391
|
title = t('settings.apis.title');
|
|
1748
1392
|
icon = <SignalIcon color={AppColors.white} size={16}/>;
|
|
1749
1393
|
rightInfo = t('settings.apis.total', { count: logs.length });
|
|
1750
|
-
content = (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16, gap: 12 }}>
|
|
1394
|
+
content = (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16, paddingBottom: 100, gap: 12 }}>
|
|
1751
1395
|
<View style={{
|
|
1752
1396
|
backgroundColor: AppColors.primaryLight,
|
|
1753
1397
|
padding: 16,
|
|
@@ -1763,8 +1407,8 @@ const SettingsPanel = () => {
|
|
|
1763
1407
|
value: maxNetworkLogs,
|
|
1764
1408
|
onChange: setMaxNetworkLogs,
|
|
1765
1409
|
min: 10,
|
|
1766
|
-
max:
|
|
1767
|
-
placeholder: 'Enter max requests (10-
|
|
1410
|
+
max: 100,
|
|
1411
|
+
placeholder: 'Enter max requests (10-100)',
|
|
1768
1412
|
},
|
|
1769
1413
|
isLast: true,
|
|
1770
1414
|
})}
|
|
@@ -1806,13 +1450,14 @@ const SettingsPanel = () => {
|
|
|
1806
1450
|
</View>),
|
|
1807
1451
|
})}
|
|
1808
1452
|
</View>
|
|
1453
|
+
<View style={{ height: 48 }}/>
|
|
1809
1454
|
</ScrollView>);
|
|
1810
1455
|
}
|
|
1811
1456
|
else if (settingsPage === 'logs') {
|
|
1812
1457
|
title = t('settings.logs.title');
|
|
1813
1458
|
icon = <TerminalIcon color={AppColors.white} size={16}/>;
|
|
1814
1459
|
rightInfo = t('settings.logs.total', { count: consoleLogs.length });
|
|
1815
|
-
content = (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16, gap: 12 }}>
|
|
1460
|
+
content = (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16, paddingBottom: 100, gap: 12 }}>
|
|
1816
1461
|
<View style={{
|
|
1817
1462
|
backgroundColor: AppColors.primaryLight,
|
|
1818
1463
|
padding: 16,
|
|
@@ -1829,8 +1474,8 @@ const SettingsPanel = () => {
|
|
|
1829
1474
|
value: maxConsoleLogs,
|
|
1830
1475
|
onChange: setMaxConsoleLogs,
|
|
1831
1476
|
min: 10,
|
|
1832
|
-
max:
|
|
1833
|
-
placeholder: 'Enter max logs (10-
|
|
1477
|
+
max: 100,
|
|
1478
|
+
placeholder: 'Enter max logs (10-100)',
|
|
1834
1479
|
},
|
|
1835
1480
|
})}
|
|
1836
1481
|
<View style={{ height: 1, backgroundColor: AppColors.dividerColor }}/>
|
|
@@ -1894,6 +1539,96 @@ const SettingsPanel = () => {
|
|
|
1894
1539
|
})}
|
|
1895
1540
|
</View>
|
|
1896
1541
|
|
|
1542
|
+
{/* Log Deduplication Card */}
|
|
1543
|
+
<View style={{
|
|
1544
|
+
backgroundColor: AppColors.primaryLight,
|
|
1545
|
+
borderRadius: 14,
|
|
1546
|
+
borderWidth: 1,
|
|
1547
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
1548
|
+
overflow: 'hidden',
|
|
1549
|
+
padding: 16,
|
|
1550
|
+
gap: 14,
|
|
1551
|
+
}}>
|
|
1552
|
+
<Text style={{
|
|
1553
|
+
fontFamily: AppFonts.interBold,
|
|
1554
|
+
fontSize: 11,
|
|
1555
|
+
lineHeight: 14,
|
|
1556
|
+
color: AppColors.grayTextWeak,
|
|
1557
|
+
letterSpacing: 0.8,
|
|
1558
|
+
}}>
|
|
1559
|
+
{t('settings.logFiltersDeduplication')}
|
|
1560
|
+
</Text>
|
|
1561
|
+
|
|
1562
|
+
{/* Show Duplicate Logs */}
|
|
1563
|
+
<View style={{
|
|
1564
|
+
flexDirection: 'row',
|
|
1565
|
+
alignItems: 'center',
|
|
1566
|
+
justifyContent: 'space-between',
|
|
1567
|
+
}}>
|
|
1568
|
+
<View style={{
|
|
1569
|
+
flexDirection: 'row',
|
|
1570
|
+
alignItems: 'center',
|
|
1571
|
+
gap: 10,
|
|
1572
|
+
flex: 1,
|
|
1573
|
+
}}>
|
|
1574
|
+
<View style={{
|
|
1575
|
+
width: 32,
|
|
1576
|
+
height: 32,
|
|
1577
|
+
borderRadius: 8,
|
|
1578
|
+
backgroundColor: AppColors.purpleShade50,
|
|
1579
|
+
alignItems: 'center',
|
|
1580
|
+
justifyContent: 'center',
|
|
1581
|
+
}}>
|
|
1582
|
+
<EyeIcon color={AppColors.purple} size={15}/>
|
|
1583
|
+
</View>
|
|
1584
|
+
<View style={{ flex: 1 }}>
|
|
1585
|
+
<Text style={{
|
|
1586
|
+
fontFamily: AppFonts.interBold,
|
|
1587
|
+
fontSize: 13.5,
|
|
1588
|
+
lineHeight: 18,
|
|
1589
|
+
color: AppColors.primaryBlack,
|
|
1590
|
+
}}>
|
|
1591
|
+
{t('settings.general.duplicateLogs')}
|
|
1592
|
+
</Text>
|
|
1593
|
+
<Text style={{
|
|
1594
|
+
fontFamily: AppFonts.interRegular,
|
|
1595
|
+
fontSize: 11,
|
|
1596
|
+
lineHeight: 15,
|
|
1597
|
+
color: AppColors.grayText,
|
|
1598
|
+
marginTop: 1,
|
|
1599
|
+
}}>
|
|
1600
|
+
{t('settings.general.duplicateLogsDescription')}
|
|
1601
|
+
</Text>
|
|
1602
|
+
</View>
|
|
1603
|
+
</View>
|
|
1604
|
+
|
|
1605
|
+
<TouchableScale accessible={true} accessibilityRole="switch" accessibilityLabel="Toggle show duplicate logs" accessibilityState={{ checked: showDuplicateLogs }} onPress={() => setShowDuplicateLogs(prev => !prev)} style={{
|
|
1606
|
+
width: 42,
|
|
1607
|
+
height: 24,
|
|
1608
|
+
borderRadius: 12,
|
|
1609
|
+
backgroundColor: showDuplicateLogs
|
|
1610
|
+
? AppColors.purple
|
|
1611
|
+
: AppColors.grayBorderSecondary,
|
|
1612
|
+
padding: 2,
|
|
1613
|
+
justifyContent: 'center',
|
|
1614
|
+
alignItems: showDuplicateLogs
|
|
1615
|
+
? 'flex-end'
|
|
1616
|
+
: 'flex-start',
|
|
1617
|
+
}}>
|
|
1618
|
+
<View style={{
|
|
1619
|
+
width: 20,
|
|
1620
|
+
height: 20,
|
|
1621
|
+
borderRadius: 10,
|
|
1622
|
+
backgroundColor: AppColors.white,
|
|
1623
|
+
shadowColor: AppColors.black,
|
|
1624
|
+
shadowOpacity: 0.18,
|
|
1625
|
+
shadowRadius: 2,
|
|
1626
|
+
shadowOffset: { width: 0, height: 1 },
|
|
1627
|
+
}}/>
|
|
1628
|
+
</TouchableScale>
|
|
1629
|
+
</View>
|
|
1630
|
+
</View>
|
|
1631
|
+
|
|
1897
1632
|
<View style={{
|
|
1898
1633
|
backgroundColor: AppColors.primaryLight,
|
|
1899
1634
|
borderRadius: 14,
|
|
@@ -1929,13 +1664,14 @@ const SettingsPanel = () => {
|
|
|
1929
1664
|
</View>),
|
|
1930
1665
|
})}
|
|
1931
1666
|
</View>
|
|
1667
|
+
<View style={{ height: 48 }}/>
|
|
1932
1668
|
</ScrollView>);
|
|
1933
1669
|
}
|
|
1934
1670
|
else if (settingsPage === 'analytics') {
|
|
1935
1671
|
title = t('settings.analytics.title');
|
|
1936
1672
|
icon = <AnalyticsIcon color={AppColors.white} size={16}/>;
|
|
1937
1673
|
rightInfo = t('settings.analytics.total', { count: analyticsEvents.length });
|
|
1938
|
-
content = (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16, gap: 12 }}>
|
|
1674
|
+
content = (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16, paddingBottom: 100, gap: 12 }}>
|
|
1939
1675
|
<View style={{
|
|
1940
1676
|
backgroundColor: AppColors.primaryLight,
|
|
1941
1677
|
padding: 16,
|
|
@@ -1951,8 +1687,8 @@ const SettingsPanel = () => {
|
|
|
1951
1687
|
value: maxAnalyticsEventsLimit,
|
|
1952
1688
|
onChange: setMaxAnalyticsEventsLimit,
|
|
1953
1689
|
min: 10,
|
|
1954
|
-
max:
|
|
1955
|
-
placeholder: 'Enter max events (10-
|
|
1690
|
+
max: 75,
|
|
1691
|
+
placeholder: 'Enter max events (10-75)',
|
|
1956
1692
|
},
|
|
1957
1693
|
isLast: true,
|
|
1958
1694
|
})}
|
|
@@ -1993,13 +1729,14 @@ const SettingsPanel = () => {
|
|
|
1993
1729
|
</View>),
|
|
1994
1730
|
})}
|
|
1995
1731
|
</View>
|
|
1732
|
+
<View style={{ height: 48 }}/>
|
|
1996
1733
|
</ScrollView>);
|
|
1997
1734
|
}
|
|
1998
1735
|
else if (settingsPage === 'redux') {
|
|
1999
1736
|
title = t('settings.redux.title');
|
|
2000
1737
|
icon = <ReduxIcon color={AppColors.white} size={16}/>;
|
|
2001
1738
|
rightInfo = t('settings.redux.reducers', { count: Object.keys(reduxState || {}).length });
|
|
2002
|
-
content = (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16, gap: 12 }}>
|
|
1739
|
+
content = (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16, paddingBottom: 100, gap: 12 }}>
|
|
2003
1740
|
<View style={{
|
|
2004
1741
|
backgroundColor: AppColors.primaryLight,
|
|
2005
1742
|
padding: 16,
|
|
@@ -2081,13 +1818,14 @@ const SettingsPanel = () => {
|
|
|
2081
1818
|
</View>),
|
|
2082
1819
|
})}
|
|
2083
1820
|
</View>
|
|
1821
|
+
<View style={{ height: 48 }}/>
|
|
2084
1822
|
</ScrollView>);
|
|
2085
1823
|
}
|
|
2086
1824
|
else if (settingsPage === 'crash') {
|
|
2087
1825
|
title = t('settings.crash.title');
|
|
2088
1826
|
icon = <CrashIcon color={AppColors.white} size={16}/>;
|
|
2089
1827
|
rightInfo = `Total: ${crashRecords?.length || 0}`;
|
|
2090
|
-
content = (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16, gap: 12 }}>
|
|
1828
|
+
content = (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16, paddingBottom: 100, gap: 12 }}>
|
|
2091
1829
|
<View style={{
|
|
2092
1830
|
backgroundColor: AppColors.primaryLight,
|
|
2093
1831
|
padding: 16,
|
|
@@ -2104,8 +1842,8 @@ const SettingsPanel = () => {
|
|
|
2104
1842
|
value: maxCrashLogs,
|
|
2105
1843
|
onChange: setMaxCrashLogs,
|
|
2106
1844
|
min: 5,
|
|
2107
|
-
max:
|
|
2108
|
-
placeholder: 'Enter max crashes (5-
|
|
1845
|
+
max: 50,
|
|
1846
|
+
placeholder: 'Enter max crashes (5-50)',
|
|
2109
1847
|
},
|
|
2110
1848
|
})}
|
|
2111
1849
|
<View style={{ height: 1, backgroundColor: AppColors.dividerColor }}/>
|
|
@@ -2167,13 +1905,14 @@ const SettingsPanel = () => {
|
|
|
2167
1905
|
</View>),
|
|
2168
1906
|
})}
|
|
2169
1907
|
</View>
|
|
1908
|
+
<View style={{ height: 48 }}/>
|
|
2170
1909
|
</ScrollView>);
|
|
2171
1910
|
}
|
|
2172
1911
|
else if (settingsPage === 'bundle') {
|
|
2173
1912
|
title = t('settings.bundle.title');
|
|
2174
1913
|
icon = <PackageIcon color={AppColors.white} size={16}/>;
|
|
2175
1914
|
rightInfo = 'Metro';
|
|
2176
|
-
content = (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16, gap: 12 }}>
|
|
1915
|
+
content = (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16, paddingBottom: 100, gap: 12 }}>
|
|
2177
1916
|
<View style={{
|
|
2178
1917
|
backgroundColor: AppColors.primaryLight,
|
|
2179
1918
|
padding: 16,
|
|
@@ -2250,13 +1989,14 @@ const SettingsPanel = () => {
|
|
|
2250
1989
|
</View>),
|
|
2251
1990
|
})}
|
|
2252
1991
|
</View>
|
|
1992
|
+
<View style={{ height: 48 }}/>
|
|
2253
1993
|
</ScrollView>);
|
|
2254
1994
|
}
|
|
2255
1995
|
else if (settingsPage === 'performance') {
|
|
2256
1996
|
title = t('settings.performance.title');
|
|
2257
1997
|
icon = <PerformanceIcon color={AppColors.white} size={16}/>;
|
|
2258
1998
|
rightInfo = '60 FPS Target';
|
|
2259
|
-
content = (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16, gap: 12 }}>
|
|
1999
|
+
content = (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16, paddingBottom: 100, gap: 12 }}>
|
|
2260
2000
|
<View style={{
|
|
2261
2001
|
backgroundColor: AppColors.primaryLight,
|
|
2262
2002
|
padding: 16,
|
|
@@ -2333,65 +2073,51 @@ const SettingsPanel = () => {
|
|
|
2333
2073
|
</View>),
|
|
2334
2074
|
})}
|
|
2335
2075
|
</View>
|
|
2076
|
+
<View style={{ height: 48 }}/>
|
|
2336
2077
|
</ScrollView>);
|
|
2337
2078
|
}
|
|
2079
|
+
const subPageAnim = useRef(new Animated.Value(0)).current;
|
|
2080
|
+
useEffect(() => {
|
|
2081
|
+
if (settingsPage !== 'main') {
|
|
2082
|
+
subPageAnim.setValue(0);
|
|
2083
|
+
Animated.spring(subPageAnim, {
|
|
2084
|
+
toValue: 1,
|
|
2085
|
+
friction: 8,
|
|
2086
|
+
tension: 65,
|
|
2087
|
+
useNativeDriver: true,
|
|
2088
|
+
}).start();
|
|
2089
|
+
}
|
|
2090
|
+
}, [settingsPage]);
|
|
2338
2091
|
return (<View style={{
|
|
2339
2092
|
flex: 1,
|
|
2340
2093
|
backgroundColor: AppColors.grayBackground,
|
|
2341
2094
|
}}>
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
lineHeight: 22,
|
|
2369
|
-
color: AppColors.white,
|
|
2370
|
-
}}>
|
|
2371
|
-
{title}
|
|
2372
|
-
</Text>
|
|
2373
|
-
</View>
|
|
2374
|
-
{rightInfo ? (<View style={{
|
|
2375
|
-
backgroundColor: `${AppColors.white}26`,
|
|
2376
|
-
paddingHorizontal: 8,
|
|
2377
|
-
paddingVertical: 4,
|
|
2378
|
-
borderRadius: 8,
|
|
2379
|
-
borderWidth: 1,
|
|
2380
|
-
borderColor: `${AppColors.white}1A`,
|
|
2381
|
-
}}>
|
|
2382
|
-
<Text style={{
|
|
2383
|
-
fontFamily: AppFonts.interBold,
|
|
2384
|
-
fontSize: 11,
|
|
2385
|
-
lineHeight: 14,
|
|
2386
|
-
color: AppColors.white,
|
|
2387
|
-
}}>
|
|
2388
|
-
{rightInfo}
|
|
2389
|
-
</Text>
|
|
2390
|
-
</View>) : null}
|
|
2391
|
-
</View>
|
|
2392
|
-
</View>
|
|
2393
|
-
</LinearGradient>
|
|
2394
|
-
{content}
|
|
2095
|
+
{/* ─── Persistent Main Settings (Retains 100% scroll position) ─── */}
|
|
2096
|
+
<View style={[
|
|
2097
|
+
StyleSheet.absoluteFill,
|
|
2098
|
+
settingsPage !== 'main' && { pointerEvents: 'none' },
|
|
2099
|
+
]}>
|
|
2100
|
+
{renderMainSettingsContent()}
|
|
2101
|
+
</View>
|
|
2102
|
+
|
|
2103
|
+
{/* ─── Sub-module Settings Overlay (Smooth Animated Slide) ─── */}
|
|
2104
|
+
{settingsPage !== 'main' && (<Animated.View style={[
|
|
2105
|
+
StyleSheet.absoluteFill,
|
|
2106
|
+
{
|
|
2107
|
+
backgroundColor: AppColors.grayBackground,
|
|
2108
|
+
opacity: subPageAnim,
|
|
2109
|
+
transform: [
|
|
2110
|
+
{
|
|
2111
|
+
translateX: subPageAnim.interpolate({
|
|
2112
|
+
inputRange: [0, 1],
|
|
2113
|
+
outputRange: [30, 0],
|
|
2114
|
+
}),
|
|
2115
|
+
},
|
|
2116
|
+
],
|
|
2117
|
+
},
|
|
2118
|
+
]}>
|
|
2119
|
+
{content}
|
|
2120
|
+
</Animated.View>)}
|
|
2395
2121
|
</View>);
|
|
2396
2122
|
};
|
|
2397
2123
|
export default SettingsPanel;
|