@umituz/react-native-settings 4.23.97 → 4.23.99
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 +1 -1
- package/src/domains/about/domain/entities/AppInfo.ts +1 -0
- package/src/domains/about/presentation/components/AboutContent.tsx +6 -6
- package/src/domains/about/presentation/screens/AboutScreen.tsx +2 -4
- package/src/domains/appearance/presentation/screens/AppearanceScreen.tsx +9 -12
- package/src/domains/disclaimer/presentation/components/DisclaimerSetting.tsx +9 -20
- package/src/domains/disclaimer/presentation/screens/DisclaimerScreen.tsx +2 -6
- package/src/domains/gamification/types/index.ts +12 -12
- package/src/domains/localization/presentation/components/LanguageSection.tsx +3 -3
- package/src/domains/localization/presentation/screens/LanguageSelectionScreen.tsx +1 -1
- package/src/domains/notifications/presentation/components/NotificationsSection.tsx +2 -4
- package/src/domains/notifications/presentation/screens/NotificationSettingsScreen.tsx +1 -3
- package/src/infrastructure/utils/configFactory.ts +3 -14
- package/src/presentation/hooks/useSettingsScreenConfig.ts +27 -12
- package/src/presentation/navigation/SettingsStackNavigator.tsx +9 -8
- package/src/presentation/navigation/hooks/useNavigationHandlers.ts +4 -2
- package/src/presentation/navigation/hooks/useSettingsScreens.ts +10 -10
- package/src/presentation/navigation/utils/navigationTranslations.ts +29 -32
- package/src/presentation/screens/SettingsScreen.tsx +5 -1
- package/src/presentation/screens/components/GamificationSettingsItem.tsx +3 -6
- package/src/presentation/screens/components/SettingsContent.tsx +9 -5
- package/src/presentation/screens/components/SettingsHeader.tsx +4 -3
- package/src/presentation/screens/components/SubscriptionSettingsItem.tsx +3 -4
- package/src/presentation/screens/components/VideoTutorialSettingsItem.tsx +2 -4
- package/src/presentation/screens/components/WalletSettingsItem.tsx +3 -4
- package/src/presentation/screens/components/sections/FeatureSettingsSection.tsx +11 -13
- package/src/presentation/screens/components/sections/IdentitySettingsSection.tsx +5 -6
- package/src/presentation/screens/components/sections/ProfileSectionLoader.tsx +11 -9
- package/src/presentation/screens/components/sections/SupportSettingsSection.tsx +22 -23
- package/src/presentation/screens/types/SettingsConfig.ts +97 -6
- package/src/presentation/utils/accountConfigUtils.ts +9 -17
- package/src/presentation/utils/config-creators/base-configs.ts +0 -22
- package/src/presentation/utils/config-creators/feature-configs.ts +0 -20
- package/src/presentation/utils/config-creators/support-configs.ts +2 -12
- package/src/presentation/utils/faqTranslator.ts +5 -18
- package/src/presentation/utils/settingsConfigFactory.ts +10 -13
- package/src/presentation/utils/useAuthHandlers.ts +13 -20
- package/src/presentation/utils/userProfileUtils.ts +2 -16
- package/src/domains/disclaimer/README.md +0 -87
- package/src/domains/disclaimer/presentation/components/DisclaimerCard.test.tsx +0 -208
- package/src/domains/disclaimer/presentation/components/DisclaimerModal.test.tsx +0 -236
- package/src/domains/disclaimer/presentation/components/DisclaimerSetting.test.tsx +0 -74
- package/src/domains/disclaimer/presentation/components/README.md +0 -97
- package/src/domains/localization/presentation/components/__tests__/LanguageItem.test.tsx +0 -106
|
@@ -1,45 +1,42 @@
|
|
|
1
|
-
|
|
2
|
-
* Navigation Translations Utility
|
|
3
|
-
* Creates translation objects for navigation screens
|
|
4
|
-
*/
|
|
1
|
+
import type { SettingsTranslations } from "../../screens/types/SettingsConfig";
|
|
5
2
|
|
|
6
|
-
export const createNotificationTranslations = (
|
|
7
|
-
screenTitle:
|
|
8
|
-
masterToggleTitle:
|
|
9
|
-
masterToggleDescription:
|
|
10
|
-
soundTitle:
|
|
11
|
-
soundDescription:
|
|
12
|
-
vibrationTitle:
|
|
13
|
-
vibrationDescription:
|
|
14
|
-
remindersTitle:
|
|
15
|
-
remindersDescription:
|
|
16
|
-
quietHoursTitle:
|
|
17
|
-
quietHoursDescription:
|
|
3
|
+
export const createNotificationTranslations = (translations?: SettingsTranslations["features"]) => ({
|
|
4
|
+
screenTitle: translations?.notifications?.title || "",
|
|
5
|
+
masterToggleTitle: translations?.notifications?.masterToggleTitle || "",
|
|
6
|
+
masterToggleDescription: translations?.notifications?.masterToggleDescription || "",
|
|
7
|
+
soundTitle: translations?.notifications?.soundTitle || "",
|
|
8
|
+
soundDescription: translations?.notifications?.soundDescription || "",
|
|
9
|
+
vibrationTitle: translations?.notifications?.vibrationTitle || "",
|
|
10
|
+
vibrationDescription: translations?.notifications?.vibrationDescription || "",
|
|
11
|
+
remindersTitle: translations?.notifications?.remindersTitle || "",
|
|
12
|
+
remindersDescription: translations?.notifications?.remindersDescription || "",
|
|
13
|
+
quietHoursTitle: translations?.notifications?.quietHoursTitle || "",
|
|
14
|
+
quietHoursDescription: translations?.notifications?.quietHoursDescription || "",
|
|
18
15
|
});
|
|
19
16
|
|
|
20
|
-
export const createQuietHoursTranslations = (
|
|
21
|
-
title:
|
|
22
|
-
description:
|
|
23
|
-
startTimeLabel:
|
|
24
|
-
endTimeLabel:
|
|
25
|
-
enabledLabel:
|
|
17
|
+
export const createQuietHoursTranslations = (translations?: SettingsTranslations["features"]) => ({
|
|
18
|
+
title: translations?.notifications?.quietHours?.title || "",
|
|
19
|
+
description: translations?.notifications?.quietHours?.description || "",
|
|
20
|
+
startTimeLabel: translations?.notifications?.quietHours?.startTimeLabel || "",
|
|
21
|
+
endTimeLabel: translations?.notifications?.quietHours?.endTimeLabel || "",
|
|
22
|
+
enabledLabel: translations?.notifications?.quietHours?.enabledLabel || "",
|
|
26
23
|
});
|
|
27
24
|
|
|
28
25
|
export const createLegalScreenProps = (
|
|
29
|
-
|
|
26
|
+
translations: SettingsTranslations["features"],
|
|
30
27
|
handlePrivacyPress: () => void,
|
|
31
28
|
handleTermsPress: () => void,
|
|
32
29
|
handleEulaPress: () => void
|
|
33
30
|
) => ({
|
|
34
|
-
title:
|
|
35
|
-
description:
|
|
36
|
-
documentsHeader:
|
|
37
|
-
privacyTitle:
|
|
38
|
-
privacyDescription:
|
|
39
|
-
termsTitle:
|
|
40
|
-
termsDescription:
|
|
41
|
-
eulaTitle:
|
|
42
|
-
eulaDescription:
|
|
31
|
+
title: translations?.legal?.title || "",
|
|
32
|
+
description: translations?.legal?.description || "",
|
|
33
|
+
documentsHeader: translations?.legal?.documentsHeader || "",
|
|
34
|
+
privacyTitle: translations?.legal?.privacyTitle || "",
|
|
35
|
+
privacyDescription: translations?.legal?.privacyDescription || "",
|
|
36
|
+
termsTitle: translations?.legal?.termsTitle || "",
|
|
37
|
+
termsDescription: translations?.legal?.termsDescription || "",
|
|
38
|
+
eulaTitle: translations?.legal?.eulaTitle || "",
|
|
39
|
+
eulaDescription: translations?.legal?.eulaDescription || "",
|
|
43
40
|
onPrivacyPress: handlePrivacyPress,
|
|
44
41
|
onTermsPress: handleTermsPress,
|
|
45
42
|
onEulaPress: handleEulaPress,
|
|
@@ -86,7 +86,11 @@ export const SettingsScreen: React.FC<SettingsScreenProps> = (props) => {
|
|
|
86
86
|
});
|
|
87
87
|
|
|
88
88
|
const header = showHeader ? (
|
|
89
|
-
<SettingsHeader
|
|
89
|
+
<SettingsHeader
|
|
90
|
+
showCloseButton={showCloseButton}
|
|
91
|
+
onClose={handleClose}
|
|
92
|
+
title={normalizedConfig.translations?.title}
|
|
93
|
+
/>
|
|
90
94
|
) : undefined;
|
|
91
95
|
|
|
92
96
|
return (
|
|
@@ -18,7 +18,6 @@ export interface GamificationSettingsItemProps {
|
|
|
18
18
|
const GamificationSettingsItemComponent: React.FC<GamificationSettingsItemProps> = ({
|
|
19
19
|
config,
|
|
20
20
|
gamificationConfig,
|
|
21
|
-
t,
|
|
22
21
|
noBackground,
|
|
23
22
|
hideMargin,
|
|
24
23
|
}) => {
|
|
@@ -31,12 +30,10 @@ const GamificationSettingsItemComponent: React.FC<GamificationSettingsItemProps>
|
|
|
31
30
|
}, [navigation, config.route]);
|
|
32
31
|
|
|
33
32
|
const icon = (config.icon || "trophy-outline") as IconName;
|
|
34
|
-
const title = config.title
|
|
33
|
+
const title = config.title;
|
|
35
34
|
|
|
36
|
-
const description = config.description ||
|
|
37
|
-
|
|
38
|
-
.replace("{level}", level.currentLevel.toString())
|
|
39
|
-
.replace("{points}", level.currentPoints.toString());
|
|
35
|
+
const description = config.description ||
|
|
36
|
+
`${level.currentLevel} • ${level.currentPoints}`;
|
|
40
37
|
|
|
41
38
|
return (
|
|
42
39
|
<SettingsItemCard
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React, { useMemo } from "react";
|
|
2
2
|
import { View, StyleSheet } from "react-native";
|
|
3
|
-
import { useLocalization } from "../../../domains/localization";
|
|
4
3
|
import { SettingsFooter } from "../../components/SettingsFooter";
|
|
5
4
|
import { SettingsSection } from "../../components/SettingsSection";
|
|
6
5
|
import { DevSettingsSection, DevSettingsProps } from "../../../domains/dev";
|
|
@@ -108,7 +107,12 @@ export const SettingsContent: React.FC<SettingsContentProps> = ({
|
|
|
108
107
|
|
|
109
108
|
return (
|
|
110
109
|
<View style={styles.container}>
|
|
111
|
-
{showUserProfile &&
|
|
110
|
+
{showUserProfile && (
|
|
111
|
+
<ProfileSectionLoader
|
|
112
|
+
userProfile={userProfile}
|
|
113
|
+
translations={translations?.profile}
|
|
114
|
+
/>
|
|
115
|
+
)}
|
|
112
116
|
|
|
113
117
|
<CustomSettingsList customSections={customSections} />
|
|
114
118
|
|
|
@@ -127,7 +131,7 @@ export const SettingsContent: React.FC<SettingsContentProps> = ({
|
|
|
127
131
|
<FeatureSettingsSection normalizedConfig={normalizedConfig} features={features} />
|
|
128
132
|
|
|
129
133
|
{(features.gamification || features.videoTutorial) && (
|
|
130
|
-
<SettingsSection title={translations?.sections?.progress
|
|
134
|
+
<SettingsSection title={translations?.sections?.progress}>
|
|
131
135
|
{features.gamification && (
|
|
132
136
|
<GamificationSettingsItem
|
|
133
137
|
config={normalizedConfig.gamification.config || {}}
|
|
@@ -155,7 +159,7 @@ export const SettingsContent: React.FC<SettingsContentProps> = ({
|
|
|
155
159
|
|
|
156
160
|
{!hasAnyFeatures && (
|
|
157
161
|
<View style={styles.emptyContainer}>
|
|
158
|
-
<SettingsSection title={emptyStateText || translations?.noOptionsAvailable
|
|
162
|
+
<SettingsSection title={emptyStateText || translations?.noOptionsAvailable}>
|
|
159
163
|
<View />
|
|
160
164
|
</SettingsSection>
|
|
161
165
|
</View>
|
|
@@ -167,7 +171,7 @@ export const SettingsContent: React.FC<SettingsContentProps> = ({
|
|
|
167
171
|
<SettingsFooter
|
|
168
172
|
versionText={footerText}
|
|
169
173
|
appVersion={appVersion}
|
|
170
|
-
versionLabel={translations?.footer?.version
|
|
174
|
+
versionLabel={translations?.footer?.version}
|
|
171
175
|
/>
|
|
172
176
|
)}
|
|
173
177
|
</View>
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Pressable } from "react-native";
|
|
3
3
|
import { useAppDesignTokens, AtomicIcon, useAppNavigation, NavigationHeader } from "@umituz/react-native-design-system";
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
|
|
6
6
|
interface SettingsHeaderProps {
|
|
7
7
|
showCloseButton?: boolean;
|
|
8
8
|
onClose?: () => void;
|
|
9
|
+
title?: string;
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
export const SettingsHeader: React.FC<SettingsHeaderProps> = ({
|
|
12
13
|
showCloseButton = false,
|
|
13
14
|
onClose,
|
|
15
|
+
title,
|
|
14
16
|
}) => {
|
|
15
17
|
const navigation = useAppNavigation();
|
|
16
18
|
const tokens = useAppDesignTokens();
|
|
17
|
-
const { t } = useLocalization();
|
|
18
19
|
|
|
19
20
|
const handleClose = () => {
|
|
20
21
|
if (onClose) {
|
|
@@ -45,7 +46,7 @@ export const SettingsHeader: React.FC<SettingsHeaderProps> = ({
|
|
|
45
46
|
|
|
46
47
|
return (
|
|
47
48
|
<NavigationHeader
|
|
48
|
-
title={
|
|
49
|
+
title={title}
|
|
49
50
|
rightElement={rightElement}
|
|
50
51
|
// If NOT showing close button, we might want a back button?
|
|
51
52
|
// But usually Settings is a root screen in a modal or stack.
|
|
@@ -7,10 +7,9 @@ import { compareConfigAndTranslate } from "../../../infrastructure/utils/memoCom
|
|
|
7
7
|
|
|
8
8
|
export interface SubscriptionSettingsItemProps {
|
|
9
9
|
config: SubscriptionConfig;
|
|
10
|
-
t?: (key: string) => string;
|
|
11
10
|
}
|
|
12
11
|
|
|
13
|
-
const SubscriptionSettingsItemComponent: React.FC<SubscriptionSettingsItemProps> = ({ config
|
|
12
|
+
const SubscriptionSettingsItemComponent: React.FC<SubscriptionSettingsItemProps> = ({ config }) => {
|
|
14
13
|
const navigation = useAppNavigation();
|
|
15
14
|
|
|
16
15
|
const handlePress = React.useCallback(() => {
|
|
@@ -23,8 +22,8 @@ const SubscriptionSettingsItemComponent: React.FC<SubscriptionSettingsItemProps>
|
|
|
23
22
|
|
|
24
23
|
return (
|
|
25
24
|
<SettingsItemCard
|
|
26
|
-
title={config.title
|
|
27
|
-
description={config.description
|
|
25
|
+
title={config.title}
|
|
26
|
+
description={config.description}
|
|
28
27
|
icon={(config.icon || "star") as IconName}
|
|
29
28
|
onPress={handlePress}
|
|
30
29
|
sectionTitle={config.sectionTitle}
|
|
@@ -7,14 +7,12 @@ import { compareConfigAndTranslate } from "../../../infrastructure/utils/memoCom
|
|
|
7
7
|
|
|
8
8
|
export interface VideoTutorialSettingsItemProps {
|
|
9
9
|
config: VideoTutorialConfig;
|
|
10
|
-
t?: (key: string) => string;
|
|
11
10
|
noBackground?: boolean;
|
|
12
11
|
hideMargin?: boolean;
|
|
13
12
|
}
|
|
14
13
|
|
|
15
14
|
const VideoTutorialSettingsItemComponent: React.FC<VideoTutorialSettingsItemProps> = ({
|
|
16
15
|
config,
|
|
17
|
-
t,
|
|
18
16
|
noBackground,
|
|
19
17
|
hideMargin,
|
|
20
18
|
}) => {
|
|
@@ -30,8 +28,8 @@ const VideoTutorialSettingsItemComponent: React.FC<VideoTutorialSettingsItemProp
|
|
|
30
28
|
}, [navigation, config.onPress, config.route]);
|
|
31
29
|
|
|
32
30
|
const icon = (config.icon || "play-circle-outline") as IconName;
|
|
33
|
-
const title = config.title
|
|
34
|
-
const description = config.description
|
|
31
|
+
const title = config.title;
|
|
32
|
+
const description = config.description;
|
|
35
33
|
|
|
36
34
|
return (
|
|
37
35
|
<SettingsItemCard
|
|
@@ -7,10 +7,9 @@ import { compareConfigAndTranslate } from "../../../infrastructure/utils/memoCom
|
|
|
7
7
|
|
|
8
8
|
export interface WalletSettingsItemProps {
|
|
9
9
|
config: WalletConfig;
|
|
10
|
-
t?: (key: string) => string;
|
|
11
10
|
}
|
|
12
11
|
|
|
13
|
-
const WalletSettingsItemComponent: React.FC<WalletSettingsItemProps> = ({ config
|
|
12
|
+
const WalletSettingsItemComponent: React.FC<WalletSettingsItemProps> = ({ config }) => {
|
|
14
13
|
const navigation = useAppNavigation();
|
|
15
14
|
|
|
16
15
|
const handlePress = React.useCallback(() => {
|
|
@@ -21,8 +20,8 @@ const WalletSettingsItemComponent: React.FC<WalletSettingsItemProps> = ({ config
|
|
|
21
20
|
|
|
22
21
|
return (
|
|
23
22
|
<SettingsItemCard
|
|
24
|
-
title={config.title
|
|
25
|
-
description={config.description
|
|
23
|
+
title={config.title}
|
|
24
|
+
description={config.description}
|
|
26
25
|
icon={(config.icon || "wallet") as IconName}
|
|
27
26
|
onPress={handlePress}
|
|
28
27
|
sectionTitle={config.sectionTitle}
|
|
@@ -2,7 +2,7 @@ import React from "react";
|
|
|
2
2
|
import { useAppNavigation } from "@umituz/react-native-design-system";
|
|
3
3
|
import { AppearanceSection } from "../../../../domains/appearance/presentation/components/AppearanceSection";
|
|
4
4
|
import { NotificationsSection } from "../../../../domains/notifications";
|
|
5
|
-
import {
|
|
5
|
+
import { getLanguageByCode } from "../../../../domains/localization";
|
|
6
6
|
import { SettingsItemCard } from "../../../components/SettingsItemCard";
|
|
7
7
|
import type { NormalizedConfig } from "../../utils/normalizeConfig";
|
|
8
8
|
import { SettingsSection } from "../../../components/SettingsSection";
|
|
@@ -35,28 +35,26 @@ export const FeatureSettingsSection: React.FC<FeatureSettingsSectionProps> = ({
|
|
|
35
35
|
}
|
|
36
36
|
}, [navigation, normalizedConfig.language.config]);
|
|
37
37
|
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
[currentLanguage]
|
|
41
|
-
);
|
|
38
|
+
const langCode = currentLanguage || "en-US";
|
|
39
|
+
const currentLanguageData = React.useMemo(() => getLanguageByCode(langCode), [langCode]);
|
|
42
40
|
|
|
43
41
|
const languageDisplayName = React.useMemo(() => {
|
|
44
|
-
if (!currentLanguageData) return
|
|
42
|
+
if (!currentLanguageData) return langCode;
|
|
45
43
|
return `${currentLanguageData.flag} ${currentLanguageData.nativeName}`;
|
|
46
|
-
}, [currentLanguageData,
|
|
44
|
+
}, [currentLanguageData, langCode]);
|
|
47
45
|
|
|
48
46
|
if (!features.appearance && !features.language && !features.notifications) return null;
|
|
49
47
|
|
|
50
48
|
return (
|
|
51
49
|
<SettingsSection
|
|
52
|
-
title={translations?.sections?.app
|
|
50
|
+
title={translations?.sections?.app}
|
|
53
51
|
>
|
|
54
52
|
{features.appearance && (
|
|
55
53
|
<AppearanceSection
|
|
56
54
|
config={{
|
|
57
55
|
...normalizedConfig.appearance.config,
|
|
58
|
-
title: translations?.features?.appearance?.title
|
|
59
|
-
description: translations?.features?.appearance?.description
|
|
56
|
+
title: translations?.features?.appearance?.title,
|
|
57
|
+
description: translations?.features?.appearance?.description,
|
|
60
58
|
}}
|
|
61
59
|
noBackground={true}
|
|
62
60
|
hideMargin={true}
|
|
@@ -65,7 +63,7 @@ export const FeatureSettingsSection: React.FC<FeatureSettingsSectionProps> = ({
|
|
|
65
63
|
|
|
66
64
|
{features.language && (
|
|
67
65
|
<SettingsItemCard
|
|
68
|
-
title={translations?.features?.language?.title
|
|
66
|
+
title={translations?.features?.language?.title}
|
|
69
67
|
description={languageDisplayName}
|
|
70
68
|
icon="globe-outline"
|
|
71
69
|
onPress={handleLanguagePress}
|
|
@@ -78,8 +76,8 @@ export const FeatureSettingsSection: React.FC<FeatureSettingsSectionProps> = ({
|
|
|
78
76
|
<NotificationsSection
|
|
79
77
|
config={{
|
|
80
78
|
...normalizedConfig.notifications.config,
|
|
81
|
-
title: translations?.features?.notifications?.title
|
|
82
|
-
description: translations?.features?.notifications?.description
|
|
79
|
+
title: translations?.features?.notifications?.title,
|
|
80
|
+
description: translations?.features?.notifications?.description,
|
|
83
81
|
}}
|
|
84
82
|
noBackground={true}
|
|
85
83
|
hideMargin={true}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { AboutSection } from "../../../../domains/about/presentation/components/AboutSection";
|
|
3
3
|
import { LegalSection } from "../../../../domains/legal/presentation/components/LegalSection";
|
|
4
|
-
import { useLocalization } from "../../../../domains/localization";
|
|
5
4
|
import type { NormalizedConfig } from "../../utils/normalizeConfig";
|
|
6
5
|
import { SettingsSection } from "../../../components/SettingsSection";
|
|
7
6
|
import { compareConfigAndFeatures } from "../../../../infrastructure/utils/memoComparisonUtils";
|
|
@@ -20,13 +19,13 @@ export const IdentitySettingsSection: React.FC<IdentitySettingsSectionProps> = (
|
|
|
20
19
|
if (!features.about && !features.legal) return null;
|
|
21
20
|
|
|
22
21
|
return (
|
|
23
|
-
<SettingsSection title={translations?.sections?.about
|
|
22
|
+
<SettingsSection title={translations?.sections?.about}>
|
|
24
23
|
{features.about && (
|
|
25
24
|
<AboutSection
|
|
26
25
|
config={{
|
|
27
26
|
...normalizedConfig.about.config,
|
|
28
|
-
title: translations?.features?.about?.title
|
|
29
|
-
description: translations?.features?.about?.description
|
|
27
|
+
title: translations?.features?.about?.title,
|
|
28
|
+
description: translations?.features?.about?.description,
|
|
30
29
|
}}
|
|
31
30
|
noBackground={true}
|
|
32
31
|
hideMargin={true}
|
|
@@ -37,8 +36,8 @@ export const IdentitySettingsSection: React.FC<IdentitySettingsSectionProps> = (
|
|
|
37
36
|
<LegalSection
|
|
38
37
|
config={{
|
|
39
38
|
...normalizedConfig.legal.config,
|
|
40
|
-
title: translations?.features?.legal?.title
|
|
41
|
-
description: translations?.features?.legal?.description
|
|
39
|
+
title: translations?.features?.legal?.title,
|
|
40
|
+
description: translations?.features?.legal?.description,
|
|
42
41
|
}}
|
|
43
42
|
noBackground={true}
|
|
44
43
|
hideMargin={true}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { View, StyleSheet } from "react-native";
|
|
3
3
|
import { ProfileSection } from "@umituz/react-native-auth";
|
|
4
|
-
import { useLocalization } from "../../../../domains/localization";
|
|
5
4
|
import { useAppNavigation } from "@umituz/react-native-design-system";
|
|
6
|
-
import { createSinglePropComparator } from "../../../../infrastructure/utils/memoComparisonUtils";
|
|
7
5
|
|
|
8
6
|
export interface ProfileSectionLoaderProps {
|
|
9
7
|
userProfile?: {
|
|
@@ -15,10 +13,14 @@ export interface ProfileSectionLoaderProps {
|
|
|
15
13
|
onPress?: () => void;
|
|
16
14
|
benefits?: string[];
|
|
17
15
|
};
|
|
16
|
+
translations?: {
|
|
17
|
+
guest?: string;
|
|
18
|
+
anonymousName?: string;
|
|
19
|
+
signIn?: string;
|
|
20
|
+
};
|
|
18
21
|
}
|
|
19
22
|
|
|
20
|
-
export const ProfileSectionLoader: React.FC<ProfileSectionLoaderProps> = React.memo(({ userProfile }) => {
|
|
21
|
-
const { t } = useLocalization();
|
|
23
|
+
export const ProfileSectionLoader: React.FC<ProfileSectionLoaderProps> = React.memo(({ userProfile, translations }) => {
|
|
22
24
|
const navigation = useAppNavigation();
|
|
23
25
|
|
|
24
26
|
const handlePress = React.useCallback(() => {
|
|
@@ -33,9 +35,9 @@ export const ProfileSectionLoader: React.FC<ProfileSectionLoaderProps> = React.m
|
|
|
33
35
|
const anonymousDisplayName = React.useMemo(() => {
|
|
34
36
|
if (!userProfile) return "";
|
|
35
37
|
return userProfile.isAnonymous && userProfile.userId
|
|
36
|
-
? `${
|
|
37
|
-
:
|
|
38
|
-
}, [userProfile,
|
|
38
|
+
? `${translations?.guest || ""} ${userProfile.userId.substring(0, 8)}`
|
|
39
|
+
: (translations?.anonymousName || "");
|
|
40
|
+
}, [userProfile, translations]);
|
|
39
41
|
|
|
40
42
|
if (!userProfile) return null;
|
|
41
43
|
|
|
@@ -52,12 +54,12 @@ export const ProfileSectionLoader: React.FC<ProfileSectionLoaderProps> = React.m
|
|
|
52
54
|
}}
|
|
53
55
|
onPress={handlePress}
|
|
54
56
|
onSignIn={userProfile.onPress}
|
|
55
|
-
signInText={
|
|
57
|
+
signInText={translations?.signIn || ""}
|
|
56
58
|
anonymousText={anonymousDisplayName}
|
|
57
59
|
/>
|
|
58
60
|
</View>
|
|
59
61
|
);
|
|
60
|
-
},
|
|
62
|
+
}, (prev, next) => prev.userProfile === next.userProfile && prev.translations === next.translations);
|
|
61
63
|
|
|
62
64
|
ProfileSectionLoader.displayName = "ProfileSectionLoader";
|
|
63
65
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React, { useCallback } from "react";
|
|
2
|
-
import { useLocalization } from "../../../../domains/localization";
|
|
3
2
|
import { useAppNavigation } from "@umituz/react-native-design-system";
|
|
4
3
|
import { SupportSection } from "../../../../domains/feedback/presentation/components/SupportSection";
|
|
5
4
|
import { SettingsSection } from "../../../components/SettingsSection";
|
|
@@ -26,7 +25,7 @@ export const SupportSettingsSection: React.FC<SupportSettingsSectionProps> = ({
|
|
|
26
25
|
if (!(features.feedback || features.rating || features.faqs)) return null;
|
|
27
26
|
|
|
28
27
|
return (
|
|
29
|
-
<SettingsSection title={translations?.sections?.support
|
|
28
|
+
<SettingsSection title={translations?.sections?.support}>
|
|
30
29
|
{(features.feedback || features.rating) && (
|
|
31
30
|
<SupportSection
|
|
32
31
|
renderSection={(props: { title: string; children: React.ReactNode }) => <>{props.children}</>}
|
|
@@ -42,8 +41,8 @@ export const SupportSettingsSection: React.FC<SupportSettingsSectionProps> = ({
|
|
|
42
41
|
feedbackConfig={{
|
|
43
42
|
enabled: features.feedback,
|
|
44
43
|
config: {
|
|
45
|
-
title: normalizedConfig.feedback.config?.title || translations?.features?.feedback?.title
|
|
46
|
-
description: normalizedConfig.feedback.config?.description || translations?.features?.feedback?.description
|
|
44
|
+
title: normalizedConfig.feedback.config?.title || translations?.features?.feedback?.title,
|
|
45
|
+
description: normalizedConfig.feedback.config?.description || translations?.features?.feedback?.description,
|
|
47
46
|
initialType: normalizedConfig.feedback.config?.initialType,
|
|
48
47
|
onSubmit: normalizedConfig.feedback.config?.onSubmit,
|
|
49
48
|
onPress: normalizedConfig.feedback.config?.onPress,
|
|
@@ -52,32 +51,32 @@ export const SupportSettingsSection: React.FC<SupportSettingsSectionProps> = ({
|
|
|
52
51
|
ratingConfig={{
|
|
53
52
|
enabled: features.rating,
|
|
54
53
|
config: {
|
|
55
|
-
title: normalizedConfig.rating.config?.title || translations?.features?.rating?.title
|
|
56
|
-
description: normalizedConfig.rating.config?.description || translations?.features?.rating?.description
|
|
54
|
+
title: normalizedConfig.rating.config?.title || translations?.features?.rating?.title,
|
|
55
|
+
description: normalizedConfig.rating.config?.description || translations?.features?.rating?.description,
|
|
57
56
|
storeUrl: normalizedConfig.rating.config?.storeUrl,
|
|
58
57
|
onRate: normalizedConfig.rating.config?.onRate,
|
|
59
58
|
}
|
|
60
59
|
}}
|
|
61
60
|
feedbackModalTexts={{
|
|
62
|
-
title: translations?.feedbackModal?.title
|
|
63
|
-
ratingLabel: translations?.feedbackModal?.ratingLabel
|
|
64
|
-
descriptionPlaceholder: translations?.feedbackModal?.descriptionPlaceholder
|
|
65
|
-
submitButton: translations?.feedbackModal?.submitButton
|
|
66
|
-
submittingButton: translations?.feedbackModal?.submittingButton
|
|
61
|
+
title: translations?.feedbackModal?.title,
|
|
62
|
+
ratingLabel: translations?.feedbackModal?.ratingLabel,
|
|
63
|
+
descriptionPlaceholder: translations?.feedbackModal?.descriptionPlaceholder,
|
|
64
|
+
submitButton: translations?.feedbackModal?.submitButton,
|
|
65
|
+
submittingButton: translations?.feedbackModal?.submittingButton,
|
|
67
66
|
feedbackTypes: [
|
|
68
|
-
{ type: 'general', label: translations?.feedbackModal?.types?.general
|
|
69
|
-
{ type: 'bug_report', label: translations?.feedbackModal?.types?.bugReport
|
|
70
|
-
{ type: 'feature_request', label: translations?.feedbackModal?.types?.featureRequest
|
|
71
|
-
{ type: 'improvement', label: translations?.feedbackModal?.types?.improvement
|
|
72
|
-
{ type: 'other', label: translations?.feedbackModal?.types?.other
|
|
67
|
+
{ type: 'general', label: translations?.feedbackModal?.types?.general },
|
|
68
|
+
{ type: 'bug_report', label: translations?.feedbackModal?.types?.bugReport },
|
|
69
|
+
{ type: 'feature_request', label: translations?.feedbackModal?.types?.featureRequest },
|
|
70
|
+
{ type: 'improvement', label: translations?.feedbackModal?.types?.improvement },
|
|
71
|
+
{ type: 'other', label: translations?.feedbackModal?.types?.other },
|
|
73
72
|
],
|
|
74
73
|
defaultTitle: (type) => {
|
|
75
74
|
const titles: Record<string, string> = {
|
|
76
|
-
general: translations?.feedbackModal?.types?.general ||
|
|
77
|
-
bug_report: translations?.feedbackModal?.types?.bugReport ||
|
|
78
|
-
feature_request: translations?.feedbackModal?.types?.featureRequest ||
|
|
79
|
-
improvement: translations?.feedbackModal?.types?.improvement ||
|
|
80
|
-
other: translations?.feedbackModal?.types?.other ||
|
|
75
|
+
general: translations?.feedbackModal?.types?.general || type,
|
|
76
|
+
bug_report: translations?.feedbackModal?.types?.bugReport || type,
|
|
77
|
+
feature_request: translations?.feedbackModal?.types?.featureRequest || type,
|
|
78
|
+
improvement: translations?.feedbackModal?.types?.improvement || type,
|
|
79
|
+
other: translations?.feedbackModal?.types?.other || type,
|
|
81
80
|
};
|
|
82
81
|
return titles[type] || type;
|
|
83
82
|
},
|
|
@@ -87,8 +86,8 @@ export const SupportSettingsSection: React.FC<SupportSettingsSectionProps> = ({
|
|
|
87
86
|
|
|
88
87
|
{features.faqs && (
|
|
89
88
|
<SettingsItemCard
|
|
90
|
-
title={normalizedConfig.faqs.config?.title || translations?.features?.faqs?.title
|
|
91
|
-
description={normalizedConfig.faqs.config?.description || translations?.features?.faqs?.description
|
|
89
|
+
title={normalizedConfig.faqs.config?.title || translations?.features?.faqs?.title}
|
|
90
|
+
description={normalizedConfig.faqs.config?.description || translations?.features?.faqs?.description}
|
|
92
91
|
icon="help-circle-outline"
|
|
93
92
|
onPress={handleFAQPress}
|
|
94
93
|
noBackground={true}
|
|
@@ -59,6 +59,17 @@ import type {
|
|
|
59
59
|
* Global Settings Translations
|
|
60
60
|
*/
|
|
61
61
|
export interface SettingsTranslations {
|
|
62
|
+
title?: string;
|
|
63
|
+
profile?: {
|
|
64
|
+
guest?: string;
|
|
65
|
+
anonymousName?: string;
|
|
66
|
+
signIn?: string;
|
|
67
|
+
signInDescription?: string;
|
|
68
|
+
anonymousBenefits?: {
|
|
69
|
+
title?: string;
|
|
70
|
+
items?: string[];
|
|
71
|
+
};
|
|
72
|
+
};
|
|
62
73
|
sections?: {
|
|
63
74
|
app?: string;
|
|
64
75
|
progress?: string;
|
|
@@ -67,14 +78,84 @@ export interface SettingsTranslations {
|
|
|
67
78
|
subscription?: string;
|
|
68
79
|
};
|
|
69
80
|
features?: {
|
|
70
|
-
appearance?: {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
81
|
+
appearance?: {
|
|
82
|
+
title?: string;
|
|
83
|
+
description?: string;
|
|
84
|
+
themeModes?: {
|
|
85
|
+
light?: string;
|
|
86
|
+
dark?: string;
|
|
87
|
+
auto?: string;
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
language?: {
|
|
91
|
+
title?: string;
|
|
92
|
+
description?: string;
|
|
93
|
+
searchPlaceholder?: string;
|
|
94
|
+
};
|
|
95
|
+
notifications?: {
|
|
96
|
+
title?: string;
|
|
97
|
+
description?: string;
|
|
98
|
+
masterToggleTitle?: string;
|
|
99
|
+
masterToggleDescription?: string;
|
|
100
|
+
soundTitle?: string;
|
|
101
|
+
soundDescription?: string;
|
|
102
|
+
vibrationTitle?: string;
|
|
103
|
+
vibrationDescription?: string;
|
|
104
|
+
remindersTitle?: string;
|
|
105
|
+
remindersDescription?: string;
|
|
106
|
+
quietHoursTitle?: string;
|
|
107
|
+
quietHoursDescription?: string;
|
|
108
|
+
quietHours?: {
|
|
109
|
+
title?: string;
|
|
110
|
+
description?: string;
|
|
111
|
+
startTimeLabel?: string;
|
|
112
|
+
endTimeLabel?: string;
|
|
113
|
+
enabledLabel?: string;
|
|
114
|
+
};
|
|
115
|
+
};
|
|
116
|
+
about?: {
|
|
117
|
+
title?: string;
|
|
118
|
+
description?: string;
|
|
119
|
+
contact?: string;
|
|
120
|
+
more?: string;
|
|
121
|
+
developer?: string;
|
|
122
|
+
email?: string;
|
|
123
|
+
website?: string;
|
|
124
|
+
moreApps?: string;
|
|
125
|
+
versionPrefix?: string;
|
|
126
|
+
};
|
|
127
|
+
legal?: {
|
|
128
|
+
title?: string;
|
|
129
|
+
description?: string;
|
|
130
|
+
documentsHeader?: string;
|
|
131
|
+
privacyTitle?: string;
|
|
132
|
+
privacyDescription?: string;
|
|
133
|
+
termsTitle?: string;
|
|
134
|
+
termsDescription?: string;
|
|
135
|
+
eulaTitle?: string;
|
|
136
|
+
eulaDescription?: string;
|
|
137
|
+
};
|
|
75
138
|
feedback?: { title?: string; description?: string };
|
|
76
139
|
rating?: { title?: string; description?: string };
|
|
77
|
-
faqs?: {
|
|
140
|
+
faqs?: {
|
|
141
|
+
title?: string;
|
|
142
|
+
description?: string;
|
|
143
|
+
searchPlaceholder?: string;
|
|
144
|
+
emptySearchTitle?: string;
|
|
145
|
+
emptySearchMessage?: string;
|
|
146
|
+
headerTitle?: string;
|
|
147
|
+
};
|
|
148
|
+
languageSelection?: {
|
|
149
|
+
searchPlaceholder?: string;
|
|
150
|
+
};
|
|
151
|
+
subscription?: {
|
|
152
|
+
title?: string;
|
|
153
|
+
description?: string;
|
|
154
|
+
};
|
|
155
|
+
videoTutorial?: {
|
|
156
|
+
title?: string;
|
|
157
|
+
description?: string;
|
|
158
|
+
};
|
|
78
159
|
};
|
|
79
160
|
feedbackModal?: {
|
|
80
161
|
title?: string;
|
|
@@ -94,6 +175,16 @@ export interface SettingsTranslations {
|
|
|
94
175
|
footer?: {
|
|
95
176
|
version?: string;
|
|
96
177
|
};
|
|
178
|
+
errors?: {
|
|
179
|
+
common?: string;
|
|
180
|
+
unknown?: string;
|
|
181
|
+
unknownError?: string;
|
|
182
|
+
appStoreUrlMissing?: string;
|
|
183
|
+
appStoreUrlNotConfigured?: string;
|
|
184
|
+
unableToOpenAppStore?: string;
|
|
185
|
+
failedToOpenAppStore?: string;
|
|
186
|
+
deleteAccountError?: string;
|
|
187
|
+
};
|
|
97
188
|
}
|
|
98
189
|
|
|
99
190
|
export interface SettingsConfig {
|