@umituz/react-native-settings 4.23.85 → 4.23.87

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.
Files changed (38) hide show
  1. package/package.json +3 -3
  2. package/src/domains/about/presentation/hooks/useAboutInfo.ts +1 -1
  3. package/src/domains/faqs/presentation/screens/FAQScreen.tsx +1 -1
  4. package/src/domains/feedback/presentation/components/FeedbackForm.styles.ts +1 -1
  5. package/src/domains/feedback/presentation/components/FeedbackForm.tsx +11 -4
  6. package/src/domains/gamification/components/GamificationScreen/GamificationScreen.tsx +1 -6
  7. package/src/domains/gamification/store/gamificationStore.ts +6 -7
  8. package/src/domains/localization/infrastructure/storage/LocalizationStore.ts +50 -181
  9. package/src/domains/localization/infrastructure/storage/localizationStoreUtils.ts +182 -0
  10. package/src/domains/notifications/infrastructure/utils/dev.ts +3 -3
  11. package/src/domains/notifications/reminders/presentation/components/ReminderForm.constants.ts +1 -1
  12. package/src/domains/notifications/reminders/presentation/components/ReminderForm.tsx +52 -46
  13. package/src/infrastructure/types/commonComponentTypes.ts +142 -0
  14. package/src/infrastructure/utils/async/core.ts +109 -0
  15. package/src/infrastructure/utils/async/debounceAndBatch.ts +69 -0
  16. package/src/infrastructure/utils/async/index.ts +8 -0
  17. package/src/infrastructure/utils/async/retryAndTimeout.ts +57 -0
  18. package/src/infrastructure/utils/configFactory.ts +101 -0
  19. package/src/infrastructure/utils/errorHandlers.ts +249 -0
  20. package/src/infrastructure/utils/index.ts +5 -0
  21. package/src/infrastructure/utils/memoComparisonUtils.ts +0 -2
  22. package/src/infrastructure/utils/memoUtils.ts +10 -2
  23. package/src/infrastructure/utils/styleTokens.ts +132 -0
  24. package/src/infrastructure/utils/validation/core.ts +42 -0
  25. package/src/infrastructure/utils/validation/formValidators.ts +82 -0
  26. package/src/infrastructure/utils/validation/index.ts +37 -0
  27. package/src/infrastructure/utils/validation/numericValidators.ts +66 -0
  28. package/src/infrastructure/utils/validation/passwordValidator.ts +53 -0
  29. package/src/infrastructure/utils/validation/textValidators.ts +118 -0
  30. package/src/presentation/hooks/useSettingsScreenConfig.ts +32 -79
  31. package/src/presentation/navigation/SettingsStackNavigator.tsx +1 -24
  32. package/src/presentation/navigation/hooks/useSettingsScreens.ts +1 -1
  33. package/src/presentation/utils/config-creators/base-configs.ts +54 -42
  34. package/src/presentation/utils/faqTranslator.ts +31 -0
  35. package/src/presentation/utils/index.ts +6 -1
  36. package/src/presentation/utils/screenFactory.ts +1 -1
  37. package/src/presentation/utils/settingsConfigFactory.ts +89 -0
  38. package/src/presentation/utils/useAuthHandlers.ts +98 -0
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Text Validators
3
+ * Validation functions for text-based inputs
4
+ */
5
+
6
+ import type { ValidationResult, TextValidationOptions } from "./core";
7
+
8
+ /**
9
+ * Validates a text field based on provided options
10
+ */
11
+ export const validateTextField = (
12
+ value: string,
13
+ options: TextValidationOptions = {}
14
+ ): ValidationResult => {
15
+ const {
16
+ minLength,
17
+ maxLength,
18
+ required = false,
19
+ pattern,
20
+ customValidator,
21
+ } = options;
22
+
23
+ // Check required
24
+ if (required && !value.trim()) {
25
+ return { isValid: false, error: "This field is required" };
26
+ }
27
+
28
+ // Skip other validations if empty and not required
29
+ if (!value.trim() && !required) {
30
+ return { isValid: true };
31
+ }
32
+
33
+ // Check min length
34
+ if (minLength && value.length < minLength) {
35
+ return { isValid: false, error: `Minimum length is ${minLength} characters` };
36
+ }
37
+
38
+ // Check max length
39
+ if (maxLength && value.length > maxLength) {
40
+ return { isValid: false, error: `Maximum length is ${maxLength} characters` };
41
+ }
42
+
43
+ // Check pattern
44
+ if (pattern && !pattern.test(value)) {
45
+ return { isValid: false, error: "Invalid format" };
46
+ }
47
+
48
+ // Custom validator
49
+ if (customValidator) {
50
+ const customError = customValidator(value);
51
+ if (customError) {
52
+ return { isValid: false, error: customError };
53
+ }
54
+ }
55
+
56
+ return { isValid: true };
57
+ };
58
+
59
+ /**
60
+ * Validates an email address
61
+ */
62
+ export const validateEmail = (
63
+ email: string,
64
+ options: { required?: boolean; allowEmpty?: boolean } = {}
65
+ ): ValidationResult => {
66
+ const { required = false, allowEmpty = false } = options;
67
+
68
+ // Check if empty
69
+ if (!email.trim()) {
70
+ if (required && !allowEmpty) {
71
+ return { isValid: false, error: "Email is required" };
72
+ }
73
+ return { isValid: true };
74
+ }
75
+
76
+ // Email regex pattern
77
+ const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
78
+ if (!emailPattern.test(email)) {
79
+ return { isValid: false, error: "Invalid email address" };
80
+ }
81
+
82
+ return { isValid: true };
83
+ };
84
+
85
+ /**
86
+ * Validates a URL
87
+ */
88
+ export const validateUrl = (url: string): ValidationResult => {
89
+ if (!url.trim()) {
90
+ return { isValid: true };
91
+ }
92
+
93
+ try {
94
+ new URL(url);
95
+ return { isValid: true };
96
+ } catch {
97
+ return { isValid: false, error: "Invalid URL" };
98
+ }
99
+ };
100
+
101
+ /**
102
+ * Validates a phone number (basic validation)
103
+ */
104
+ export const validatePhoneNumber = (phone: string): ValidationResult => {
105
+ if (!phone.trim()) {
106
+ return { isValid: true };
107
+ }
108
+
109
+ // Remove all non-digit characters
110
+ const digitsOnly = phone.replace(/\D/g, "");
111
+
112
+ // Check if length is reasonable (10-15 digits)
113
+ if (digitsOnly.length < 10 || digitsOnly.length > 15) {
114
+ return { isValid: false, error: "Invalid phone number" };
115
+ }
116
+
117
+ return { isValid: true };
118
+ };
@@ -6,29 +6,14 @@
6
6
  * Apps pass subscription config from subscription package.
7
7
  */
8
8
 
9
- import { useMemo, useCallback } from "react";
10
- import { Linking } from "react-native";
11
- import {
12
- useAuth,
13
- useAccountManagement,
14
- useAuthModalStore,
15
- useUserProfile,
16
- } from "@umituz/react-native-auth";
17
- import { AlertService } from "@umituz/react-native-design-system";
9
+ import { useMemo } from "react";
10
+ import { useAuth, useUserProfile } from "@umituz/react-native-auth";
18
11
  import { useLocalization } from "../../domains/localization";
19
- import {
20
- createAppearanceConfig,
21
- createLanguageConfig,
22
- createNotificationsConfig,
23
- createAboutConfig,
24
- createLegalConfig,
25
- createFeedbackConfig,
26
- createRatingConfig,
27
- createFAQConfig,
28
- createSubscriptionConfig,
29
- } from "../utils/config-creators";
30
12
  import { createUserProfileDisplay } from "../utils/userProfileUtils";
31
13
  import { createAccountConfig } from "../utils/accountConfigUtils";
14
+ import { useAuthHandlers } from "../utils/useAuthHandlers";
15
+ import { translateFAQData } from "../utils/faqTranslator";
16
+ import { useSettingsConfigFactory } from "../utils/settingsConfigFactory";
32
17
  import type { SettingsConfig } from "../screens/types";
33
18
  import type { FeedbackFormData } from "../utils/config-creators";
34
19
  import type { AppInfo, FAQData, UserProfileDisplay, AdditionalScreen } from "../navigation/types";
@@ -80,54 +65,31 @@ export const useSettingsScreenConfig = (
80
65
  } = features;
81
66
 
82
67
  const { t } = useLocalization();
83
- const { user, loading, isAuthReady, signOut } = useAuth();
84
- const { deleteAccount } = useAccountManagement();
68
+ const { user, loading, isAuthReady } = useAuth();
85
69
  const userProfileData = useUserProfile({});
86
- const { showAuthModal } = useAuthModalStore();
87
70
 
88
- const handleRatePress = useCallback(async () => {
89
- const url = appInfo.appStoreUrl;
90
- if (url && (await Linking.canOpenURL(url))) {
91
- await Linking.openURL(url);
92
- }
93
- }, [appInfo.appStoreUrl]);
71
+ // Use centralized auth handlers
72
+ const { handleRatePress, handleSignOut, handleDeleteAccount, handleSignIn } =
73
+ useAuthHandlers(appInfo);
94
74
 
95
- const handleSignOut = useCallback(async () => {
96
- try {
97
- await signOut();
98
- } catch {
99
- AlertService.createErrorAlert(t("common.error"), t("auth.errors.unknownError"));
100
- }
101
- }, [signOut, t]);
102
-
103
- const handleDeleteAccount = useCallback(async () => {
104
- try {
105
- await deleteAccount();
106
- } catch {
107
- AlertService.createErrorAlert(t("common.error"), t("settings.account.deleteError"));
108
- }
109
- }, [deleteAccount, t]);
110
-
111
- const handleSignIn = useCallback(() => {
112
- showAuthModal(() => {}, "login");
113
- }, [showAuthModal]);
114
-
115
- const settingsConfig = useMemo((): SettingsConfig => ({
116
- appearance: showAppearance ? createAppearanceConfig(t) : false,
117
- language: showLanguage ? createLanguageConfig(t) : false,
118
- notifications: showNotifications ? createNotificationsConfig(t) : false,
119
- feedback: showFeedback ? createFeedbackConfig(t, onFeedbackSubmit) : false,
120
- about: showAbout ? createAboutConfig(t) : false,
121
- legal: showLegal ? createLegalConfig(t) : false,
122
- faqs: showFaqs ? createFAQConfig(t) : false,
123
- rating: showRating ? createRatingConfig(t, handleRatePress, appInfo.appStoreUrl || "") : false,
124
- subscription: createSubscriptionConfig(t, isPremium, "SubscriptionDetail"),
125
- disclaimer: false,
126
- }), [
127
- t, onFeedbackSubmit, handleRatePress, appInfo.appStoreUrl, isPremium,
128
- showAppearance, showLanguage, showNotifications, showFeedback,
129
- showAbout, showLegal, showFaqs, showRating,
130
- ]);
75
+ // Use settings config factory
76
+ const settingsConfig = useSettingsConfigFactory({
77
+ t,
78
+ onFeedbackSubmit,
79
+ handleRatePress,
80
+ appStoreUrl: appInfo.appStoreUrl || "",
81
+ isPremium,
82
+ features: {
83
+ notifications: showNotifications,
84
+ appearance: showAppearance,
85
+ language: showLanguage,
86
+ feedback: showFeedback,
87
+ rating: showRating,
88
+ faqs: showFaqs,
89
+ about: showAbout,
90
+ legal: showLegal,
91
+ },
92
+ });
131
93
 
132
94
  const userProfile = useMemo(() => createUserProfileDisplay({
133
95
  profileData: userProfileData,
@@ -147,20 +109,11 @@ export const useSettingsScreenConfig = (
147
109
  t,
148
110
  }), [user, userProfileData, handleSignIn, handleSignOut, handleDeleteAccount, t]);
149
111
 
150
- const translatedFaqData = useMemo((): FAQData | undefined => {
151
- if (!faqData) return undefined;
152
- return {
153
- categories: faqData.categories.map((category) => ({
154
- id: category.id,
155
- title: t(category.title),
156
- items: category.items.map((item) => ({
157
- id: item.id,
158
- question: t(item.question, { appName: appInfo.name }),
159
- answer: t(item.answer, { appName: appInfo.name }),
160
- })),
161
- })),
162
- };
163
- }, [faqData, t, appInfo.name]);
112
+ // Use centralized FAQ translation
113
+ const translatedFaqData = useMemo(() =>
114
+ translateFAQData(faqData, t, appInfo),
115
+ [faqData, t, appInfo]
116
+ );
164
117
 
165
118
  return {
166
119
  settingsConfig,
@@ -7,20 +7,10 @@
7
7
 
8
8
  import React from "react";
9
9
  import {
10
- useAppDesignTokens,
11
10
  StackNavigator,
12
- type StackScreen,
13
11
  type StackNavigatorConfig,
14
12
  } from "@umituz/react-native-design-system";
15
- import { useLocalization, LanguageSelectionScreen } from "../../domains/localization";
16
- import { NotificationSettingsScreen } from "../../domains/notifications";
17
- import { AccountScreen } from "@umituz/react-native-auth";
18
- import { SettingsScreen } from "../screens/SettingsScreen";
19
- import { AppearanceScreen } from "../screens/AppearanceScreen";
20
- import { FAQScreen } from "../../domains/faqs";
21
- import { AboutScreen } from "../../domains/about";
22
- import { LegalScreen } from "../../domains/legal";
23
- import { GamificationScreen } from "../../domains/gamification";
13
+ import { useLocalization } from "../../domains/localization";
24
14
  import { useNavigationHandlers, useSettingsScreens } from "./hooks";
25
15
  import {
26
16
  createNotificationTranslations,
@@ -33,20 +23,7 @@ export const SettingsStackNavigator: React.FC<SettingsStackNavigatorProps> = (pr
33
23
  const {
34
24
  appInfo,
35
25
  legalUrls,
36
- faqData,
37
- config = {},
38
- showUserProfile = false,
39
- userProfile,
40
- accountConfig,
41
- additionalScreens = [],
42
- devSettings,
43
- customSections = [],
44
- showHeader = true,
45
- showCloseButton = false,
46
- onClose,
47
- gamificationConfig,
48
26
  } = props;
49
- const tokens = useAppDesignTokens();
50
27
  const { t } = useLocalization();
51
28
  const { handlePrivacyPress, handleTermsPress, handleEulaPress, aboutConfig } =
52
29
  useNavigationHandlers(appInfo, legalUrls);
@@ -1,4 +1,4 @@
1
- import React, { useMemo } from 'react';
1
+ import { useMemo } from 'react';
2
2
  import type { StackScreen } from "@umituz/react-native-design-system";
3
3
  import { LanguageSelectionScreen } from "../../../domains/localization";
4
4
  import { NotificationSettingsScreen } from "../../../domains/notifications";
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Base Settings Config Creators
3
3
  * Standard settings: appearance, language, notifications, about, legal
4
+ * Refactored to use configFactory pattern for consistency
4
5
  */
5
6
 
6
7
  import type {
@@ -11,6 +12,7 @@ import type {
11
12
  LegalConfig,
12
13
  } from "../../screens/types";
13
14
  import type { TranslationFunction } from "./types";
15
+ import { createBaseConfig, createConfigWithExtensions } from "../../../infrastructure/utils/configFactory";
14
16
 
15
17
  /**
16
18
  * Create appearance configuration
@@ -18,14 +20,15 @@ import type { TranslationFunction } from "./types";
18
20
  export const createAppearanceConfig = (
19
21
  t: TranslationFunction,
20
22
  routeOrOnPress?: string | (() => void),
21
- ): AppearanceConfig => ({
22
- enabled: true,
23
- title: t("settings.appearance.title"),
24
- description: t("settings.appearance.description"),
25
- icon: "color-palette-outline",
26
- route: typeof routeOrOnPress === "string" ? routeOrOnPress : undefined,
27
- onPress: typeof routeOrOnPress === "function" ? routeOrOnPress : undefined,
28
- });
23
+ ): AppearanceConfig => {
24
+ return createBaseConfig<AppearanceConfig>({
25
+ t,
26
+ titleKey: "settings.appearance.title",
27
+ descriptionKey: "settings.appearance.description",
28
+ icon: "color-palette-outline",
29
+ routeOrOnPress,
30
+ });
31
+ };
29
32
 
30
33
  /**
31
34
  * Create language configuration
@@ -33,14 +36,15 @@ export const createAppearanceConfig = (
33
36
  export const createLanguageConfig = (
34
37
  t: TranslationFunction,
35
38
  routeOrOnPress?: string | (() => void),
36
- ): LanguageConfig => ({
37
- enabled: true,
38
- title: t("settings.language.title"),
39
- description: t("settings.language.description"),
40
- icon: "globe-outline",
41
- route: typeof routeOrOnPress === "string" ? routeOrOnPress : undefined,
42
- onPress: typeof routeOrOnPress === "function" ? routeOrOnPress : undefined,
43
- });
39
+ ): LanguageConfig => {
40
+ return createBaseConfig<LanguageConfig>({
41
+ t,
42
+ titleKey: "settings.language.title",
43
+ descriptionKey: "settings.language.description",
44
+ icon: "globe-outline",
45
+ routeOrOnPress,
46
+ });
47
+ };
44
48
 
45
49
  /**
46
50
  * Create notifications configuration
@@ -48,16 +52,22 @@ export const createLanguageConfig = (
48
52
  export const createNotificationsConfig = (
49
53
  t: TranslationFunction,
50
54
  routeOrOnPress?: string | (() => void),
51
- ): NotificationsConfig => ({
52
- enabled: true,
53
- showToggle: false,
54
- route: typeof routeOrOnPress === "string" ? routeOrOnPress : "Notifications",
55
- onPress: typeof routeOrOnPress === "function" ? routeOrOnPress : undefined,
56
- title: t("settings.notifications.title"),
57
- description: t("settings.notifications.description"),
58
- sectionTitle: t("settings.notifications.sectionTitle"),
59
- icon: "notifications-outline",
60
- });
55
+ ): NotificationsConfig => {
56
+ return createConfigWithExtensions<NotificationsConfig>(
57
+ {
58
+ t,
59
+ titleKey: "settings.notifications.title",
60
+ descriptionKey: "settings.notifications.description",
61
+ icon: "notifications-outline",
62
+ routeOrOnPress,
63
+ defaultRoute: "Notifications",
64
+ },
65
+ {
66
+ showToggle: false,
67
+ sectionTitle: t("settings.notifications.sectionTitle"),
68
+ }
69
+ );
70
+ };
61
71
 
62
72
  /**
63
73
  * Create about configuration
@@ -65,14 +75,15 @@ export const createNotificationsConfig = (
65
75
  export const createAboutConfig = (
66
76
  t: TranslationFunction,
67
77
  routeOrOnPress?: string | (() => void),
68
- ): AboutConfig => ({
69
- enabled: true,
70
- title: t("settings.about.title"),
71
- description: t("settings.about.description"),
72
- icon: "information-circle-outline",
73
- route: typeof routeOrOnPress === "string" ? routeOrOnPress : undefined,
74
- onPress: typeof routeOrOnPress === "function" ? routeOrOnPress : undefined,
75
- });
78
+ ): AboutConfig => {
79
+ return createBaseConfig<AboutConfig>({
80
+ t,
81
+ titleKey: "settings.about.title",
82
+ descriptionKey: "settings.about.description",
83
+ icon: "information-circle-outline",
84
+ routeOrOnPress,
85
+ });
86
+ };
76
87
 
77
88
  /**
78
89
  * Create legal configuration
@@ -80,11 +91,12 @@ export const createAboutConfig = (
80
91
  export const createLegalConfig = (
81
92
  t: TranslationFunction,
82
93
  routeOrOnPress?: string | (() => void),
83
- ): LegalConfig => ({
84
- enabled: true,
85
- title: t("settings.legal.title"),
86
- description: t("settings.legal.description"),
87
- icon: "document-text-outline",
88
- route: typeof routeOrOnPress === "string" ? routeOrOnPress : undefined,
89
- onPress: typeof routeOrOnPress === "function" ? routeOrOnPress : undefined,
90
- });
94
+ ): LegalConfig => {
95
+ return createBaseConfig<LegalConfig>({
96
+ t,
97
+ titleKey: "settings.legal.title",
98
+ descriptionKey: "settings.legal.description",
99
+ icon: "document-text-outline",
100
+ routeOrOnPress,
101
+ });
102
+ };
@@ -0,0 +1,31 @@
1
+ /**
2
+ * FAQ Translation Utility
3
+ * Handles translation of FAQ data
4
+ */
5
+
6
+ import type { TranslationFunction } from "./config-creators/types";
7
+ import type { FAQData } from "../navigation/types";
8
+ import type { AppInfo } from "../navigation/types";
9
+
10
+ /**
11
+ * Translates FAQ data using the provided translation function
12
+ */
13
+ export const translateFAQData = (
14
+ faqData: FAQData | undefined,
15
+ t: TranslationFunction,
16
+ _appInfo: AppInfo
17
+ ): FAQData | undefined => {
18
+ if (!faqData) return undefined;
19
+
20
+ return {
21
+ categories: faqData.categories.map((category) => ({
22
+ id: category.id,
23
+ title: t(category.title),
24
+ items: category.items.map((item) => ({
25
+ id: item.id,
26
+ question: t(item.question),
27
+ answer: t(item.answer),
28
+ })),
29
+ })),
30
+ };
31
+ };
@@ -1,5 +1,10 @@
1
1
  /**
2
- * Settings Utilities
2
+ * Presentation Utilities
3
3
  */
4
4
 
5
5
  export * from "./config-creators";
6
+ export * from "./userProfileUtils";
7
+ export * from "./accountConfigUtils";
8
+ export * from "./faqTranslator";
9
+ export * from "./settingsConfigFactory";
10
+ export * from "./useAuthHandlers";
@@ -36,7 +36,7 @@ export function createStackScreen(
36
36
  /**
37
37
  * Create a screen with props
38
38
  */
39
- export function createScreenWithProps<P extends Record<string, unknown>>(
39
+ export function createScreenWithProps<P>(
40
40
  name: string,
41
41
  component: React.ComponentType<P>,
42
42
  props: P,
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Settings Config Factory Utility
3
+ * Creates settings configuration based on feature flags
4
+ */
5
+
6
+ import { useMemo } from "react";
7
+ import type { TranslationFunction, FeedbackFormData } from "./config-creators/types";
8
+ import type { SettingsConfig } from "../screens/types";
9
+ import {
10
+ createAppearanceConfig,
11
+ createLanguageConfig,
12
+ createNotificationsConfig,
13
+ createAboutConfig,
14
+ createLegalConfig,
15
+ createFeedbackConfig,
16
+ createRatingConfig,
17
+ createFAQConfig,
18
+ createSubscriptionConfig,
19
+ } from "./config-creators";
20
+
21
+ export interface SettingsConfigFactoryParams {
22
+ t: TranslationFunction;
23
+ onFeedbackSubmit: (data: FeedbackFormData) => Promise<void>;
24
+ handleRatePress: () => void;
25
+ appStoreUrl: string;
26
+ isPremium: boolean;
27
+ features: {
28
+ notifications: boolean;
29
+ appearance: boolean;
30
+ language: boolean;
31
+ feedback: boolean;
32
+ rating: boolean;
33
+ faqs: boolean;
34
+ about: boolean;
35
+ legal: boolean;
36
+ };
37
+ }
38
+
39
+ /**
40
+ * Creates settings configuration based on enabled features
41
+ */
42
+ export const createSettingsConfig = (
43
+ params: SettingsConfigFactoryParams
44
+ ): SettingsConfig => {
45
+ const {
46
+ t,
47
+ onFeedbackSubmit,
48
+ handleRatePress,
49
+ appStoreUrl,
50
+ isPremium,
51
+ features,
52
+ } = params;
53
+
54
+ return {
55
+ appearance: features.appearance ? createAppearanceConfig(t) : false,
56
+ language: features.language ? createLanguageConfig(t) : false,
57
+ notifications: features.notifications ? createNotificationsConfig(t) : false,
58
+ feedback: features.feedback ? createFeedbackConfig(t, onFeedbackSubmit) : false,
59
+ about: features.about ? createAboutConfig(t) : false,
60
+ legal: features.legal ? createLegalConfig(t) : false,
61
+ faqs: features.faqs ? createFAQConfig(t) : false,
62
+ rating: features.rating ? createRatingConfig(t, handleRatePress, appStoreUrl) : false,
63
+ subscription: createSubscriptionConfig(t, isPremium, "SubscriptionDetail"),
64
+ disclaimer: false,
65
+ };
66
+ };
67
+
68
+ /**
69
+ * Hook for creating settings config with memoization
70
+ */
71
+ export const useSettingsConfigFactory = (
72
+ params: SettingsConfigFactoryParams
73
+ ): SettingsConfig => {
74
+ return useMemo(() => createSettingsConfig(params), [
75
+ params.t,
76
+ params.onFeedbackSubmit,
77
+ params.handleRatePress,
78
+ params.appStoreUrl,
79
+ params.isPremium,
80
+ params.features.appearance,
81
+ params.features.language,
82
+ params.features.notifications,
83
+ params.features.feedback,
84
+ params.features.about,
85
+ params.features.legal,
86
+ params.features.faqs,
87
+ params.features.rating,
88
+ ]);
89
+ };