@umituz/react-native-settings 4.23.84 → 4.23.86

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 (59) hide show
  1. package/package.json +3 -3
  2. package/src/domains/about/presentation/hooks/useAboutInfo.ts +1 -3
  3. package/src/domains/appearance/presentation/components/ColorPicker.tsx +0 -1
  4. package/src/domains/appearance/presentation/components/ThemeModeSection.tsx +0 -1
  5. package/src/domains/appearance/presentation/components/ThemeOption.tsx +0 -1
  6. package/src/domains/faqs/presentation/screens/FAQScreen.tsx +1 -1
  7. package/src/domains/feedback/presentation/components/FeedbackForm.styles.ts +1 -1
  8. package/src/domains/feedback/presentation/components/FeedbackForm.tsx +1 -2
  9. package/src/domains/feedback/presentation/components/FeedbackModal.tsx +12 -12
  10. package/src/domains/feedback/presentation/components/SupportSection.tsx +0 -1
  11. package/src/domains/gamification/components/GamificationScreen/GamificationScreen.tsx +1 -6
  12. package/src/domains/localization/infrastructure/components/useLanguageSwitcher.ts +0 -1
  13. package/src/domains/localization/infrastructure/hooks/useLanguageSelection.ts +0 -4
  14. package/src/domains/localization/infrastructure/hooks/useTranslation.ts +0 -1
  15. package/src/domains/localization/infrastructure/storage/LanguageInitializer.ts +0 -1
  16. package/src/domains/localization/infrastructure/storage/LanguageSwitcher.ts +0 -4
  17. package/src/domains/localization/infrastructure/storage/LocalizationStore.ts +0 -5
  18. package/src/domains/localization/presentation/components/LanguageItem.tsx +0 -1
  19. package/src/domains/localization/presentation/providers/LocalizationManager.tsx +0 -1
  20. package/src/domains/localization/presentation/screens/LanguageSelectionScreen.tsx +0 -3
  21. package/src/domains/notifications/infrastructure/services/NotificationService.ts +0 -1
  22. package/src/domains/notifications/infrastructure/utils/dev.ts +3 -6
  23. package/src/domains/notifications/quietHours/infrastructure/hooks/useQuietHoursActions.ts +0 -1
  24. package/src/domains/notifications/reminders/infrastructure/hooks/useReminderActions.ts +0 -6
  25. package/src/domains/notifications/reminders/presentation/components/ReminderForm.constants.ts +1 -1
  26. package/src/domains/notifications/reminders/presentation/components/ReminderForm.tsx +1 -6
  27. package/src/domains/rating/application/services/RatingService.ts +13 -63
  28. package/src/domains/rating/infrastructure/storage/RatingStorage.ts +14 -36
  29. package/src/domains/rating/presentation/hooks/useAppRating.tsx +0 -1
  30. package/src/infrastructure/utils/dateUtils.ts +61 -0
  31. package/src/infrastructure/utils/memoComparisonUtils.ts +66 -0
  32. package/src/infrastructure/utils/sanitizers.ts +49 -0
  33. package/src/infrastructure/utils/translationHelpers.ts +81 -0
  34. package/src/infrastructure/utils/validators.ts +59 -0
  35. package/src/presentation/components/SettingsItemCard.tsx +129 -172
  36. package/src/presentation/components/settings/SettingsItemCardContent.tsx +70 -0
  37. package/src/presentation/components/settings/SettingsItemCardRightElement.tsx +42 -0
  38. package/src/presentation/components/settings/SettingsItemCardSection.tsx +29 -0
  39. package/src/presentation/hooks/useSettingsScreenConfig.ts +19 -54
  40. package/src/presentation/navigation/SettingsStackNavigator.tsx +1 -24
  41. package/src/presentation/navigation/hooks/useSettingsScreens.ts +76 -90
  42. package/src/presentation/screens/components/GamificationSettingsItem.tsx +20 -17
  43. package/src/presentation/screens/components/SettingsContent.tsx +29 -0
  44. package/src/presentation/screens/components/SubscriptionSettingsItem.tsx +13 -4
  45. package/src/presentation/screens/components/VideoTutorialSettingsItem.tsx +47 -0
  46. package/src/presentation/screens/components/WalletSettingsItem.tsx +13 -4
  47. package/src/presentation/screens/components/sections/CustomSettingsList.tsx +12 -5
  48. package/src/presentation/screens/components/sections/FeatureSettingsSection.tsx +12 -11
  49. package/src/presentation/screens/components/sections/IdentitySettingsSection.tsx +4 -1
  50. package/src/presentation/screens/components/sections/ProfileSectionLoader.tsx +16 -10
  51. package/src/presentation/screens/components/sections/SupportSettingsSection.tsx +9 -4
  52. package/src/presentation/screens/hooks/useFeatureDetection.ts +2 -0
  53. package/src/presentation/screens/types/SettingsConfig.ts +8 -1
  54. package/src/presentation/screens/types/UserFeatureConfig.ts +20 -0
  55. package/src/presentation/screens/types/index.ts +1 -0
  56. package/src/presentation/screens/utils/normalizeConfig.ts +7 -1
  57. package/src/presentation/utils/accountConfigUtils.ts +67 -0
  58. package/src/presentation/utils/screenFactory.ts +87 -0
  59. package/src/presentation/utils/userProfileUtils.ts +51 -0
@@ -1,195 +1,152 @@
1
1
  import React from "react";
2
2
  import { View, Pressable, StyleSheet, type StyleProp, type ViewStyle } from "react-native";
3
3
  import {
4
- useAppDesignTokens,
5
- AtomicIcon,
6
- AtomicText,
7
- AtomicSwitch,
8
- type IconName,
9
- withAlpha,
4
+ useAppDesignTokens,
5
+ type IconName,
6
+ withAlpha,
10
7
  } from "@umituz/react-native-design-system";
8
+ import { validateTitle, validateDescription, validateSwitchProps } from "../../infrastructure/utils/validators";
9
+ import { sanitizeTitle, sanitizeDescription } from "../../infrastructure/utils/sanitizers";
10
+ import { SettingsItemCardRightElement } from "./settings/SettingsItemCardRightElement";
11
+ import { SettingsItemCardContent } from "./settings/SettingsItemCardContent";
12
+ import { SettingsItemCardSection } from "./settings/SettingsItemCardSection";
11
13
 
12
14
  export interface SettingsItemCardProps {
13
- title: string;
14
- description?: string;
15
- icon: IconName;
16
- onPress?: () => void;
17
- containerStyle?: StyleProp<ViewStyle>;
18
- sectionTitle?: string;
19
- rightIcon?: IconName;
20
- iconBgColor?: string;
21
- iconColor?: string;
22
- showChevron?: boolean;
23
- showSwitch?: boolean;
24
- switchValue?: boolean;
25
- onSwitchChange?: (value: boolean) => void;
26
- disabled?: boolean;
27
- noBackground?: boolean;
28
- hideMargin?: boolean;
15
+ title: string;
16
+ description?: string;
17
+ icon: IconName;
18
+ onPress?: () => void;
19
+ containerStyle?: StyleProp<ViewStyle>;
20
+ sectionTitle?: string;
21
+ rightIcon?: IconName;
22
+ iconBgColor?: string;
23
+ iconColor?: string;
24
+ showChevron?: boolean;
25
+ showSwitch?: boolean;
26
+ switchValue?: boolean;
27
+ onSwitchChange?: (value: boolean) => void;
28
+ disabled?: boolean;
29
+ noBackground?: boolean;
30
+ hideMargin?: boolean;
29
31
  }
30
32
 
31
-
32
33
  export const SettingsItemCard: React.FC<SettingsItemCardProps> = ({
33
- title,
34
- description,
35
- icon,
36
- onPress,
37
- containerStyle,
38
- sectionTitle,
39
- rightIcon = "chevron-forward",
40
- iconBgColor,
41
- iconColor,
42
- showChevron,
43
- showSwitch = false,
44
- switchValue,
45
- onSwitchChange,
46
- disabled = false,
47
- noBackground = false,
48
- hideMargin = false,
34
+ title,
35
+ description,
36
+ icon,
37
+ onPress,
38
+ containerStyle: propContainerStyle,
39
+ sectionTitle,
40
+ rightIcon = "chevron-forward",
41
+ iconBgColor,
42
+ iconColor,
43
+ showChevron,
44
+ showSwitch = false,
45
+ switchValue,
46
+ onSwitchChange,
47
+ disabled = false,
48
+ noBackground = false,
49
+ hideMargin = false,
49
50
  }) => {
51
+ const tokens = useAppDesignTokens();
52
+ const colors = tokens.colors;
50
53
 
51
- const tokens = useAppDesignTokens();
52
- const colors = tokens.colors;
54
+ // Sanitize props (before hooks)
55
+ const sanitizedTitle = sanitizeTitle(title);
56
+ const sanitizedDescription = sanitizeDescription(description);
57
+ const sanitizedSectionTitle = sectionTitle?.trim().slice(0, 100);
53
58
 
54
- // Validate props in development
55
- if (__DEV__) {
56
- if (!title || typeof title !== 'string') {
57
- console.warn('[SettingsItemCard] Invalid title prop:', title);
58
- }
59
- if (description && typeof description !== 'string') {
60
- console.warn('[SettingsItemCard] Invalid description prop:', description);
61
- }
62
- if (showSwitch && !onSwitchChange) {
63
- console.warn('[SettingsItemCard] Switch shown but no onSwitchChange provided. Switch changes will be ignored.');
64
- }
65
- }
59
+ const defaultIconBg = iconBgColor || withAlpha(colors.primary, 0.15);
60
+ const defaultIconColor = iconColor || colors.primary;
61
+ const isClickable = !!onPress && !showSwitch;
62
+ const shouldShowChevron = !showSwitch && (showChevron ?? isClickable);
66
63
 
67
- // Sanitize string props (trim and limit length)
68
- const sanitizedTitle = title?.trim().slice(0, 200) || '';
69
- const sanitizedDescription = description?.trim().slice(0, 500);
64
+ // All hooks must be called before any early returns
65
+ const rightElement = React.useMemo(
66
+ () => (
67
+ <SettingsItemCardRightElement
68
+ showSwitch={showSwitch}
69
+ switchValue={switchValue}
70
+ onSwitchChange={onSwitchChange}
71
+ disabled={disabled}
72
+ shouldShowChevron={shouldShowChevron}
73
+ rightIcon={rightIcon}
74
+ />
75
+ ),
76
+ [showSwitch, switchValue, onSwitchChange, disabled, shouldShowChevron, rightIcon]
77
+ );
70
78
 
71
- const defaultIconBg = iconBgColor || withAlpha(colors.primary, 0.15);
72
- const defaultIconColor = iconColor || colors.primary;
73
- const isClickable = !!onPress && !showSwitch;
74
- const shouldShowChevron = !showSwitch && (showChevron ?? isClickable);
79
+ const content = React.useMemo(
80
+ () => (
81
+ <SettingsItemCardContent
82
+ icon={icon}
83
+ title={sanitizedTitle}
84
+ description={sanitizedDescription}
85
+ iconBgColor={defaultIconBg}
86
+ iconColor={defaultIconColor}
87
+ disabled={disabled}
88
+ rightElement={rightElement}
89
+ />
90
+ ),
91
+ [icon, sanitizedTitle, sanitizedDescription, defaultIconBg, defaultIconColor, disabled, rightElement]
92
+ );
75
93
 
76
- const renderRightElement = () => {
77
- if (showSwitch) {
78
- return (
79
- <AtomicSwitch
80
- value={!!switchValue}
81
- onValueChange={onSwitchChange || (() => {
82
- if (__DEV__) {
83
- console.warn('[SettingsItemCard] Switch toggled but no onSwitchChange handler provided');
84
- }
85
- })}
86
- disabled={disabled}
87
- />
88
- );
89
- }
90
- if (shouldShowChevron) {
91
- return <AtomicIcon name={rightIcon} size="sm" color="textSecondary" />;
92
- }
93
- return null;
94
- };
94
+ const containerStyle = React.useMemo(
95
+ () => [
96
+ styles.sectionContainer,
97
+ {
98
+ backgroundColor: noBackground ? "transparent" : colors.surface,
99
+ borderRadius: noBackground ? 0 : tokens.borders.radius.lg,
100
+ },
101
+ hideMargin && { marginBottom: 0 },
102
+ propContainerStyle,
103
+ ],
104
+ [noBackground, colors.surface, tokens.borders.radius.lg, hideMargin, propContainerStyle]
105
+ );
95
106
 
96
- const renderContent = () => (
97
- <View style={styles.content}>
98
- <View style={[styles.iconContainer, { backgroundColor: defaultIconBg, borderRadius: tokens.borders.radius.md }]}>
99
- <AtomicIcon name={icon} size="lg" customColor={defaultIconColor} />
100
- </View>
101
- <View style={styles.textContainer}>
102
- <AtomicText
103
- type="bodyLarge"
104
- color={disabled ? "onSurfaceVariant" : "onSurface"}
105
- numberOfLines={1}
106
- style={{ marginBottom: sanitizedDescription ? tokens.spacing.xs : 0, opacity: disabled ? 0.6 : 1 }}
107
- >
108
- {sanitizedTitle}
109
- </AtomicText>
110
- {!!sanitizedDescription && (
111
- <AtomicText type="bodyMedium" color="textSecondary" numberOfLines={2}>
112
- {sanitizedDescription}
113
- </AtomicText>
114
- )}
115
- </View>
116
- {renderRightElement()}
117
- </View>
118
- );
107
+ // Validate after hooks (silent validation, no render)
108
+ const titleWarning = validateTitle(title);
109
+ const descWarning = validateDescription(description);
110
+ const switchWarning = validateSwitchProps(showSwitch, onSwitchChange);
119
111
 
120
- return (
121
- <View
122
- style={[
123
- styles.sectionContainer,
124
- {
125
- backgroundColor: noBackground ? "transparent" : colors.surface,
126
- borderRadius: noBackground ? 0 : tokens.borders.radius.lg,
127
- },
128
- hideMargin && { marginBottom: 0 },
129
- containerStyle,
130
- ]}
131
- >
112
+ if (titleWarning || descWarning || switchWarning) {
113
+ return null;
114
+ }
132
115
 
133
-
134
- {!!sectionTitle && (
135
- <View style={styles.headerContainer}>
136
- <AtomicText type="labelMedium" color="textSecondary" style={{ textTransform: 'uppercase' }}>
137
- {sectionTitle.trim().slice(0, 100)}
138
- </AtomicText>
139
- </View>
140
- )}
141
- {isClickable ? (
142
- <Pressable
143
- style={({ pressed }) => [
144
- styles.itemContainer,
145
- {
146
- backgroundColor: pressed ? withAlpha(colors.primary, 0.08) : "transparent",
147
- },
148
- ]}
149
- onPress={onPress}
150
- >
151
- {renderContent()}
152
- </Pressable>
153
- ) : (
154
- <View style={styles.itemContainer}>
155
- {renderContent()}
156
- </View>
157
- )}
116
+ return (
117
+ <View style={containerStyle}>
118
+ <SettingsItemCardSection sectionTitle={sanitizedSectionTitle} />
119
+ {isClickable ? (
120
+ <Pressable
121
+ style={({ pressed }) => [
122
+ styles.itemContainer,
123
+ {
124
+ backgroundColor: pressed ? withAlpha(colors.primary, 0.08) : "transparent",
125
+ },
126
+ ]}
127
+ onPress={onPress}
128
+ >
129
+ {content}
130
+ </Pressable>
131
+ ) : (
132
+ <View style={styles.itemContainer}>
133
+ {content}
158
134
  </View>
159
- );
135
+ )}
136
+ </View>
137
+ );
160
138
  };
161
139
 
162
140
  const styles = StyleSheet.create({
163
- sectionContainer: {
164
- marginBottom: 16,
165
- overflow: "hidden",
166
- },
167
- headerContainer: {
168
- paddingHorizontal: 16,
169
- paddingTop: 16,
170
- paddingBottom: 8,
171
- },
172
- itemContainer: {
173
- flexDirection: "row",
174
- alignItems: "center",
175
- paddingHorizontal: 16,
176
- paddingVertical: 16,
177
- minHeight: 72,
178
- },
179
- content: {
180
- flex: 1,
181
- flexDirection: "row",
182
- alignItems: "center",
183
- },
184
- iconContainer: {
185
- width: 48,
186
- height: 48,
187
- justifyContent: "center",
188
- alignItems: "center",
189
- marginRight: 16,
190
- },
191
- textContainer: {
192
- flex: 1,
193
- marginRight: 8,
194
- },
141
+ sectionContainer: {
142
+ marginBottom: 16,
143
+ overflow: "hidden",
144
+ },
145
+ itemContainer: {
146
+ flexDirection: "row",
147
+ alignItems: "center",
148
+ paddingHorizontal: 16,
149
+ paddingVertical: 16,
150
+ minHeight: 72,
151
+ },
195
152
  });
@@ -0,0 +1,70 @@
1
+ import React from "react";
2
+ import { View } from "react-native";
3
+ import { useAppDesignTokens, AtomicIcon, AtomicText, type IconName } from "@umituz/react-native-design-system";
4
+
5
+ export interface SettingsItemCardContentProps {
6
+ icon: IconName;
7
+ title: string;
8
+ description?: string;
9
+ iconBgColor: string;
10
+ iconColor: string;
11
+ disabled?: boolean;
12
+ rightElement: React.ReactElement;
13
+ }
14
+
15
+ export const SettingsItemCardContent: React.FC<SettingsItemCardContentProps> = React.memo(({
16
+ icon,
17
+ title,
18
+ description,
19
+ iconBgColor,
20
+ iconColor,
21
+ disabled,
22
+ rightElement,
23
+ }) => {
24
+ const tokens = useAppDesignTokens();
25
+
26
+ return (
27
+ <View style={styles.content}>
28
+ <View style={[styles.iconContainer, { backgroundColor: iconBgColor, borderRadius: tokens.borders.radius.md }]}>
29
+ <AtomicIcon name={icon} size="lg" customColor={iconColor} />
30
+ </View>
31
+ <View style={styles.textContainer}>
32
+ <AtomicText
33
+ type="bodyLarge"
34
+ color={disabled ? "onSurfaceVariant" : "onSurface"}
35
+ numberOfLines={1}
36
+ style={{ marginBottom: description ? tokens.spacing.xs : 0, opacity: disabled ? 0.6 : 1 }}
37
+ >
38
+ {title}
39
+ </AtomicText>
40
+ {!!description && (
41
+ <AtomicText type="bodyMedium" color="textSecondary" numberOfLines={2}>
42
+ {description}
43
+ </AtomicText>
44
+ )}
45
+ </View>
46
+ {rightElement}
47
+ </View>
48
+ );
49
+ });
50
+
51
+ SettingsItemCardContent.displayName = "SettingsItemCardContent";
52
+
53
+ const styles = {
54
+ content: {
55
+ flex: 1,
56
+ flexDirection: "row",
57
+ alignItems: "center",
58
+ },
59
+ iconContainer: {
60
+ width: 48,
61
+ height: 48,
62
+ justifyContent: "center",
63
+ alignItems: "center",
64
+ marginRight: 16,
65
+ },
66
+ textContainer: {
67
+ flex: 1,
68
+ marginRight: 8,
69
+ },
70
+ } as const;
@@ -0,0 +1,42 @@
1
+ import React from "react";
2
+ import { AtomicIcon, AtomicSwitch, type IconName } from "@umituz/react-native-design-system";
3
+
4
+ export interface SettingsItemCardRightElementProps {
5
+ showSwitch: boolean;
6
+ switchValue?: boolean;
7
+ onSwitchChange?: (value: boolean) => void;
8
+ disabled?: boolean;
9
+ shouldShowChevron: boolean;
10
+ rightIcon: IconName;
11
+ }
12
+
13
+ export const SettingsItemCardRightElement: React.FC<SettingsItemCardRightElementProps> = React.memo(({
14
+ showSwitch,
15
+ switchValue,
16
+ onSwitchChange,
17
+ disabled,
18
+ shouldShowChevron,
19
+ rightIcon,
20
+ }) => {
21
+ const handleSwitchChange = React.useCallback((value: boolean) => {
22
+ if (onSwitchChange) {
23
+ onSwitchChange(value);
24
+ }
25
+ }, [onSwitchChange]);
26
+
27
+ if (showSwitch) {
28
+ return (
29
+ <AtomicSwitch
30
+ value={!!switchValue}
31
+ onValueChange={handleSwitchChange}
32
+ disabled={disabled}
33
+ />
34
+ );
35
+ }
36
+ if (shouldShowChevron) {
37
+ return <AtomicIcon name={rightIcon} size="sm" color="textSecondary" />;
38
+ }
39
+ return null;
40
+ });
41
+
42
+ SettingsItemCardRightElement.displayName = "SettingsItemCardRightElement";
@@ -0,0 +1,29 @@
1
+ import React from "react";
2
+ import { View } from "react-native";
3
+ import { AtomicText } from "@umituz/react-native-design-system";
4
+
5
+ export interface SettingsItemCardSectionProps {
6
+ sectionTitle?: string;
7
+ }
8
+
9
+ export const SettingsItemCardSection: React.FC<SettingsItemCardSectionProps> = React.memo(({ sectionTitle }) => {
10
+ if (!sectionTitle) return null;
11
+
12
+ return (
13
+ <View style={styles.headerContainer}>
14
+ <AtomicText type="labelMedium" color="textSecondary" style={{ textTransform: "uppercase" }}>
15
+ {sectionTitle}
16
+ </AtomicText>
17
+ </View>
18
+ );
19
+ });
20
+
21
+ SettingsItemCardSection.displayName = "SettingsItemCardSection";
22
+
23
+ const styles = {
24
+ headerContainer: {
25
+ paddingHorizontal: 16,
26
+ paddingTop: 16,
27
+ paddingBottom: 8,
28
+ },
29
+ } as const;
@@ -27,6 +27,8 @@ import {
27
27
  createFAQConfig,
28
28
  createSubscriptionConfig,
29
29
  } from "../utils/config-creators";
30
+ import { createUserProfileDisplay } from "../utils/userProfileUtils";
31
+ import { createAccountConfig } from "../utils/accountConfigUtils";
30
32
  import type { SettingsConfig } from "../screens/types";
31
33
  import type { FeedbackFormData } from "../utils/config-creators";
32
34
  import type { AppInfo, FAQData, UserProfileDisplay, AdditionalScreen } from "../navigation/types";
@@ -127,60 +129,23 @@ export const useSettingsScreenConfig = (
127
129
  showAbout, showLegal, showFaqs, showRating,
128
130
  ]);
129
131
 
130
- const userProfile = useMemo((): UserProfileDisplay => {
131
- const isAnonymous = userProfileData?.isAnonymous ?? true;
132
-
133
- // Ensure t function is available before using it
134
- const anonymousName = typeof t === 'function'
135
- ? t("settings.profile.anonymousName")
136
- : 'Anonymous';
137
-
138
- return {
139
- displayName: userProfileData?.displayName || anonymousName,
140
- userId: userProfileData?.userId ?? undefined,
141
- isAnonymous,
142
- avatarUrl: userProfileData?.avatarUrl ?? undefined,
143
- onPress: isAnonymous ? handleSignIn : undefined,
144
- accountSettingsRoute: isAnonymous ? undefined : "Account",
145
- };
146
- }, [userProfileData, t, handleSignIn]);
147
-
148
- const accountConfig = useMemo((): AccountScreenConfig => {
149
- const isAnonymous = user?.isAnonymous ?? true;
150
-
151
- // Ensure t function is available before using it
152
- const getTranslation = (key: string, fallback: string) =>
153
- typeof t === 'function' ? t(key) : fallback;
154
-
155
- return {
156
- profile: {
157
- displayName: userProfileData?.displayName || user?.displayName || getTranslation("settings.profile.anonymousName", "Anonymous"),
158
- userId: userProfileData?.userId ?? user?.uid ?? undefined,
159
- isAnonymous,
160
- avatarUrl: userProfileData?.avatarUrl ?? user?.photoURL ?? undefined,
161
- benefits: isAnonymous ? [
162
- getTranslation("settings.profile.benefits.saveHistory", "Save history"),
163
- getTranslation("settings.profile.benefits.syncDevices", "Sync devices"),
164
- getTranslation("settings.profile.benefits.cloudSync", "Cloud sync"),
165
- getTranslation("settings.profile.benefits.secureBackup", "Secure backup"),
166
- ] : undefined,
167
- },
168
- isAnonymous,
169
- editProfileText: getTranslation("settings.account.editProfile", "Edit Profile"),
170
- onSignIn: handleSignIn,
171
- accountActions: {
172
- onLogout: handleSignOut,
173
- onDeleteAccount: handleDeleteAccount,
174
- logoutText: getTranslation("settings.account.logout", "Log Out"),
175
- logoutConfirmTitle: getTranslation("settings.account.logoutConfirmTitle", "Log Out"),
176
- logoutConfirmMessage: getTranslation("settings.account.logoutConfirmMessage", "Are you sure you want to log out?"),
177
- cancelText: getTranslation("common.cancel", "Cancel"),
178
- deleteAccountText: getTranslation("settings.account.deleteAccount", "Delete Account"),
179
- deleteConfirmTitle: getTranslation("settings.account.deleteConfirmTitle", "Delete Account"),
180
- deleteConfirmMessage: getTranslation("settings.account.deleteConfirmMessage", "Are you sure you want to delete your account? This action cannot be undone."),
181
- },
182
- };
183
- }, [user, userProfileData, handleSignIn, handleSignOut, handleDeleteAccount, t]);
132
+ const userProfile = useMemo(() => createUserProfileDisplay({
133
+ profileData: userProfileData,
134
+ t,
135
+ onSignIn: handleSignIn,
136
+ }), [userProfileData, t, handleSignIn]);
137
+
138
+ const accountConfig = useMemo(() => createAccountConfig({
139
+ displayName: userProfileData?.displayName || user?.displayName || undefined,
140
+ userId: userProfileData?.userId ?? user?.uid ?? undefined,
141
+ photoURL: user?.photoURL ?? undefined,
142
+ isAnonymous: user?.isAnonymous,
143
+ avatarUrl: userProfileData?.avatarUrl ?? undefined,
144
+ onSignIn: handleSignIn,
145
+ onLogout: handleSignOut,
146
+ onDeleteAccount: handleDeleteAccount,
147
+ t,
148
+ }), [user, userProfileData, handleSignIn, handleSignOut, handleDeleteAccount, t]);
184
149
 
185
150
  const translatedFaqData = useMemo((): FAQData | undefined => {
186
151
  if (!faqData) return undefined;
@@ -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);