@umituz/react-native-settings 4.23.83 → 4.23.85
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/presentation/hooks/useAboutInfo.ts +0 -2
- package/src/domains/appearance/presentation/components/ColorPicker.tsx +0 -1
- package/src/domains/appearance/presentation/components/ThemeModeSection.tsx +0 -1
- package/src/domains/appearance/presentation/components/ThemeOption.tsx +0 -1
- package/src/domains/feedback/presentation/components/FeedbackForm.tsx +0 -1
- package/src/domains/feedback/presentation/components/FeedbackModal.tsx +16 -19
- package/src/domains/feedback/presentation/components/SupportSection.tsx +0 -1
- package/src/domains/localization/infrastructure/components/useLanguageSwitcher.ts +0 -1
- package/src/domains/localization/infrastructure/hooks/useLanguageSelection.ts +0 -4
- package/src/domains/localization/infrastructure/hooks/useTranslation.ts +0 -1
- package/src/domains/localization/infrastructure/storage/LanguageInitializer.ts +0 -1
- package/src/domains/localization/infrastructure/storage/LanguageSwitcher.ts +0 -4
- package/src/domains/localization/infrastructure/storage/LocalizationStore.ts +0 -5
- package/src/domains/localization/presentation/components/LanguageItem.tsx +0 -1
- package/src/domains/localization/presentation/providers/LocalizationManager.tsx +0 -1
- package/src/domains/localization/presentation/screens/LanguageSelectionScreen.tsx +0 -3
- package/src/domains/notifications/infrastructure/services/NotificationService.ts +0 -1
- package/src/domains/notifications/infrastructure/utils/dev.ts +0 -3
- package/src/domains/notifications/quietHours/infrastructure/hooks/useQuietHoursActions.ts +0 -1
- package/src/domains/notifications/reminders/infrastructure/hooks/useReminderActions.ts +0 -6
- package/src/domains/notifications/reminders/presentation/components/ReminderForm.tsx +0 -5
- package/src/domains/rating/application/services/RatingService.ts +13 -63
- package/src/domains/rating/infrastructure/storage/RatingStorage.ts +14 -36
- package/src/domains/rating/presentation/hooks/useAppRating.tsx +0 -1
- package/src/domains/video-tutorials/presentation/components/VideoTutorialCard.tsx +17 -14
- package/src/domains/video-tutorials/presentation/screens/VideoTutorialsScreen.tsx +46 -32
- package/src/infrastructure/utils/dateUtils.ts +61 -0
- package/src/infrastructure/utils/memoComparisonUtils.ts +68 -0
- package/src/infrastructure/utils/sanitizers.ts +49 -0
- package/src/infrastructure/utils/translationHelpers.ts +81 -0
- package/src/infrastructure/utils/validators.ts +59 -0
- package/src/presentation/components/SettingsItemCard.tsx +129 -172
- package/src/presentation/components/settings/SettingsItemCardContent.tsx +70 -0
- package/src/presentation/components/settings/SettingsItemCardRightElement.tsx +42 -0
- package/src/presentation/components/settings/SettingsItemCardSection.tsx +29 -0
- package/src/presentation/hooks/useSettingsScreenConfig.ts +19 -54
- package/src/presentation/navigation/hooks/useSettingsScreens.ts +75 -89
- package/src/presentation/screens/components/GamificationSettingsItem.tsx +20 -17
- package/src/presentation/screens/components/SettingsContent.tsx +29 -0
- package/src/presentation/screens/components/SubscriptionSettingsItem.tsx +13 -4
- package/src/presentation/screens/components/VideoTutorialSettingsItem.tsx +47 -0
- package/src/presentation/screens/components/WalletSettingsItem.tsx +13 -4
- package/src/presentation/screens/components/sections/CustomSettingsList.tsx +12 -5
- package/src/presentation/screens/components/sections/FeatureSettingsSection.tsx +12 -11
- package/src/presentation/screens/components/sections/IdentitySettingsSection.tsx +4 -1
- package/src/presentation/screens/components/sections/ProfileSectionLoader.tsx +16 -10
- package/src/presentation/screens/components/sections/SupportSettingsSection.tsx +9 -4
- package/src/presentation/screens/hooks/useFeatureDetection.ts +2 -0
- package/src/presentation/screens/types/SettingsConfig.ts +8 -1
- package/src/presentation/screens/types/UserFeatureConfig.ts +20 -0
- package/src/presentation/screens/types/index.ts +1 -0
- package/src/presentation/screens/utils/normalizeConfig.ts +7 -1
- package/src/presentation/utils/accountConfigUtils.ts +67 -0
- package/src/presentation/utils/screenFactory.ts +87 -0
- package/src/presentation/utils/userProfileUtils.ts +51 -0
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.85",
|
|
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",
|
|
@@ -102,7 +102,6 @@ export const useAboutInfo = (
|
|
|
102
102
|
repository.destroy();
|
|
103
103
|
} catch (error) {
|
|
104
104
|
// Log cleanup error but don't throw
|
|
105
|
-
console.warn('Error during repository cleanup:', error);
|
|
106
105
|
}
|
|
107
106
|
}
|
|
108
107
|
};
|
|
@@ -124,7 +123,6 @@ export const useAboutInfo = (
|
|
|
124
123
|
isInitializedRef.current = true;
|
|
125
124
|
}
|
|
126
125
|
}).catch((error) => {
|
|
127
|
-
console.error('Failed to load AppInfoFactory:', error);
|
|
128
126
|
});
|
|
129
127
|
}
|
|
130
128
|
}, [initialConfig, autoInit]);
|
|
@@ -42,7 +42,6 @@ export const ColorPicker: React.FC<ColorPickerProps> = ({
|
|
|
42
42
|
onValueChange(color);
|
|
43
43
|
} catch (error) {
|
|
44
44
|
// Log error for debugging while preventing UI crashes
|
|
45
|
-
console.error('Failed to change color:', error);
|
|
46
45
|
// Optionally: Show user feedback about the error
|
|
47
46
|
}
|
|
48
47
|
}, [value, onValueChange]);
|
|
@@ -64,7 +64,6 @@ export const FeedbackForm: React.FC<FeedbackFormProps> = ({
|
|
|
64
64
|
} catch (err) {
|
|
65
65
|
const errorMessage = err instanceof Error ? err.message : "Failed to submit feedback";
|
|
66
66
|
setError(errorMessage);
|
|
67
|
-
console.error("[FeedbackForm] Submission error:", err);
|
|
68
67
|
} finally {
|
|
69
68
|
setIsSubmittingLocal(false);
|
|
70
69
|
}
|
|
@@ -34,34 +34,31 @@ export const FeedbackModal: React.FC<FeedbackModalProps> = ({
|
|
|
34
34
|
const tokens = useAppDesignTokens();
|
|
35
35
|
const styles = getStyles(tokens);
|
|
36
36
|
|
|
37
|
+
const header = (
|
|
38
|
+
<View style={styles.header}>
|
|
39
|
+
<View style={styles.headerText}>
|
|
40
|
+
{title && <AtomicText style={{ fontSize: 20, fontWeight: '600' }}>{title}</AtomicText>}
|
|
41
|
+
{subtitle && <AtomicText style={{ fontSize: 14, marginTop: 4 }}>{subtitle}</AtomicText>}
|
|
42
|
+
</View>
|
|
43
|
+
<TouchableOpacity
|
|
44
|
+
onPress={onClose}
|
|
45
|
+
style={[styles.closeButton, { backgroundColor: tokens.colors.surfaceVariant }]}
|
|
46
|
+
>
|
|
47
|
+
<AtomicIcon name="close" size="sm" color="onSurface" />
|
|
48
|
+
</TouchableOpacity>
|
|
49
|
+
</View>
|
|
50
|
+
);
|
|
51
|
+
|
|
37
52
|
return (
|
|
38
53
|
<BaseModal visible={visible} onClose={onClose}>
|
|
39
54
|
<ScreenLayout
|
|
55
|
+
header={header}
|
|
40
56
|
scrollable={true}
|
|
41
57
|
edges={[]}
|
|
42
58
|
keyboardAvoiding={true}
|
|
43
59
|
contentContainerStyle={styles.content}
|
|
44
60
|
hideScrollIndicator={false}
|
|
45
61
|
>
|
|
46
|
-
<View style={[styles.header, { borderBottomColor: tokens.colors.border }]}>
|
|
47
|
-
<View style={styles.headerText}>
|
|
48
|
-
<AtomicText type="headlineSmall" color="textPrimary">
|
|
49
|
-
{title}
|
|
50
|
-
</AtomicText>
|
|
51
|
-
{subtitle && (
|
|
52
|
-
<AtomicText type="bodySmall" color="textSecondary" style={{ marginTop: 4 }}>
|
|
53
|
-
{subtitle}
|
|
54
|
-
</AtomicText>
|
|
55
|
-
)}
|
|
56
|
-
</View>
|
|
57
|
-
<TouchableOpacity
|
|
58
|
-
onPress={onClose}
|
|
59
|
-
style={[styles.closeButton, { backgroundColor: tokens.colors.surfaceVariant }]}
|
|
60
|
-
>
|
|
61
|
-
<AtomicIcon name="close" size="sm" color="onSurface" />
|
|
62
|
-
</TouchableOpacity>
|
|
63
|
-
</View>
|
|
64
|
-
|
|
65
62
|
<FeedbackForm
|
|
66
63
|
onSubmit={onSubmit}
|
|
67
64
|
initialType={initialType}
|
|
@@ -76,7 +76,6 @@ export const SupportSection: React.FC<SupportSectionProps> = ({
|
|
|
76
76
|
} catch (error) {
|
|
77
77
|
// If the passed onSubmit throws, we log it.
|
|
78
78
|
if (__DEV__) {
|
|
79
|
-
console.error("[SupportSection] Feedback submission error:", error);
|
|
80
79
|
}
|
|
81
80
|
// Optionally keep modal open? Or close it?
|
|
82
81
|
// If we keep it open, user can retry.
|
|
@@ -24,7 +24,6 @@ export const useLanguageSwitcher = ({ onPress, disabled }: UseLanguageSwitcherPr
|
|
|
24
24
|
|
|
25
25
|
if (!lang) {
|
|
26
26
|
// This should never happen if repository is set up correctly
|
|
27
|
-
console.error('[useLanguageSwitcher] No valid language found. Check language repository configuration.');
|
|
28
27
|
// Return a minimal fallback language object
|
|
29
28
|
return {
|
|
30
29
|
code: 'en',
|
|
@@ -18,19 +18,15 @@ export const useLanguageSelection = () => {
|
|
|
18
18
|
|
|
19
19
|
const handleLanguageSelect = async (code: string, onComplete?: () => void) => {
|
|
20
20
|
if (__DEV__) {
|
|
21
|
-
console.log('[useLanguageSelection] handleLanguageSelect called:', { code, currentLanguage });
|
|
22
21
|
}
|
|
23
22
|
setSelectedCode(code);
|
|
24
23
|
if (__DEV__) {
|
|
25
|
-
console.log('[useLanguageSelection] Calling setLanguage...');
|
|
26
24
|
}
|
|
27
25
|
await setLanguage(code);
|
|
28
26
|
if (__DEV__) {
|
|
29
|
-
console.log('[useLanguageSelection] Language changed to:', code);
|
|
30
27
|
}
|
|
31
28
|
onComplete?.();
|
|
32
29
|
if (__DEV__) {
|
|
33
|
-
console.log('[useLanguageSelection] onComplete callback executed');
|
|
34
30
|
}
|
|
35
31
|
};
|
|
36
32
|
|
|
@@ -34,7 +34,6 @@ export class LanguageInitializer {
|
|
|
34
34
|
return finalLanguage;
|
|
35
35
|
} catch {
|
|
36
36
|
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
37
|
-
console.warn("[LanguageInitializer] Failed to restore language, falling back to device locale");
|
|
38
37
|
}
|
|
39
38
|
return await this.setupFallbackLanguage();
|
|
40
39
|
}
|
|
@@ -23,25 +23,21 @@ export class LanguageSwitcher {
|
|
|
23
23
|
isRTL: boolean;
|
|
24
24
|
}> {
|
|
25
25
|
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
26
|
-
console.log('[LanguageSwitcher] switchLanguage called:', languageCode);
|
|
27
26
|
}
|
|
28
27
|
|
|
29
28
|
const language = languageRepository.getLanguageByCode(languageCode);
|
|
30
29
|
|
|
31
30
|
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
32
|
-
console.log('[LanguageSwitcher] Language object:', language);
|
|
33
31
|
}
|
|
34
32
|
|
|
35
33
|
await i18n.changeLanguage(languageCode);
|
|
36
34
|
|
|
37
35
|
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
38
|
-
console.log('[LanguageSwitcher] i18n language changed to:', i18n.language);
|
|
39
36
|
}
|
|
40
37
|
|
|
41
38
|
await storageRepository.setString(LANGUAGE_STORAGE_KEY, languageCode);
|
|
42
39
|
|
|
43
40
|
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
44
|
-
console.log('[LanguageSwitcher] Saved to storage');
|
|
45
41
|
}
|
|
46
42
|
|
|
47
43
|
return {
|
|
@@ -57,7 +57,6 @@ export const useLocalizationStore = create<LocalizationStoreType>((set, get) =>
|
|
|
57
57
|
} catch (error) {
|
|
58
58
|
// Log and set fallback state
|
|
59
59
|
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
60
|
-
console.error('[LocalizationStore] Initialization failed:', error);
|
|
61
60
|
}
|
|
62
61
|
|
|
63
62
|
set({
|
|
@@ -107,14 +106,12 @@ export const useLocalizationStore = create<LocalizationStoreType>((set, get) =>
|
|
|
107
106
|
|
|
108
107
|
languageSwitchTimer = setTimeout(async () => {
|
|
109
108
|
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
110
|
-
console.log('[LocalizationStore] setLanguage called:', languageCode);
|
|
111
109
|
}
|
|
112
110
|
|
|
113
111
|
try {
|
|
114
112
|
const result = await LanguageSwitcher.switchLanguage(languageCode);
|
|
115
113
|
|
|
116
114
|
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
117
|
-
console.log('[LocalizationStore] LanguageSwitcher result:', result);
|
|
118
115
|
}
|
|
119
116
|
|
|
120
117
|
set({
|
|
@@ -123,7 +120,6 @@ export const useLocalizationStore = create<LocalizationStoreType>((set, get) =>
|
|
|
123
120
|
});
|
|
124
121
|
|
|
125
122
|
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
126
|
-
console.log('[LocalizationStore] Store updated with new language:', result.languageCode);
|
|
127
123
|
}
|
|
128
124
|
|
|
129
125
|
// Resolve ALL pending promises
|
|
@@ -134,7 +130,6 @@ export const useLocalizationStore = create<LocalizationStoreType>((set, get) =>
|
|
|
134
130
|
const errorMessage = error instanceof Error ? error : new Error(String(error));
|
|
135
131
|
|
|
136
132
|
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
137
|
-
console.error('[LocalizationStore] Language switch failed:', error);
|
|
138
133
|
}
|
|
139
134
|
|
|
140
135
|
// Reject all pending promises
|
|
@@ -32,7 +32,6 @@ export const LocalizationManager: React.FC<LocalizationProviderProps> = ({
|
|
|
32
32
|
setIsI18nReady(true);
|
|
33
33
|
}
|
|
34
34
|
} catch (error) {
|
|
35
|
-
console.error('Failed to initialize localization:', error);
|
|
36
35
|
if (isMounted) {
|
|
37
36
|
setIsI18nReady(true); // Set ready even on error to prevent indefinite loading
|
|
38
37
|
}
|
|
@@ -39,16 +39,13 @@ export const LanguageSelectionScreen: React.FC<LanguageSelectionScreenProps> = (
|
|
|
39
39
|
|
|
40
40
|
const onSelect = async (code: string) => {
|
|
41
41
|
if (__DEV__) {
|
|
42
|
-
console.log('[LanguageSelectionScreen] onSelect called with code:', code);
|
|
43
42
|
}
|
|
44
43
|
await handleLanguageSelect(code, () => {
|
|
45
44
|
if (__DEV__) {
|
|
46
|
-
console.log('[LanguageSelectionScreen] Navigating back using standard navigation');
|
|
47
45
|
}
|
|
48
46
|
navigation.goBack();
|
|
49
47
|
});
|
|
50
48
|
if (__DEV__) {
|
|
51
|
-
console.log('[LanguageSelectionScreen] Language change completed');
|
|
52
49
|
}
|
|
53
50
|
};
|
|
54
51
|
|
|
@@ -8,18 +8,15 @@ export const isDev = () => {
|
|
|
8
8
|
|
|
9
9
|
export const devLog = (message: string, ...args: unknown[]) => {
|
|
10
10
|
if (isDev()) {
|
|
11
|
-
console.log(message, ...args);
|
|
12
11
|
}
|
|
13
12
|
};
|
|
14
13
|
|
|
15
14
|
export const devError = (message: string, ...args: unknown[]) => {
|
|
16
15
|
if (isDev()) {
|
|
17
|
-
console.error(message, ...args);
|
|
18
16
|
}
|
|
19
17
|
};
|
|
20
18
|
|
|
21
19
|
export const devWarn = (message: string, ...args: unknown[]) => {
|
|
22
20
|
if (isDev()) {
|
|
23
|
-
console.warn(message, ...args);
|
|
24
21
|
}
|
|
25
22
|
};
|
|
@@ -37,7 +37,6 @@ export const useReminderActions = () => {
|
|
|
37
37
|
reminder.notificationId = notificationId;
|
|
38
38
|
} catch (error) {
|
|
39
39
|
// Log error for debugging
|
|
40
|
-
console.error('[useReminderActions] Failed to schedule notification:', error);
|
|
41
40
|
reminder.enabled = false;
|
|
42
41
|
}
|
|
43
42
|
|
|
@@ -58,7 +57,6 @@ export const useReminderActions = () => {
|
|
|
58
57
|
try {
|
|
59
58
|
await scheduler.cancelNotification(existing.notificationId);
|
|
60
59
|
} catch (error) {
|
|
61
|
-
console.error('[useReminderActions] Failed to cancel notification:', error);
|
|
62
60
|
// Continue with update even if cancellation fails
|
|
63
61
|
}
|
|
64
62
|
}
|
|
@@ -76,7 +74,6 @@ export const useReminderActions = () => {
|
|
|
76
74
|
});
|
|
77
75
|
updated.notificationId = notificationId;
|
|
78
76
|
} catch (error) {
|
|
79
|
-
console.error('[useReminderActions] Failed to schedule notification:', error);
|
|
80
77
|
updated.enabled = false;
|
|
81
78
|
updated.notificationId = undefined;
|
|
82
79
|
}
|
|
@@ -99,7 +96,6 @@ export const useReminderActions = () => {
|
|
|
99
96
|
try {
|
|
100
97
|
await scheduler.cancelNotification(reminder.notificationId);
|
|
101
98
|
} catch (error) {
|
|
102
|
-
console.error('[useReminderActions] Failed to cancel notification:', error);
|
|
103
99
|
// Continue with deletion even if cancellation fails
|
|
104
100
|
}
|
|
105
101
|
}
|
|
@@ -120,7 +116,6 @@ export const useReminderActions = () => {
|
|
|
120
116
|
await scheduler.cancelNotification(reminder.notificationId);
|
|
121
117
|
await updateReminder(id, { enabled: false, notificationId: undefined });
|
|
122
118
|
} catch (error) {
|
|
123
|
-
console.error('[useReminderActions] Failed to disable reminder:', error);
|
|
124
119
|
throw error; // Re-throw to allow caller to handle
|
|
125
120
|
}
|
|
126
121
|
} else if (!reminder.enabled) {
|
|
@@ -134,7 +129,6 @@ export const useReminderActions = () => {
|
|
|
134
129
|
});
|
|
135
130
|
await updateReminder(id, { enabled: true, notificationId });
|
|
136
131
|
} catch (error) {
|
|
137
|
-
console.error('[useReminderActions] Failed to enable reminder:', error);
|
|
138
132
|
await updateReminder(id, { enabled: false }); // Ensure disabled state
|
|
139
133
|
throw error; // Re-throw to allow caller to handle
|
|
140
134
|
}
|
|
@@ -76,30 +76,25 @@ export const ReminderForm: React.FC<ReminderFormProps> = ({
|
|
|
76
76
|
|
|
77
77
|
// Validate title
|
|
78
78
|
if (!trimmedTitle) {
|
|
79
|
-
console.warn('Reminder title is required');
|
|
80
79
|
return;
|
|
81
80
|
}
|
|
82
81
|
|
|
83
82
|
if (trimmedTitle.length > MAX_TITLE_LENGTH) {
|
|
84
|
-
console.warn(`Reminder title exceeds maximum length of ${MAX_TITLE_LENGTH}`);
|
|
85
83
|
return;
|
|
86
84
|
}
|
|
87
85
|
|
|
88
86
|
// Validate body length
|
|
89
87
|
if (trimmedBody.length > MAX_BODY_LENGTH) {
|
|
90
|
-
console.warn(`Reminder body exceeds maximum length of ${MAX_BODY_LENGTH}`);
|
|
91
88
|
return;
|
|
92
89
|
}
|
|
93
90
|
|
|
94
91
|
// Validate time values
|
|
95
92
|
if (!isValidHour(hour) || !isValidMinute(minute)) {
|
|
96
|
-
console.warn('Invalid time values');
|
|
97
93
|
return;
|
|
98
94
|
}
|
|
99
95
|
|
|
100
96
|
// Validate weekday if frequency is weekly
|
|
101
97
|
if (frequency === 'weekly' && !isValidWeekday(weekday)) {
|
|
102
|
-
console.warn('Invalid weekday value');
|
|
103
98
|
return;
|
|
104
99
|
}
|
|
105
100
|
|
|
@@ -26,21 +26,21 @@ function daysBetween(dateString: string, now: Date): number {
|
|
|
26
26
|
return Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Format date to ISO string
|
|
31
|
+
*/
|
|
32
|
+
function toISOString(date: Date = new Date()): string {
|
|
33
|
+
return date.toISOString();
|
|
34
|
+
}
|
|
35
|
+
|
|
29
36
|
/**
|
|
30
37
|
* Track an event occurrence
|
|
31
38
|
*/
|
|
32
39
|
export async function trackEvent(eventType: string): Promise<void> {
|
|
33
40
|
try {
|
|
34
41
|
await incrementEventCount(eventType);
|
|
35
|
-
|
|
36
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
37
|
-
const count = await getEventCount(eventType);
|
|
38
|
-
console.log(`[RatingService] Event tracked: ${eventType}, count: ${count}`);
|
|
39
|
-
}
|
|
40
42
|
} catch (error) {
|
|
41
|
-
|
|
42
|
-
console.error("[RatingService] Error tracking event:", error);
|
|
43
|
-
}
|
|
43
|
+
// Silent error handling
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
|
|
@@ -51,17 +51,11 @@ export async function shouldShowPrompt(config: RatingConfig): Promise<boolean> {
|
|
|
51
51
|
try {
|
|
52
52
|
const hasRated = await getHasRated();
|
|
53
53
|
if (hasRated) {
|
|
54
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
55
|
-
console.log("[RatingService] User has already rated, skipping prompt");
|
|
56
|
-
}
|
|
57
54
|
return false;
|
|
58
55
|
}
|
|
59
56
|
|
|
60
57
|
const dismissed = await getDismissed();
|
|
61
58
|
if (dismissed) {
|
|
62
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
63
|
-
console.log("[RatingService] User permanently dismissed prompt");
|
|
64
|
-
}
|
|
65
59
|
return false;
|
|
66
60
|
}
|
|
67
61
|
|
|
@@ -69,11 +63,6 @@ export async function shouldShowPrompt(config: RatingConfig): Promise<boolean> {
|
|
|
69
63
|
const minCount = config.minEventCount ?? 3;
|
|
70
64
|
|
|
71
65
|
if (eventCount < minCount) {
|
|
72
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
73
|
-
console.log(
|
|
74
|
-
`[RatingService] Event count ${eventCount} < ${minCount}, not showing prompt`
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
66
|
return false;
|
|
78
67
|
}
|
|
79
68
|
|
|
@@ -84,24 +73,12 @@ export async function shouldShowPrompt(config: RatingConfig): Promise<boolean> {
|
|
|
84
73
|
const daysSinceLastPrompt = daysBetween(lastPromptDate, new Date());
|
|
85
74
|
|
|
86
75
|
if (daysSinceLastPrompt < cooldownDays) {
|
|
87
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
88
|
-
console.log(
|
|
89
|
-
`[RatingService] Cooldown period active: ${daysSinceLastPrompt}/${cooldownDays} days`
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
76
|
return false;
|
|
93
77
|
}
|
|
94
78
|
}
|
|
95
79
|
|
|
96
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
97
|
-
console.log("[RatingService] All criteria met, prompt should be shown");
|
|
98
|
-
}
|
|
99
|
-
|
|
100
80
|
return true;
|
|
101
81
|
} catch (error) {
|
|
102
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
103
|
-
console.error("[RatingService] Error checking criteria:", error);
|
|
104
|
-
}
|
|
105
82
|
return false;
|
|
106
83
|
}
|
|
107
84
|
}
|
|
@@ -111,16 +88,9 @@ export async function shouldShowPrompt(config: RatingConfig): Promise<boolean> {
|
|
|
111
88
|
*/
|
|
112
89
|
export async function markPromptShown(eventType: string): Promise<void> {
|
|
113
90
|
try {
|
|
114
|
-
|
|
115
|
-
await setLastPromptDate(eventType, now);
|
|
116
|
-
|
|
117
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
118
|
-
console.log(`[RatingService] Prompt shown marked for: ${eventType}`);
|
|
119
|
-
}
|
|
91
|
+
await setLastPromptDate(eventType, toISOString());
|
|
120
92
|
} catch (error) {
|
|
121
|
-
|
|
122
|
-
console.error("[RatingService] Error marking prompt shown:", error);
|
|
123
|
-
}
|
|
93
|
+
// Silent error handling
|
|
124
94
|
}
|
|
125
95
|
}
|
|
126
96
|
|
|
@@ -130,14 +100,8 @@ export async function markPromptShown(eventType: string): Promise<void> {
|
|
|
130
100
|
export async function markRated(): Promise<void> {
|
|
131
101
|
try {
|
|
132
102
|
await setHasRated(true);
|
|
133
|
-
|
|
134
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
135
|
-
console.log("[RatingService] User marked as rated");
|
|
136
|
-
}
|
|
137
103
|
} catch (error) {
|
|
138
|
-
|
|
139
|
-
console.error("[RatingService] Error marking rated:", error);
|
|
140
|
-
}
|
|
104
|
+
// Silent error handling
|
|
141
105
|
}
|
|
142
106
|
}
|
|
143
107
|
|
|
@@ -147,14 +111,8 @@ export async function markRated(): Promise<void> {
|
|
|
147
111
|
export async function markDismissed(): Promise<void> {
|
|
148
112
|
try {
|
|
149
113
|
await setDismissed(true);
|
|
150
|
-
|
|
151
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
152
|
-
console.log("[RatingService] User marked as dismissed");
|
|
153
|
-
}
|
|
154
114
|
} catch (error) {
|
|
155
|
-
|
|
156
|
-
console.error("[RatingService] Error marking dismissed:", error);
|
|
157
|
-
}
|
|
115
|
+
// Silent error handling
|
|
158
116
|
}
|
|
159
117
|
}
|
|
160
118
|
|
|
@@ -171,15 +129,7 @@ export async function getState(eventType: string): Promise<RatingState> {
|
|
|
171
129
|
export async function reset(eventType?: string): Promise<void> {
|
|
172
130
|
try {
|
|
173
131
|
await resetStorage(eventType);
|
|
174
|
-
|
|
175
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
176
|
-
console.log(
|
|
177
|
-
`[RatingService] Reset ${eventType ? `event: ${eventType}` : "all rating data"}`
|
|
178
|
-
);
|
|
179
|
-
}
|
|
180
132
|
} catch (error) {
|
|
181
|
-
|
|
182
|
-
console.error("[RatingService] Error resetting:", error);
|
|
183
|
-
}
|
|
133
|
+
// Silent error handling
|
|
184
134
|
}
|
|
185
135
|
}
|
|
@@ -24,10 +24,7 @@ export async function getEventCount(eventType: string): Promise<number> {
|
|
|
24
24
|
const result = await storageRepository.getString(KEYS.eventCount(eventType), "0");
|
|
25
25
|
const count = parseInt(unwrap(result, "0"), 10);
|
|
26
26
|
return Number.isNaN(count) ? 0 : count;
|
|
27
|
-
} catch
|
|
28
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
29
|
-
console.error("[RatingStorage] Error getting event count:", error);
|
|
30
|
-
}
|
|
27
|
+
} catch {
|
|
31
28
|
return 0;
|
|
32
29
|
}
|
|
33
30
|
}
|
|
@@ -38,10 +35,8 @@ export async function getEventCount(eventType: string): Promise<number> {
|
|
|
38
35
|
export async function setEventCount(eventType: string, count: number): Promise<void> {
|
|
39
36
|
try {
|
|
40
37
|
await storageRepository.setString(KEYS.eventCount(eventType), count.toString());
|
|
41
|
-
} catch
|
|
42
|
-
|
|
43
|
-
console.error("[RatingStorage] Error setting event count:", error);
|
|
44
|
-
}
|
|
38
|
+
} catch {
|
|
39
|
+
// Silent error handling
|
|
45
40
|
}
|
|
46
41
|
}
|
|
47
42
|
|
|
@@ -61,10 +56,7 @@ export async function getLastPromptDate(eventType: string): Promise<string | nul
|
|
|
61
56
|
const result = await storageRepository.getString(KEYS.lastPrompt(eventType), "");
|
|
62
57
|
const date = unwrap(result, "");
|
|
63
58
|
return date || null;
|
|
64
|
-
} catch
|
|
65
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
66
|
-
console.error("[RatingStorage] Error getting last prompt date:", error);
|
|
67
|
-
}
|
|
59
|
+
} catch {
|
|
68
60
|
return null;
|
|
69
61
|
}
|
|
70
62
|
}
|
|
@@ -75,10 +67,8 @@ export async function getLastPromptDate(eventType: string): Promise<string | nul
|
|
|
75
67
|
export async function setLastPromptDate(eventType: string, date: string): Promise<void> {
|
|
76
68
|
try {
|
|
77
69
|
await storageRepository.setString(KEYS.lastPrompt(eventType), date);
|
|
78
|
-
} catch
|
|
79
|
-
|
|
80
|
-
console.error("[RatingStorage] Error setting last prompt date:", error);
|
|
81
|
-
}
|
|
70
|
+
} catch {
|
|
71
|
+
// Silent error handling
|
|
82
72
|
}
|
|
83
73
|
}
|
|
84
74
|
|
|
@@ -89,10 +79,7 @@ export async function getHasRated(): Promise<boolean> {
|
|
|
89
79
|
try {
|
|
90
80
|
const result = await storageRepository.getString(KEYS.hasRated, "false");
|
|
91
81
|
return unwrap(result, "false") === "true";
|
|
92
|
-
} catch
|
|
93
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
94
|
-
console.error("[RatingStorage] Error getting hasRated:", error);
|
|
95
|
-
}
|
|
82
|
+
} catch {
|
|
96
83
|
return false;
|
|
97
84
|
}
|
|
98
85
|
}
|
|
@@ -103,10 +90,8 @@ export async function getHasRated(): Promise<boolean> {
|
|
|
103
90
|
export async function setHasRated(value: boolean): Promise<void> {
|
|
104
91
|
try {
|
|
105
92
|
await storageRepository.setString(KEYS.hasRated, value.toString());
|
|
106
|
-
} catch
|
|
107
|
-
|
|
108
|
-
console.error("[RatingStorage] Error setting hasRated:", error);
|
|
109
|
-
}
|
|
93
|
+
} catch {
|
|
94
|
+
// Silent error handling
|
|
110
95
|
}
|
|
111
96
|
}
|
|
112
97
|
|
|
@@ -117,10 +102,7 @@ export async function getDismissed(): Promise<boolean> {
|
|
|
117
102
|
try {
|
|
118
103
|
const result = await storageRepository.getString(KEYS.dismissed, "false");
|
|
119
104
|
return unwrap(result, "false") === "true";
|
|
120
|
-
} catch
|
|
121
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
122
|
-
console.error("[RatingStorage] Error getting dismissed:", error);
|
|
123
|
-
}
|
|
105
|
+
} catch {
|
|
124
106
|
return false;
|
|
125
107
|
}
|
|
126
108
|
}
|
|
@@ -131,10 +113,8 @@ export async function getDismissed(): Promise<boolean> {
|
|
|
131
113
|
export async function setDismissed(value: boolean): Promise<void> {
|
|
132
114
|
try {
|
|
133
115
|
await storageRepository.setString(KEYS.dismissed, value.toString());
|
|
134
|
-
} catch
|
|
135
|
-
|
|
136
|
-
console.error("[RatingStorage] Error setting dismissed:", error);
|
|
137
|
-
}
|
|
116
|
+
} catch {
|
|
117
|
+
// Silent error handling
|
|
138
118
|
}
|
|
139
119
|
}
|
|
140
120
|
|
|
@@ -174,9 +154,7 @@ export async function reset(eventType?: string): Promise<void> {
|
|
|
174
154
|
ratingKeys.map((key) => storageRepository.removeItem(key))
|
|
175
155
|
);
|
|
176
156
|
}
|
|
177
|
-
} catch
|
|
178
|
-
|
|
179
|
-
console.error("[RatingStorage] Error resetting data:", error);
|
|
180
|
-
}
|
|
157
|
+
} catch {
|
|
158
|
+
// Silent error handling
|
|
181
159
|
}
|
|
182
160
|
}
|