@umituz/react-native-settings 4.7.2 → 4.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-settings",
3
- "version": "4.7.2",
3
+ "version": "4.9.0",
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",
@@ -51,6 +51,7 @@
51
51
  "@babel/plugin-transform-runtime": "^7.28.5",
52
52
  "@expo/vector-icons": "^14.0.0",
53
53
  "@react-native/babel-preset": "^0.83.0",
54
+ "@react-navigation/native": "^6.1.17",
54
55
  "@react-navigation/stack": "^7.6.12",
55
56
  "@testing-library/jest-native": "^5.4.3",
56
57
  "@testing-library/react-hooks": "^8.0.1",
package/src/index.ts CHANGED
@@ -76,3 +76,5 @@ export type { CloudSyncSettingProps } from './presentation/components/CloudSyncS
76
76
  export { StorageClearSetting } from './presentation/components/StorageClearSetting';
77
77
  export type { StorageClearSettingProps } from './presentation/components/StorageClearSetting';
78
78
 
79
+ export { DevSettingsSection } from './presentation/components/DevSettingsSection';
80
+ export type { DevSettingsProps } from './presentation/components/DevSettingsSection';
@@ -35,7 +35,7 @@ const getDefaultSettings = (userId: string): UserSettings => {
35
35
  if (DEFAULT_SETTINGS_CACHE.has(userId)) {
36
36
  return DEFAULT_SETTINGS_CACHE.get(userId)!;
37
37
  }
38
-
38
+
39
39
  const settings = {
40
40
  userId,
41
41
  theme: 'auto' as const,
@@ -48,7 +48,7 @@ const getDefaultSettings = (userId: string): UserSettings => {
48
48
  privacyMode: false,
49
49
  updatedAt: new Date(),
50
50
  };
51
-
51
+
52
52
  DEFAULT_SETTINGS_CACHE.set(userId, settings);
53
53
  return settings;
54
54
  };
@@ -62,12 +62,12 @@ export const useSettingsStore = create<SettingsStore>((set, get) => ({
62
62
  if (__DEV__) {
63
63
  console.log('SettingsStore: Loading settings for user:', userId);
64
64
  }
65
-
65
+
66
66
  set({ loading: true, error: null });
67
67
 
68
68
  try {
69
69
  const defaultSettings = getDefaultSettings(userId);
70
- const storageKey = createUserKey(StorageKey.SETTINGS, userId);
70
+ const storageKey = createUserKey(StorageKey.USER_PREFERENCES, userId);
71
71
 
72
72
  // ✅ DRY: Storage domain handles JSON parse, error handling
73
73
  const result = await storageRepository.getItem<UserSettings>(storageKey, defaultSettings);
@@ -127,7 +127,7 @@ export const useSettingsStore = create<SettingsStore>((set, get) => ({
127
127
  updatedAt: new Date(),
128
128
  };
129
129
 
130
- const storageKey = createUserKey(StorageKey.SETTINGS, currentSettings.userId);
130
+ const storageKey = createUserKey(StorageKey.USER_PREFERENCES, currentSettings.userId);
131
131
 
132
132
  // ✅ DRY: Storage domain replaces JSON.stringify + AsyncStorage + try/catch
133
133
  const result = await storageRepository.setItem(storageKey, updatedSettings);
@@ -153,7 +153,7 @@ export const useSettingsStore = create<SettingsStore>((set, get) => ({
153
153
  set({ loading: true, error: null });
154
154
 
155
155
  const defaultSettings = getDefaultSettings(userId);
156
- const storageKey = createUserKey(StorageKey.SETTINGS, userId);
156
+ const storageKey = createUserKey(StorageKey.USER_PREFERENCES, userId);
157
157
 
158
158
  // ✅ DRY: Storage domain replaces JSON.stringify + AsyncStorage + try/catch
159
159
  const result = await storageRepository.setItem(storageKey, defaultSettings);
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Dev Settings Section Component
3
+ * Only visible in __DEV__ mode
4
+ * Provides development utilities like clearing storage
5
+ */
6
+
7
+ import React from "react";
8
+ import { Alert } from "react-native";
9
+ import { Feather } from "@expo/vector-icons";
10
+ import { useLocalization } from "@umituz/react-native-localization";
11
+ import { useAppDesignTokens } from "@umituz/react-native-design-system-theme";
12
+ import { SettingsSection } from "./SettingsSection";
13
+ import { SettingItem } from "./SettingItem";
14
+
15
+ // Icon wrapper for SettingItem compatibility
16
+ const TrashIcon: React.FC<{ size?: number; color?: string }> = ({ size = 24, color }) => (
17
+ <Feather name="trash-2" size={size} color={color} />
18
+ );
19
+
20
+ export interface DevSettingsProps {
21
+ /** Callback to clear all storage and reset app */
22
+ onClearAllData?: () => Promise<void>;
23
+ /** Custom title for the section */
24
+ sectionTitle?: string;
25
+ /** Custom title for clear data button */
26
+ clearDataTitle?: string;
27
+ /** Custom description for clear data button */
28
+ clearDataDescription?: string;
29
+ }
30
+
31
+ export const DevSettingsSection: React.FC<DevSettingsProps> = ({
32
+ onClearAllData,
33
+ sectionTitle,
34
+ clearDataTitle,
35
+ clearDataDescription,
36
+ }) => {
37
+ const { t } = useLocalization();
38
+ const tokens = useAppDesignTokens();
39
+
40
+ // Only render in development mode
41
+ if (!__DEV__) {
42
+ return null;
43
+ }
44
+
45
+ // Don't render if no handler provided
46
+ if (!onClearAllData) {
47
+ return null;
48
+ }
49
+
50
+ const handleClearData = () => {
51
+ Alert.alert(
52
+ t("settings.devSettings.clearData.confirmTitle") || "Clear All Data?",
53
+ t("settings.devSettings.clearData.confirmMessage") || "This will clear all app data and reset to initial state. This action cannot be undone.",
54
+ [
55
+ {
56
+ text: t("common.cancel") || "Cancel",
57
+ style: "cancel",
58
+ },
59
+ {
60
+ text: t("common.confirm") || "Confirm",
61
+ style: "destructive",
62
+ onPress: async () => {
63
+ try {
64
+ await onClearAllData();
65
+ } catch {
66
+ Alert.alert(
67
+ t("common.error") || "Error",
68
+ t("settings.devSettings.clearData.error") || "Failed to clear data"
69
+ );
70
+ }
71
+ },
72
+ },
73
+ ]
74
+ );
75
+ };
76
+
77
+ return (
78
+ <SettingsSection
79
+ title={sectionTitle || t("settings.devSettings.title") || "Developer"}
80
+ >
81
+ <SettingItem
82
+ icon={TrashIcon}
83
+ title={clearDataTitle || t("settings.devSettings.clearData.title") || "Clear All Data"}
84
+ value={
85
+ clearDataDescription ||
86
+ t("settings.devSettings.clearData.description") || "Reset app to initial state (DEV only)"
87
+ }
88
+ onPress={handleClearData}
89
+ iconColor={tokens.colors.error}
90
+ titleColor={tokens.colors.error}
91
+ isLast={true}
92
+ />
93
+ </SettingsSection>
94
+ );
95
+ };
@@ -11,6 +11,7 @@ import { useAppDesignTokens } from "@umituz/react-native-design-system-theme";
11
11
  import { SettingsScreen } from "../screens/SettingsScreen";
12
12
  import { AppearanceScreen } from "../screens/AppearanceScreen";
13
13
  import type { SettingsConfig } from "../screens/types";
14
+ import type { DevSettingsProps } from "../components/DevSettingsSection";
14
15
 
15
16
  // Default param list - can be extended by apps
16
17
  export type SettingsStackParamList = {
@@ -58,6 +59,11 @@ export interface SettingsStackNavigatorProps {
58
59
  component: React.ComponentType<any>;
59
60
  options?: any;
60
61
  }>;
62
+
63
+ /**
64
+ * Dev settings (only shown in __DEV__ mode)
65
+ */
66
+ devSettings?: DevSettingsProps;
61
67
  }
62
68
 
63
69
  const Stack = createStackNavigator<SettingsStackParamList>();
@@ -68,6 +74,7 @@ export const SettingsStackNavigator: React.FC<SettingsStackNavigatorProps> = ({
68
74
  showUserProfile = false,
69
75
  userProfile,
70
76
  additionalScreens = [],
77
+ devSettings,
71
78
  }) => {
72
79
  const tokens = useAppDesignTokens();
73
80
 
@@ -93,11 +100,12 @@ export const SettingsStackNavigator: React.FC<SettingsStackNavigatorProps> = ({
93
100
  appVersion={appVersion}
94
101
  showUserProfile={showUserProfile}
95
102
  userProfile={userProfile}
103
+ devSettings={devSettings}
96
104
  />
97
105
  );
98
106
  Wrapper.displayName = "SettingsScreenWrapper";
99
107
  return Wrapper;
100
- }, [config, appVersion, showUserProfile, userProfile]);
108
+ }, [config, appVersion, showUserProfile, userProfile, devSettings]);
101
109
 
102
110
  return (
103
111
  <Stack.Navigator screenOptions={screenOptions}>
@@ -16,6 +16,7 @@ import { SettingsErrorBoundary } from "../components/SettingsErrorBoundary";
16
16
  import { normalizeSettingsConfig } from "./utils/normalizeConfig";
17
17
  import { useFeatureDetection } from "./hooks/useFeatureDetection";
18
18
  import type { SettingsConfig, CustomSettingsSection } from "./types";
19
+ import type { DevSettingsProps } from "../components/DevSettingsSection";
19
20
 
20
21
  export interface SettingsScreenProps {
21
22
  config?: SettingsConfig;
@@ -48,6 +49,8 @@ export interface SettingsScreenProps {
48
49
  featureOptions?: {
49
50
  notificationServiceAvailable?: boolean;
50
51
  };
52
+ /** Dev settings (only shown in __DEV__ mode) */
53
+ devSettings?: DevSettingsProps;
51
54
  }
52
55
 
53
56
  export const SettingsScreen: React.FC<SettingsScreenProps> = ({
@@ -61,6 +64,7 @@ export const SettingsScreen: React.FC<SettingsScreenProps> = ({
61
64
  showCloseButton = false,
62
65
  onClose,
63
66
  featureOptions,
67
+ devSettings,
64
68
  }) => {
65
69
  const navigation = useNavigation();
66
70
  const { themeMode } = useDesignSystemTheme();
@@ -92,6 +96,7 @@ export const SettingsScreen: React.FC<SettingsScreenProps> = ({
92
96
  appVersion={appVersion}
93
97
  customSections={customSections}
94
98
  showCloseButton={showCloseButton}
99
+ devSettings={devSettings}
95
100
  />
96
101
  </SettingsErrorBoundary>
97
102
  </View>
@@ -11,6 +11,7 @@ import { useLocalization } from "@umituz/react-native-localization";
11
11
  import { SettingsFooter } from "../../components/SettingsFooter";
12
12
  import { UserProfileHeader } from "../../components/UserProfileHeader";
13
13
  import { SettingsSection } from "../../components/SettingsSection";
14
+ import { DevSettingsSection, DevSettingsProps } from "../../components/DevSettingsSection";
14
15
  import { NotificationsSection } from "@umituz/react-native-notifications";
15
16
  import { AboutSection } from "@umituz/react-native-about";
16
17
  import { LegalSection } from "@umituz/react-native-legal";
@@ -59,6 +60,8 @@ interface SettingsContentProps {
59
60
  appVersion?: string;
60
61
  customSections?: CustomSettingsSection[];
61
62
  showCloseButton?: boolean;
63
+ /** Dev settings (only shown in __DEV__ mode) */
64
+ devSettings?: DevSettingsProps;
62
65
  }
63
66
 
64
67
  export const SettingsContent: React.FC<SettingsContentProps> = ({
@@ -72,6 +75,7 @@ export const SettingsContent: React.FC<SettingsContentProps> = ({
72
75
  appVersion,
73
76
  customSections = [],
74
77
  showCloseButton = false,
78
+ devSettings,
75
79
  }) => {
76
80
  const tokens = useAppDesignTokens();
77
81
  const insets = useSafeAreaInsets();
@@ -122,23 +126,71 @@ export const SettingsContent: React.FC<SettingsContentProps> = ({
122
126
  )}
123
127
 
124
128
  {features.appearance && (
125
- <AppearanceSection config={normalizedConfig.appearance.config} />
129
+ <AppearanceSection
130
+ config={{
131
+ ...normalizedConfig.appearance.config,
132
+ title:
133
+ normalizedConfig.appearance.config?.title ||
134
+ t("settings.appearance.title"),
135
+ description:
136
+ normalizedConfig.appearance.config?.description ||
137
+ t("settings.appearance.description"),
138
+ }}
139
+ />
126
140
  )}
127
141
 
128
142
  {features.language && (
129
- <LanguageSection config={normalizedConfig.language.config} />
143
+ <LanguageSection
144
+ config={{
145
+ ...normalizedConfig.language.config,
146
+ title: t("settings.languageSelection.title"),
147
+ description:
148
+ normalizedConfig.language.config?.description ||
149
+ t("settings.languageSelection.description"),
150
+ }}
151
+ />
130
152
  )}
131
153
 
132
154
  {features.notifications && (
133
- <NotificationsSection config={normalizedConfig.notifications.config} />
155
+ <NotificationsSection
156
+ config={{
157
+ ...normalizedConfig.notifications.config,
158
+ title:
159
+ normalizedConfig.notifications.config?.title ||
160
+ t("settings.notifications.title"),
161
+ description:
162
+ normalizedConfig.notifications.config?.description ||
163
+ t("settings.notifications.description"),
164
+ }}
165
+ />
134
166
  )}
135
167
 
136
168
  {features.about && (
137
- <AboutSection config={normalizedConfig.about.config} />
169
+ <AboutSection
170
+ config={{
171
+ ...normalizedConfig.about.config,
172
+ title:
173
+ normalizedConfig.about.config?.title ||
174
+ t("settings.about.title"),
175
+ description:
176
+ normalizedConfig.about.config?.description ||
177
+ t("settings.about.description"),
178
+ }}
179
+ />
138
180
  )}
139
181
 
140
182
  {features.legal && (
141
- <LegalSection config={normalizedConfig.legal.config} />
183
+ <LegalSection
184
+ config={{
185
+ ...normalizedConfig.legal.config,
186
+ title:
187
+ normalizedConfig.legal.config?.title ||
188
+ t("settings.legal.title"),
189
+ description:
190
+ normalizedConfig.legal.config?.description ||
191
+ t("settings.legal.description"),
192
+ }}
193
+ />
142
194
  )}
143
195
 
144
196
  {features.disclaimer && DisclaimerSetting && (
@@ -168,6 +220,15 @@ export const SettingsContent: React.FC<SettingsContentProps> = ({
168
220
  </View>
169
221
  )}
170
222
 
223
+ {devSettings && (
224
+ <DevSettingsSection
225
+ onClearAllData={devSettings.onClearAllData}
226
+ sectionTitle={devSettings.sectionTitle}
227
+ clearDataTitle={devSettings.clearDataTitle}
228
+ clearDataDescription={devSettings.clearDataDescription}
229
+ />
230
+ )}
231
+
171
232
  {showFooter && <SettingsFooter versionText={footerText} appVersion={appVersion} />}
172
233
  </ScrollView>
173
234
  );