@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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-settings",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "Settings management for React Native apps - user preferences, theme, language, notifications",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
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 { useTranslation } from 'react-i18next';
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
- export const SettingsScreen: React.FC = () => {
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
- <List.Section style={{ marginBottom: 8 }}>
68
- <List.Subheader style={{ color: theme.colors.textSecondary }}>{t('settings.sections.appearance')}</List.Subheader>
69
- <SettingItem
70
- icon="Palette"
71
- iconGradient={theme.colors.settingGradients.themeLight as unknown as string[]}
72
- title={t('settings.appearance.title')}
73
- description={t('settings.appearance.themeDescription')}
74
- onPress={handleAppearancePress}
75
- testID="appearance-button"
76
- />
77
- </List.Section>
78
-
79
- {/* General Section */}
80
- <List.Section style={{ marginBottom: 8 }}>
81
- <List.Subheader style={{ color: theme.colors.textSecondary }}>{t('settings.sections.general')}</List.Subheader>
82
- <SettingItem
83
- icon="Bell"
84
- iconGradient={theme.colors.settingGradients.notifications as unknown as string[]}
85
- title={t('settings.notifications.title')}
86
- description={t('settings.notifications.description')}
87
- onPress={handleNotificationsPress}
88
- testID="notifications-button"
89
- />
90
- </List.Section>
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
- <List.Section style={{ marginBottom: 8 }}>
94
- <List.Subheader style={{ color: theme.colors.textSecondary }}>{t('settings.sections.about')}</List.Subheader>
95
- <SettingItem
96
- icon="Info"
97
- iconGradient={theme.colors.settingGradients.info as unknown as string[]}
98
- title={t('settings.about.title')}
99
- description={t('settings.about.description')}
100
- onPress={handleAboutPress}
101
- testID="about-button"
102
- />
103
- <Divider />
104
- <SettingItem
105
- icon="FileText"
106
- iconGradient={theme.colors.settingGradients.info as unknown as string[]}
107
- title={t('settings.legal.title')}
108
- description={t('settings.legal.description')}
109
- onPress={handleLegalPress}
110
- testID="legal-button"
111
- />
112
- </List.Section>
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
+