@umituz/react-native-settings 1.2.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -33,9 +33,16 @@ export {
|
|
|
33
33
|
// =============================================================================
|
|
34
34
|
|
|
35
35
|
export { SettingsScreen } from './presentation/screens/SettingsScreen';
|
|
36
|
+
export type { SettingsScreenProps } from './presentation/screens/SettingsScreen';
|
|
36
37
|
export { AppearanceScreen } from './presentation/screens/AppearanceScreen';
|
|
37
38
|
export { LanguageSelectionScreen } from './presentation/screens/LanguageSelectionScreen';
|
|
38
39
|
|
|
40
|
+
// =============================================================================
|
|
41
|
+
// PRESENTATION LAYER - Types
|
|
42
|
+
// =============================================================================
|
|
43
|
+
|
|
44
|
+
export type { SettingsConfig } from './presentation/screens/types';
|
|
45
|
+
|
|
39
46
|
// =============================================================================
|
|
40
47
|
// PRESENTATION LAYER - Components
|
|
41
48
|
// =============================================================================
|
|
@@ -8,9 +8,10 @@
|
|
|
8
8
|
* - Material Design 3 compliance
|
|
9
9
|
* - OFFLINE MODE: No account, premium, feedback, or donation
|
|
10
10
|
* - Optimized spacing for better visual density
|
|
11
|
+
* - Configurable features via SettingsConfig prop
|
|
11
12
|
*/
|
|
12
13
|
|
|
13
|
-
import React from 'react';
|
|
14
|
+
import React, { useMemo } from 'react';
|
|
14
15
|
import { List, Divider } from 'react-native-paper';
|
|
15
16
|
|
|
16
17
|
import { useNavigation } from '@react-navigation/native';
|
|
@@ -18,7 +19,7 @@ import { useTheme } from '@umituz/react-native-design-system-theme';
|
|
|
18
19
|
import { ScreenLayout } from '@umituz/react-native-design-system';
|
|
19
20
|
import { SettingItem } from '../components/SettingItem';
|
|
20
21
|
import { getLanguageByCode, useLocalization } from '@umituz/react-native-localization';
|
|
21
|
-
import {
|
|
22
|
+
import { SettingsConfig } from './types';
|
|
22
23
|
|
|
23
24
|
// Optional notification service - only import if package is available
|
|
24
25
|
let notificationService: any = null;
|
|
@@ -29,16 +30,79 @@ try {
|
|
|
29
30
|
// Package not available, notificationService will be null
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Check if a navigation screen exists in the navigation state
|
|
35
|
+
*/
|
|
36
|
+
const hasNavigationScreen = (navigation: any, screenName: string): boolean => {
|
|
37
|
+
try {
|
|
38
|
+
const state = navigation.getState();
|
|
39
|
+
if (!state) return false;
|
|
40
|
+
|
|
41
|
+
// Recursively check all routes in navigation state
|
|
42
|
+
const checkRoutes = (routes: any[]): boolean => {
|
|
43
|
+
if (!routes || !Array.isArray(routes)) return false;
|
|
44
|
+
|
|
45
|
+
for (const route of routes) {
|
|
46
|
+
if (route.name === screenName) {
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
// Check nested navigators
|
|
50
|
+
if (route.state?.routes) {
|
|
51
|
+
if (checkRoutes(route.state.routes)) {
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return false;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
return checkRoutes(state.routes || []);
|
|
60
|
+
} catch {
|
|
61
|
+
// If we can't check navigation state, assume it's not available
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export interface SettingsScreenProps {
|
|
67
|
+
/**
|
|
68
|
+
* Configuration for which settings features to show
|
|
69
|
+
* @default { appearance: 'auto', notifications: 'auto', about: 'auto', legal: 'auto' }
|
|
70
|
+
*/
|
|
71
|
+
config?: SettingsConfig;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export const SettingsScreen: React.FC<SettingsScreenProps> = ({
|
|
75
|
+
config = {}
|
|
76
|
+
}) => {
|
|
33
77
|
const navigation = useNavigation();
|
|
34
78
|
const { theme, themeMode } = useTheme();
|
|
35
|
-
const { currentLanguage } = useLocalization();
|
|
36
|
-
const { t } = useTranslation();
|
|
79
|
+
const { currentLanguage, t } = useLocalization();
|
|
37
80
|
|
|
38
81
|
const currentLang = getLanguageByCode(currentLanguage);
|
|
39
82
|
const languageDisplay = currentLang ? `${currentLang.flag} ${currentLang.nativeName}` : 'English';
|
|
40
83
|
const themeDisplay = themeMode === 'dark' ? t('settings.darkMode') : t('settings.lightMode');
|
|
41
84
|
|
|
85
|
+
// Determine which features should be shown
|
|
86
|
+
const features = useMemo(() => {
|
|
87
|
+
const appearanceConfig = config.appearance ?? 'auto';
|
|
88
|
+
const notificationsConfig = config.notifications ?? 'auto';
|
|
89
|
+
const aboutConfig = config.about ?? 'auto';
|
|
90
|
+
const legalConfig = config.legal ?? 'auto';
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
appearance: appearanceConfig === true ||
|
|
94
|
+
(appearanceConfig === 'auto' && hasNavigationScreen(navigation, 'Appearance')),
|
|
95
|
+
notifications: notificationsConfig === true ||
|
|
96
|
+
(notificationsConfig === 'auto' &&
|
|
97
|
+
notificationService !== null &&
|
|
98
|
+
hasNavigationScreen(navigation, 'Notifications')),
|
|
99
|
+
about: aboutConfig === true ||
|
|
100
|
+
(aboutConfig === 'auto' && hasNavigationScreen(navigation, 'About')),
|
|
101
|
+
legal: legalConfig === true ||
|
|
102
|
+
(legalConfig === 'auto' && hasNavigationScreen(navigation, 'Legal')),
|
|
103
|
+
};
|
|
104
|
+
}, [config, navigation]);
|
|
105
|
+
|
|
42
106
|
const handleAppearancePress = () => {
|
|
43
107
|
navigation.navigate('Appearance' as never);
|
|
44
108
|
};
|
|
@@ -64,52 +128,62 @@ export const SettingsScreen: React.FC = () => {
|
|
|
64
128
|
return (
|
|
65
129
|
<ScreenLayout testID="settings-screen" hideScrollIndicator>
|
|
66
130
|
{/* Appearance Section */}
|
|
67
|
-
|
|
68
|
-
<List.
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
131
|
+
{features.appearance && (
|
|
132
|
+
<List.Section style={{ marginBottom: 8 }}>
|
|
133
|
+
<List.Subheader style={{ color: theme.colors.textSecondary }}>{t('settings.sections.appearance')}</List.Subheader>
|
|
134
|
+
<SettingItem
|
|
135
|
+
icon="Palette"
|
|
136
|
+
iconGradient={theme.colors.settingGradients.themeLight as unknown as string[]}
|
|
137
|
+
title={t('settings.appearance.title')}
|
|
138
|
+
description={t('settings.appearance.themeDescription')}
|
|
139
|
+
onPress={handleAppearancePress}
|
|
140
|
+
testID="appearance-button"
|
|
141
|
+
/>
|
|
142
|
+
</List.Section>
|
|
143
|
+
)}
|
|
144
|
+
|
|
145
|
+
{/* General Section - Notifications */}
|
|
146
|
+
{features.notifications && (
|
|
147
|
+
<List.Section style={{ marginBottom: 8 }}>
|
|
148
|
+
<List.Subheader style={{ color: theme.colors.textSecondary }}>{t('settings.sections.general')}</List.Subheader>
|
|
149
|
+
<SettingItem
|
|
150
|
+
icon="Bell"
|
|
151
|
+
iconGradient={theme.colors.settingGradients.notifications as unknown as string[]}
|
|
152
|
+
title={t('settings.notifications.title')}
|
|
153
|
+
description={t('settings.notifications.description')}
|
|
154
|
+
onPress={handleNotificationsPress}
|
|
155
|
+
testID="notifications-button"
|
|
156
|
+
/>
|
|
157
|
+
</List.Section>
|
|
158
|
+
)}
|
|
91
159
|
|
|
92
160
|
{/* About & Legal Section */}
|
|
93
|
-
|
|
94
|
-
<List.
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
161
|
+
{(features.about || features.legal) && (
|
|
162
|
+
<List.Section style={{ marginBottom: 8 }}>
|
|
163
|
+
<List.Subheader style={{ color: theme.colors.textSecondary }}>{t('settings.sections.about')}</List.Subheader>
|
|
164
|
+
{features.about && (
|
|
165
|
+
<SettingItem
|
|
166
|
+
icon="Info"
|
|
167
|
+
iconGradient={theme.colors.settingGradients.info as unknown as string[]}
|
|
168
|
+
title={t('settings.about.title')}
|
|
169
|
+
description={t('settings.about.description')}
|
|
170
|
+
onPress={handleAboutPress}
|
|
171
|
+
testID="about-button"
|
|
172
|
+
/>
|
|
173
|
+
)}
|
|
174
|
+
{features.about && features.legal && <Divider />}
|
|
175
|
+
{features.legal && (
|
|
176
|
+
<SettingItem
|
|
177
|
+
icon="FileText"
|
|
178
|
+
iconGradient={theme.colors.settingGradients.info as unknown as string[]}
|
|
179
|
+
title={t('settings.legal.title')}
|
|
180
|
+
description={t('settings.legal.description')}
|
|
181
|
+
onPress={handleLegalPress}
|
|
182
|
+
testID="legal-button"
|
|
183
|
+
/>
|
|
184
|
+
)}
|
|
185
|
+
</List.Section>
|
|
186
|
+
)}
|
|
113
187
|
</ScreenLayout>
|
|
114
188
|
);
|
|
115
189
|
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings Configuration
|
|
3
|
+
*
|
|
4
|
+
* Controls which settings features are visible in the SettingsScreen.
|
|
5
|
+
* Each feature can be:
|
|
6
|
+
* - true: Always show (if navigation screen exists)
|
|
7
|
+
* - false: Never show
|
|
8
|
+
* - 'auto': Automatically detect (check if navigation screen exists and package is available)
|
|
9
|
+
*/
|
|
10
|
+
export interface SettingsConfig {
|
|
11
|
+
/**
|
|
12
|
+
* Show Appearance settings (Theme & Language)
|
|
13
|
+
* @default 'auto'
|
|
14
|
+
*/
|
|
15
|
+
appearance?: boolean | 'auto';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Show Notifications settings
|
|
19
|
+
* @default 'auto'
|
|
20
|
+
*/
|
|
21
|
+
notifications?: boolean | 'auto';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Show About settings
|
|
25
|
+
* @default 'auto'
|
|
26
|
+
*/
|
|
27
|
+
about?: boolean | 'auto';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Show Legal settings (Terms, Privacy Policy)
|
|
31
|
+
* @default 'auto'
|
|
32
|
+
*/
|
|
33
|
+
legal?: boolean | 'auto';
|
|
34
|
+
}
|
|
35
|
+
|