@umituz/react-native-settings 4.20.61 → 4.21.1

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 (78) hide show
  1. package/package.json +8 -60
  2. package/src/domains/gamification/README.md +343 -0
  3. package/src/domains/gamification/components/AchievementCard.tsx +142 -0
  4. package/src/domains/gamification/components/AchievementItem.tsx +182 -0
  5. package/src/domains/gamification/components/AchievementToast.tsx +122 -0
  6. package/src/domains/gamification/components/GamificationScreen/AchievementsList.tsx +84 -0
  7. package/src/domains/gamification/components/GamificationScreen/Header.tsx +29 -0
  8. package/src/domains/gamification/components/GamificationScreen/StatsGrid.tsx +51 -0
  9. package/src/domains/gamification/components/GamificationScreen/index.tsx +111 -0
  10. package/src/domains/gamification/components/GamificationScreen/styles.ts +43 -0
  11. package/src/domains/gamification/components/GamificationScreen/types.ts +77 -0
  12. package/src/domains/gamification/components/GamificationScreenWrapper.tsx +91 -0
  13. package/src/domains/gamification/components/GamificationSettingsItem.tsx +33 -0
  14. package/src/domains/gamification/components/LevelProgress.tsx +129 -0
  15. package/src/domains/gamification/components/PointsBadge.tsx +60 -0
  16. package/src/domains/gamification/components/StatsCard.tsx +89 -0
  17. package/src/domains/gamification/components/StreakDisplay.tsx +119 -0
  18. package/src/domains/gamification/components/index.ts +13 -0
  19. package/src/domains/gamification/examples/gamification.config.example.ts +70 -0
  20. package/src/domains/gamification/examples/localization.example.json +71 -0
  21. package/src/domains/gamification/hooks/useGamification.ts +91 -0
  22. package/src/domains/gamification/index.ts +65 -0
  23. package/src/domains/gamification/store/gamificationStore.ts +162 -0
  24. package/src/domains/gamification/types/index.ts +103 -0
  25. package/src/domains/gamification/types/settings.ts +28 -0
  26. package/src/domains/gamification/utils/calculations.ts +85 -0
  27. package/src/index.ts +18 -8
  28. package/src/presentation/navigation/SettingsStackNavigator.tsx +12 -0
  29. package/src/presentation/navigation/types.ts +2 -0
  30. package/src/presentation/navigation/utils/navigationScreenOptions.ts +7 -0
  31. package/src/presentation/screens/types/UserFeatureConfig.ts +2 -0
  32. package/src/presentation/utils/configCreators.ts +147 -0
  33. package/src/presentation/utils/index.ts +5 -0
  34. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -51
  35. package/.github/ISSUE_TEMPLATE/documentation.md +0 -52
  36. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -63
  37. package/.github/PULL_REQUEST_TEMPLATE.md +0 -84
  38. package/AI_AGENT_GUIDELINES.md +0 -367
  39. package/ARCHITECTURE.md +0 -246
  40. package/CHANGELOG.md +0 -67
  41. package/CODE_OF_CONDUCT.md +0 -75
  42. package/CONTRIBUTING.md +0 -107
  43. package/DOCUMENTATION_MIGRATION.md +0 -319
  44. package/DOCUMENTATION_TEMPLATE.md +0 -155
  45. package/SECURITY.md +0 -98
  46. package/SETTINGS_SCREEN_GUIDE.md +0 -185
  47. package/TESTING.md +0 -358
  48. package/src/__tests__/integration.test.tsx +0 -371
  49. package/src/__tests__/performance.test.tsx +0 -369
  50. package/src/__tests__/setup.test.tsx +0 -20
  51. package/src/__tests__/setup.ts +0 -154
  52. package/src/domains/about/__tests__/integration.test.tsx +0 -328
  53. package/src/domains/about/__tests__/types.d.ts +0 -5
  54. package/src/domains/about/domain/entities/__tests__/AppInfo.test.ts +0 -93
  55. package/src/domains/about/infrastructure/repositories/__tests__/AboutRepository.test.ts +0 -153
  56. package/src/domains/about/presentation/components/__tests__/AboutContent.simple.test.tsx +0 -178
  57. package/src/domains/about/presentation/components/__tests__/AboutContent.test.tsx +0 -293
  58. package/src/domains/about/presentation/components/__tests__/AboutHeader.test.tsx +0 -201
  59. package/src/domains/about/presentation/components/__tests__/AboutSettingItem.test.tsx +0 -71
  60. package/src/domains/about/presentation/hooks/__tests__/useAboutInfo.simple.test.tsx +0 -229
  61. package/src/domains/about/presentation/hooks/__tests__/useAboutInfo.test.tsx +0 -240
  62. package/src/domains/about/presentation/screens/__tests__/AboutScreen.simple.test.tsx +0 -199
  63. package/src/domains/about/presentation/screens/__tests__/AboutScreen.test.tsx +0 -366
  64. package/src/domains/about/utils/__tests__/index.test.ts +0 -408
  65. package/src/domains/appearance/__tests__/components/AppearanceScreen.test.tsx +0 -195
  66. package/src/domains/appearance/__tests__/hooks/index.test.tsx +0 -232
  67. package/src/domains/appearance/__tests__/integration/index.test.tsx +0 -207
  68. package/src/domains/appearance/__tests__/services/appearanceService.test.ts +0 -299
  69. package/src/domains/appearance/__tests__/setup.ts +0 -88
  70. package/src/domains/appearance/__tests__/stores/appearanceStore.test.tsx +0 -175
  71. package/src/domains/cloud-sync/presentation/components/__tests__/CloudSyncSetting.test.tsx +0 -78
  72. package/src/domains/legal/__tests__/ContentValidationService.test.ts +0 -195
  73. package/src/domains/legal/__tests__/StyleCacheService.test.ts +0 -110
  74. package/src/domains/legal/__tests__/UrlHandlerService.test.ts +0 -71
  75. package/src/domains/legal/__tests__/setup.ts +0 -82
  76. package/src/presentation/components/__tests__/SettingsErrorBoundary.test.tsx +0 -186
  77. package/src/presentation/screens/__tests__/SettingsScreen.test.tsx +0 -322
  78. package/src/presentation/screens/hooks/__tests__/useFeatureDetection.test.tsx +0 -261
@@ -1,232 +0,0 @@
1
- /**
2
- * Hooks Tests
3
- */
4
-
5
- import { renderHook, act } from '@testing-library/react-native';
6
- import { useAppearance, useAppearanceActions } from '../../hooks';
7
- import type { ThemeMode, CustomThemeColors } from '../../types';
8
-
9
- // Mock design system theme
10
- jest.mock('@umituz/react-native-design-system', () => ({
11
- useTheme: jest.fn(() => ({
12
- getState: jest.fn(() => ({
13
- setThemeMode: jest.fn(),
14
- })),
15
- })),
16
- useDesignSystemTheme: jest.fn(() => ({
17
- getState: jest.fn(() => ({
18
- setThemeMode: jest.fn(),
19
- setCustomColors: jest.fn(),
20
- })),
21
- })),
22
- }));
23
-
24
- const mockUseTheme = require('@umituz/react-native-design-system').useTheme;
25
- const mockUseDesignSystemTheme = require('@umituz/react-native-design-system').useDesignSystemTheme;
26
-
27
- describe('useAppearance', () => {
28
- beforeEach(() => {
29
- jest.clearAllMocks();
30
-
31
- mockUseTheme.getState.mockReturnValue({
32
- setThemeMode: jest.fn(),
33
- });
34
-
35
- mockUseDesignSystemTheme.getState.mockReturnValue({
36
- setThemeMode: jest.fn(),
37
- setCustomColors: jest.fn(),
38
- });
39
- });
40
-
41
- afterEach(() => {
42
- jest.restoreAllMocks();
43
- });
44
-
45
- it('should return appearance state and actions', () => {
46
- const { result } = renderHook(() => useAppearance());
47
-
48
- expect(result.current).toHaveProperty('themeMode');
49
- expect(result.current).toHaveProperty('customColors');
50
- expect(result.current).toHaveProperty('isInitialized');
51
- expect(result.current).toHaveProperty('setThemeMode');
52
- expect(result.current).toHaveProperty('toggleTheme');
53
- expect(result.current).toHaveProperty('setCustomColors');
54
- expect(result.current).toHaveProperty('resetCustomColors');
55
- expect(result.current).toHaveProperty('reset');
56
-
57
- expect(typeof result.current.setThemeMode).toBe('function');
58
- expect(typeof result.current.toggleTheme).toBe('function');
59
- expect(typeof result.current.setCustomColors).toBe('function');
60
- expect(typeof result.current.resetCustomColors).toBe('function');
61
- expect(typeof result.current.reset).toBe('function');
62
- });
63
-
64
- it('should have stable function references', () => {
65
- const { result: result1 } = renderHook(() => useAppearance());
66
- const { result: result2 } = renderHook(() => useAppearance());
67
-
68
- // Functions should be stable across renders
69
- expect(result1.current.setThemeMode).toBe(result2.current.setThemeMode);
70
- expect(result1.current.toggleTheme).toBe(result2.current.toggleTheme);
71
- expect(result1.current.setCustomColors).toBe(result2.current.setCustomColors);
72
- expect(result1.current.resetCustomColors).toBe(result2.current.resetCustomColors);
73
- expect(result1.current.reset).toBe(result2.current.reset);
74
- });
75
-
76
- it('should call service methods correctly', async () => {
77
- const { result } = renderHook(() => useAppearance());
78
-
79
- const mockSetThemeMode = mockUseTheme.getState().setThemeMode;
80
- const mockSetCustomColors = mockUseDesignSystemTheme.getState().setCustomColors;
81
-
82
- await act(async () => {
83
- await result.current.setThemeMode('light');
84
- });
85
-
86
- expect(mockSetThemeMode).toHaveBeenCalledWith('light');
87
- });
88
-
89
- it('should handle errors gracefully', async () => {
90
- const { result } = renderHook(() => useAppearance());
91
-
92
- const mockSetThemeMode = mockUseTheme.getState().setThemeMode;
93
- const error = new Error('Service error');
94
- mockSetThemeMode.mockImplementation(() => {
95
- throw error;
96
- });
97
-
98
- await expect(result.current.setThemeMode('light')).rejects.toThrow(error);
99
- });
100
- });
101
-
102
- describe('useAppearanceActions', () => {
103
- beforeEach(() => {
104
- jest.clearAllMocks();
105
- });
106
-
107
- afterEach(() => {
108
- jest.restoreAllMocks();
109
- });
110
-
111
- it('should return actions and local state', () => {
112
- const { result } = renderHook(() => useAppearanceActions());
113
-
114
- expect(result.current).toHaveProperty('localCustomColors');
115
- expect(result.current).toHaveProperty('handleThemeSelect');
116
- expect(result.current).toHaveProperty('handleColorChange');
117
- expect(result.current).toHaveProperty('handleResetColors');
118
-
119
- expect(typeof result.current.handleThemeSelect).toBe('function');
120
- expect(typeof result.current.handleColorChange).toBe('function');
121
- expect(typeof result.current.handleResetColors).toBe('function');
122
- });
123
-
124
- it('should initialize with empty custom colors', () => {
125
- const { result } = renderHook(() => useAppearanceActions());
126
-
127
- expect(result.current.localCustomColors).toEqual({});
128
- });
129
-
130
- it('should handle theme selection', async () => {
131
- const { result } = renderHook(() => useAppearanceActions());
132
-
133
- const mockSetThemeMode = mockUseTheme.getState().setThemeMode;
134
-
135
- await act(async () => {
136
- await result.current.handleThemeSelect('light');
137
- });
138
-
139
- expect(mockSetThemeMode).toHaveBeenCalledWith('light');
140
- });
141
-
142
- it('should handle color change', () => {
143
- const { result } = renderHook(() => useAppearanceActions());
144
-
145
- const mockSetCustomColors = mockUseDesignSystemTheme.getState().setCustomColors;
146
-
147
- act(() => {
148
- result.current.handleColorChange('primary', '#FF0000');
149
- });
150
-
151
- expect(mockSetCustomColors).toHaveBeenCalledWith({
152
- primary: '#FF0000',
153
- });
154
- });
155
-
156
- it('should not update if color is same', () => {
157
- const { result } = renderHook(() => useAppearanceActions());
158
-
159
- const mockSetCustomColors = mockUseDesignSystemTheme.getState().setCustomColors;
160
-
161
- act(() => {
162
- result.current.handleColorChange('primary', '#FF0000');
163
- result.current.handleColorChange('primary', '#FF0000'); // Same color
164
- });
165
-
166
- // Should only be called once due to optimization
167
- expect(mockSetCustomColors).toHaveBeenCalledTimes(1);
168
- });
169
-
170
- it('should handle reset colors', () => {
171
- const { result } = renderHook(() => useAppearanceActions());
172
-
173
- const mockResetCustomColors = mockUseDesignSystemTheme.getState().setCustomColors;
174
-
175
- act(() => {
176
- result.current.handleResetColors();
177
- });
178
-
179
- expect(mockResetCustomColors).toHaveBeenCalled();
180
- });
181
-
182
- it('should handle reset colors with config', () => {
183
- const onConfirm = jest.fn();
184
- const config = { onResetConfirm };
185
-
186
- const { result } = renderHook(() => useAppearanceActions(config));
187
-
188
- const mockResetCustomColors = mockUseDesignSystemTheme.getState().setCustomColors;
189
-
190
- act(() => {
191
- result.current.handleResetColors();
192
- });
193
-
194
- expect(mockResetCustomColors).toHaveBeenCalled();
195
- expect(onConfirm).toHaveBeenCalled();
196
- });
197
-
198
- it('should sync local colors with store changes', () => {
199
- const { result, rerender } = renderHook(
200
- () => useAppearanceActions(),
201
- {
202
- initialProps: { customColors: { primary: '#FF0000' } }
203
- }
204
- );
205
-
206
- expect(result.current.localCustomColors).toEqual({ primary: '#FF0000' });
207
-
208
- // Simulate store change
209
- rerender({ customColors: { primary: '#00FF00' } });
210
-
211
- expect(result.current.localCustomColors).toEqual({ primary: '#00FF00' });
212
- });
213
-
214
- it('should have stable function references', () => {
215
- const { result: result1 } = renderHook(() => useAppearanceActions());
216
- const { result: result2 } = renderHook(() => useAppearanceActions());
217
-
218
- // Functions should be stable across renders
219
- expect(result1.current.handleThemeSelect).toBe(result2.current.handleThemeSelect);
220
- expect(result1.current.handleColorChange).toBe(result2.current.handleColorChange);
221
- expect(result1.current.handleResetColors).toBe(result2.current.handleResetColors);
222
- });
223
-
224
- it('should cleanup on unmount', () => {
225
- const { unmount } = renderHook(() => useAppearanceActions());
226
-
227
- unmount();
228
-
229
- // Should not throw any errors during cleanup
230
- expect(true).toBe(true);
231
- });
232
- });
@@ -1,207 +0,0 @@
1
- /**
2
- * Integration Tests
3
- */
4
-
5
- import React from 'react';
6
- import { render, fireEvent, act } from '@testing-library/react-native';
7
- import { AppearanceService, appearanceService } from '../../infrastructure/services/appearanceService';
8
- import { useAppearanceStore } from '../../infrastructure/stores/appearanceStore';
9
- import { AppearanceScreen } from '../../presentation/screens/AppearanceScreen';
10
- import type { ThemeMode, CustomThemeColors } from '../../types';
11
-
12
- // Mock design system theme
13
- jest.mock('@umituz/react-native-design-system', () => ({
14
- useTheme: {
15
- getState: jest.fn(() => ({
16
- setThemeMode: jest.fn(),
17
- })),
18
- },
19
- useDesignSystemTheme: {
20
- getState: jest.fn(() => ({
21
- setThemeMode: jest.fn(),
22
- setCustomColors: jest.fn(),
23
- })),
24
- },
25
- }));
26
-
27
- // Mock storage
28
- jest.mock('../../infrastructure/storage/appearanceStorage', () => ({
29
- AppearanceStorage: {
30
- getSettings: jest.fn(() => Promise.resolve(null)),
31
- setSettings: jest.fn(() => Promise.resolve()),
32
- clear: jest.fn(() => Promise.resolve()),
33
- },
34
- }));
35
-
36
- const mockUseTheme = require('@umituz/react-native-design-system').useTheme;
37
- const mockUseDesignSystemTheme = require('@umituz/react-native-design-system').useDesignSystemTheme;
38
- const mockAppearanceStorage = require('../../infrastructure/storage/appearanceStorage').AppearanceStorage;
39
-
40
- describe('Appearance Integration Tests', () => {
41
- beforeEach(() => {
42
- jest.clearAllMocks();
43
- });
44
-
45
- afterEach(() => {
46
- jest.restoreAllMocks();
47
- });
48
-
49
- it('should initialize and render correctly', async () => {
50
- const { getByTestId } = render(<AppearanceScreen />);
51
-
52
- // Should render without crashing
53
- expect(getByTestId('appearance-screen')).toBeTruthy();
54
-
55
- // Should initialize service
56
- await act(async () => {
57
- await appearanceService.initialize();
58
- });
59
-
60
- expect(mockAppearanceStorage.getSettings).toHaveBeenCalled();
61
- expect(mockUseTheme.getState().setThemeMode).toHaveBeenCalled();
62
- expect(mockUseDesignSystemTheme.getState().setThemeMode).toHaveBeenCalled();
63
- });
64
-
65
- it('should handle theme mode changes end-to-end', async () => {
66
- const { getByTestId } = render(<AppearanceScreen />);
67
-
68
- // Initialize service
69
- await act(async () => {
70
- await appearanceService.initialize();
71
- });
72
-
73
- // Change theme mode
74
- await act(async () => {
75
- await appearanceService.setThemeMode('light');
76
- });
77
-
78
- // Verify all systems are updated
79
- expect(mockUseTheme.getState().setThemeMode).toHaveBeenCalledWith('light');
80
- expect(mockUseDesignSystemTheme.getState().setThemeMode).toHaveBeenCalledWith('light');
81
- expect(mockAppearanceStorage.setSettings).toHaveBeenCalledWith({
82
- themeMode: 'light',
83
- });
84
- });
85
-
86
- it('should handle custom color changes end-to-end', async () => {
87
- const { getByTestId } = render(<AppearanceScreen />);
88
-
89
- // Initialize service
90
- await act(async () => {
91
- await appearanceService.initialize();
92
- });
93
-
94
- // Change custom colors
95
- const newColors: CustomThemeColors = {
96
- primary: '#FF0000',
97
- secondary: '#00FF00',
98
- };
99
-
100
- await act(async () => {
101
- await appearanceService.setCustomColors(newColors);
102
- });
103
-
104
- // Verify all systems are updated
105
- expect(mockUseDesignSystemTheme.getState().setCustomColors).toHaveBeenCalledWith(newColors);
106
- expect(mockAppearanceStorage.setSettings).toHaveBeenCalledWith({
107
- themeMode: 'dark', // Default theme
108
- customColors: newColors,
109
- });
110
- });
111
-
112
- it('should handle reset end-to-end', async () => {
113
- const { getByTestId } = render(<AppearanceScreen />);
114
-
115
- // Initialize with custom settings
116
- await act(async () => {
117
- await appearanceService.setThemeMode('light');
118
- await appearanceService.setCustomColors({
119
- primary: '#FF0000',
120
- secondary: '#00FF00',
121
- });
122
- });
123
-
124
- // Reset everything
125
- await act(async () => {
126
- await appearanceService.reset();
127
- });
128
-
129
- // Verify reset
130
- expect(mockAppearanceStorage.clear).toHaveBeenCalled();
131
- expect(mockUseTheme.getState().setThemeMode).toHaveBeenCalledWith('dark');
132
- expect(mockUseDesignSystemTheme.getState().setThemeMode).toHaveBeenCalledWith('dark');
133
- expect(mockUseDesignSystemTheme.getState().setCustomColors).toHaveBeenCalledWith(undefined);
134
- });
135
-
136
- it('should handle errors gracefully', async () => {
137
- const { getByTestId } = render(<AppearanceScreen />);
138
-
139
- // Mock storage to throw error
140
- mockAppearanceStorage.setSettings.mockRejectedValue(new Error('Storage failed'));
141
-
142
- // Should still render without crashing
143
- expect(getByTestId('appearance-screen')).toBeTruthy();
144
-
145
- // Should handle error gracefully
146
- await act(async () => {
147
- await appearanceService.setThemeMode('light');
148
- });
149
-
150
- // Should still attempt to update despite storage error
151
- expect(mockUseTheme.getState().setThemeMode).toHaveBeenCalled();
152
- });
153
-
154
- it('should prevent memory leaks during rapid updates', async () => {
155
- const { getByTestId } = render(<AppearanceScreen />);
156
-
157
- // Initialize service
158
- await act(async () => {
159
- await appearanceService.initialize();
160
- });
161
-
162
- // Rapid theme changes
163
- const promises = [];
164
- for (let i = 0; i < 10; i++) {
165
- promises.push(
166
- act(async () => {
167
- await appearanceService.setThemeMode(i % 2 === 0 ? 'light' : 'dark');
168
- })
169
- );
170
- }
171
-
172
- await Promise.all(promises);
173
-
174
- // Should handle rapid changes without memory leaks
175
- expect(getByTestId('appearance-screen')).toBeTruthy();
176
-
177
- // Verify final state
178
- const finalTheme = i % 2 === 0 ? 'dark' : 'light';
179
- expect(mockUseTheme.getState().setThemeMode).toHaveBeenLastCalledWith(finalTheme);
180
- });
181
-
182
- it('should maintain performance during heavy usage', async () => {
183
- const { getByTestId } = render(<AppearanceScreen />);
184
-
185
- const startTime = performance.now();
186
-
187
- // Heavy usage simulation
188
- await act(async () => {
189
- await appearanceService.initialize();
190
-
191
- // Rapid color changes
192
- for (let i = 0; i < 20; i++) {
193
- const colors: CustomThemeColors = {
194
- primary: `#${i.toString(16).padStart(6, '0')}`,
195
- };
196
- await appearanceService.setCustomColors(colors);
197
- }
198
- });
199
-
200
- const endTime = performance.now();
201
- const duration = endTime - startTime;
202
-
203
- // Should complete within reasonable time
204
- expect(duration).toBeLessThan(1000); // 1 second for 20 color changes
205
- expect(getByTestId('appearance-screen')).toBeTruthy();
206
- });
207
- });