@umituz/react-native-settings 4.23.72 → 4.23.73
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/screens/AboutScreen.tsx +10 -173
- package/src/domains/about/presentation/screens/AboutScreenContainer.tsx +109 -0
- package/src/domains/about/presentation/screens/AboutScreenContent.tsx +122 -0
- package/src/domains/dev/presentation/screens/EnvViewerScreen.tsx +51 -50
- package/src/domains/disclaimer/presentation/screens/DisclaimerScreen.tsx +28 -40
- package/src/domains/feedback/presentation/components/FeedbackModal.tsx +32 -43
- package/src/domains/gamification/components/GamificationScreen/GamificationScreen.tsx +122 -0
- package/src/domains/gamification/components/GamificationScreen/GamificationScreenWithConfig.tsx +72 -0
- package/src/domains/gamification/components/GamificationScreen/index.tsx +8 -178
- package/src/domains/gamification/components/index.ts +2 -1
- package/src/domains/legal/presentation/screens/LegalContentScreen.tsx +19 -29
- package/src/domains/notifications/infrastructure/services/NotificationManager.ts +0 -2
- package/src/domains/notifications/infrastructure/services/NotificationService.ts +5 -1
- package/src/infrastructure/utils/index.ts +7 -0
- package/src/infrastructure/utils/memoUtils.ts +159 -0
- package/src/infrastructure/utils/styleUtils.ts +190 -0
- package/src/presentation/screens/SettingsScreen.tsx +0 -5
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memo Utilities
|
|
3
|
+
* Centralized memoization helpers to reduce code duplication
|
|
4
|
+
*/
|
|
5
|
+
import { useMemo, useCallback, useRef, DependencyList } from 'react';
|
|
6
|
+
import type { DesignTokens } from '@umituz/react-native-design-system';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Custom hook to create memoized styles from a style factory function
|
|
10
|
+
* @param styleFactory Function that creates styles
|
|
11
|
+
* @param tokens Design tokens
|
|
12
|
+
* @param deps Dependencies for memoization
|
|
13
|
+
* @returns Memoized styles object
|
|
14
|
+
*/
|
|
15
|
+
export function useMemoizedStyles<T>(
|
|
16
|
+
styleFactory: (tokens: DesignTokens) => T,
|
|
17
|
+
tokens: DesignTokens,
|
|
18
|
+
deps: DependencyList = []
|
|
19
|
+
): T {
|
|
20
|
+
return useMemo(() => styleFactory(tokens), [tokens, ...deps]);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Custom hook to create a memoized callback with proper type inference
|
|
25
|
+
* @param callback Function to memoize
|
|
26
|
+
* @param deps Dependencies for memoization
|
|
27
|
+
* @returns Memoized callback
|
|
28
|
+
*/
|
|
29
|
+
export function useMemoizedCallback<T extends (...args: any[]) => any>(
|
|
30
|
+
callback: T,
|
|
31
|
+
deps: DependencyList
|
|
32
|
+
): T {
|
|
33
|
+
return useCallback(callback, deps) as T;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Custom hook to create a memoized value with proper type inference
|
|
38
|
+
* @param factory Function that creates the value
|
|
39
|
+
* @param deps Dependencies for memoization
|
|
40
|
+
* @returns Memoized value
|
|
41
|
+
*/
|
|
42
|
+
export function useMemoizedValue<T>(
|
|
43
|
+
factory: () => T,
|
|
44
|
+
deps: DependencyList
|
|
45
|
+
): T {
|
|
46
|
+
return useMemo(factory, deps);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Creates a memoized style object with proper caching
|
|
51
|
+
* @param styleCreator Function that creates styles
|
|
52
|
+
* @param deps Dependencies for memoization
|
|
53
|
+
* @returns Memoized styles
|
|
54
|
+
*/
|
|
55
|
+
export function useStyledMemo<T extends Record<string, any>>(
|
|
56
|
+
styleCreator: () => T,
|
|
57
|
+
deps: DependencyList = []
|
|
58
|
+
): T {
|
|
59
|
+
return useMemo(styleCreator, deps);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Memoizes a value with a custom equality check (non-hook version)
|
|
64
|
+
* @param value Value to memoize
|
|
65
|
+
* @param _isEqual Custom equality function
|
|
66
|
+
* @returns Memoized value
|
|
67
|
+
*/
|
|
68
|
+
export function memoWithEquality<T>(
|
|
69
|
+
value: T,
|
|
70
|
+
_isEqual: (prev: T, next: T) => boolean
|
|
71
|
+
): T {
|
|
72
|
+
// This is a utility function, not a hook
|
|
73
|
+
// It cannot use hooks internally
|
|
74
|
+
return value;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Creates a cache key for style memoization
|
|
79
|
+
* @param tokens Design tokens
|
|
80
|
+
* @param prefix Optional prefix for the key
|
|
81
|
+
* @returns Cache key string
|
|
82
|
+
*/
|
|
83
|
+
export function createStyleCacheKey(
|
|
84
|
+
tokens: DesignTokens,
|
|
85
|
+
prefix: string = ''
|
|
86
|
+
): string {
|
|
87
|
+
const { colors, spacing, typography } = tokens;
|
|
88
|
+
|
|
89
|
+
return `${prefix}-${JSON.stringify({
|
|
90
|
+
colors: { primary: colors.primary, background: colors.backgroundPrimary },
|
|
91
|
+
spacing: { md: spacing.md, lg: spacing.lg },
|
|
92
|
+
typography: { body: typography.bodyMedium.responsiveFontSize },
|
|
93
|
+
})}`;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Memoizes a value with a custom equality check
|
|
98
|
+
* @param value Value to memoize
|
|
99
|
+
* @param _isEqual Custom equality function
|
|
100
|
+
* @returns Memoized value
|
|
101
|
+
*/
|
|
102
|
+
export function useMemoWithEquality<T>(
|
|
103
|
+
value: T,
|
|
104
|
+
_isEqual: (prev: T, next: T) => boolean
|
|
105
|
+
): T {
|
|
106
|
+
const ref = useRef<T>(value);
|
|
107
|
+
|
|
108
|
+
return useMemo(() => {
|
|
109
|
+
if (!_isEqual(ref.current, value)) {
|
|
110
|
+
ref.current = value;
|
|
111
|
+
}
|
|
112
|
+
return ref.current;
|
|
113
|
+
}, [value, _isEqual]);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Custom hook that creates a debounced callback
|
|
118
|
+
* @param callback Function to debounce
|
|
119
|
+
* @param delay Delay in milliseconds
|
|
120
|
+
* @returns Debounced callback
|
|
121
|
+
*/
|
|
122
|
+
export function useDebouncedCallback<T extends (...args: any[]) => any>(
|
|
123
|
+
callback: T,
|
|
124
|
+
delay: number
|
|
125
|
+
): T {
|
|
126
|
+
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
|
|
127
|
+
|
|
128
|
+
return useCallback((...args: Parameters<T>) => {
|
|
129
|
+
if (timeoutRef.current) {
|
|
130
|
+
clearTimeout(timeoutRef.current);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
timeoutRef.current = setTimeout(() => {
|
|
134
|
+
callback(...args);
|
|
135
|
+
}, delay);
|
|
136
|
+
}, [callback, delay]) as T;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Custom hook that creates a throttled callback
|
|
141
|
+
* @param callback Function to throttle
|
|
142
|
+
* @param delay Delay in milliseconds
|
|
143
|
+
* @returns Throttled callback
|
|
144
|
+
*/
|
|
145
|
+
export function useThrottledCallback<T extends (...args: any[]) => any>(
|
|
146
|
+
callback: T,
|
|
147
|
+
delay: number
|
|
148
|
+
): T {
|
|
149
|
+
const lastRunRef = useRef<number>(0);
|
|
150
|
+
|
|
151
|
+
return useCallback((...args: Parameters<T>) => {
|
|
152
|
+
const now = Date.now();
|
|
153
|
+
|
|
154
|
+
if (now - lastRunRef.current >= delay) {
|
|
155
|
+
callback(...args);
|
|
156
|
+
lastRunRef.current = now;
|
|
157
|
+
}
|
|
158
|
+
}, [callback, delay]) as T;
|
|
159
|
+
}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Style Utilities
|
|
3
|
+
* Centralized style creation functions to reduce code duplication
|
|
4
|
+
*/
|
|
5
|
+
import { StyleSheet, ViewStyle, TextStyle, ImageStyle } from 'react-native';
|
|
6
|
+
import type { DesignTokens } from '@umituz/react-native-design-system';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Creates a container style with flex 1
|
|
10
|
+
*/
|
|
11
|
+
export const createContainerStyle = (overrides: ViewStyle = {}): ViewStyle => ({
|
|
12
|
+
flex: 1,
|
|
13
|
+
...overrides,
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Creates a centered container style
|
|
18
|
+
*/
|
|
19
|
+
export const createCenteredContainerStyle = (overrides: ViewStyle = {}): ViewStyle => ({
|
|
20
|
+
flex: 1,
|
|
21
|
+
justifyContent: 'center',
|
|
22
|
+
alignItems: 'center',
|
|
23
|
+
...overrides,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Creates a row style for horizontal layouts
|
|
28
|
+
*/
|
|
29
|
+
export const createRowStyle = (overrides: ViewStyle = {}): ViewStyle => ({
|
|
30
|
+
flexDirection: 'row',
|
|
31
|
+
alignItems: 'center',
|
|
32
|
+
...overrides,
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Creates a header style
|
|
37
|
+
*/
|
|
38
|
+
export const createHeaderStyle = (tokens: DesignTokens, overrides: ViewStyle = {}): ViewStyle => ({
|
|
39
|
+
paddingHorizontal: tokens.spacing.lg,
|
|
40
|
+
paddingVertical: tokens.spacing.md,
|
|
41
|
+
...overrides,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Creates a section style
|
|
46
|
+
*/
|
|
47
|
+
export const createSectionStyle = (tokens: DesignTokens, overrides: ViewStyle = {}): ViewStyle => ({
|
|
48
|
+
padding: tokens.spacing.lg,
|
|
49
|
+
...overrides,
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Creates a card style
|
|
54
|
+
*/
|
|
55
|
+
export const createCardStyle = (tokens: DesignTokens, overrides: ViewStyle = {}): ViewStyle => ({
|
|
56
|
+
backgroundColor: tokens.colors.surface,
|
|
57
|
+
borderRadius: tokens.borders.radius.md,
|
|
58
|
+
padding: tokens.spacing.lg,
|
|
59
|
+
...overrides,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Creates a title text style
|
|
64
|
+
*/
|
|
65
|
+
export const createTitleStyle = (tokens: DesignTokens, overrides: TextStyle = {}): TextStyle => ({
|
|
66
|
+
fontSize: tokens.typography.headlineMedium.responsiveFontSize,
|
|
67
|
+
fontWeight: '600',
|
|
68
|
+
color: tokens.colors.textPrimary,
|
|
69
|
+
...overrides,
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Creates a subtitle text style
|
|
74
|
+
*/
|
|
75
|
+
export const createSubtitleStyle = (tokens: DesignTokens, overrides: TextStyle = {}): TextStyle => ({
|
|
76
|
+
fontSize: tokens.typography.bodyMedium.responsiveFontSize,
|
|
77
|
+
color: tokens.colors.textSecondary,
|
|
78
|
+
...overrides,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Creates a button style
|
|
83
|
+
*/
|
|
84
|
+
export const createButtonStyle = (tokens: DesignTokens, overrides: ViewStyle = {}): ViewStyle => ({
|
|
85
|
+
backgroundColor: tokens.colors.primary,
|
|
86
|
+
borderRadius: tokens.borders.radius.md,
|
|
87
|
+
paddingVertical: tokens.spacing.md,
|
|
88
|
+
paddingHorizontal: tokens.spacing.lg,
|
|
89
|
+
...overrides,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Creates an icon container style
|
|
94
|
+
*/
|
|
95
|
+
export const createIconContainerStyle = (
|
|
96
|
+
size: number = 48,
|
|
97
|
+
tokens: DesignTokens,
|
|
98
|
+
overrides: ViewStyle = {}
|
|
99
|
+
): ViewStyle => ({
|
|
100
|
+
width: size,
|
|
101
|
+
height: size,
|
|
102
|
+
borderRadius: size / 2,
|
|
103
|
+
justifyContent: 'center',
|
|
104
|
+
alignItems: 'center',
|
|
105
|
+
backgroundColor: tokens.colors.surfaceSecondary,
|
|
106
|
+
...overrides,
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Creates a scroll content style
|
|
111
|
+
*/
|
|
112
|
+
export const createScrollContentStyle = (tokens: DesignTokens, overrides: ViewStyle = {}): ViewStyle => ({
|
|
113
|
+
padding: tokens.spacing.lg,
|
|
114
|
+
...overrides,
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Creates a separator/border style
|
|
119
|
+
*/
|
|
120
|
+
export const createSeparatorStyle = (tokens: DesignTokens, overrides: ViewStyle = {}): ViewStyle => ({
|
|
121
|
+
height: 1,
|
|
122
|
+
backgroundColor: tokens.colors.border,
|
|
123
|
+
...overrides,
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Creates a margin utility style
|
|
128
|
+
*/
|
|
129
|
+
export const createMarginStyle = (
|
|
130
|
+
spacing: 'xs' | 'sm' | 'md' | 'lg' | 'xl',
|
|
131
|
+
tokens: DesignTokens,
|
|
132
|
+
overrides: ViewStyle = {}
|
|
133
|
+
): ViewStyle => ({
|
|
134
|
+
margin: tokens.spacing[spacing],
|
|
135
|
+
...overrides,
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Creates a padding utility style
|
|
140
|
+
*/
|
|
141
|
+
export const createPaddingStyle = (
|
|
142
|
+
spacing: 'xs' | 'sm' | 'md' | 'lg' | 'xl',
|
|
143
|
+
tokens: DesignTokens,
|
|
144
|
+
overrides: ViewStyle = {}
|
|
145
|
+
): ViewStyle => ({
|
|
146
|
+
padding: tokens.spacing[spacing],
|
|
147
|
+
...overrides,
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Combines multiple styles into one
|
|
152
|
+
*/
|
|
153
|
+
export const combineStyles = (
|
|
154
|
+
...styles: (ViewStyle | TextStyle | ImageStyle | undefined | false)[]
|
|
155
|
+
): ViewStyle | TextStyle | ImageStyle => {
|
|
156
|
+
return StyleSheet.flatten(styles.filter(Boolean));
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Creates a responsive style based on screen dimensions
|
|
161
|
+
*/
|
|
162
|
+
export const createResponsiveStyle = (
|
|
163
|
+
_tokens: DesignTokens,
|
|
164
|
+
phoneStyle: ViewStyle,
|
|
165
|
+
_tabletStyle?: ViewStyle
|
|
166
|
+
): ViewStyle => {
|
|
167
|
+
// For now, return phone style. Can be enhanced with actual responsive logic
|
|
168
|
+
return phoneStyle;
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Type guard for ViewStyle
|
|
173
|
+
*/
|
|
174
|
+
export const isViewStyle = (style: any): style is ViewStyle => {
|
|
175
|
+
return style && typeof style === 'object';
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Creates a safe area aware style
|
|
180
|
+
*/
|
|
181
|
+
export const createSafeAreaStyle = (
|
|
182
|
+
insets: { top?: number; bottom?: number; left?: number; right?: number },
|
|
183
|
+
overrides: ViewStyle = {}
|
|
184
|
+
): ViewStyle => ({
|
|
185
|
+
paddingTop: insets.top,
|
|
186
|
+
paddingBottom: insets.bottom,
|
|
187
|
+
paddingLeft: insets.left,
|
|
188
|
+
paddingRight: insets.right,
|
|
189
|
+
...overrides,
|
|
190
|
+
});
|
|
@@ -7,7 +7,6 @@ import React from "react";
|
|
|
7
7
|
import {
|
|
8
8
|
ScreenLayout,
|
|
9
9
|
useAppNavigation,
|
|
10
|
-
ErrorBoundary,
|
|
11
10
|
} from "@umituz/react-native-design-system";
|
|
12
11
|
import { SettingsHeader } from "./components/SettingsHeader";
|
|
13
12
|
import { SettingsContent } from "./components/SettingsContent";
|
|
@@ -95,7 +94,6 @@ export const SettingsScreen: React.FC<SettingsScreenProps> = ({
|
|
|
95
94
|
// Workaround: Use conditional rendering with type assertion
|
|
96
95
|
if (showHeader) {
|
|
97
96
|
return <ScreenLayout header={<SettingsHeader showCloseButton={showCloseButton} onClose={onClose} />}>
|
|
98
|
-
<ErrorBoundary>
|
|
99
97
|
{children ?? (
|
|
100
98
|
<SettingsContent
|
|
101
99
|
normalizedConfig={normalizedConfig}
|
|
@@ -110,12 +108,10 @@ export const SettingsScreen: React.FC<SettingsScreenProps> = ({
|
|
|
110
108
|
gamificationConfig={gamificationConfig}
|
|
111
109
|
/>
|
|
112
110
|
)}
|
|
113
|
-
</ErrorBoundary>
|
|
114
111
|
</ScreenLayout>;
|
|
115
112
|
}
|
|
116
113
|
|
|
117
114
|
return <ScreenLayout>
|
|
118
|
-
<ErrorBoundary>
|
|
119
115
|
{children ?? (
|
|
120
116
|
<SettingsContent
|
|
121
117
|
normalizedConfig={normalizedConfig}
|
|
@@ -130,6 +126,5 @@ export const SettingsScreen: React.FC<SettingsScreenProps> = ({
|
|
|
130
126
|
gamificationConfig={gamificationConfig}
|
|
131
127
|
/>
|
|
132
128
|
)}
|
|
133
|
-
</ErrorBoundary>
|
|
134
129
|
</ScreenLayout>;
|
|
135
130
|
};
|