@umituz/react-native-settings 5.2.1 → 5.2.6
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/presentation/hooks/useSettingsScreenConfig.ts +11 -24
- package/src/presentation/navigation/SettingsStackNavigator.tsx +1 -0
- package/src/presentation/navigation/hooks/useSettingsScreens.ts +1 -2
- package/src/presentation/utils/accountConfigUtils.ts +2 -2
- package/src/presentation/utils/index.ts +0 -1
- package/src/presentation/utils/screenFactory.ts +1 -1
- package/src/presentation/utils/useAuthHandlers.ts +0 -100
- package/src/presentation/utils/usePasswordPromptNavigation.ts +0 -53
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-settings",
|
|
3
|
-
"version": "5.2.
|
|
3
|
+
"version": "5.2.6",
|
|
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",
|
|
@@ -7,10 +7,9 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { useMemo } from "react";
|
|
10
|
-
import { useAuth, useUserProfile } from "@umituz/react-native-auth";
|
|
10
|
+
import { useAuth, useUserProfile, useAuthHandlers } from "@umituz/react-native-auth";
|
|
11
11
|
import { createUserProfileDisplay } from "../utils/userProfileUtils";
|
|
12
12
|
import { createAccountConfig } from "../utils/accountConfigUtils";
|
|
13
|
-
import { useAuthHandlers } from "../utils/useAuthHandlers";
|
|
14
13
|
import { translateFAQData } from "../utils/faqTranslator";
|
|
15
14
|
import { useSettingsConfigFactory } from "../utils/settingsConfigFactory";
|
|
16
15
|
import type { SettingsConfig, SettingsTranslations } from "../screens/types";
|
|
@@ -104,16 +103,6 @@ export const useSettingsScreenConfig = (
|
|
|
104
103
|
translations,
|
|
105
104
|
};
|
|
106
105
|
|
|
107
|
-
// Add subscription title and description from translations if available
|
|
108
|
-
if (config.subscription && typeof config.subscription === 'object' && translations?.features?.subscription) {
|
|
109
|
-
config.subscription = {
|
|
110
|
-
...config.subscription,
|
|
111
|
-
title: translations.features.subscription.title,
|
|
112
|
-
description: translations.features.subscription.description,
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Add subscription title and description from translations if available
|
|
117
106
|
if (config.subscription && typeof config.subscription === 'object') {
|
|
118
107
|
config.subscription = {
|
|
119
108
|
...config.subscription,
|
|
@@ -123,25 +112,23 @@ export const useSettingsScreenConfig = (
|
|
|
123
112
|
};
|
|
124
113
|
}
|
|
125
114
|
|
|
126
|
-
// Add gamification title and description
|
|
127
115
|
if (config.gamification) {
|
|
128
116
|
const existingConfig = typeof config.gamification === 'object' ? config.gamification : { enabled: true };
|
|
129
117
|
config.gamification = {
|
|
130
|
-
...
|
|
118
|
+
...existingConfig,
|
|
131
119
|
enabled: true,
|
|
132
|
-
title: translations?.features?.gamification?.title ||
|
|
133
|
-
description: translations?.features?.gamification?.description ||
|
|
120
|
+
title: translations?.features?.gamification?.title || existingConfig.title || "Your Progress",
|
|
121
|
+
description: translations?.features?.gamification?.description || existingConfig.description,
|
|
134
122
|
};
|
|
135
123
|
}
|
|
136
124
|
|
|
137
|
-
// Add videoTutorial title and description
|
|
138
125
|
if (config.videoTutorial) {
|
|
139
126
|
const existingConfig = typeof config.videoTutorial === 'object' ? config.videoTutorial : { enabled: true };
|
|
140
127
|
config.videoTutorial = {
|
|
141
|
-
...
|
|
128
|
+
...existingConfig,
|
|
142
129
|
enabled: true,
|
|
143
|
-
title: translations?.features?.videoTutorial?.title ||
|
|
144
|
-
description: translations?.features?.videoTutorial?.description ||
|
|
130
|
+
title: translations?.features?.videoTutorial?.title || existingConfig.title || "Video Tutorials",
|
|
131
|
+
description: translations?.features?.videoTutorial?.description || existingConfig.description,
|
|
145
132
|
};
|
|
146
133
|
}
|
|
147
134
|
|
|
@@ -154,11 +141,11 @@ export const useSettingsScreenConfig = (
|
|
|
154
141
|
}), [userProfileData, handleSignIn]);
|
|
155
142
|
|
|
156
143
|
const accountConfig = useMemo(() => createAccountConfig({
|
|
157
|
-
displayName: userProfileData?.displayName || user?.displayName
|
|
158
|
-
userId: userProfileData?.userId ?? user?.uid
|
|
159
|
-
photoURL: user?.photoURL
|
|
144
|
+
displayName: userProfileData?.displayName || user?.displayName,
|
|
145
|
+
userId: userProfileData?.userId ?? user?.uid,
|
|
146
|
+
photoURL: user?.photoURL,
|
|
160
147
|
isAnonymous: user?.isAnonymous,
|
|
161
|
-
avatarUrl: userProfileData?.avatarUrl
|
|
148
|
+
avatarUrl: userProfileData?.avatarUrl,
|
|
162
149
|
onSignIn: handleSignIn,
|
|
163
150
|
onLogout: handleSignOut,
|
|
164
151
|
onDeleteAccount: handleDeleteAccount,
|
|
@@ -2,8 +2,7 @@ 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";
|
|
5
|
-
import { AccountScreen } from "@umituz/react-native-auth";
|
|
6
|
-
import { PasswordPromptScreen } from "@umituz/react-native-firebase";
|
|
5
|
+
import { AccountScreen, PasswordPromptScreen } from "@umituz/react-native-auth";
|
|
7
6
|
import { SettingsScreen } from "../../screens/SettingsScreen";
|
|
8
7
|
import { AppearanceScreen } from "../../screens/AppearanceScreen";
|
|
9
8
|
import { FAQScreen } from "../../../domains/faqs";
|
|
@@ -69,9 +69,9 @@ export function createAccountConfig(params: CreateAccountConfigParams): AccountS
|
|
|
69
69
|
return {
|
|
70
70
|
profile: {
|
|
71
71
|
displayName: displayName || "",
|
|
72
|
-
userId
|
|
72
|
+
userId,
|
|
73
73
|
isAnonymous: anonymous,
|
|
74
|
-
avatarUrl: avatarUrl ?? photoURL
|
|
74
|
+
avatarUrl: avatarUrl ?? photoURL,
|
|
75
75
|
},
|
|
76
76
|
isAnonymous: anonymous,
|
|
77
77
|
editProfileText: translations?.editProfile || "",
|
|
@@ -55,7 +55,7 @@ export function createScreenWithProps<P>(
|
|
|
55
55
|
export function convertAdditionalScreen(screen: AdditionalScreen): StackScreen {
|
|
56
56
|
const stackScreen: Partial<StackScreen> = { name: screen.name };
|
|
57
57
|
if (screen.component) stackScreen.component = screen.component;
|
|
58
|
-
if (screen.children) stackScreen.children = screen.children;
|
|
58
|
+
if (screen.children) stackScreen.children = screen.children as any;
|
|
59
59
|
if (screen.options) stackScreen.options = screen.options;
|
|
60
60
|
return stackScreen as StackScreen;
|
|
61
61
|
}
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Auth Handlers Hook
|
|
3
|
-
* Centralized authentication-related handlers for settings screen
|
|
4
|
-
* Uses auth package for all auth operations - no duplication
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { useCallback } from "react";
|
|
8
|
-
import { Linking, Alert } from "react-native";
|
|
9
|
-
import {
|
|
10
|
-
useAuth,
|
|
11
|
-
useAuthModalStore,
|
|
12
|
-
useAccountManagement,
|
|
13
|
-
} from "@umituz/react-native-auth";
|
|
14
|
-
import { AlertService } from "@umituz/react-native-design-system";
|
|
15
|
-
import type { AppInfo } from "../navigation/types";
|
|
16
|
-
import type { SettingsTranslations } from "../screens/types";
|
|
17
|
-
import { usePasswordPromptNavigation } from "./usePasswordPromptNavigation";
|
|
18
|
-
|
|
19
|
-
declare const __DEV__: boolean;
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Hook that provides authentication-related handlers
|
|
23
|
-
*/
|
|
24
|
-
export const useAuthHandlers = (appInfo: AppInfo, translations?: SettingsTranslations["account"] & SettingsTranslations["errors"]) => {
|
|
25
|
-
const { signOut } = useAuth();
|
|
26
|
-
const { showAuthModal } = useAuthModalStore();
|
|
27
|
-
|
|
28
|
-
const { showPasswordPrompt } = usePasswordPromptNavigation({
|
|
29
|
-
title: translations?.deleteAccountTitle || "Confirm Account Deletion",
|
|
30
|
-
message: translations?.deleteAccountMessage || "Please enter your password to permanently delete your account. This action cannot be undone.",
|
|
31
|
-
cancelText: translations?.cancel || "Cancel",
|
|
32
|
-
confirmText: translations?.delete || "Delete",
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
const { deleteAccount: deleteAccountFromAuth } = useAccountManagement({
|
|
36
|
-
onPasswordRequired: showPasswordPrompt,
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
const handleRatePress = useCallback(async () => {
|
|
40
|
-
const url = appInfo.appStoreUrl;
|
|
41
|
-
if (!url) {
|
|
42
|
-
Alert.alert(translations?.common || "", translations?.appStoreUrlNotConfigured || "");
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
try {
|
|
47
|
-
const canOpen = await Linking.canOpenURL(url);
|
|
48
|
-
if (!canOpen) {
|
|
49
|
-
Alert.alert(
|
|
50
|
-
translations?.common || "",
|
|
51
|
-
translations?.unableToOpenAppStore || ""
|
|
52
|
-
);
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
await Linking.openURL(url);
|
|
56
|
-
} catch (error) {
|
|
57
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
58
|
-
console.error("[useAuthHandlers] Failed to open app store:", error);
|
|
59
|
-
}
|
|
60
|
-
Alert.alert(translations?.common || "", translations?.failedToOpenAppStore || "");
|
|
61
|
-
}
|
|
62
|
-
}, [appInfo.appStoreUrl, translations]);
|
|
63
|
-
|
|
64
|
-
const handleSignOut = useCallback(async () => {
|
|
65
|
-
try {
|
|
66
|
-
await signOut();
|
|
67
|
-
} catch (error) {
|
|
68
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
69
|
-
console.error("[useAuthHandlers] Sign out failed:", error);
|
|
70
|
-
}
|
|
71
|
-
AlertService.createErrorAlert(
|
|
72
|
-
translations?.common || "",
|
|
73
|
-
translations?.unknown || ""
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
}, [signOut, translations]);
|
|
77
|
-
|
|
78
|
-
const handleDeleteAccount = useCallback(async () => {
|
|
79
|
-
try {
|
|
80
|
-
await deleteAccountFromAuth();
|
|
81
|
-
} catch (error) {
|
|
82
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
83
|
-
AlertService.createErrorAlert(
|
|
84
|
-
translations?.common || "Error",
|
|
85
|
-
errorMessage || translations?.deleteAccountError || "Failed to delete account"
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
}, [deleteAccountFromAuth, translations]);
|
|
89
|
-
|
|
90
|
-
const handleSignIn = useCallback(() => {
|
|
91
|
-
showAuthModal(undefined, "login");
|
|
92
|
-
}, [showAuthModal]);
|
|
93
|
-
|
|
94
|
-
return {
|
|
95
|
-
handleRatePress,
|
|
96
|
-
handleSignOut,
|
|
97
|
-
handleDeleteAccount,
|
|
98
|
-
handleSignIn,
|
|
99
|
-
};
|
|
100
|
-
};
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Password Prompt Navigation Hook
|
|
3
|
-
* Navigation-based password prompt that maintains Promise interface
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { useCallback, useRef } from 'react';
|
|
7
|
-
import { AppNavigation } from '@umituz/react-native-design-system';
|
|
8
|
-
|
|
9
|
-
export interface UsePasswordPromptNavigationOptions {
|
|
10
|
-
title?: string;
|
|
11
|
-
message?: string;
|
|
12
|
-
confirmText?: string;
|
|
13
|
-
cancelText?: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface UsePasswordPromptNavigationReturn {
|
|
17
|
-
showPasswordPrompt: () => Promise<string | null>;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export const usePasswordPromptNavigation = (
|
|
21
|
-
options: UsePasswordPromptNavigationOptions
|
|
22
|
-
): UsePasswordPromptNavigationReturn => {
|
|
23
|
-
const { title, message, confirmText, cancelText } = options;
|
|
24
|
-
const resolveRef = useRef<((value: string | null) => void) | null>(null);
|
|
25
|
-
|
|
26
|
-
const showPasswordPrompt = useCallback((): Promise<string | null> => {
|
|
27
|
-
return new Promise<string | null>((resolve) => {
|
|
28
|
-
resolveRef.current = resolve;
|
|
29
|
-
|
|
30
|
-
const params = {
|
|
31
|
-
onComplete: (password: string | null) => {
|
|
32
|
-
if (resolveRef.current) {
|
|
33
|
-
resolveRef.current(password);
|
|
34
|
-
resolveRef.current = null;
|
|
35
|
-
}
|
|
36
|
-
},
|
|
37
|
-
title,
|
|
38
|
-
message,
|
|
39
|
-
confirmText,
|
|
40
|
-
cancelText,
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
AppNavigation.navigate('Settings', {
|
|
44
|
-
screen: 'PasswordPrompt',
|
|
45
|
-
params,
|
|
46
|
-
} as any);
|
|
47
|
-
});
|
|
48
|
-
}, [title, message, confirmText, cancelText]);
|
|
49
|
-
|
|
50
|
-
return {
|
|
51
|
-
showPasswordPrompt,
|
|
52
|
-
};
|
|
53
|
-
};
|