@umituz/react-native-settings 4.23.97 → 4.23.98
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 +14 -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 +61 -3
- 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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-settings",
|
|
3
|
-
"version": "4.23.
|
|
3
|
+
"version": "4.23.98",
|
|
4
4
|
"description": "Complete settings hub for React Native apps - consolidated package with settings, localization, about, legal, appearance, feedback, FAQs, rating, and gamification",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -41,11 +41,11 @@ export const AboutContent: React.FC<AboutContentProps> = ({
|
|
|
41
41
|
<View style={styles.content}>
|
|
42
42
|
{hasContactInfo && (
|
|
43
43
|
<View style={styles.section}>
|
|
44
|
-
<AboutSectionHeader title={texts.contact || "
|
|
44
|
+
<AboutSectionHeader title={texts.contact || ""} />
|
|
45
45
|
|
|
46
46
|
{appInfo.developer && (
|
|
47
47
|
<AboutSettingItem
|
|
48
|
-
title={texts.developer || "
|
|
48
|
+
title={texts.developer || ""}
|
|
49
49
|
value={appInfo.developer}
|
|
50
50
|
testID="developer-item"
|
|
51
51
|
/>
|
|
@@ -53,7 +53,7 @@ export const AboutContent: React.FC<AboutContentProps> = ({
|
|
|
53
53
|
|
|
54
54
|
{appInfo.contactEmail && (
|
|
55
55
|
<AboutSettingItem
|
|
56
|
-
title={texts.email || "
|
|
56
|
+
title={texts.email || ""}
|
|
57
57
|
value={appInfo.contactEmail}
|
|
58
58
|
onPress={config.actions?.onEmailPress}
|
|
59
59
|
testID="email-item"
|
|
@@ -63,7 +63,7 @@ export const AboutContent: React.FC<AboutContentProps> = ({
|
|
|
63
63
|
|
|
64
64
|
{appInfo.websiteUrl && (
|
|
65
65
|
<AboutSettingItem
|
|
66
|
-
title={texts.website || "
|
|
66
|
+
title={texts.website || ""}
|
|
67
67
|
value={appInfo.websiteDisplay || appInfo.websiteUrl}
|
|
68
68
|
onPress={config.actions?.onWebsitePress}
|
|
69
69
|
testID="website-item"
|
|
@@ -75,9 +75,9 @@ export const AboutContent: React.FC<AboutContentProps> = ({
|
|
|
75
75
|
|
|
76
76
|
{hasMoreInfo && (
|
|
77
77
|
<View style={styles.section}>
|
|
78
|
-
<AboutSectionHeader title={texts.more || "
|
|
78
|
+
<AboutSectionHeader title={texts.more || ""} />
|
|
79
79
|
<AboutSettingItem
|
|
80
|
-
title={texts.moreApps || "
|
|
80
|
+
title={texts.moreApps || ""}
|
|
81
81
|
onPress={config.actions?.onMoreAppsPress}
|
|
82
82
|
testID="more-apps-item"
|
|
83
83
|
showChevron={!!config.actions?.onMoreAppsPress}
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
* Optimized for performance and memory safety
|
|
6
6
|
*/
|
|
7
7
|
import { ScreenLayout, NavigationHeader, useAppDesignTokens, useAppNavigation, AtomicText, AtomicSpinner } from '@umituz/react-native-design-system';
|
|
8
|
-
import { useLocalization } from '../../../localization';
|
|
9
8
|
import { useAboutInfo } from '../hooks/useAboutInfo';
|
|
10
9
|
import { AboutScreenContent } from './AboutScreenContent';
|
|
11
10
|
|
|
@@ -34,7 +33,6 @@ export const AboutScreen: React.FC<AboutScreenProps> = (props) => {
|
|
|
34
33
|
const { config, testID = 'about-screen' } = props;
|
|
35
34
|
const tokens = useAppDesignTokens();
|
|
36
35
|
const navigation = useAppNavigation();
|
|
37
|
-
const { t } = useLocalization();
|
|
38
36
|
|
|
39
37
|
const { appInfo, loading, error } = useAboutInfo({
|
|
40
38
|
autoInit: true,
|
|
@@ -43,7 +41,7 @@ export const AboutScreen: React.FC<AboutScreenProps> = (props) => {
|
|
|
43
41
|
|
|
44
42
|
const header = (
|
|
45
43
|
<NavigationHeader
|
|
46
|
-
title={
|
|
44
|
+
title={config.texts?.title || ""}
|
|
47
45
|
onBackPress={() => navigation.goBack()}
|
|
48
46
|
/>
|
|
49
47
|
);
|
|
@@ -57,7 +55,7 @@ export const AboutScreen: React.FC<AboutScreenProps> = (props) => {
|
|
|
57
55
|
}
|
|
58
56
|
|
|
59
57
|
if (error || !appInfo) {
|
|
60
|
-
const errorText = error ? `${config.texts?.errorPrefix ||
|
|
58
|
+
const errorText = error ? `${config.texts?.errorPrefix || ""} ${error}` : (config.texts?.noInfo || "");
|
|
61
59
|
return (
|
|
62
60
|
<ScreenLayout header={header} testID={testID}>
|
|
63
61
|
<AtomicText type="bodyMedium" color="error" style={{ textAlign: 'center', marginTop: 20 }}>
|
|
@@ -12,7 +12,6 @@ import {
|
|
|
12
12
|
NavigationHeader,
|
|
13
13
|
useAppNavigation
|
|
14
14
|
} from "@umituz/react-native-design-system";
|
|
15
|
-
import { useLocalization } from "../../../localization";
|
|
16
15
|
import { useAppearance } from "../../hooks/useAppearance";
|
|
17
16
|
import { useAppearanceActions } from "../../hooks/useAppearanceActions";
|
|
18
17
|
import {
|
|
@@ -41,7 +40,6 @@ export const AppearanceScreen: React.FC<AppearanceScreenProps> = ({
|
|
|
41
40
|
}) => {
|
|
42
41
|
const navigation = useAppNavigation();
|
|
43
42
|
const tokens = useAppDesignTokens();
|
|
44
|
-
const { t } = useLocalization();
|
|
45
43
|
const { themeMode } = useAppearance();
|
|
46
44
|
const {
|
|
47
45
|
localCustomColors,
|
|
@@ -75,17 +73,17 @@ export const AppearanceScreen: React.FC<AppearanceScreenProps> = ({
|
|
|
75
73
|
const themes: ThemeOptionConfig[] = [
|
|
76
74
|
{
|
|
77
75
|
mode: "light",
|
|
78
|
-
title: texts?.lightMode?.title ??
|
|
79
|
-
subtitle: texts?.lightMode?.subtitle ??
|
|
80
|
-
description: texts?.lightMode?.description ??
|
|
76
|
+
title: texts?.lightMode?.title ?? "",
|
|
77
|
+
subtitle: texts?.lightMode?.subtitle ?? "",
|
|
78
|
+
description: texts?.lightMode?.description ?? "",
|
|
81
79
|
features: texts?.lightMode?.features,
|
|
82
80
|
featuresTitle: texts?.featuresSectionTitle,
|
|
83
81
|
},
|
|
84
82
|
{
|
|
85
83
|
mode: "dark",
|
|
86
|
-
title: texts?.darkMode?.title ??
|
|
87
|
-
subtitle: texts?.darkMode?.subtitle ??
|
|
88
|
-
description: texts?.darkMode?.description ??
|
|
84
|
+
title: texts?.darkMode?.title ?? "",
|
|
85
|
+
subtitle: texts?.darkMode?.subtitle ?? "",
|
|
86
|
+
description: texts?.darkMode?.description ?? "",
|
|
89
87
|
features: texts?.darkMode?.features,
|
|
90
88
|
featuresTitle: texts?.featuresSectionTitle,
|
|
91
89
|
},
|
|
@@ -96,8 +94,8 @@ export const AppearanceScreen: React.FC<AppearanceScreenProps> = ({
|
|
|
96
94
|
tokens={tokens}
|
|
97
95
|
themeMode={themeMode}
|
|
98
96
|
onThemeSelect={handleThemeSelect}
|
|
99
|
-
title={texts?.themeSectionTitle ??
|
|
100
|
-
description={texts?.themeSectionDescription ??
|
|
97
|
+
title={texts?.themeSectionTitle ?? ""}
|
|
98
|
+
description={texts?.themeSectionDescription ?? ""}
|
|
101
99
|
themes={themes}
|
|
102
100
|
/>
|
|
103
101
|
);
|
|
@@ -111,7 +109,6 @@ export const AppearanceScreen: React.FC<AppearanceScreenProps> = ({
|
|
|
111
109
|
texts?.lightMode,
|
|
112
110
|
texts?.darkMode,
|
|
113
111
|
texts?.featuresSectionTitle,
|
|
114
|
-
t,
|
|
115
112
|
]);
|
|
116
113
|
|
|
117
114
|
const colorsSectionMemo = useMemo(() => {
|
|
@@ -163,7 +160,7 @@ export const AppearanceScreen: React.FC<AppearanceScreenProps> = ({
|
|
|
163
160
|
hideScrollIndicator
|
|
164
161
|
header={
|
|
165
162
|
<NavigationHeader
|
|
166
|
-
title={
|
|
163
|
+
title={texts?.title || ""}
|
|
167
164
|
onBackPress={() => navigation.goBack()}
|
|
168
165
|
/>
|
|
169
166
|
}
|
|
@@ -21,40 +21,32 @@ import React, { useState, useEffect, useCallback } from 'react';
|
|
|
21
21
|
import { Modal } from 'react-native';
|
|
22
22
|
|
|
23
23
|
import { useAppDesignTokens, withAlpha } from '@umituz/react-native-design-system';
|
|
24
|
-
import { useLocalization } from '../../../localization';
|
|
25
24
|
import { DisclaimerCard } from './DisclaimerCard';
|
|
26
25
|
import { DisclaimerModal } from './DisclaimerModal';
|
|
27
26
|
|
|
28
27
|
export interface DisclaimerSettingProps {
|
|
29
|
-
/** Custom title
|
|
30
|
-
|
|
31
|
-
/** Custom
|
|
32
|
-
|
|
33
|
-
/** Custom short message
|
|
34
|
-
|
|
28
|
+
/** Custom title */
|
|
29
|
+
title?: string;
|
|
30
|
+
/** Custom content */
|
|
31
|
+
content?: string;
|
|
32
|
+
/** Custom short message */
|
|
33
|
+
shortMessage?: string;
|
|
35
34
|
/** Custom icon name */
|
|
36
35
|
iconName?: string;
|
|
37
36
|
/** Custom icon color */
|
|
38
37
|
iconColor?: string;
|
|
39
38
|
/** Custom background color */
|
|
40
39
|
backgroundColor?: string;
|
|
41
|
-
/** Custom modal title */
|
|
42
|
-
modalTitle?: string;
|
|
43
|
-
/** Custom modal content */
|
|
44
|
-
modalContent?: string;
|
|
45
40
|
}
|
|
46
41
|
|
|
47
42
|
export const DisclaimerSetting: React.FC<DisclaimerSettingProps> = ({
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
43
|
+
title = "",
|
|
44
|
+
content = "",
|
|
45
|
+
shortMessage = "",
|
|
51
46
|
iconName = "alert-triangle",
|
|
52
47
|
iconColor,
|
|
53
48
|
backgroundColor,
|
|
54
|
-
modalTitle,
|
|
55
|
-
modalContent,
|
|
56
49
|
}) => {
|
|
57
|
-
const { t } = useLocalization();
|
|
58
50
|
const tokens = useAppDesignTokens();
|
|
59
51
|
const [modalVisible, setModalVisible] = useState(false);
|
|
60
52
|
|
|
@@ -64,9 +56,6 @@ export const DisclaimerSetting: React.FC<DisclaimerSettingProps> = ({
|
|
|
64
56
|
};
|
|
65
57
|
}, []);
|
|
66
58
|
|
|
67
|
-
const title = modalTitle || t(titleKey);
|
|
68
|
-
const content = modalContent || t(messageKey);
|
|
69
|
-
const shortMessage = t(shortMessageKey);
|
|
70
59
|
const finalIconColor = iconColor || tokens.colors.warning;
|
|
71
60
|
const finalBackgroundColor = backgroundColor || withAlpha(finalIconColor, 0.1);
|
|
72
61
|
|
|
@@ -23,7 +23,6 @@ import {
|
|
|
23
23
|
} from '@umituz/react-native-design-system';
|
|
24
24
|
import { AtomicText, AtomicIcon } from '@umituz/react-native-design-system';
|
|
25
25
|
import type { IconName } from '@umituz/react-native-design-system';
|
|
26
|
-
import { useLocalization } from '../../../localization';
|
|
27
26
|
|
|
28
27
|
export interface DisclaimerScreenProps {
|
|
29
28
|
/** Custom title (overrides translation) */
|
|
@@ -40,17 +39,14 @@ export interface DisclaimerScreenProps {
|
|
|
40
39
|
|
|
41
40
|
export const DisclaimerScreen: React.FC<DisclaimerScreenProps> = ({
|
|
42
41
|
title,
|
|
43
|
-
titleKey = 'settings.disclaimer.title',
|
|
44
42
|
content,
|
|
45
|
-
contentKey = 'settings.disclaimer.message',
|
|
46
43
|
iconName = 'alert-triangle',
|
|
47
44
|
}) => {
|
|
48
|
-
const { t } = useLocalization();
|
|
49
45
|
const tokens = useAppDesignTokens();
|
|
50
46
|
const styles = getStyles(tokens);
|
|
51
47
|
|
|
52
|
-
const displayTitle = title ||
|
|
53
|
-
const displayContent = content ||
|
|
48
|
+
const displayTitle = title || "";
|
|
49
|
+
const displayContent = content || "";
|
|
54
50
|
|
|
55
51
|
const navigation = useAppNavigation();
|
|
56
52
|
|
|
@@ -44,17 +44,17 @@ export interface StreakState {
|
|
|
44
44
|
|
|
45
45
|
// Gamification Translations
|
|
46
46
|
export interface GamificationTranslations {
|
|
47
|
-
title
|
|
48
|
-
statsTitle
|
|
49
|
-
pointsLabel
|
|
50
|
-
totalCompletedLabel
|
|
51
|
-
achievementsTitle
|
|
52
|
-
streakTitle
|
|
53
|
-
bestStreak
|
|
54
|
-
currentStreak
|
|
55
|
-
days
|
|
56
|
-
levelTitle
|
|
57
|
-
emptyAchievements
|
|
47
|
+
title?: string;
|
|
48
|
+
statsTitle?: string;
|
|
49
|
+
pointsLabel?: string;
|
|
50
|
+
totalCompletedLabel?: string;
|
|
51
|
+
achievementsTitle?: string;
|
|
52
|
+
streakTitle?: string;
|
|
53
|
+
bestStreak?: string;
|
|
54
|
+
currentStreak?: string;
|
|
55
|
+
days?: string;
|
|
56
|
+
levelTitle?: string;
|
|
57
|
+
emptyAchievements?: string;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
// Gamification Config (provided by app via props)
|
|
@@ -65,7 +65,7 @@ export interface GamificationConfig {
|
|
|
65
65
|
pointsPerAction?: number;
|
|
66
66
|
streakBonusMultiplier?: number;
|
|
67
67
|
enabled?: boolean;
|
|
68
|
-
translations
|
|
68
|
+
translations?: GamificationTranslations;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
export type GamificationSettingsConfig = GamificationConfig;
|
|
@@ -29,15 +29,15 @@ export const LanguageSection: React.FC<LanguageSectionProps> = ({
|
|
|
29
29
|
sectionTitle,
|
|
30
30
|
}) => {
|
|
31
31
|
const tokens = useAppDesignTokens();
|
|
32
|
-
const {
|
|
32
|
+
const { currentLanguage } = useLocalization();
|
|
33
33
|
const navigation = useAppNavigation();
|
|
34
34
|
|
|
35
35
|
const route = config?.route || 'LanguageSelection';
|
|
36
|
-
const title = config?.title ||
|
|
36
|
+
const title = config?.title || "";
|
|
37
37
|
const displaySectionTitle = sectionTitle || title;
|
|
38
38
|
|
|
39
39
|
const currentLang = getLanguageByCode(currentLanguage);
|
|
40
|
-
const defaultLanguageDisplay = config?.defaultLanguageDisplay ||
|
|
40
|
+
const defaultLanguageDisplay = config?.defaultLanguageDisplay || "";
|
|
41
41
|
const languageDisplay = currentLang
|
|
42
42
|
? `${currentLang.flag} ${currentLang.nativeName}`
|
|
43
43
|
: defaultLanguageDisplay;
|
|
@@ -24,7 +24,7 @@ export const LanguageSelectionScreen: React.FC<LanguageSelectionScreenProps> = (
|
|
|
24
24
|
headerTitle,
|
|
25
25
|
onBackPress,
|
|
26
26
|
styles: customStyles,
|
|
27
|
-
searchPlaceholder
|
|
27
|
+
searchPlaceholder,
|
|
28
28
|
testID = 'language-selection-screen',
|
|
29
29
|
}) => {
|
|
30
30
|
const tokens = useAppDesignTokens();
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React, { useCallback } from 'react';
|
|
2
2
|
import type { StyleProp, ViewStyle } from 'react-native';
|
|
3
3
|
import { useAppNavigation } from '@umituz/react-native-design-system';
|
|
4
|
-
import { useLocalization } from '../../../localization';
|
|
5
4
|
import { SettingsItemCard } from '../../../../presentation/components/SettingsItemCard';
|
|
6
5
|
|
|
7
6
|
export interface NotificationsSectionConfig {
|
|
@@ -26,7 +25,6 @@ export const NotificationsSection: React.FC<NotificationsSectionProps> = ({
|
|
|
26
25
|
hideMargin,
|
|
27
26
|
}) => {
|
|
28
27
|
const navigation = useAppNavigation();
|
|
29
|
-
const { t } = useLocalization();
|
|
30
28
|
|
|
31
29
|
const handlePress = useCallback(() => {
|
|
32
30
|
if (config?.onPress) {
|
|
@@ -37,8 +35,8 @@ export const NotificationsSection: React.FC<NotificationsSectionProps> = ({
|
|
|
37
35
|
}
|
|
38
36
|
}, [config?.route, config?.onPress, navigation]);
|
|
39
37
|
|
|
40
|
-
const title = config?.title ||
|
|
41
|
-
const description = config?.description ||
|
|
38
|
+
const title = config?.title || "";
|
|
39
|
+
const description = config?.description || "";
|
|
42
40
|
|
|
43
41
|
return (
|
|
44
42
|
<SettingsItemCard
|
|
@@ -13,7 +13,6 @@ import {
|
|
|
13
13
|
useAppDesignTokens,
|
|
14
14
|
useAppNavigation
|
|
15
15
|
} from '@umituz/react-native-design-system';
|
|
16
|
-
import { useLocalization } from '../../../localization';
|
|
17
16
|
import { QuietHoursCard } from '../../quietHours/presentation/components/QuietHoursCard';
|
|
18
17
|
import { SettingRow } from '../components/SettingRow';
|
|
19
18
|
import { RemindersNavRow } from '../components/RemindersNavRow';
|
|
@@ -38,7 +37,6 @@ export const NotificationSettingsScreen: React.FC<NotificationSettingsScreenProp
|
|
|
38
37
|
}) => {
|
|
39
38
|
const navigation = useAppNavigation();
|
|
40
39
|
const tokens = useAppDesignTokens();
|
|
41
|
-
const { t } = useLocalization();
|
|
42
40
|
const styles = createStyles(tokens);
|
|
43
41
|
const reminders = useReminders();
|
|
44
42
|
const { setStartTime, setEndTime } = useQuietHoursActions();
|
|
@@ -63,7 +61,7 @@ export const NotificationSettingsScreen: React.FC<NotificationSettingsScreenProp
|
|
|
63
61
|
// Navigate to reminders screen when implemented
|
|
64
62
|
};
|
|
65
63
|
|
|
66
|
-
const headerTitle = translations.screenTitle ||
|
|
64
|
+
const headerTitle = translations.screenTitle || "";
|
|
67
65
|
|
|
68
66
|
if (isLoading) {
|
|
69
67
|
return (
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Generic configuration creator to reduce duplication in base-configs
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Feature visibility configuration
|
|
@@ -29,9 +29,6 @@ export interface BaseConfigType {
|
|
|
29
29
|
* Configuration parameters for creating a settings item config
|
|
30
30
|
*/
|
|
31
31
|
export interface ConfigCreatorParams {
|
|
32
|
-
t: TranslationFunction;
|
|
33
|
-
titleKey: string;
|
|
34
|
-
descriptionKey: string;
|
|
35
32
|
icon: string;
|
|
36
33
|
routeOrOnPress?: string | (() => void);
|
|
37
34
|
defaultRoute?: string;
|
|
@@ -44,12 +41,10 @@ export interface ConfigCreatorParams {
|
|
|
44
41
|
export const createBaseConfig = <T extends BaseConfigType = BaseConfigType>(
|
|
45
42
|
params: ConfigCreatorParams
|
|
46
43
|
): T => {
|
|
47
|
-
const {
|
|
44
|
+
const { icon, routeOrOnPress, defaultRoute } = params;
|
|
48
45
|
|
|
49
46
|
return {
|
|
50
47
|
enabled: true,
|
|
51
|
-
title: t(titleKey),
|
|
52
|
-
description: t(descriptionKey),
|
|
53
48
|
icon,
|
|
54
49
|
route: typeof routeOrOnPress === "string" ? routeOrOnPress : defaultRoute,
|
|
55
50
|
onPress: typeof routeOrOnPress === "function" ? routeOrOnPress : undefined,
|
|
@@ -82,18 +77,12 @@ export const createDisabledConfig = <T extends BaseConfigType>(
|
|
|
82
77
|
*/
|
|
83
78
|
export const createBatchConfigs = <T extends BaseConfigType>(
|
|
84
79
|
items: Array<{
|
|
85
|
-
titleKey: string;
|
|
86
|
-
descriptionKey: string;
|
|
87
80
|
icon: string;
|
|
88
81
|
routeOrOnPress?: string | (() => void);
|
|
89
|
-
}
|
|
90
|
-
t: TranslationFunction
|
|
82
|
+
}>
|
|
91
83
|
): T[] => {
|
|
92
84
|
return items.map((item) =>
|
|
93
85
|
createBaseConfig<T>({
|
|
94
|
-
t,
|
|
95
|
-
titleKey: item.titleKey,
|
|
96
|
-
descriptionKey: item.descriptionKey,
|
|
97
86
|
icon: item.icon,
|
|
98
87
|
routeOrOnPress: item.routeOrOnPress,
|
|
99
88
|
})
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
|
|
9
9
|
import { useMemo } from "react";
|
|
10
10
|
import { useAuth, useUserProfile } from "@umituz/react-native-auth";
|
|
11
|
-
import { useLocalization } from "../../domains/localization";
|
|
12
11
|
import { createUserProfileDisplay } from "../utils/userProfileUtils";
|
|
13
12
|
import { createAccountConfig } from "../utils/accountConfigUtils";
|
|
14
13
|
import { useAuthHandlers } from "../utils/useAuthHandlers";
|
|
@@ -18,6 +17,7 @@ import type { SettingsConfig } from "../screens/types";
|
|
|
18
17
|
import type { FeedbackFormData } from "../utils/config-creators";
|
|
19
18
|
import type { AppInfo, FAQData, UserProfileDisplay, AdditionalScreen } from "../navigation/types";
|
|
20
19
|
import type { AccountScreenConfig } from "@umituz/react-native-auth";
|
|
20
|
+
import type { SettingsTranslations } from "../screens/types/SettingsConfig";
|
|
21
21
|
|
|
22
22
|
export interface SettingsFeatures {
|
|
23
23
|
notifications?: boolean;
|
|
@@ -37,6 +37,7 @@ export interface UseSettingsScreenConfigParams {
|
|
|
37
37
|
onFeedbackSubmit: (data: FeedbackFormData) => Promise<void>;
|
|
38
38
|
additionalScreens?: AdditionalScreen[];
|
|
39
39
|
features?: SettingsFeatures;
|
|
40
|
+
translations?: SettingsTranslations;
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
export interface SettingsScreenConfigResult {
|
|
@@ -51,7 +52,7 @@ export interface SettingsScreenConfigResult {
|
|
|
51
52
|
export const useSettingsScreenConfig = (
|
|
52
53
|
params: UseSettingsScreenConfigParams
|
|
53
54
|
): SettingsScreenConfigResult => {
|
|
54
|
-
const { appInfo, faqData, isPremium, onFeedbackSubmit, features = {} } = params;
|
|
55
|
+
const { appInfo, faqData, isPremium, onFeedbackSubmit, features = {}, translations } = params;
|
|
55
56
|
|
|
56
57
|
const {
|
|
57
58
|
notifications: showNotifications = true,
|
|
@@ -64,17 +65,15 @@ export const useSettingsScreenConfig = (
|
|
|
64
65
|
legal: showLegal = true,
|
|
65
66
|
} = features;
|
|
66
67
|
|
|
67
|
-
const { t } = useLocalization();
|
|
68
68
|
const { user, loading, isAuthReady } = useAuth();
|
|
69
69
|
const userProfileData = useUserProfile({});
|
|
70
70
|
|
|
71
71
|
// Use centralized auth handlers
|
|
72
72
|
const { handleRatePress, handleSignOut, handleDeleteAccount, handleSignIn } =
|
|
73
|
-
useAuthHandlers(appInfo);
|
|
73
|
+
useAuthHandlers(appInfo, translations?.errors);
|
|
74
74
|
|
|
75
75
|
// Use settings config factory
|
|
76
|
-
const
|
|
77
|
-
t,
|
|
76
|
+
const baseSettingsConfig = useSettingsConfigFactory({
|
|
78
77
|
onFeedbackSubmit,
|
|
79
78
|
handleRatePress,
|
|
80
79
|
appStoreUrl: appInfo.appStoreUrl || "",
|
|
@@ -91,11 +90,15 @@ export const useSettingsScreenConfig = (
|
|
|
91
90
|
},
|
|
92
91
|
});
|
|
93
92
|
|
|
93
|
+
const settingsConfig = useMemo(() => ({
|
|
94
|
+
...baseSettingsConfig,
|
|
95
|
+
translations,
|
|
96
|
+
}), [baseSettingsConfig, translations]);
|
|
97
|
+
|
|
94
98
|
const userProfile = useMemo(() => createUserProfileDisplay({
|
|
95
99
|
profileData: userProfileData,
|
|
96
|
-
t,
|
|
97
100
|
onSignIn: handleSignIn,
|
|
98
|
-
}), [userProfileData,
|
|
101
|
+
}), [userProfileData, handleSignIn]);
|
|
99
102
|
|
|
100
103
|
const accountConfig = useMemo(() => createAccountConfig({
|
|
101
104
|
displayName: userProfileData?.displayName || user?.displayName || undefined,
|
|
@@ -106,13 +109,12 @@ export const useSettingsScreenConfig = (
|
|
|
106
109
|
onSignIn: handleSignIn,
|
|
107
110
|
onLogout: handleSignOut,
|
|
108
111
|
onDeleteAccount: handleDeleteAccount,
|
|
109
|
-
|
|
110
|
-
}), [user, userProfileData, handleSignIn, handleSignOut, handleDeleteAccount, t]);
|
|
112
|
+
}), [user, userProfileData, handleSignIn, handleSignOut, handleDeleteAccount]);
|
|
111
113
|
|
|
112
114
|
// Use centralized FAQ translation
|
|
113
115
|
const translatedFaqData = useMemo(() =>
|
|
114
|
-
translateFAQData(faqData,
|
|
115
|
-
[faqData,
|
|
116
|
+
translateFAQData(faqData, (key: string) => "", appInfo),
|
|
117
|
+
[faqData, appInfo]
|
|
116
118
|
);
|
|
117
119
|
|
|
118
120
|
return {
|
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
StackNavigator,
|
|
12
12
|
type StackNavigatorConfig,
|
|
13
13
|
} from "@umituz/react-native-design-system";
|
|
14
|
-
import { useLocalization } from "../../domains/localization";
|
|
15
14
|
import { useNavigationHandlers, useSettingsScreens } from "./hooks";
|
|
16
15
|
import {
|
|
17
16
|
createNotificationTranslations,
|
|
@@ -24,10 +23,13 @@ export const SettingsStackNavigator: React.FC<SettingsStackNavigatorProps> = (pr
|
|
|
24
23
|
const {
|
|
25
24
|
appInfo,
|
|
26
25
|
legalUrls,
|
|
26
|
+
config,
|
|
27
27
|
} = props;
|
|
28
|
-
const
|
|
28
|
+
const translations = config?.translations?.features;
|
|
29
|
+
const aboutTranslations = translations?.about;
|
|
30
|
+
|
|
29
31
|
const { handlePrivacyPress, handleTermsPress, handleEulaPress, aboutConfig } =
|
|
30
|
-
useNavigationHandlers(appInfo, legalUrls);
|
|
32
|
+
useNavigationHandlers(appInfo, legalUrls, aboutTranslations);
|
|
31
33
|
|
|
32
34
|
const screenOptions = React.useMemo(
|
|
33
35
|
() => ({
|
|
@@ -36,11 +38,11 @@ export const SettingsStackNavigator: React.FC<SettingsStackNavigatorProps> = (pr
|
|
|
36
38
|
[]
|
|
37
39
|
);
|
|
38
40
|
|
|
39
|
-
const notificationTranslations = React.useMemo(() => createNotificationTranslations(
|
|
40
|
-
const quietHoursTranslations = React.useMemo(() => createQuietHoursTranslations(
|
|
41
|
+
const notificationTranslations = React.useMemo(() => createNotificationTranslations(translations), [translations]);
|
|
42
|
+
const quietHoursTranslations = React.useMemo(() => createQuietHoursTranslations(translations), [translations]);
|
|
41
43
|
const legalScreenProps = React.useMemo(
|
|
42
|
-
() => createLegalScreenProps(
|
|
43
|
-
[
|
|
44
|
+
() => createLegalScreenProps(translations, handlePrivacyPress, handleTermsPress, handleEulaPress),
|
|
45
|
+
[translations, handlePrivacyPress, handleTermsPress, handleEulaPress]
|
|
44
46
|
);
|
|
45
47
|
|
|
46
48
|
const screens = useSettingsScreens({
|
|
@@ -49,7 +51,6 @@ export const SettingsStackNavigator: React.FC<SettingsStackNavigatorProps> = (pr
|
|
|
49
51
|
legalProps: legalScreenProps,
|
|
50
52
|
notificationTranslations,
|
|
51
53
|
quietHoursTranslations,
|
|
52
|
-
t,
|
|
53
54
|
});
|
|
54
55
|
|
|
55
56
|
const navigatorConfig: StackNavigatorConfig<SettingsStackParamList> = {
|
|
@@ -17,7 +17,8 @@ interface NavigationHandlersResult {
|
|
|
17
17
|
|
|
18
18
|
export const useNavigationHandlers = (
|
|
19
19
|
appInfo: AppInfo,
|
|
20
|
-
legalUrls: LegalUrls
|
|
20
|
+
legalUrls: LegalUrls,
|
|
21
|
+
aboutTranslations?: AboutConfig["texts"]
|
|
21
22
|
): NavigationHandlersResult => {
|
|
22
23
|
const handlePrivacyPress = useCallback(() => {
|
|
23
24
|
Linking.openURL(legalUrls.privacy);
|
|
@@ -45,8 +46,9 @@ export const useNavigationHandlers = (
|
|
|
45
46
|
websiteDisplay: appInfo.websiteDisplay,
|
|
46
47
|
moreAppsUrl: appInfo.moreAppsUrl,
|
|
47
48
|
},
|
|
49
|
+
texts: aboutTranslations,
|
|
48
50
|
}),
|
|
49
|
-
[appInfo]
|
|
51
|
+
[appInfo, aboutTranslations]
|
|
50
52
|
);
|
|
51
53
|
|
|
52
54
|
return {
|
|
@@ -23,7 +23,6 @@ export interface UseSettingsScreensProps extends SettingsStackNavigatorProps {
|
|
|
23
23
|
legalProps: any;
|
|
24
24
|
notificationTranslations: any;
|
|
25
25
|
quietHoursTranslations: any;
|
|
26
|
-
t: (key: string) => string;
|
|
27
26
|
}
|
|
28
27
|
|
|
29
28
|
export const useSettingsScreens = (props: UseSettingsScreensProps): StackScreen[] => {
|
|
@@ -46,9 +45,10 @@ export const useSettingsScreens = (props: UseSettingsScreensProps): StackScreen[
|
|
|
46
45
|
gamificationConfig,
|
|
47
46
|
videoTutorialConfig,
|
|
48
47
|
accountConfig,
|
|
49
|
-
t,
|
|
50
48
|
} = props;
|
|
51
49
|
|
|
50
|
+
const translations = config?.translations?.features;
|
|
51
|
+
|
|
52
52
|
return useMemo(() => {
|
|
53
53
|
const settingsMainScreen = createScreenWithProps(
|
|
54
54
|
"SettingsMain",
|
|
@@ -96,10 +96,10 @@ export const useSettingsScreens = (props: UseSettingsScreensProps): StackScreen[
|
|
|
96
96
|
!!(faqData && faqData.categories?.length > 0),
|
|
97
97
|
() => createScreenWithProps("FAQ", FAQScreen, {
|
|
98
98
|
categories: faqData!.categories,
|
|
99
|
-
searchPlaceholder:
|
|
100
|
-
emptySearchTitle:
|
|
101
|
-
emptySearchMessage:
|
|
102
|
-
headerTitle:
|
|
99
|
+
searchPlaceholder: translations?.faqs?.searchPlaceholder || "",
|
|
100
|
+
emptySearchTitle: translations?.faqs?.emptySearchTitle || "",
|
|
101
|
+
emptySearchMessage: translations?.faqs?.emptySearchMessage || "",
|
|
102
|
+
headerTitle: translations?.faqs?.headerTitle || "",
|
|
103
103
|
})
|
|
104
104
|
);
|
|
105
105
|
|
|
@@ -108,8 +108,8 @@ export const useSettingsScreens = (props: UseSettingsScreensProps): StackScreen[
|
|
|
108
108
|
const gamificationScreen = createScreenWithProps("Gamification", GamificationScreen as any, { config: gamificationConfig });
|
|
109
109
|
|
|
110
110
|
const languageScreen = createScreenWithProps("LanguageSelection", LanguageSelectionScreen, {
|
|
111
|
-
headerTitle:
|
|
112
|
-
searchPlaceholder:
|
|
111
|
+
headerTitle: translations?.language?.title || "",
|
|
112
|
+
searchPlaceholder: translations?.languageSelection?.searchPlaceholder || "",
|
|
113
113
|
});
|
|
114
114
|
|
|
115
115
|
const accountScreen = createConditionalScreen(
|
|
@@ -119,7 +119,7 @@ export const useSettingsScreens = (props: UseSettingsScreensProps): StackScreen[
|
|
|
119
119
|
|
|
120
120
|
const videoTutorialScreen = createScreenWithProps("VideoTutorial", VideoTutorialsScreen as any, {
|
|
121
121
|
...videoTutorialConfig,
|
|
122
|
-
title: videoTutorialConfig?.title ||
|
|
122
|
+
title: videoTutorialConfig?.title || translations?.videoTutorial?.title || "",
|
|
123
123
|
});
|
|
124
124
|
|
|
125
125
|
return combineScreens(
|
|
@@ -132,7 +132,7 @@ export const useSettingsScreens = (props: UseSettingsScreensProps): StackScreen[
|
|
|
132
132
|
videoTutorialScreen
|
|
133
133
|
);
|
|
134
134
|
}, [
|
|
135
|
-
|
|
135
|
+
translations,
|
|
136
136
|
showHeader,
|
|
137
137
|
showCloseButton,
|
|
138
138
|
onClose,
|