@umituz/react-native-settings 2.0.0 → 2.4.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.
- package/README.md +129 -3
- package/lib/__tests__/setup.d.ts +5 -0
- package/lib/__tests__/setup.d.ts.map +1 -0
- package/lib/__tests__/setup.js +143 -0
- package/lib/__tests__/setup.js.map +1 -0
- package/lib/domain/repositories/ISettingsRepository.d.ts +51 -0
- package/lib/domain/repositories/ISettingsRepository.d.ts.map +1 -0
- package/lib/domain/repositories/ISettingsRepository.js +8 -0
- package/lib/domain/repositories/ISettingsRepository.js.map +1 -0
- package/lib/index.d.ts +35 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +32 -0
- package/lib/index.js.map +1 -0
- package/lib/infrastructure/storage/SettingsStore.d.ts +36 -0
- package/lib/infrastructure/storage/SettingsStore.d.ts.map +1 -0
- package/lib/infrastructure/storage/SettingsStore.js +144 -0
- package/lib/infrastructure/storage/SettingsStore.js.map +1 -0
- package/lib/presentation/components/CloudSyncSetting.d.ts +16 -0
- package/lib/presentation/components/CloudSyncSetting.d.ts.map +1 -0
- package/lib/presentation/components/CloudSyncSetting.js +30 -0
- package/lib/presentation/components/CloudSyncSetting.js.map +1 -0
- package/lib/presentation/components/DisclaimerCard.d.ts +15 -0
- package/lib/presentation/components/DisclaimerCard.d.ts.map +1 -0
- package/lib/presentation/components/DisclaimerCard.js +73 -0
- package/lib/presentation/components/DisclaimerCard.js.map +1 -0
- package/lib/presentation/components/DisclaimerModal.d.ts +13 -0
- package/lib/presentation/components/DisclaimerModal.d.ts.map +1 -0
- package/lib/presentation/components/DisclaimerModal.js +62 -0
- package/lib/presentation/components/DisclaimerModal.js.map +1 -0
- package/lib/presentation/components/DisclaimerSetting.d.ts +39 -0
- package/lib/presentation/components/DisclaimerSetting.d.ts.map +1 -0
- package/lib/presentation/components/DisclaimerSetting.js +59 -0
- package/lib/presentation/components/DisclaimerSetting.js.map +1 -0
- package/lib/presentation/components/SettingItem.d.ts +45 -0
- package/lib/presentation/components/SettingItem.d.ts.map +1 -0
- package/lib/presentation/components/SettingItem.js +113 -0
- package/lib/presentation/components/SettingItem.js.map +1 -0
- package/lib/presentation/components/SettingsErrorBoundary.d.ts +23 -0
- package/lib/presentation/components/SettingsErrorBoundary.d.ts.map +1 -0
- package/lib/presentation/components/SettingsErrorBoundary.js +73 -0
- package/lib/presentation/components/SettingsErrorBoundary.js.map +1 -0
- package/lib/presentation/components/SettingsFooter.d.ts +11 -0
- package/lib/presentation/components/SettingsFooter.d.ts.map +1 -0
- package/lib/presentation/components/SettingsFooter.js +31 -0
- package/lib/presentation/components/SettingsFooter.js.map +1 -0
- package/lib/presentation/components/SettingsSection.d.ts +13 -0
- package/lib/presentation/components/SettingsSection.d.ts.map +1 -0
- package/lib/presentation/components/SettingsSection.js +37 -0
- package/lib/presentation/components/SettingsSection.js.map +1 -0
- package/lib/presentation/components/StorageClearSetting.d.ts +16 -0
- package/lib/presentation/components/StorageClearSetting.d.ts.map +1 -0
- package/lib/presentation/components/StorageClearSetting.js +21 -0
- package/lib/presentation/components/StorageClearSetting.js.map +1 -0
- package/lib/presentation/components/UserProfileHeader.d.ts +30 -0
- package/lib/presentation/components/UserProfileHeader.d.ts.map +1 -0
- package/lib/presentation/components/UserProfileHeader.js +119 -0
- package/lib/presentation/components/UserProfileHeader.js.map +1 -0
- package/lib/presentation/screens/AppearanceScreen.d.ts +8 -0
- package/lib/presentation/screens/AppearanceScreen.d.ts.map +1 -0
- package/lib/presentation/screens/AppearanceScreen.js +8 -0
- package/lib/presentation/screens/AppearanceScreen.js.map +1 -0
- package/lib/presentation/screens/SettingsScreen.d.ts +38 -0
- package/lib/presentation/screens/SettingsScreen.d.ts.map +1 -0
- package/lib/presentation/screens/SettingsScreen.js +37 -0
- package/lib/presentation/screens/SettingsScreen.js.map +1 -0
- package/lib/presentation/screens/components/AboutLegalSection.d.ts +15 -0
- package/lib/presentation/screens/components/AboutLegalSection.d.ts.map +1 -0
- package/lib/presentation/screens/components/AboutLegalSection.js +28 -0
- package/lib/presentation/screens/components/AboutLegalSection.js.map +1 -0
- package/lib/presentation/screens/components/AppearanceSection.d.ts +12 -0
- package/lib/presentation/screens/components/AppearanceSection.d.ts.map +1 -0
- package/lib/presentation/screens/components/AppearanceSection.js +21 -0
- package/lib/presentation/screens/components/AppearanceSection.js.map +1 -0
- package/lib/presentation/screens/components/LanguageSection.d.ts +12 -0
- package/lib/presentation/screens/components/LanguageSection.d.ts.map +1 -0
- package/lib/presentation/screens/components/LanguageSection.js +26 -0
- package/lib/presentation/screens/components/LanguageSection.js.map +1 -0
- package/lib/presentation/screens/components/NotificationsSection.d.ts +12 -0
- package/lib/presentation/screens/components/NotificationsSection.d.ts.map +1 -0
- package/lib/presentation/screens/components/NotificationsSection.js +58 -0
- package/lib/presentation/screens/components/NotificationsSection.js.map +1 -0
- package/lib/presentation/screens/components/SettingsContent.d.ts +36 -0
- package/lib/presentation/screens/components/SettingsContent.d.ts.map +1 -0
- package/lib/presentation/screens/components/SettingsContent.js +81 -0
- package/lib/presentation/screens/components/SettingsContent.js.map +1 -0
- package/lib/presentation/screens/components/SettingsHeader.d.ts +12 -0
- package/lib/presentation/screens/components/SettingsHeader.d.ts.map +1 -0
- package/lib/presentation/screens/components/SettingsHeader.js +59 -0
- package/lib/presentation/screens/components/SettingsHeader.js.map +1 -0
- package/lib/presentation/screens/components/index.d.ts +9 -0
- package/lib/presentation/screens/components/index.d.ts.map +1 -0
- package/lib/presentation/screens/components/index.js +9 -0
- package/lib/presentation/screens/components/index.js.map +1 -0
- package/lib/presentation/screens/hooks/useFeatureDetection.d.ts +21 -0
- package/lib/presentation/screens/hooks/useFeatureDetection.d.ts.map +1 -0
- package/lib/presentation/screens/hooks/useFeatureDetection.js +82 -0
- package/lib/presentation/screens/hooks/useFeatureDetection.js.map +1 -0
- package/lib/presentation/screens/types/CustomSection.d.ts +19 -0
- package/lib/presentation/screens/types/CustomSection.d.ts.map +1 -0
- package/lib/presentation/screens/types/CustomSection.js +6 -0
- package/lib/presentation/screens/types/CustomSection.js.map +1 -0
- package/lib/presentation/screens/types/ExtendedConfig.d.ts +68 -0
- package/lib/presentation/screens/types/ExtendedConfig.d.ts.map +1 -0
- package/lib/presentation/screens/types/ExtendedConfig.js +6 -0
- package/lib/presentation/screens/types/ExtendedConfig.js.map +1 -0
- package/lib/presentation/screens/types/FeatureConfig.d.ts +95 -0
- package/lib/presentation/screens/types/FeatureConfig.d.ts.map +1 -0
- package/lib/presentation/screens/types/FeatureConfig.js +6 -0
- package/lib/presentation/screens/types/FeatureConfig.js.map +1 -0
- package/lib/presentation/screens/types/SettingsConfig.d.ts +97 -0
- package/lib/presentation/screens/types/SettingsConfig.d.ts.map +1 -0
- package/lib/presentation/screens/types/SettingsConfig.js +6 -0
- package/lib/presentation/screens/types/SettingsConfig.js.map +1 -0
- package/lib/presentation/screens/types/index.d.ts +10 -0
- package/lib/presentation/screens/types/index.d.ts.map +1 -0
- package/lib/presentation/screens/types/index.js +6 -0
- package/lib/presentation/screens/types/index.js.map +1 -0
- package/lib/presentation/screens/utils/normalizeConfig.d.ts +44 -0
- package/lib/presentation/screens/utils/normalizeConfig.d.ts.map +1 -0
- package/lib/presentation/screens/utils/normalizeConfig.js +38 -0
- package/lib/presentation/screens/utils/normalizeConfig.js.map +1 -0
- package/package.json +46 -11
- package/src/__tests__/integration.test.tsx +371 -0
- package/src/__tests__/performance.test.tsx +369 -0
- package/src/__tests__/setup.test.tsx +20 -0
- package/src/__tests__/setup.ts +157 -0
- package/src/index.ts +9 -0
- package/src/infrastructure/storage/SettingsStore.ts +90 -45
- package/src/infrastructure/storage/__tests__/SettingsStore.test.tsx +302 -0
- package/src/presentation/components/CloudSyncSetting.tsx +11 -17
- package/src/presentation/components/DisclaimerCard.tsx +115 -0
- package/src/presentation/components/DisclaimerModal.tsx +104 -0
- package/src/presentation/components/DisclaimerSetting.tsx +77 -159
- package/src/presentation/components/SettingItem.tsx +11 -2
- package/src/presentation/components/SettingsErrorBoundary.tsx +126 -0
- package/src/presentation/components/StorageClearSetting.tsx +13 -8
- package/src/presentation/components/UserProfileHeader.tsx +48 -11
- package/src/presentation/components/__tests__/CloudSyncSetting.test.tsx +78 -0
- package/src/presentation/components/__tests__/DisclaimerCard.test.tsx +208 -0
- package/src/presentation/components/__tests__/DisclaimerModal.test.tsx +236 -0
- package/src/presentation/components/__tests__/DisclaimerSetting.test.tsx +74 -0
- package/src/presentation/components/__tests__/SettingItem.test.tsx +189 -0
- package/src/presentation/components/__tests__/SettingsErrorBoundary.test.tsx +186 -0
- package/src/presentation/screens/SettingsScreen.tsx +29 -159
- package/src/presentation/screens/__tests__/SettingsScreen.test.tsx +322 -0
- package/src/presentation/screens/components/AboutLegalSection.tsx +14 -5
- package/src/presentation/screens/components/AppearanceSection.tsx +1 -1
- package/src/presentation/screens/components/LanguageSection.tsx +2 -1
- package/src/presentation/screens/components/NotificationsSection.tsx +19 -14
- package/src/presentation/screens/components/SettingsContent.tsx +167 -0
- package/src/presentation/screens/components/SettingsHeader.tsx +79 -0
- package/src/presentation/screens/hooks/__tests__/useFeatureDetection.test.tsx +261 -0
- package/src/presentation/screens/hooks/useFeatureDetection.ts +15 -5
- package/src/presentation/screens/types/CustomSection.ts +20 -0
- package/src/presentation/screens/types/ExtendedConfig.ts +68 -0
- package/src/presentation/screens/types/FeatureConfig.ts +102 -0
- package/src/presentation/screens/types/SettingsConfig.ts +116 -0
- package/src/presentation/screens/types/index.ts +20 -0
- package/src/presentation/screens/utils/normalizeConfig.ts +2 -1
- package/src/presentation/screens/types.ts +0 -263
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ npm install @umituz/react-native-settings
|
|
|
20
20
|
## Peer Dependencies
|
|
21
21
|
|
|
22
22
|
```bash
|
|
23
|
-
npm install zustand lucide-react-native @umituz/react-native-storage @umituz/react-native-design-system @umituz/react-native-design-system-theme @umituz/react-native-localization @umituz/react-native-
|
|
23
|
+
npm install zustand lucide-react-native @umituz/react-native-storage @umituz/react-native-design-system @umituz/react-native-design-system-atoms @umituz/react-native-design-system-organisms @umituz/react-native-design-system-theme @umituz/react-native-localization @umituz/react-native-appearance @react-navigation/native react-native-safe-area-context expo-linear-gradient
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
## Usage
|
|
@@ -179,8 +179,51 @@ import { SettingsFooter } from '@umituz/react-native-settings';
|
|
|
179
179
|
```tsx
|
|
180
180
|
import { DisclaimerSetting } from '@umituz/react-native-settings';
|
|
181
181
|
|
|
182
|
-
//
|
|
182
|
+
// Basic usage with translation keys
|
|
183
183
|
<DisclaimerSetting />
|
|
184
|
+
|
|
185
|
+
// Custom props
|
|
186
|
+
<DisclaimerSetting
|
|
187
|
+
titleKey="custom.disclaimer.title"
|
|
188
|
+
messageKey="custom.disclaimer.message"
|
|
189
|
+
shortMessageKey="custom.disclaimer.shortMessage"
|
|
190
|
+
iconName="Info"
|
|
191
|
+
iconColor="#F59E0B"
|
|
192
|
+
modalTitle="Custom Disclaimer"
|
|
193
|
+
modalContent="This is a custom disclaimer message for your app."
|
|
194
|
+
/>
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Cloud Sync Setting Component
|
|
198
|
+
|
|
199
|
+
```tsx
|
|
200
|
+
import { CloudSyncSetting } from '@umituz/react-native-settings';
|
|
201
|
+
|
|
202
|
+
// Basic usage
|
|
203
|
+
<CloudSyncSetting />
|
|
204
|
+
|
|
205
|
+
// With custom props
|
|
206
|
+
<CloudSyncSetting
|
|
207
|
+
title="Cloud Sync"
|
|
208
|
+
description="Sync your data across devices"
|
|
209
|
+
isSyncing={false}
|
|
210
|
+
lastSynced={new Date()}
|
|
211
|
+
onPress={() => handleSync()}
|
|
212
|
+
iconColor="#3B82F6"
|
|
213
|
+
/>
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Settings Error Boundary
|
|
217
|
+
|
|
218
|
+
```tsx
|
|
219
|
+
import { SettingsErrorBoundary } from '@umituz/react-native-settings';
|
|
220
|
+
|
|
221
|
+
<SettingsErrorBoundary
|
|
222
|
+
fallbackTitle="custom.error.title"
|
|
223
|
+
fallbackMessage="custom.error.message"
|
|
224
|
+
>
|
|
225
|
+
<YourSettingsComponents />
|
|
226
|
+
</SettingsErrorBoundary>
|
|
184
227
|
```
|
|
185
228
|
|
|
186
229
|
## API Reference
|
|
@@ -266,7 +309,48 @@ Footer component displaying app version.
|
|
|
266
309
|
|
|
267
310
|
### `DisclaimerSetting`
|
|
268
311
|
|
|
269
|
-
Disclaimer component
|
|
312
|
+
Disclaimer component with modal display for legal notices.
|
|
313
|
+
|
|
314
|
+
**Props:**
|
|
315
|
+
- `titleKey?: string` - Translation key for title (default: "settings.disclaimer.title")
|
|
316
|
+
- `messageKey?: string` - Translation key for message (default: "settings.disclaimer.message")
|
|
317
|
+
- `shortMessageKey?: string` - Translation key for short message (default: "settings.disclaimer.shortMessage")
|
|
318
|
+
- `iconName?: string` - Icon name (default: "AlertTriangle")
|
|
319
|
+
- `iconColor?: string` - Custom icon color
|
|
320
|
+
- `backgroundColor?: string` - Custom background color
|
|
321
|
+
- `modalTitle?: string` - Custom modal title (overrides translation)
|
|
322
|
+
- `modalContent?: string` - Custom modal content (overrides translation)
|
|
323
|
+
|
|
324
|
+
### `CloudSyncSetting`
|
|
325
|
+
|
|
326
|
+
Cloud sync setting component with status display.
|
|
327
|
+
|
|
328
|
+
**Props:**
|
|
329
|
+
- `title?: string` - Custom title (default: "cloud_sync" translation key)
|
|
330
|
+
- `description?: string` - Custom description
|
|
331
|
+
- `isSyncing?: boolean` - Whether currently syncing
|
|
332
|
+
- `lastSynced?: Date | null` - Last sync time
|
|
333
|
+
- `onPress?: () => void` - Press handler
|
|
334
|
+
- `iconColor?: string` - Custom icon color
|
|
335
|
+
- `titleColor?: string` - Custom title color
|
|
336
|
+
|
|
337
|
+
### `DisclaimerCard`
|
|
338
|
+
|
|
339
|
+
Card component for disclaimer display (used internally by DisclaimerSetting).
|
|
340
|
+
|
|
341
|
+
### `DisclaimerModal`
|
|
342
|
+
|
|
343
|
+
Modal component for full disclaimer display (used internally by DisclaimerSetting).
|
|
344
|
+
|
|
345
|
+
### `SettingsErrorBoundary`
|
|
346
|
+
|
|
347
|
+
Error boundary component for settings screens.
|
|
348
|
+
|
|
349
|
+
**Props:**
|
|
350
|
+
- `children: ReactNode` - Child components
|
|
351
|
+
- `fallback?: ReactNode` - Custom fallback component
|
|
352
|
+
- `fallbackTitle?: string` - Custom error title translation key
|
|
353
|
+
- `fallbackMessage?: string` - Custom error message translation key
|
|
270
354
|
|
|
271
355
|
## Types
|
|
272
356
|
|
|
@@ -300,6 +384,48 @@ interface UserSettings {
|
|
|
300
384
|
|
|
301
385
|
⚠️ **Translations**: Settings screens require i18n translations. Make sure to provide translations for settings keys.
|
|
302
386
|
|
|
387
|
+
⚠️ **Dynamic Text**: All text in this package uses translation keys to be app-agnostic. Provide translations like:
|
|
388
|
+
- `cloud_sync`, `syncing`, `sync_to_cloud`, `never_synced`, `just_now`, `Xm_ago`, `Xh_ago`, `Xd_ago`
|
|
389
|
+
- `error_boundary.title`, `error_boundary.message`, `error_boundary.dev_title`, `error_boundary.dev_message`
|
|
390
|
+
- `settings.disclaimer.title`, `settings.disclaimer.message`, `settings.disclaimer.shortMessage`
|
|
391
|
+
|
|
392
|
+
⚠️ **Design System**: Uses @umituz/react-native-design-system packages for consistent styling across apps.
|
|
393
|
+
|
|
394
|
+
⚠️ **Development Logs**: All console logs are wrapped in `__DEV__` checks for production safety.
|
|
395
|
+
|
|
396
|
+
## Architecture
|
|
397
|
+
|
|
398
|
+
This package follows **Domain-Driven Design (DDD)** principles:
|
|
399
|
+
|
|
400
|
+
- **Domain Layer**: Repository interfaces and business entities
|
|
401
|
+
- **Infrastructure Layer**: Storage implementation with Zustand
|
|
402
|
+
- **Presentation Layer**: UI components and screens
|
|
403
|
+
|
|
404
|
+
### Key Principles
|
|
405
|
+
|
|
406
|
+
✅ **SOLID**: Single responsibility, open/closed, Liskov substitution, interface segregation, dependency inversion
|
|
407
|
+
✅ **DRY**: No code duplication, reusable components
|
|
408
|
+
✅ **KISS**: Simple, maintainable code
|
|
409
|
+
✅ **200-line limit**: All files under 200 lines for maintainability
|
|
410
|
+
✅ **TypeScript**: Full type safety
|
|
411
|
+
✅ **Memory Leak Prevention**: Proper cleanup and error handling
|
|
412
|
+
✅ **App-Agnostic**: No hardcoded app-specific text or logic
|
|
413
|
+
✅ **Test Coverage**: Comprehensive test suite
|
|
414
|
+
|
|
415
|
+
## Performance
|
|
416
|
+
|
|
417
|
+
- ✅ **Optimized Rendering**: React.memo and useMemo where appropriate
|
|
418
|
+
- ✅ **Memory Management**: Proper cleanup in useEffect hooks
|
|
419
|
+
- ✅ **Error Boundaries**: Prevent crashes and provide graceful fallbacks
|
|
420
|
+
- ✅ **Development Logs**: __DEV__ only logging for production safety
|
|
421
|
+
|
|
422
|
+
## Version History
|
|
423
|
+
|
|
424
|
+
- **v2.2.0**: Major refactor - removed hardcoded text, improved architecture, added comprehensive tests
|
|
425
|
+
- **v2.1.0**: Enhanced component structure and TypeScript support
|
|
426
|
+
- **v2.0.0**: Breaking changes - removed LanguageSelectionScreen, improved API
|
|
427
|
+
- **v1.x.x**: Initial releases with basic settings functionality
|
|
428
|
+
|
|
303
429
|
## License
|
|
304
430
|
|
|
305
431
|
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/__tests__/setup.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Jest Test Setup
|
|
3
|
+
* Mock all external dependencies
|
|
4
|
+
*/
|
|
5
|
+
// Mock React Native modules
|
|
6
|
+
jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper');
|
|
7
|
+
// Mock design system packages
|
|
8
|
+
jest.mock('@umituz/react-native-design-system-theme', () => ({
|
|
9
|
+
useDesignSystemTheme: () => ({
|
|
10
|
+
themeMode: 'light',
|
|
11
|
+
}),
|
|
12
|
+
useAppDesignTokens: () => ({
|
|
13
|
+
colors: {
|
|
14
|
+
backgroundPrimary: '#ffffff',
|
|
15
|
+
primary: '#007AFF',
|
|
16
|
+
textPrimary: '#000000',
|
|
17
|
+
textSecondary: '#666666',
|
|
18
|
+
surface: '#f5f5f5',
|
|
19
|
+
borderLight: '#e0e0e0',
|
|
20
|
+
warning: '#FF9800',
|
|
21
|
+
},
|
|
22
|
+
spacing: {
|
|
23
|
+
md: 16,
|
|
24
|
+
},
|
|
25
|
+
typography: {
|
|
26
|
+
labelLarge: {
|
|
27
|
+
fontWeight: '500',
|
|
28
|
+
fontSize: 14,
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
}),
|
|
32
|
+
withAlpha: jest.fn((color, alpha) => `${color}${alpha}`),
|
|
33
|
+
}));
|
|
34
|
+
jest.mock('@umituz/react-native-design-system-atoms', () => ({
|
|
35
|
+
AtomicText: ({ children, type, color, style, testID }) => {
|
|
36
|
+
const React = require('react');
|
|
37
|
+
const { Text } = require('react-native');
|
|
38
|
+
return React.createElement(Text, {
|
|
39
|
+
style,
|
|
40
|
+
testID: testID || `atomic-text-${type}-${color}`
|
|
41
|
+
}, children);
|
|
42
|
+
},
|
|
43
|
+
AtomicIcon: ({ name, color, size, style, testID }) => {
|
|
44
|
+
const React = require('react');
|
|
45
|
+
const { Text } = require('react-native');
|
|
46
|
+
return React.createElement(Text, {
|
|
47
|
+
style,
|
|
48
|
+
testID: testID || `atomic-icon-${name}-${color}-${size}`
|
|
49
|
+
}, `Icon: ${name}`);
|
|
50
|
+
},
|
|
51
|
+
}));
|
|
52
|
+
// Mock localization
|
|
53
|
+
jest.mock('@umituz/react-native-localization', () => ({
|
|
54
|
+
useLocalization: () => ({
|
|
55
|
+
t: (key) => key,
|
|
56
|
+
changeLanguage: jest.fn(),
|
|
57
|
+
currentLanguage: 'en-US',
|
|
58
|
+
}),
|
|
59
|
+
}));
|
|
60
|
+
// Mock storage
|
|
61
|
+
jest.mock('@umituz/react-native-storage', () => ({
|
|
62
|
+
storageRepository: {
|
|
63
|
+
getItem: jest.fn(),
|
|
64
|
+
setItem: jest.fn(),
|
|
65
|
+
removeItem: jest.fn(),
|
|
66
|
+
clear: jest.fn(),
|
|
67
|
+
},
|
|
68
|
+
StorageKey: {
|
|
69
|
+
SETTINGS: 'settings',
|
|
70
|
+
},
|
|
71
|
+
createUserKey: (key, userId) => `${key}_${userId}`,
|
|
72
|
+
unwrap: (result, defaultValue) => result.success ? result.data : defaultValue,
|
|
73
|
+
}));
|
|
74
|
+
// Mock lucide-react-native
|
|
75
|
+
jest.mock('lucide-react-native', () => ({
|
|
76
|
+
Cloud: 'Cloud',
|
|
77
|
+
Bell: 'Bell',
|
|
78
|
+
Palette: 'Palette',
|
|
79
|
+
ChevronRight: 'ChevronRight',
|
|
80
|
+
AlertTriangle: 'AlertTriangle',
|
|
81
|
+
Info: 'Info',
|
|
82
|
+
X: 'X',
|
|
83
|
+
ArrowRight: 'ArrowRight',
|
|
84
|
+
Settings: 'Settings',
|
|
85
|
+
}));
|
|
86
|
+
// Mock navigation
|
|
87
|
+
jest.mock('@react-navigation/native', () => ({
|
|
88
|
+
useNavigation: () => ({
|
|
89
|
+
navigate: jest.fn(),
|
|
90
|
+
goBack: jest.fn(),
|
|
91
|
+
getState: jest.fn(() => ({
|
|
92
|
+
routes: [{ name: 'Settings' }],
|
|
93
|
+
})),
|
|
94
|
+
setOptions: jest.fn(),
|
|
95
|
+
isFocused: jest.fn(() => true),
|
|
96
|
+
addListener: jest.fn(() => jest.fn()),
|
|
97
|
+
removeListener: jest.fn(),
|
|
98
|
+
}),
|
|
99
|
+
useFocusEffect: jest.fn(),
|
|
100
|
+
useIsFocused: jest.fn(() => true),
|
|
101
|
+
NavigationContainer: ({ children }) => children,
|
|
102
|
+
}));
|
|
103
|
+
// Mock safe area context
|
|
104
|
+
jest.mock('react-native-safe-area-context', () => ({
|
|
105
|
+
SafeAreaProvider: ({ children }) => children,
|
|
106
|
+
SafeAreaView: ({ children }) => children,
|
|
107
|
+
useSafeAreaInsets: () => ({
|
|
108
|
+
top: 0,
|
|
109
|
+
bottom: 0,
|
|
110
|
+
left: 0,
|
|
111
|
+
right: 0,
|
|
112
|
+
}),
|
|
113
|
+
}));
|
|
114
|
+
// Mock linear gradient
|
|
115
|
+
jest.mock('expo-linear-gradient', () => ({
|
|
116
|
+
LinearGradient: ({ children }) => children,
|
|
117
|
+
}));
|
|
118
|
+
// Mock notification service
|
|
119
|
+
jest.mock('@umituz/react-native-notifications', () => ({
|
|
120
|
+
notificationService: {
|
|
121
|
+
hasPermissions: jest.fn(() => Promise.resolve(true)),
|
|
122
|
+
requestPermissions: jest.fn(() => Promise.resolve()),
|
|
123
|
+
},
|
|
124
|
+
}));
|
|
125
|
+
// Mock appearance
|
|
126
|
+
jest.mock('@umituz/react-native-appearance', () => ({
|
|
127
|
+
useAppearance: () => ({
|
|
128
|
+
colorScheme: 'light',
|
|
129
|
+
setColorScheme: jest.fn(),
|
|
130
|
+
}),
|
|
131
|
+
}));
|
|
132
|
+
// Mock console methods in tests
|
|
133
|
+
global.console = {
|
|
134
|
+
...console,
|
|
135
|
+
warn: jest.fn(),
|
|
136
|
+
error: jest.fn(),
|
|
137
|
+
};
|
|
138
|
+
// Set up __DEV__ mock
|
|
139
|
+
Object.defineProperty(global, '__DEV__', {
|
|
140
|
+
value: true,
|
|
141
|
+
writable: true,
|
|
142
|
+
});
|
|
143
|
+
//# sourceMappingURL=setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/__tests__/setup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings Repository Interface
|
|
3
|
+
*
|
|
4
|
+
* Defines contracts for settings persistence and retrieval
|
|
5
|
+
* Pure business logic - no dependencies on external frameworks
|
|
6
|
+
*/
|
|
7
|
+
export interface UserSettings {
|
|
8
|
+
userId: string;
|
|
9
|
+
theme: 'light' | 'dark' | 'auto';
|
|
10
|
+
language: string;
|
|
11
|
+
notificationsEnabled: boolean;
|
|
12
|
+
emailNotifications: boolean;
|
|
13
|
+
pushNotifications: boolean;
|
|
14
|
+
soundEnabled: boolean;
|
|
15
|
+
vibrationEnabled: boolean;
|
|
16
|
+
privacyMode: boolean;
|
|
17
|
+
updatedAt: Date;
|
|
18
|
+
}
|
|
19
|
+
export interface SettingsError extends Error {
|
|
20
|
+
code: 'LOAD_FAILED' | 'SAVE_FAILED' | 'NOT_FOUND' | 'INVALID_DATA';
|
|
21
|
+
}
|
|
22
|
+
export type SettingsResult<T> = {
|
|
23
|
+
success: true;
|
|
24
|
+
data: T;
|
|
25
|
+
} | {
|
|
26
|
+
success: false;
|
|
27
|
+
error: SettingsError;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Settings Repository Interface
|
|
31
|
+
* Repository pattern for settings management
|
|
32
|
+
*/
|
|
33
|
+
export interface ISettingsRepository {
|
|
34
|
+
/**
|
|
35
|
+
* Load user settings from persistent storage
|
|
36
|
+
*/
|
|
37
|
+
loadSettings(userId: string): Promise<SettingsResult<UserSettings>>;
|
|
38
|
+
/**
|
|
39
|
+
* Save user settings to persistent storage
|
|
40
|
+
*/
|
|
41
|
+
saveSettings(settings: Partial<UserSettings>): Promise<SettingsResult<UserSettings>>;
|
|
42
|
+
/**
|
|
43
|
+
* Reset settings to default values
|
|
44
|
+
*/
|
|
45
|
+
resetSettings(userId: string): Promise<SettingsResult<UserSettings>>;
|
|
46
|
+
/**
|
|
47
|
+
* Get default settings for a user
|
|
48
|
+
*/
|
|
49
|
+
getDefaultSettings(userId: string): UserSettings;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=ISettingsRepository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ISettingsRepository.d.ts","sourceRoot":"","sources":["../../../src/domain/repositories/ISettingsRepository.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,YAAY,EAAE,OAAO,CAAC;IACtB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,aAAc,SAAQ,KAAK;IAC1C,IAAI,EAAE,aAAa,GAAG,aAAa,GAAG,WAAW,GAAG,cAAc,CAAC;CACpE;AAED,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI;IAC9B,OAAO,EAAE,IAAI,CAAC;IACd,IAAI,EAAE,CAAC,CAAC;CACT,GAAG;IACF,OAAO,EAAE,KAAK,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;CACtB,CAAC;AAEF;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC;IAEpE;;OAEG;IACH,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC;IAErF;;OAEG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC;IAErE;;OAEG;IACH,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAAC;CAClD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ISettingsRepository.js","sourceRoot":"","sources":["../../../src/domain/repositories/ISettingsRepository.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @umituz/react-native-settings - Public API
|
|
3
|
+
*
|
|
4
|
+
* Settings management for React Native apps
|
|
5
|
+
* User preferences, theme, language, notifications
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* import { useSettings, useSettingsStore, SettingsScreen, AppearanceScreen, LanguageSelectionScreen, SettingItem, DisclaimerSetting } from '@umituz/react-native-settings';
|
|
9
|
+
*/
|
|
10
|
+
export type { ISettingsRepository, UserSettings, SettingsError, SettingsResult, } from './domain/repositories/ISettingsRepository';
|
|
11
|
+
export { useSettingsStore, useSettings, } from './infrastructure/storage/SettingsStore';
|
|
12
|
+
export { SettingsScreen } from './presentation/screens/SettingsScreen';
|
|
13
|
+
export type { SettingsScreenProps } from './presentation/screens/SettingsScreen';
|
|
14
|
+
export { AppearanceScreen } from './presentation/screens/AppearanceScreen';
|
|
15
|
+
export type { SettingsConfig, CustomSettingsSection } from './presentation/screens/types';
|
|
16
|
+
export { SettingItem } from './presentation/components/SettingItem';
|
|
17
|
+
export type { SettingItemProps } from './presentation/components/SettingItem';
|
|
18
|
+
export { SettingsSection } from './presentation/components/SettingsSection';
|
|
19
|
+
export type { SettingsSectionProps } from './presentation/components/SettingsSection';
|
|
20
|
+
export { SettingsFooter } from './presentation/components/SettingsFooter';
|
|
21
|
+
export type { SettingsFooterProps } from './presentation/components/SettingsFooter';
|
|
22
|
+
export { UserProfileHeader } from './presentation/components/UserProfileHeader';
|
|
23
|
+
export type { UserProfileHeaderProps } from './presentation/components/UserProfileHeader';
|
|
24
|
+
export { DisclaimerSetting } from './presentation/components/DisclaimerSetting';
|
|
25
|
+
export type { DisclaimerSettingProps } from './presentation/components/DisclaimerSetting';
|
|
26
|
+
export { DisclaimerCard } from './presentation/components/DisclaimerCard';
|
|
27
|
+
export type { DisclaimerCardProps } from './presentation/components/DisclaimerCard';
|
|
28
|
+
export { DisclaimerModal } from './presentation/components/DisclaimerModal';
|
|
29
|
+
export type { DisclaimerModalProps } from './presentation/components/DisclaimerModal';
|
|
30
|
+
export { SettingsErrorBoundary } from './presentation/components/SettingsErrorBoundary';
|
|
31
|
+
export { CloudSyncSetting } from './presentation/components/CloudSyncSetting';
|
|
32
|
+
export type { CloudSyncSettingProps } from './presentation/components/CloudSyncSetting';
|
|
33
|
+
export { StorageClearSetting } from './presentation/components/StorageClearSetting';
|
|
34
|
+
export type { StorageClearSettingProps } from './presentation/components/StorageClearSetting';
|
|
35
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,YAAY,EACV,mBAAmB,EACnB,YAAY,EACZ,aAAa,EACb,cAAc,GACf,MAAM,2CAA2C,CAAC;AAMnD,OAAO,EACL,gBAAgB,EAChB,WAAW,GACZ,MAAM,wCAAwC,CAAC;AAMhD,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AACvE,YAAY,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AACjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAM3E,YAAY,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAM1F,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAC;AACpE,YAAY,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAE9E,OAAO,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAC;AAC5E,YAAY,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEtF,OAAO,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAC;AAC1E,YAAY,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAC;AAEpF,OAAO,EAAE,iBAAiB,EAAE,MAAM,6CAA6C,CAAC;AAChF,YAAY,EAAE,sBAAsB,EAAE,MAAM,6CAA6C,CAAC;AAE1F,OAAO,EAAE,iBAAiB,EAAE,MAAM,6CAA6C,CAAC;AAChF,YAAY,EAAE,sBAAsB,EAAE,MAAM,6CAA6C,CAAC;AAE1F,OAAO,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAC;AAC1E,YAAY,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAC;AAEpF,OAAO,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAC;AAC5E,YAAY,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEtF,OAAO,EAAE,qBAAqB,EAAE,MAAM,iDAAiD,CAAC;AAExF,OAAO,EAAE,gBAAgB,EAAE,MAAM,4CAA4C,CAAC;AAC9E,YAAY,EAAE,qBAAqB,EAAE,MAAM,4CAA4C,CAAC;AAExF,OAAO,EAAE,mBAAmB,EAAE,MAAM,+CAA+C,CAAC;AACpF,YAAY,EAAE,wBAAwB,EAAE,MAAM,+CAA+C,CAAC"}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @umituz/react-native-settings - Public API
|
|
3
|
+
*
|
|
4
|
+
* Settings management for React Native apps
|
|
5
|
+
* User preferences, theme, language, notifications
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* import { useSettings, useSettingsStore, SettingsScreen, AppearanceScreen, LanguageSelectionScreen, SettingItem, DisclaimerSetting } from '@umituz/react-native-settings';
|
|
9
|
+
*/
|
|
10
|
+
// =============================================================================
|
|
11
|
+
// INFRASTRUCTURE LAYER - Storage
|
|
12
|
+
// =============================================================================
|
|
13
|
+
export { useSettingsStore, useSettings, } from './infrastructure/storage/SettingsStore';
|
|
14
|
+
// =============================================================================
|
|
15
|
+
// PRESENTATION LAYER - Screens
|
|
16
|
+
// =============================================================================
|
|
17
|
+
export { SettingsScreen } from './presentation/screens/SettingsScreen';
|
|
18
|
+
export { AppearanceScreen } from './presentation/screens/AppearanceScreen';
|
|
19
|
+
// =============================================================================
|
|
20
|
+
// PRESENTATION LAYER - Components
|
|
21
|
+
// =============================================================================
|
|
22
|
+
export { SettingItem } from './presentation/components/SettingItem';
|
|
23
|
+
export { SettingsSection } from './presentation/components/SettingsSection';
|
|
24
|
+
export { SettingsFooter } from './presentation/components/SettingsFooter';
|
|
25
|
+
export { UserProfileHeader } from './presentation/components/UserProfileHeader';
|
|
26
|
+
export { DisclaimerSetting } from './presentation/components/DisclaimerSetting';
|
|
27
|
+
export { DisclaimerCard } from './presentation/components/DisclaimerCard';
|
|
28
|
+
export { DisclaimerModal } from './presentation/components/DisclaimerModal';
|
|
29
|
+
export { SettingsErrorBoundary } from './presentation/components/SettingsErrorBoundary';
|
|
30
|
+
export { CloudSyncSetting } from './presentation/components/CloudSyncSetting';
|
|
31
|
+
export { StorageClearSetting } from './presentation/components/StorageClearSetting';
|
|
32
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAaH,gFAAgF;AAChF,iCAAiC;AACjC,gFAAgF;AAEhF,OAAO,EACL,gBAAgB,EAChB,WAAW,GACZ,MAAM,wCAAwC,CAAC;AAEhD,gFAAgF;AAChF,+BAA+B;AAC/B,gFAAgF;AAEhF,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAEvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAQ3E,gFAAgF;AAChF,kCAAkC;AAClC,gFAAgF;AAEhF,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAC;AAGpE,OAAO,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAC;AAG5E,OAAO,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAC;AAG1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,6CAA6C,CAAC;AAGhF,OAAO,EAAE,iBAAiB,EAAE,MAAM,6CAA6C,CAAC;AAGhF,OAAO,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAC;AAG1E,OAAO,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAC;AAG5E,OAAO,EAAE,qBAAqB,EAAE,MAAM,iDAAiD,CAAC;AAExF,OAAO,EAAE,gBAAgB,EAAE,MAAM,4CAA4C,CAAC;AAG9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,+CAA+C,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings Store - Zustand State Management
|
|
3
|
+
*
|
|
4
|
+
* Global settings state for app preferences
|
|
5
|
+
* Manages theme, language, notifications, and privacy settings
|
|
6
|
+
*
|
|
7
|
+
* DDD ARCHITECTURE: Uses @umituz/react-native-storage for all storage operations
|
|
8
|
+
* - Type-safe storage with StorageKey enum
|
|
9
|
+
* - Result pattern for error handling
|
|
10
|
+
* - Single source of truth for all storage
|
|
11
|
+
*/
|
|
12
|
+
import type { UserSettings } from '../../domain/repositories/ISettingsRepository';
|
|
13
|
+
interface SettingsStore {
|
|
14
|
+
settings: UserSettings | null;
|
|
15
|
+
loading: boolean;
|
|
16
|
+
error: string | null;
|
|
17
|
+
loadSettings: (userId: string) => Promise<void>;
|
|
18
|
+
updateSettings: (updates: Partial<UserSettings>) => Promise<void>;
|
|
19
|
+
resetSettings: (userId: string) => Promise<void>;
|
|
20
|
+
clearError: () => void;
|
|
21
|
+
}
|
|
22
|
+
export declare const useSettingsStore: import("zustand").UseBoundStore<import("zustand").StoreApi<SettingsStore>>;
|
|
23
|
+
/**
|
|
24
|
+
* Hook for accessing settings state
|
|
25
|
+
*/
|
|
26
|
+
export declare const useSettings: () => {
|
|
27
|
+
settings: UserSettings | null;
|
|
28
|
+
loading: boolean;
|
|
29
|
+
error: string | null;
|
|
30
|
+
loadSettings: (userId: string) => Promise<void>;
|
|
31
|
+
updateSettings: (updates: Partial<UserSettings>) => Promise<void>;
|
|
32
|
+
resetSettings: (userId: string) => Promise<void>;
|
|
33
|
+
clearError: () => void;
|
|
34
|
+
};
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=SettingsStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SettingsStore.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/storage/SettingsStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+CAA+C,CAAC;AAElF,UAAU,aAAa;IAErB,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAGrB,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,cAAc,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClE,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,UAAU,EAAE,MAAM,IAAI,CAAC;CACxB;AA4BD,eAAO,MAAM,gBAAgB,4EAiH1B,CAAC;AAEJ;;GAEG;AACH,eAAO,MAAM,WAAW;;;;2BAtJC,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC;8BACrB,OAAO,CAAC,YAAY,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC;4BACzC,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC;sBAC9B,IAAI;CAgKvB,CAAC"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings Store - Zustand State Management
|
|
3
|
+
*
|
|
4
|
+
* Global settings state for app preferences
|
|
5
|
+
* Manages theme, language, notifications, and privacy settings
|
|
6
|
+
*
|
|
7
|
+
* DDD ARCHITECTURE: Uses @umituz/react-native-storage for all storage operations
|
|
8
|
+
* - Type-safe storage with StorageKey enum
|
|
9
|
+
* - Result pattern for error handling
|
|
10
|
+
* - Single source of truth for all storage
|
|
11
|
+
*/
|
|
12
|
+
import { create } from 'zustand';
|
|
13
|
+
import { storageRepository, StorageKey, createUserKey, unwrap } from '@umituz/react-native-storage';
|
|
14
|
+
const DEFAULT_OFFLINE_USER_ID = 'offline_user';
|
|
15
|
+
const DEFAULT_SETTINGS_CACHE = new Map();
|
|
16
|
+
const getDefaultSettings = (userId) => {
|
|
17
|
+
if (DEFAULT_SETTINGS_CACHE.has(userId)) {
|
|
18
|
+
return DEFAULT_SETTINGS_CACHE.get(userId);
|
|
19
|
+
}
|
|
20
|
+
const settings = {
|
|
21
|
+
userId,
|
|
22
|
+
theme: 'auto',
|
|
23
|
+
language: 'en-US',
|
|
24
|
+
notificationsEnabled: true,
|
|
25
|
+
emailNotifications: true,
|
|
26
|
+
pushNotifications: true,
|
|
27
|
+
soundEnabled: true,
|
|
28
|
+
vibrationEnabled: true,
|
|
29
|
+
privacyMode: false,
|
|
30
|
+
updatedAt: new Date(),
|
|
31
|
+
};
|
|
32
|
+
DEFAULT_SETTINGS_CACHE.set(userId, settings);
|
|
33
|
+
return settings;
|
|
34
|
+
};
|
|
35
|
+
export const useSettingsStore = create((set, get) => ({
|
|
36
|
+
settings: null,
|
|
37
|
+
loading: false,
|
|
38
|
+
error: null,
|
|
39
|
+
loadSettings: async (userId) => {
|
|
40
|
+
if (__DEV__) {
|
|
41
|
+
console.log('SettingsStore: Loading settings for user:', userId);
|
|
42
|
+
}
|
|
43
|
+
set({ loading: true, error: null });
|
|
44
|
+
try {
|
|
45
|
+
const defaultSettings = getDefaultSettings(userId);
|
|
46
|
+
const storageKey = createUserKey(StorageKey.SETTINGS, userId);
|
|
47
|
+
// ✅ DRY: Storage domain handles JSON parse, error handling
|
|
48
|
+
const result = await storageRepository.getItem(storageKey, defaultSettings);
|
|
49
|
+
const data = unwrap(result, defaultSettings);
|
|
50
|
+
// ✅ CLEAN CODE: Auto-save defaults if not exists
|
|
51
|
+
if (!result.success) {
|
|
52
|
+
await storageRepository.setItem(storageKey, defaultSettings);
|
|
53
|
+
}
|
|
54
|
+
set({
|
|
55
|
+
settings: data,
|
|
56
|
+
loading: false,
|
|
57
|
+
error: null,
|
|
58
|
+
});
|
|
59
|
+
if (__DEV__) {
|
|
60
|
+
console.log('SettingsStore: Settings loaded successfully');
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
if (__DEV__) {
|
|
65
|
+
console.error('SettingsStore: Failed to load settings:', error);
|
|
66
|
+
}
|
|
67
|
+
set({ loading: false, error: 'Failed to load settings' });
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
updateSettings: async (updates) => {
|
|
71
|
+
if (__DEV__) {
|
|
72
|
+
console.log('SettingsStore: Updating settings with:', updates);
|
|
73
|
+
}
|
|
74
|
+
const { settings } = get();
|
|
75
|
+
// ✅ CLEAN CODE: Auto-initialize if settings not loaded
|
|
76
|
+
if (!settings) {
|
|
77
|
+
await get().loadSettings(DEFAULT_OFFLINE_USER_ID);
|
|
78
|
+
}
|
|
79
|
+
// ✅ DEFENSIVE: Verify settings loaded successfully
|
|
80
|
+
const currentSettings = get().settings;
|
|
81
|
+
if (!currentSettings) {
|
|
82
|
+
const errorMsg = 'Failed to initialize settings';
|
|
83
|
+
if (__DEV__) {
|
|
84
|
+
console.error('SettingsStore:', errorMsg);
|
|
85
|
+
}
|
|
86
|
+
set({ error: errorMsg });
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
set({ loading: true, error: null });
|
|
90
|
+
try {
|
|
91
|
+
const updatedSettings = {
|
|
92
|
+
...currentSettings,
|
|
93
|
+
...updates,
|
|
94
|
+
updatedAt: new Date(),
|
|
95
|
+
};
|
|
96
|
+
const storageKey = createUserKey(StorageKey.SETTINGS, currentSettings.userId);
|
|
97
|
+
// ✅ DRY: Storage domain replaces JSON.stringify + AsyncStorage + try/catch
|
|
98
|
+
const result = await storageRepository.setItem(storageKey, updatedSettings);
|
|
99
|
+
set({
|
|
100
|
+
settings: result.success ? updatedSettings : currentSettings,
|
|
101
|
+
loading: false,
|
|
102
|
+
error: null,
|
|
103
|
+
});
|
|
104
|
+
if (__DEV__) {
|
|
105
|
+
console.log('SettingsStore: Settings updated successfully');
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
if (__DEV__) {
|
|
110
|
+
console.error('SettingsStore: Failed to update settings:', error);
|
|
111
|
+
}
|
|
112
|
+
set({ loading: false, error: 'Failed to update settings' });
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
resetSettings: async (userId) => {
|
|
116
|
+
set({ loading: true, error: null });
|
|
117
|
+
const defaultSettings = getDefaultSettings(userId);
|
|
118
|
+
const storageKey = createUserKey(StorageKey.SETTINGS, userId);
|
|
119
|
+
// ✅ DRY: Storage domain replaces JSON.stringify + AsyncStorage + try/catch
|
|
120
|
+
const result = await storageRepository.setItem(storageKey, defaultSettings);
|
|
121
|
+
set({
|
|
122
|
+
settings: result.success ? defaultSettings : get().settings,
|
|
123
|
+
loading: false,
|
|
124
|
+
error: null,
|
|
125
|
+
});
|
|
126
|
+
},
|
|
127
|
+
clearError: () => set({ error: null }),
|
|
128
|
+
}));
|
|
129
|
+
/**
|
|
130
|
+
* Hook for accessing settings state
|
|
131
|
+
*/
|
|
132
|
+
export const useSettings = () => {
|
|
133
|
+
const { settings, loading, error, loadSettings, updateSettings, resetSettings, clearError } = useSettingsStore();
|
|
134
|
+
return {
|
|
135
|
+
settings,
|
|
136
|
+
loading,
|
|
137
|
+
error,
|
|
138
|
+
loadSettings,
|
|
139
|
+
updateSettings,
|
|
140
|
+
resetSettings,
|
|
141
|
+
clearError,
|
|
142
|
+
};
|
|
143
|
+
};
|
|
144
|
+
//# sourceMappingURL=SettingsStore.js.map
|