@umituz/react-native-settings 4.20.56 → 4.20.58
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 +146 -4
- package/package.json +1 -2
- package/src/__tests__/setup.ts +1 -4
- package/src/application/README.md +322 -0
- package/src/domains/about/README.md +452 -0
- package/src/domains/about/presentation/hooks/README.md +350 -0
- package/src/domains/appearance/README.md +596 -0
- package/src/domains/appearance/hooks/README.md +366 -0
- package/src/domains/appearance/infrastructure/services/README.md +455 -0
- package/src/domains/appearance/presentation/components/README.md +493 -0
- package/src/domains/cloud-sync/README.md +451 -0
- package/src/domains/cloud-sync/presentation/components/README.md +493 -0
- package/src/domains/dev/README.md +477 -0
- package/src/domains/disclaimer/README.md +421 -0
- package/src/domains/disclaimer/presentation/components/README.md +394 -0
- package/src/domains/faqs/README.md +586 -0
- package/src/domains/feedback/README.md +565 -0
- package/src/domains/feedback/presentation/hooks/README.md +428 -0
- package/src/domains/legal/README.md +549 -0
- package/src/domains/rating/README.md +452 -0
- package/src/domains/rating/presentation/components/README.md +475 -0
- package/src/domains/video-tutorials/README.md +482 -0
- package/src/domains/video-tutorials/presentation/components/README.md +433 -0
- package/src/infrastructure/README.md +509 -0
- package/src/infrastructure/repositories/README.md +475 -0
- package/src/infrastructure/services/README.md +510 -0
- package/src/presentation/components/README.md +482 -0
- package/src/presentation/components/SettingsErrorBoundary/README.md +455 -0
- package/src/presentation/components/SettingsFooter/README.md +446 -0
- package/src/presentation/components/SettingsItemCard/README.md +457 -0
- package/src/presentation/components/SettingsSection/README.md +421 -0
- package/src/presentation/hooks/README.md +413 -0
- package/src/presentation/hooks/mutations/README.md +430 -0
- package/src/presentation/hooks/queries/README.md +441 -0
- package/src/presentation/navigation/README.md +532 -0
- package/src/presentation/navigation/components/README.md +330 -0
- package/src/presentation/navigation/hooks/README.md +399 -0
- package/src/presentation/navigation/utils/README.md +442 -0
- package/src/presentation/screens/README.md +525 -0
- package/src/presentation/screens/components/SettingsContent/README.md +404 -0
- package/src/presentation/screens/components/SettingsHeader/README.md +322 -0
- package/src/presentation/screens/components/sections/CustomSettingsList/README.md +388 -0
- package/src/presentation/screens/components/sections/FeatureSettingsSection/README.md +232 -0
- package/src/presentation/screens/components/sections/IdentitySettingsSection/README.md +325 -0
- package/src/presentation/screens/components/sections/ProfileSectionLoader/README.md +480 -0
- package/src/presentation/screens/components/sections/SupportSettingsSection/README.md +391 -0
- package/src/presentation/screens/hooks/README.md +383 -0
- package/src/presentation/screens/types/README.md +439 -0
- package/src/presentation/screens/utils/README.md +288 -0
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
# Cloud Sync Domain
|
|
2
|
+
|
|
3
|
+
The Cloud Sync domain provides components for displaying and managing cloud synchronization status in your React Native app.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Sync Status Display**: Show current sync status with visual indicators
|
|
8
|
+
- **Last Synced Info**: Display relative time of last synchronization
|
|
9
|
+
- **Sync Progress**: Show syncing state during active synchronization
|
|
10
|
+
- **Interactive Sync**: Allow users to trigger manual sync
|
|
11
|
+
- **Customizable Messages**: Custom sync status descriptions
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
This domain is part of `@umituz/react-native-settings`. Install the package to use it:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @umituz/react-native-settings
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Components
|
|
22
|
+
|
|
23
|
+
### CloudSyncSetting
|
|
24
|
+
|
|
25
|
+
Display cloud sync status and allow triggering manual sync.
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
import { CloudSyncSetting } from '@umituz/react-native-settings';
|
|
29
|
+
|
|
30
|
+
function MySettings() {
|
|
31
|
+
const [isSyncing, setIsSyncing] = useState(false);
|
|
32
|
+
const [lastSynced, setLastSynced] = useState(new Date());
|
|
33
|
+
|
|
34
|
+
const handleSync = async () => {
|
|
35
|
+
setIsSyncing(true);
|
|
36
|
+
await performSync();
|
|
37
|
+
setIsSyncing(false);
|
|
38
|
+
setLastSynced(new Date());
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<CloudSyncSetting
|
|
43
|
+
isSyncing={isSyncing}
|
|
44
|
+
lastSynced={lastSynced}
|
|
45
|
+
onPress={handleSync}
|
|
46
|
+
/>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
#### Props
|
|
52
|
+
|
|
53
|
+
| Prop | Type | Default | Description |
|
|
54
|
+
|------|------|---------|-------------|
|
|
55
|
+
| `title` | `string` | `'cloud_sync'` | Setting title |
|
|
56
|
+
| `description` | `string` | `undefined` | Custom status description |
|
|
57
|
+
| `isSyncing` | `boolean` | `false` | Syncing state |
|
|
58
|
+
| `lastSynced` | `Date \| null` | `undefined` | Last sync timestamp |
|
|
59
|
+
| `onPress` | `() => void` | `undefined` | Press handler |
|
|
60
|
+
| `disabled` | `boolean` | `false` | Disable interaction |
|
|
61
|
+
|
|
62
|
+
#### Relative Time Display
|
|
63
|
+
|
|
64
|
+
The component automatically formats the `lastSynced` timestamp into relative time:
|
|
65
|
+
- `"last_synced_just_now"` - Less than 1 minute ago
|
|
66
|
+
- `"last_synced_5m_ago"` - 5 minutes ago
|
|
67
|
+
- `"last_synced_2h_ago"` - 2 hours ago
|
|
68
|
+
- `"last_synced_3d_ago"` - 3 days ago
|
|
69
|
+
|
|
70
|
+
You can use these as translation keys or provide your own `description` prop.
|
|
71
|
+
|
|
72
|
+
## Examples
|
|
73
|
+
|
|
74
|
+
### Basic Cloud Sync
|
|
75
|
+
|
|
76
|
+
```tsx
|
|
77
|
+
import { CloudSyncSetting } from '@umituz/react-native-settings';
|
|
78
|
+
import { useState } from 'react';
|
|
79
|
+
|
|
80
|
+
function BasicCloudSync() {
|
|
81
|
+
const [isSyncing, setIsSyncing] = useState(false);
|
|
82
|
+
const [lastSynced, setLastSynced] = useState<Date | null>(null);
|
|
83
|
+
|
|
84
|
+
const handleSync = async () => {
|
|
85
|
+
setIsSyncing(true);
|
|
86
|
+
try {
|
|
87
|
+
await syncData();
|
|
88
|
+
setLastSynced(new Date());
|
|
89
|
+
} catch (error) {
|
|
90
|
+
console.error('Sync failed:', error);
|
|
91
|
+
} finally {
|
|
92
|
+
setIsSyncing(false);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
return (
|
|
97
|
+
<CloudSyncSetting
|
|
98
|
+
isSyncing={isSyncing}
|
|
99
|
+
lastSynced={lastSynced}
|
|
100
|
+
onPress={handleSync}
|
|
101
|
+
/>
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### With Custom Description
|
|
107
|
+
|
|
108
|
+
```tsx
|
|
109
|
+
function CloudSyncWithDescription() {
|
|
110
|
+
const syncStatus = 'Synced 5 minutes ago';
|
|
111
|
+
|
|
112
|
+
return (
|
|
113
|
+
<CloudSyncSetting
|
|
114
|
+
title="iCloud Sync"
|
|
115
|
+
description={syncStatus}
|
|
116
|
+
onPress={() => console.log('Sync pressed')}
|
|
117
|
+
/>
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Disabled State
|
|
123
|
+
|
|
124
|
+
```tsx
|
|
125
|
+
function DisabledCloudSync() {
|
|
126
|
+
return (
|
|
127
|
+
<CloudSyncSetting
|
|
128
|
+
title="Cloud Sync"
|
|
129
|
+
description="Sync disabled"
|
|
130
|
+
disabled={true}
|
|
131
|
+
/>
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### With Translations
|
|
137
|
+
|
|
138
|
+
```tsx
|
|
139
|
+
import { useTranslation } from 'react-i18next';
|
|
140
|
+
import { CloudSyncSetting } from '@umituz/react-native-settings';
|
|
141
|
+
|
|
142
|
+
function LocalizedCloudSync() {
|
|
143
|
+
const { t } = useTranslation();
|
|
144
|
+
const [isSyncing, setIsSyncing] = useState(false);
|
|
145
|
+
const [lastSynced, setLastSynced] = useState<Date | null>(null);
|
|
146
|
+
|
|
147
|
+
// Get translation key based on state
|
|
148
|
+
const getDescription = () => {
|
|
149
|
+
if (isSyncing) return t('sync.syncing');
|
|
150
|
+
if (!lastSynced) return t('sync.never');
|
|
151
|
+
// Calculate relative time and return appropriate translation key
|
|
152
|
+
const timeAgo = calculateTimeAgo(lastSynced);
|
|
153
|
+
return t(`sync.${timeAgo}`);
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
return (
|
|
157
|
+
<CloudSyncSetting
|
|
158
|
+
title={t('sync.title')}
|
|
159
|
+
description={getDescription()}
|
|
160
|
+
isSyncing={isSyncing}
|
|
161
|
+
lastSynced={lastSynced}
|
|
162
|
+
onPress={handleSync}
|
|
163
|
+
/>
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Complete Integration
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
import { CloudSyncSetting } from '@umituz/react-native-settings';
|
|
172
|
+
import { SettingsSection } from '@umituz/react-native-settings';
|
|
173
|
+
|
|
174
|
+
function CloudSyncSettings() {
|
|
175
|
+
const [syncState, setSyncState] = useState({
|
|
176
|
+
isSyncing: false,
|
|
177
|
+
lastSynced: null as Date | null,
|
|
178
|
+
error: null as string | null,
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
const handleSync = async () => {
|
|
182
|
+
setSyncState(prev => ({ ...prev, isSyncing: true, error: null }));
|
|
183
|
+
|
|
184
|
+
try {
|
|
185
|
+
await cloudSyncService.sync();
|
|
186
|
+
setSyncState({
|
|
187
|
+
isSyncing: false,
|
|
188
|
+
lastSynced: new Date(),
|
|
189
|
+
error: null,
|
|
190
|
+
});
|
|
191
|
+
} catch (error) {
|
|
192
|
+
setSyncState(prev => ({
|
|
193
|
+
...prev,
|
|
194
|
+
isSyncing: false,
|
|
195
|
+
error: error.message,
|
|
196
|
+
}));
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
return (
|
|
201
|
+
<SettingsSection title="Sync">
|
|
202
|
+
<CloudSyncSetting
|
|
203
|
+
title="Cloud Backup"
|
|
204
|
+
isSyncing={syncState.isSyncing}
|
|
205
|
+
lastSynced={syncState.lastSynced}
|
|
206
|
+
description={syncState.error || undefined}
|
|
207
|
+
onPress={handleSync}
|
|
208
|
+
disabled={syncState.isSyncing}
|
|
209
|
+
/>
|
|
210
|
+
</SettingsSection>
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### With Auto-Sync
|
|
216
|
+
|
|
217
|
+
```tsx
|
|
218
|
+
import { useEffect, useState } from 'react';
|
|
219
|
+
import { CloudSyncSetting } from '@umituz/react-native-settings';
|
|
220
|
+
|
|
221
|
+
function AutoSyncCloudSync() {
|
|
222
|
+
const [isSyncing, setIsSyncing] = useState(false);
|
|
223
|
+
const [lastSynced, setLastSynced] = useState<Date | null>(null);
|
|
224
|
+
const [autoSync, setAutoSync] = useState(true);
|
|
225
|
+
|
|
226
|
+
// Auto-sync every 5 minutes
|
|
227
|
+
useEffect(() => {
|
|
228
|
+
if (!autoSync) return;
|
|
229
|
+
|
|
230
|
+
const interval = setInterval(async () => {
|
|
231
|
+
await performSync();
|
|
232
|
+
}, 5 * 60 * 1000);
|
|
233
|
+
|
|
234
|
+
return () => clearInterval(interval);
|
|
235
|
+
}, [autoSync]);
|
|
236
|
+
|
|
237
|
+
const performSync = async () => {
|
|
238
|
+
setIsSyncing(true);
|
|
239
|
+
try {
|
|
240
|
+
await syncData();
|
|
241
|
+
setLastSynced(new Date());
|
|
242
|
+
} finally {
|
|
243
|
+
setIsSyncing(false);
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
return (
|
|
248
|
+
<SettingsSection title="Sync Settings">
|
|
249
|
+
<SettingsItemCard
|
|
250
|
+
title="Auto-Sync"
|
|
251
|
+
value={autoSync ? 'Enabled' : 'Disabled'}
|
|
252
|
+
onPress={() => setAutoSync(!autoSync)}
|
|
253
|
+
/>
|
|
254
|
+
<CloudSyncSetting
|
|
255
|
+
isSyncing={isSyncing}
|
|
256
|
+
lastSynced={lastSynced}
|
|
257
|
+
onPress={performSync}
|
|
258
|
+
/>
|
|
259
|
+
</SettingsSection>
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### Real-Time Sync Status
|
|
265
|
+
|
|
266
|
+
```tsx
|
|
267
|
+
import { useState, useEffect } from 'react';
|
|
268
|
+
import { CloudSyncSetting } from '@umituz/react-native-settings';
|
|
269
|
+
|
|
270
|
+
function RealTimeCloudSync() {
|
|
271
|
+
const [syncStatus, setSyncStatus] = useState({
|
|
272
|
+
isSyncing: false,
|
|
273
|
+
lastSynced: null as Date | null,
|
|
274
|
+
syncCount: 0,
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
useEffect(() => {
|
|
278
|
+
// Subscribe to sync events
|
|
279
|
+
const unsubscribe = cloudSyncService.onSyncChange((status) => {
|
|
280
|
+
setSyncStatus(status);
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
return unsubscribe;
|
|
284
|
+
}, []);
|
|
285
|
+
|
|
286
|
+
return (
|
|
287
|
+
<CloudSyncSetting
|
|
288
|
+
title="Real-time Sync"
|
|
289
|
+
isSyncing={syncStatus.isSyncing}
|
|
290
|
+
lastSynced={syncStatus.lastSynced}
|
|
291
|
+
onPress={() => cloudSyncService.triggerSync()}
|
|
292
|
+
/>
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
## Architecture
|
|
298
|
+
|
|
299
|
+
```
|
|
300
|
+
src/domains/cloud-sync/
|
|
301
|
+
├── presentation/
|
|
302
|
+
│ └── components/
|
|
303
|
+
│ ├── CloudSyncSetting.tsx # Main sync setting component
|
|
304
|
+
│ └── __tests__/
|
|
305
|
+
│ └── CloudSyncSetting.test.tsx
|
|
306
|
+
└── index.ts # Public API exports
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## Best Practices
|
|
310
|
+
|
|
311
|
+
1. **Clear Status**: Always show current sync status clearly
|
|
312
|
+
2. **Error Handling**: Display sync errors prominently
|
|
313
|
+
3. **Manual Trigger**: Allow users to manually trigger sync
|
|
314
|
+
4. **Prevent Duplicate Syncs**: Disable sync button while syncing
|
|
315
|
+
5. **Auto-Sync**: Implement automatic sync intervals
|
|
316
|
+
6. **Conflict Resolution**: Handle sync conflicts gracefully
|
|
317
|
+
7. **Background Sync**: Use background sync for better UX
|
|
318
|
+
8. **Progress Indicators**: Show progress for large syncs
|
|
319
|
+
|
|
320
|
+
## Testing
|
|
321
|
+
|
|
322
|
+
```tsx
|
|
323
|
+
import { render, fireEvent, waitFor } from '@testing-library/react-native';
|
|
324
|
+
import { CloudSyncSetting } from '@umituz/react-native-settings';
|
|
325
|
+
|
|
326
|
+
describe('CloudSyncSetting', () => {
|
|
327
|
+
it('displays syncing state', () => {
|
|
328
|
+
const { getByText } = render(
|
|
329
|
+
<CloudSyncSetting
|
|
330
|
+
isSyncing={true}
|
|
331
|
+
onPress={() => {}}
|
|
332
|
+
/>
|
|
333
|
+
);
|
|
334
|
+
|
|
335
|
+
expect(getByText(/syncing/i)).toBeTruthy();
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
it('displays last synced time', () => {
|
|
339
|
+
const lastSynced = new Date(Date.now() - 5 * 60 * 1000); // 5 minutes ago
|
|
340
|
+
const { getByText } = render(
|
|
341
|
+
<CloudSyncSetting
|
|
342
|
+
lastSynced={lastSynced}
|
|
343
|
+
onPress={() => {}}
|
|
344
|
+
/>
|
|
345
|
+
);
|
|
346
|
+
|
|
347
|
+
expect(getByText(/5m_ago/i)).toBeTruthy();
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
it('calls onPress when pressed', () => {
|
|
351
|
+
const mockPress = jest.fn();
|
|
352
|
+
const { getByTestId } = render(
|
|
353
|
+
<CloudSyncSetting
|
|
354
|
+
onPress={mockPress}
|
|
355
|
+
/>
|
|
356
|
+
);
|
|
357
|
+
|
|
358
|
+
fireEvent.press(getByTestId('settings-item-card'));
|
|
359
|
+
expect(mockPress).toHaveBeenCalled();
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
it('does not respond to press when syncing', () => {
|
|
363
|
+
const mockPress = jest.fn();
|
|
364
|
+
const { getByTestId } = render(
|
|
365
|
+
<CloudSyncSetting
|
|
366
|
+
isSyncing={true}
|
|
367
|
+
onPress={mockPress}
|
|
368
|
+
/>
|
|
369
|
+
);
|
|
370
|
+
|
|
371
|
+
fireEvent.press(getByTestId('settings-item-card'));
|
|
372
|
+
expect(mockPress).not.toHaveBeenCalled();
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
it('shows custom description when provided', () => {
|
|
376
|
+
const { getByText } = render(
|
|
377
|
+
<CloudSyncSetting
|
|
378
|
+
description="Custom sync message"
|
|
379
|
+
onPress={() => {}}
|
|
380
|
+
/>
|
|
381
|
+
);
|
|
382
|
+
|
|
383
|
+
expect(getByText('Custom sync message')).toBeTruthy();
|
|
384
|
+
});
|
|
385
|
+
});
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
## Integration Examples
|
|
389
|
+
|
|
390
|
+
### With Cloud Services
|
|
391
|
+
|
|
392
|
+
```tsx
|
|
393
|
+
// iCloud sync (iOS)
|
|
394
|
+
import CloudSyncSetting from '@umituz/react-native-settings';
|
|
395
|
+
|
|
396
|
+
function iCloudSync() {
|
|
397
|
+
const [isSyncing, setIsSyncing] = useState(false);
|
|
398
|
+
const [lastSynced, setLastSynced] = useState<Date | null>(null);
|
|
399
|
+
|
|
400
|
+
const syncWithiCloud = async () => {
|
|
401
|
+
setIsSyncing(true);
|
|
402
|
+
try {
|
|
403
|
+
await CKContainer.defaultContainer().sync();
|
|
404
|
+
setLastSynced(new Date());
|
|
405
|
+
} finally {
|
|
406
|
+
setIsSyncing(false);
|
|
407
|
+
}
|
|
408
|
+
};
|
|
409
|
+
|
|
410
|
+
return (
|
|
411
|
+
<CloudSyncSetting
|
|
412
|
+
title="iCloud"
|
|
413
|
+
isSyncing={isSyncing}
|
|
414
|
+
lastSynced={lastSynced}
|
|
415
|
+
onPress={syncWithiCloud}
|
|
416
|
+
/>
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// Firebase sync
|
|
421
|
+
function FirebaseSync() {
|
|
422
|
+
const [isSyncing, setIsSyncing] = useState(false);
|
|
423
|
+
|
|
424
|
+
const syncWithFirebase = async () => {
|
|
425
|
+
setIsSyncing(true);
|
|
426
|
+
try {
|
|
427
|
+
await firebase.firestore().sync();
|
|
428
|
+
} finally {
|
|
429
|
+
setIsSyncing(false);
|
|
430
|
+
}
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
return (
|
|
434
|
+
<CloudSyncSetting
|
|
435
|
+
title="Firebase"
|
|
436
|
+
isSyncing={isSyncing}
|
|
437
|
+
onPress={syncWithFirebase}
|
|
438
|
+
/>
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
## Related
|
|
444
|
+
|
|
445
|
+
- **Settings**: Main settings management
|
|
446
|
+
- **Storage**: Data persistence layer
|
|
447
|
+
- **Dev**: Development utilities including storage clearing
|
|
448
|
+
|
|
449
|
+
## License
|
|
450
|
+
|
|
451
|
+
MIT
|