@umituz/react-native-settings 4.20.25 → 4.20.27

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.20.25",
3
+ "version": "4.20.27",
4
4
  "description": "Complete settings hub for React Native apps - consolidated package with settings, about, legal, appearance, feedback, FAQs, and rating",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -36,8 +36,6 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "@react-native-async-storage/async-storage": "^2.2.0",
39
- "@react-native-firebase/app": "^23.7.0",
40
- "@react-native-firebase/firestore": "^23.7.0",
41
39
  "@umituz/react-native-auth": "latest",
42
40
  "@umituz/react-native-design-system": "latest",
43
41
  "@umituz/react-native-localization": "latest",
package/src/index.ts CHANGED
@@ -53,8 +53,13 @@ export { AppearanceScreen } from './presentation/screens/AppearanceScreen';
53
53
  export { SettingsStackNavigator } from './presentation/navigation/SettingsStackNavigator';
54
54
  export type {
55
55
  SettingsStackNavigatorProps,
56
- SettingsStackParamList
57
- } from './presentation/navigation/SettingsStackNavigator';
56
+ SettingsStackParamList,
57
+ AppInfo,
58
+ LegalUrls,
59
+ UserProfileConfig,
60
+ AdditionalScreen,
61
+ FAQData,
62
+ } from './presentation/navigation/types';
58
63
 
59
64
  // =============================================================================
60
65
  // PRESENTATION LAYER - Types
@@ -1,152 +1,166 @@
1
1
  /**
2
2
  * Settings Stack Navigator
3
- *
4
- * Base stack navigator for settings screens
5
- * Can be extended by apps to add custom screens
3
+ *
4
+ * Complete settings navigation with all screens.
5
+ * Receives appInfo and legalUrls from app.
6
6
  */
7
7
 
8
8
  import React, { useMemo } from "react";
9
9
  import { createStackNavigator } from "@react-navigation/stack";
10
10
  import { useAppDesignTokens } from "@umituz/react-native-design-system";
11
+ import { useLocalization } from "@umituz/react-native-localization";
11
12
  import { SettingsScreen } from "../screens/SettingsScreen";
12
13
  import { AppearanceScreen } from "../screens/AppearanceScreen";
13
- import type { SettingsConfig, CustomSettingsSection, AppearanceConfig } from "../screens/types";
14
- import type { DevSettingsProps } from "../components/DevSettingsSection";
15
- import type { AppearanceTexts } from "../../domains/appearance/types";
16
-
17
- // Default param list - can be extended by apps
18
- export type SettingsStackParamList = {
19
- Settings: { config?: SettingsConfig };
20
- Appearance: undefined;
21
- // About and Legal screens will be handled by external packages
22
- };
23
-
24
- export interface SettingsStackNavigatorProps {
25
- /**
26
- * Settings configuration
27
- */
28
- config?: SettingsConfig;
29
-
30
- /**
31
- * App version number from app config (e.g., "1.0.0")
32
- */
33
- appVersion?: string;
34
-
35
- /**
36
- * Show user profile header
37
- */
38
- showUserProfile?: boolean;
39
-
40
- /**
41
- * User profile props for anonymous/authenticated users
42
- */
43
- userProfile?: {
44
- displayName?: string;
45
- userId?: string;
46
- isAnonymous?: boolean;
47
- avatarUrl?: string;
48
- accountSettingsRoute?: string;
49
- onPress?: () => void;
50
- anonymousDisplayName?: string;
51
- avatarServiceUrl?: string;
52
- };
53
-
54
- /**
55
- * Additional screens to register
56
- * Apps can add their own screens here
57
- */
58
- additionalScreens?: Array<{
59
- name: string;
60
- component: React.ComponentType<any>;
61
- options?: any;
62
- }>;
63
-
64
- /**
65
- * Dev settings (only shown in __DEV__ mode)
66
- */
67
- devSettings?: DevSettingsProps;
68
-
69
- /**
70
- * Custom sections to render in settings list
71
- * Use this to add app-specific items like subscription
72
- */
73
- customSections?: CustomSettingsSection[];
74
- }
14
+ import { LegalScreen } from "../../domains/legal";
15
+ import { AboutScreen } from "../../domains/about";
16
+ import { FAQScreen } from "../../domains/faqs";
17
+ import { useNavigationHandlers } from "./hooks";
18
+ import type { SettingsStackParamList, SettingsStackNavigatorProps } from "./types";
75
19
 
76
20
  const Stack = createStackNavigator<SettingsStackParamList>();
77
21
 
78
22
  export const SettingsStackNavigator: React.FC<SettingsStackNavigatorProps> = ({
79
- config = {},
80
- appVersion,
81
- showUserProfile = false,
82
- userProfile,
83
- additionalScreens = [],
84
- devSettings,
85
- customSections = [],
23
+ appInfo,
24
+ legalUrls,
25
+ faqData,
26
+ config = {},
27
+ showUserProfile = false,
28
+ userProfile,
29
+ additionalScreens = [],
30
+ devSettings,
31
+ customSections = [],
86
32
  }) => {
87
- const tokens = useAppDesignTokens();
88
-
89
- const screenOptions = {
90
- headerStyle: {
91
- backgroundColor: tokens.colors.surface,
92
- borderBottomColor: tokens.colors.borderLight,
93
- borderBottomWidth: 1,
94
- },
95
- headerTitleStyle: {
96
- fontSize: 18,
97
- fontWeight: "600" as const,
98
- color: tokens.colors.textPrimary,
99
- },
100
- headerTintColor: tokens.colors.textPrimary,
101
- };
102
-
103
- // Memoize SettingsScreen wrapper to prevent remounting on every render
104
- const SettingsScreenWrapper = React.useMemo(() => {
105
- const Wrapper = () => (
106
- <SettingsScreen
107
- config={config}
108
- appVersion={appVersion}
109
- showUserProfile={showUserProfile}
110
- userProfile={userProfile}
111
- devSettings={devSettings}
112
- customSections={customSections}
113
- />
114
- );
115
- Wrapper.displayName = "SettingsScreenWrapper";
116
- return Wrapper;
117
- }, [config, appVersion, showUserProfile, userProfile, devSettings, customSections]);
118
-
119
- return (
120
- <Stack.Navigator screenOptions={screenOptions}>
121
- <Stack.Screen
122
- name="Settings"
123
- component={SettingsScreenWrapper}
124
- options={{
125
- headerShown: false,
126
- title: "Settings",
127
- }}
128
- />
129
-
130
- <Stack.Screen
131
- name="Appearance"
132
- component={AppearanceScreen}
133
- options={{
134
- headerShown: true,
135
- headerTitle: "Appearance",
136
- headerTitleAlign: "center",
137
- headerBackTitle: "Settings",
138
- }}
139
- />
140
-
141
- {/* Render additional screens */}
142
- {additionalScreens.map((screen) => (
143
- <Stack.Screen
144
- key={screen.name}
145
- name={screen.name as any}
146
- component={screen.component}
147
- options={screen.options}
148
- />
149
- ))}
150
- </Stack.Navigator>
33
+ const tokens = useAppDesignTokens();
34
+ const { t } = useLocalization();
35
+ const { handlePrivacyPress, handleTermsPress, handleEulaPress, aboutConfig } =
36
+ useNavigationHandlers(appInfo, legalUrls);
37
+
38
+ const screenOptions = useMemo(
39
+ () => ({
40
+ headerStyle: {
41
+ backgroundColor: tokens.colors.surface,
42
+ borderBottomColor: tokens.colors.borderLight,
43
+ borderBottomWidth: 1,
44
+ },
45
+ headerTitleStyle: {
46
+ fontSize: 18,
47
+ fontWeight: "600" as const,
48
+ color: tokens.colors.textPrimary,
49
+ },
50
+ headerTintColor: tokens.colors.textPrimary,
51
+ }),
52
+ [tokens]
53
+ );
54
+
55
+ const SettingsScreenWrapper = useMemo(() => {
56
+ const Wrapper = () => (
57
+ <SettingsScreen
58
+ config={config}
59
+ appVersion={appInfo.version}
60
+ showUserProfile={showUserProfile}
61
+ userProfile={userProfile}
62
+ devSettings={devSettings}
63
+ customSections={customSections}
64
+ />
151
65
  );
66
+ Wrapper.displayName = "SettingsScreenWrapper";
67
+ return Wrapper;
68
+ }, [config, appInfo.version, showUserProfile, userProfile, devSettings, customSections]);
69
+
70
+ const LegalScreenWrapper = useMemo(() => {
71
+ const Wrapper = () => (
72
+ <LegalScreen
73
+ title={t("settings.legal.title")}
74
+ description={t("settings.legal.description")}
75
+ documentsHeader={t("settings.legal.documentsHeader")}
76
+ privacyTitle={t("settings.legal.privacyTitle")}
77
+ privacyDescription={t("settings.legal.privacyDescription")}
78
+ termsTitle={t("settings.legal.termsTitle")}
79
+ termsDescription={t("settings.legal.termsDescription")}
80
+ eulaTitle={t("settings.legal.eulaTitle")}
81
+ eulaDescription={t("settings.legal.eulaDescription")}
82
+ onPrivacyPress={handlePrivacyPress}
83
+ onTermsPress={handleTermsPress}
84
+ onEulaPress={handleEulaPress}
85
+ />
86
+ );
87
+ Wrapper.displayName = "LegalScreenWrapper";
88
+ return Wrapper;
89
+ }, [t, handlePrivacyPress, handleTermsPress, handleEulaPress]);
90
+
91
+ const AboutScreenWrapper = useMemo(() => {
92
+ const Wrapper = () => <AboutScreen config={aboutConfig} />;
93
+ Wrapper.displayName = "AboutScreenWrapper";
94
+ return Wrapper;
95
+ }, [aboutConfig]);
96
+
97
+ return (
98
+ <Stack.Navigator screenOptions={screenOptions}>
99
+ <Stack.Screen
100
+ name="Settings"
101
+ component={SettingsScreenWrapper}
102
+ options={{ headerShown: false }}
103
+ />
104
+
105
+ <Stack.Screen
106
+ name="Appearance"
107
+ component={AppearanceScreen}
108
+ options={{
109
+ headerShown: true,
110
+ headerTitle: t("settings.appearance.title"),
111
+ headerTitleAlign: "center",
112
+ }}
113
+ />
114
+
115
+ <Stack.Screen
116
+ name="About"
117
+ component={AboutScreenWrapper}
118
+ options={{
119
+ headerShown: true,
120
+ headerTitle: t("settings.about.title"),
121
+ headerTitleAlign: "center",
122
+ }}
123
+ />
124
+
125
+ <Stack.Screen
126
+ name="Legal"
127
+ component={LegalScreenWrapper}
128
+ options={{
129
+ headerShown: true,
130
+ headerTitle: t("settings.legal.title"),
131
+ headerTitleAlign: "center",
132
+ }}
133
+ />
134
+
135
+ {faqData && faqData.categories.length > 0 && (
136
+ <Stack.Screen
137
+ name="FAQ"
138
+ options={{
139
+ headerShown: true,
140
+ headerTitle: t("settings.faqs.title"),
141
+ headerTitleAlign: "center",
142
+ }}
143
+ >
144
+ {() => (
145
+ <FAQScreen
146
+ categories={faqData.categories}
147
+ searchPlaceholder={t("settings.faqs.searchPlaceholder")}
148
+ emptySearchTitle={t("settings.faqs.emptySearchTitle")}
149
+ emptySearchMessage={t("settings.faqs.emptySearchMessage")}
150
+ headerTitle={t("settings.faqs.headerTitle")}
151
+ />
152
+ )}
153
+ </Stack.Screen>
154
+ )}
155
+
156
+ {additionalScreens.map((screen) => (
157
+ <Stack.Screen
158
+ key={screen.name}
159
+ name={screen.name as keyof SettingsStackParamList}
160
+ component={screen.component}
161
+ options={screen.options}
162
+ />
163
+ ))}
164
+ </Stack.Navigator>
165
+ );
152
166
  };
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Navigation Hooks
3
+ */
4
+
5
+ export { useNavigationHandlers } from "./useNavigationHandlers";
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Navigation Handlers Hook
3
+ * Provides URL handlers and config generation for settings screens
4
+ */
5
+
6
+ import { useCallback, useMemo } from "react";
7
+ import { Linking } from "react-native";
8
+ import type { AppInfo, LegalUrls } from "../types";
9
+ import type { AboutConfig } from "../../../domains/about";
10
+
11
+ interface NavigationHandlersResult {
12
+ handlePrivacyPress: () => void;
13
+ handleTermsPress: () => void;
14
+ handleEulaPress: () => void;
15
+ aboutConfig: AboutConfig;
16
+ }
17
+
18
+ export const useNavigationHandlers = (
19
+ appInfo: AppInfo,
20
+ legalUrls: LegalUrls
21
+ ): NavigationHandlersResult => {
22
+ const handlePrivacyPress = useCallback(() => {
23
+ Linking.openURL(legalUrls.privacy);
24
+ }, [legalUrls.privacy]);
25
+
26
+ const handleTermsPress = useCallback(() => {
27
+ Linking.openURL(legalUrls.terms);
28
+ }, [legalUrls.terms]);
29
+
30
+ const handleEulaPress = useCallback(() => {
31
+ if (legalUrls.eula) {
32
+ Linking.openURL(legalUrls.eula);
33
+ }
34
+ }, [legalUrls.eula]);
35
+
36
+ const aboutConfig: AboutConfig = useMemo(
37
+ () => ({
38
+ appInfo: {
39
+ name: appInfo.name,
40
+ version: appInfo.version,
41
+ description: appInfo.description,
42
+ developer: appInfo.developer,
43
+ contactEmail: appInfo.contactEmail,
44
+ websiteUrl: appInfo.websiteUrl,
45
+ websiteDisplay: appInfo.websiteDisplay,
46
+ moreAppsUrl: appInfo.moreAppsUrl,
47
+ },
48
+ }),
49
+ [appInfo]
50
+ );
51
+
52
+ return {
53
+ handlePrivacyPress,
54
+ handleTermsPress,
55
+ handleEulaPress,
56
+ aboutConfig,
57
+ };
58
+ };
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Settings Navigation Types
3
+ */
4
+
5
+ import type { SettingsConfig, CustomSettingsSection } from "../screens/types";
6
+ import type { DevSettingsProps } from "../components/DevSettingsSection";
7
+ import type { FAQCategory } from "../../domains/faqs";
8
+
9
+ /**
10
+ * App Info passed from main app (APP_INFO constant)
11
+ */
12
+ export interface AppInfo {
13
+ name: string;
14
+ version: string;
15
+ description?: string;
16
+ developer?: string;
17
+ contactEmail?: string;
18
+ websiteUrl?: string;
19
+ websiteDisplay?: string;
20
+ moreAppsUrl?: string;
21
+ appStoreId?: string;
22
+ appStoreUrl?: string;
23
+ }
24
+
25
+ /**
26
+ * Legal URLs passed from main app (LEGAL_URLS constant)
27
+ */
28
+ export interface LegalUrls {
29
+ privacy: string;
30
+ terms: string;
31
+ eula?: string;
32
+ }
33
+
34
+ /**
35
+ * Navigation param list
36
+ */
37
+ export type SettingsStackParamList = {
38
+ Settings: undefined;
39
+ Appearance: undefined;
40
+ About: undefined;
41
+ Legal: undefined;
42
+ FAQ: undefined;
43
+ };
44
+
45
+ /**
46
+ * User profile configuration
47
+ */
48
+ export interface UserProfileConfig {
49
+ displayName?: string;
50
+ userId?: string;
51
+ isAnonymous?: boolean;
52
+ avatarUrl?: string;
53
+ accountSettingsRoute?: string;
54
+ onPress?: () => void;
55
+ anonymousDisplayName?: string;
56
+ avatarServiceUrl?: string;
57
+ }
58
+
59
+ /**
60
+ * Additional screen configuration
61
+ */
62
+ export interface AdditionalScreen {
63
+ name: string;
64
+ component: React.ComponentType<any>;
65
+ options?: Record<string, any>;
66
+ }
67
+
68
+ /**
69
+ * FAQ Data passed from main app
70
+ */
71
+ export interface FAQData {
72
+ categories: FAQCategory[];
73
+ }
74
+
75
+ /**
76
+ * Settings Stack Navigator Props
77
+ */
78
+ export interface SettingsStackNavigatorProps {
79
+ appInfo: AppInfo;
80
+ legalUrls: LegalUrls;
81
+ faqData?: FAQData;
82
+ config?: SettingsConfig;
83
+ showUserProfile?: boolean;
84
+ userProfile?: UserProfileConfig;
85
+ additionalScreens?: AdditionalScreen[];
86
+ devSettings?: DevSettingsProps;
87
+ customSections?: CustomSettingsSection[];
88
+ }