@umituz/react-native-settings 4.23.86 → 4.23.87

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/package.json +1 -1
  2. package/src/domains/feedback/presentation/components/FeedbackForm.tsx +10 -3
  3. package/src/domains/gamification/store/gamificationStore.ts +6 -7
  4. package/src/domains/localization/infrastructure/storage/LocalizationStore.ts +50 -181
  5. package/src/domains/localization/infrastructure/storage/localizationStoreUtils.ts +182 -0
  6. package/src/domains/notifications/reminders/presentation/components/ReminderForm.tsx +51 -45
  7. package/src/infrastructure/types/commonComponentTypes.ts +142 -0
  8. package/src/infrastructure/utils/async/core.ts +109 -0
  9. package/src/infrastructure/utils/async/debounceAndBatch.ts +69 -0
  10. package/src/infrastructure/utils/async/index.ts +8 -0
  11. package/src/infrastructure/utils/async/retryAndTimeout.ts +57 -0
  12. package/src/infrastructure/utils/configFactory.ts +101 -0
  13. package/src/infrastructure/utils/errorHandlers.ts +249 -0
  14. package/src/infrastructure/utils/index.ts +5 -0
  15. package/src/infrastructure/utils/memoUtils.ts +10 -2
  16. package/src/infrastructure/utils/styleTokens.ts +132 -0
  17. package/src/infrastructure/utils/validation/core.ts +42 -0
  18. package/src/infrastructure/utils/validation/formValidators.ts +82 -0
  19. package/src/infrastructure/utils/validation/index.ts +37 -0
  20. package/src/infrastructure/utils/validation/numericValidators.ts +66 -0
  21. package/src/infrastructure/utils/validation/passwordValidator.ts +53 -0
  22. package/src/infrastructure/utils/validation/textValidators.ts +118 -0
  23. package/src/presentation/hooks/useSettingsScreenConfig.ts +32 -79
  24. package/src/presentation/utils/config-creators/base-configs.ts +54 -42
  25. package/src/presentation/utils/faqTranslator.ts +31 -0
  26. package/src/presentation/utils/index.ts +6 -1
  27. package/src/presentation/utils/settingsConfigFactory.ts +89 -0
  28. package/src/presentation/utils/useAuthHandlers.ts +98 -0
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Common Component Types
3
+ * Shared interfaces for common component props to reduce duplication
4
+ */
5
+
6
+ import type { StyleProp, ViewStyle } from "react-native";
7
+ import type { IconName } from "@umituz/react-native-design-system";
8
+
9
+ /**
10
+ * Base props for settings item components
11
+ */
12
+ export interface BaseSettingsItemProps {
13
+ title: string;
14
+ description?: string;
15
+ icon?: IconName;
16
+ onPress?: () => void;
17
+ disabled?: boolean;
18
+ style?: StyleProp<ViewStyle>;
19
+ testID?: string;
20
+ }
21
+
22
+ /**
23
+ * Base props for card components
24
+ */
25
+ export interface BaseCardProps {
26
+ style?: StyleProp<ViewStyle>;
27
+ testID?: string;
28
+ }
29
+
30
+ /**
31
+ * Base props for section components
32
+ */
33
+ export interface BaseSectionProps {
34
+ title?: string;
35
+ style?: StyleProp<ViewStyle>;
36
+ testID?: string;
37
+ }
38
+
39
+ /**
40
+ * Navigation item props
41
+ */
42
+ export interface NavigationItemProps extends BaseSettingsItemProps {
43
+ route?: string;
44
+ showChevron?: boolean;
45
+ }
46
+
47
+ /**
48
+ * Toggle item props (items with switches)
49
+ */
50
+ export interface ToggleItemProps extends BaseSettingsItemProps {
51
+ showSwitch: true;
52
+ switchValue: boolean;
53
+ onSwitchChange: (value: boolean) => void;
54
+ }
55
+
56
+ /**
57
+ * Pressable item props
58
+ */
59
+ export interface PressableItemProps extends BaseSettingsItemProps {
60
+ onPress: () => void;
61
+ }
62
+
63
+ /**
64
+ * Icon styling props
65
+ */
66
+ export interface IconStyleProps {
67
+ iconBgColor?: string;
68
+ iconColor?: string;
69
+ iconSize?: number;
70
+ }
71
+
72
+ /**
73
+ * Loading state props
74
+ */
75
+ export interface LoadingStateProps {
76
+ loading?: boolean;
77
+ }
78
+
79
+ /**
80
+ * Badge props (for notification counts, etc.)
81
+ */
82
+ export interface BadgeProps {
83
+ badge?: string | number;
84
+ badgeColor?: string;
85
+ badgeTextColor?: string;
86
+ }
87
+
88
+ /**
89
+ * Screen header props
90
+ */
91
+ export interface ScreenHeaderProps {
92
+ title: string;
93
+ subtitle?: string;
94
+ showBackButton?: boolean;
95
+ onBackPress?: () => void;
96
+ rightElement?: React.ReactNode;
97
+ style?: StyleProp<ViewStyle>;
98
+ }
99
+
100
+ /**
101
+ * List item props
102
+ */
103
+ export interface ListItemProps extends BaseSettingsItemProps {
104
+ rightElement?: React.ReactNode;
105
+ leftElement?: React.ReactNode;
106
+ }
107
+
108
+ /**
109
+ * Modal props
110
+ */
111
+ export interface BaseModalProps {
112
+ visible: boolean;
113
+ onClose: () => void;
114
+ title?: string;
115
+ testID?: string;
116
+ }
117
+
118
+ /**
119
+ * Form input props
120
+ */
121
+ export interface BaseInputProps {
122
+ value: string;
123
+ onChangeText: (text: string) => void;
124
+ placeholder?: string;
125
+ error?: string;
126
+ disabled?: boolean;
127
+ style?: StyleProp<ViewStyle>;
128
+ testID?: string;
129
+ }
130
+
131
+ /**
132
+ * Button props
133
+ */
134
+ export interface BaseButtonProps {
135
+ title: string;
136
+ onPress: () => void;
137
+ disabled?: boolean;
138
+ loading?: boolean;
139
+ variant?: "primary" | "secondary" | "danger" | "ghost";
140
+ style?: StyleProp<ViewStyle>;
141
+ testID?: string;
142
+ }
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Core Async Operation Utilities
3
+ * Base types and handlers for async operations
4
+ */
5
+
6
+ import type { ValidationResult } from "../validation";
7
+
8
+ /**
9
+ * Result type for async operations
10
+ */
11
+ export type AsyncResult<T, E = Error> =
12
+ | { success: true; data: T }
13
+ | { success: false; error: E };
14
+
15
+ /**
16
+ * Generic async handler with error handling
17
+ */
18
+ export const handleAsyncOperation = async <T>(
19
+ operation: () => Promise<T>,
20
+ onError?: (error: Error) => void
21
+ ): Promise<AsyncResult<T>> => {
22
+ try {
23
+ const data = await operation();
24
+ return { success: true, data };
25
+ } catch (error) {
26
+ const err = error instanceof Error ? error : new Error(String(error));
27
+ if (onError) {
28
+ onError(err);
29
+ }
30
+ return { success: false, error: err };
31
+ }
32
+ };
33
+
34
+ /**
35
+ * Async operation with loading state
36
+ * FIXED: Properly handles errors in onSuccess callback
37
+ */
38
+ export const createAsyncHandler = <T extends unknown[], R>(
39
+ handler: (...args: T) => Promise<R>,
40
+ options: {
41
+ onLoadingStart?: () => void;
42
+ onLoadingEnd?: () => void;
43
+ onError?: (error: Error) => void;
44
+ onSuccess?: (result: R) => void;
45
+ }
46
+ ) => {
47
+ return async (...args: T): Promise<void> => {
48
+ const { onLoadingStart, onLoadingEnd, onError, onSuccess } = options;
49
+
50
+ let loadingStarted = false;
51
+
52
+ try {
53
+ onLoadingStart?.();
54
+ loadingStarted = true;
55
+ const result = await handler(...args);
56
+ // FIXED: Wrap onSuccess in try-catch to handle errors separately
57
+ try {
58
+ onSuccess?.(result);
59
+ } catch (callbackError) {
60
+ // Log callback error but don't treat it as handler error
61
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
62
+ console.error("[createAsyncHandler] onSuccess callback error:", callbackError);
63
+ }
64
+ }
65
+ } catch (error) {
66
+ const err = error instanceof Error ? error : new Error(String(error));
67
+ onError?.(err);
68
+ } finally {
69
+ // FIXED: Only call onLoadingEnd if it was started
70
+ if (loadingStarted) {
71
+ try {
72
+ onLoadingEnd?.();
73
+ } catch (callbackError) {
74
+ // Log callback error but don't throw
75
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
76
+ console.error("[createAsyncHandler] onLoadingEnd callback error:", callbackError);
77
+ }
78
+ }
79
+ }
80
+ }
81
+ };
82
+ };
83
+
84
+ /**
85
+ * Async operation with validation
86
+ */
87
+ export const createValidatedAsyncHandler = <T, R>(
88
+ validator: (data: T) => ValidationResult,
89
+ handler: (data: T) => Promise<R>,
90
+ options: {
91
+ onValidationError?: (error: string) => void;
92
+ onError?: (error: Error) => void;
93
+ } = {}
94
+ ) => {
95
+ return async (data: T): Promise<AsyncResult<R>> => {
96
+ const { onValidationError, onError } = options;
97
+
98
+ // Validate first
99
+ const validationResult = validator(data);
100
+ if (!validationResult.isValid) {
101
+ const error = new Error(validationResult.error || "Validation failed");
102
+ onValidationError?.(error.message);
103
+ return { success: false, error };
104
+ }
105
+
106
+ // Execute handler
107
+ return handleAsyncOperation(() => handler(data), onError);
108
+ };
109
+ };
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Debounce and Batch Utilities
3
+ * Utilities for debouncing and batching async operations
4
+ */
5
+
6
+ import type { AsyncResult } from "./core";
7
+
8
+ /**
9
+ * Debounced async operation
10
+ */
11
+ export const createDebouncedAsyncOperation = <T extends unknown[], R>(
12
+ operation: (...args: T) => Promise<R>,
13
+ delayMs: number
14
+ ): ((...args: T) => Promise<R>) => {
15
+ let timeoutId: NodeJS.Timeout | null = null;
16
+
17
+ return (...args: T): Promise<R> => {
18
+ if (timeoutId) {
19
+ clearTimeout(timeoutId);
20
+ }
21
+
22
+ return new Promise((resolve, reject) => {
23
+ timeoutId = setTimeout(async () => {
24
+ try {
25
+ const result = await operation(...args);
26
+ resolve(result);
27
+ } catch (error) {
28
+ reject(error);
29
+ }
30
+ }, delayMs);
31
+ });
32
+ };
33
+ };
34
+
35
+ /**
36
+ * Batch async operations
37
+ */
38
+ export const batchAsyncOperations = async <T, R>(
39
+ items: T[],
40
+ operation: (item: T) => Promise<R>,
41
+ options: {
42
+ concurrency?: number;
43
+ onProgress?: (completed: number, total: number) => void;
44
+ } = {}
45
+ ): Promise<AsyncResult<R[]>> => {
46
+ const { concurrency = 5, onProgress } = options;
47
+
48
+ try {
49
+ const results: R[] = [];
50
+ const batches: T[][] = [];
51
+
52
+ // Create batches
53
+ for (let i = 0; i < items.length; i += concurrency) {
54
+ batches.push(items.slice(i, i + concurrency));
55
+ }
56
+
57
+ // Process batches
58
+ for (const batch of batches) {
59
+ const batchResults = await Promise.all(batch.map(operation));
60
+ results.push(...batchResults);
61
+ onProgress?.(results.length, items.length);
62
+ }
63
+
64
+ return { success: true, data: results };
65
+ } catch (error) {
66
+ const err = error instanceof Error ? error : new Error(String(error));
67
+ return { success: false, error: err };
68
+ }
69
+ };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Async Utilities
3
+ * Barrel export for all async utility modules
4
+ */
5
+
6
+ export * from "./core";
7
+ export * from "./retryAndTimeout";
8
+ export * from "./debounceAndBatch";
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Retry and Timeout Utilities
3
+ * Utilities for handling retries and timeouts in async operations
4
+ */
5
+
6
+ /**
7
+ * Retry utility for async operations
8
+ */
9
+ export const retryAsyncOperation = async <T>(
10
+ operation: () => Promise<T>,
11
+ options: {
12
+ maxAttempts?: number;
13
+ delayMs?: number;
14
+ backoffMultiplier?: number;
15
+ onRetry?: (attempt: number, error: Error) => void;
16
+ } = {}
17
+ ): Promise<T> => {
18
+ const {
19
+ maxAttempts = 3,
20
+ delayMs = 1000,
21
+ backoffMultiplier = 2,
22
+ onRetry,
23
+ } = options;
24
+
25
+ let lastError: Error | undefined;
26
+
27
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
28
+ try {
29
+ return await operation();
30
+ } catch (error) {
31
+ lastError = error instanceof Error ? error : new Error(String(error));
32
+
33
+ if (attempt < maxAttempts) {
34
+ onRetry?.(attempt, lastError);
35
+ const delay = delayMs * Math.pow(backoffMultiplier, attempt - 1);
36
+ await new Promise((resolve) => setTimeout(resolve, delay));
37
+ }
38
+ }
39
+ }
40
+
41
+ throw lastError || new Error("Operation failed after retries");
42
+ };
43
+
44
+ /**
45
+ * Timeout wrapper for async operations
46
+ */
47
+ export const withTimeout = async <T>(
48
+ operation: Promise<T>,
49
+ timeoutMs: number,
50
+ timeoutMessage: string = "Operation timed out"
51
+ ): Promise<T> => {
52
+ const timeoutPromise = new Promise<never>((_, reject) => {
53
+ setTimeout(() => reject(new Error(timeoutMessage)), timeoutMs);
54
+ });
55
+
56
+ return Promise.race([operation, timeoutPromise]);
57
+ };
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Configuration Factory
3
+ * Generic configuration creator to reduce duplication in base-configs
4
+ */
5
+
6
+ import type { TranslationFunction } from "../../presentation/utils/config-creators/types";
7
+
8
+ /**
9
+ * Feature visibility configuration
10
+ * - true: Always show (if navigation screen exists)
11
+ * - false: Never show
12
+ * - 'auto': Automatically detect (check if navigation screen exists and package is available)
13
+ */
14
+ export type FeatureVisibility = boolean | "auto";
15
+
16
+ /**
17
+ * Base configuration type for all settings items
18
+ */
19
+ export interface BaseConfigType {
20
+ enabled?: FeatureVisibility;
21
+ title?: string;
22
+ description?: string;
23
+ icon?: string;
24
+ route?: string;
25
+ onPress?: () => void;
26
+ }
27
+
28
+ /**
29
+ * Configuration parameters for creating a settings item config
30
+ */
31
+ export interface ConfigCreatorParams {
32
+ t: TranslationFunction;
33
+ titleKey: string;
34
+ descriptionKey: string;
35
+ icon: string;
36
+ routeOrOnPress?: string | (() => void);
37
+ defaultRoute?: string;
38
+ }
39
+
40
+ /**
41
+ * Generic configuration creator function
42
+ * Reduces duplication across all config creators
43
+ */
44
+ export const createBaseConfig = <T extends BaseConfigType = BaseConfigType>(
45
+ params: ConfigCreatorParams
46
+ ): T => {
47
+ const { t, titleKey, descriptionKey, icon, routeOrOnPress, defaultRoute } = params;
48
+
49
+ return {
50
+ enabled: true,
51
+ title: t(titleKey),
52
+ description: t(descriptionKey),
53
+ icon,
54
+ route: typeof routeOrOnPress === "string" ? routeOrOnPress : defaultRoute,
55
+ onPress: typeof routeOrOnPress === "function" ? routeOrOnPress : undefined,
56
+ } as T;
57
+ };
58
+
59
+ /**
60
+ * Create a configuration with extended properties
61
+ */
62
+ export const createConfigWithExtensions = <T extends BaseConfigType>(
63
+ baseParams: ConfigCreatorParams,
64
+ extensions: Partial<Omit<T, keyof BaseConfigType>>
65
+ ): T => {
66
+ const baseConfig = createBaseConfig<T>(baseParams);
67
+ return { ...baseConfig, ...extensions };
68
+ };
69
+
70
+ /**
71
+ * Create a disabled configuration
72
+ */
73
+ export const createDisabledConfig = <T extends BaseConfigType>(
74
+ params: Omit<ConfigCreatorParams, "routeOrOnPress" | "defaultRoute">
75
+ ): T => {
76
+ const baseConfig = createBaseConfig<T>(params);
77
+ return { ...baseConfig, enabled: false } as T;
78
+ };
79
+
80
+ /**
81
+ * Batch create configurations
82
+ */
83
+ export const createBatchConfigs = <T extends BaseConfigType>(
84
+ items: Array<{
85
+ titleKey: string;
86
+ descriptionKey: string;
87
+ icon: string;
88
+ routeOrOnPress?: string | (() => void);
89
+ }>,
90
+ t: TranslationFunction
91
+ ): T[] => {
92
+ return items.map((item) =>
93
+ createBaseConfig<T>({
94
+ t,
95
+ titleKey: item.titleKey,
96
+ descriptionKey: item.descriptionKey,
97
+ icon: item.icon,
98
+ routeOrOnPress: item.routeOrOnPress,
99
+ })
100
+ );
101
+ };