@umituz/react-native-settings 4.20.58 → 4.20.60
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/.github/ISSUE_TEMPLATE/bug_report.md +51 -0
- package/.github/ISSUE_TEMPLATE/documentation.md +52 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +63 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +84 -0
- package/AI_AGENT_GUIDELINES.md +367 -0
- package/ARCHITECTURE.md +246 -0
- package/CHANGELOG.md +67 -0
- package/CODE_OF_CONDUCT.md +75 -0
- package/CONTRIBUTING.md +107 -0
- package/DOCUMENTATION_MIGRATION.md +319 -0
- package/DOCUMENTATION_TEMPLATE.md +155 -0
- package/LICENSE +21 -0
- package/README.md +321 -498
- package/SECURITY.md +98 -0
- package/SETTINGS_SCREEN_GUIDE.md +185 -0
- package/TESTING.md +358 -0
- package/package.json +13 -2
- package/src/application/README.md +85 -271
- package/src/domains/about/README.md +85 -440
- package/src/domains/about/presentation/hooks/README.md +93 -348
- package/src/domains/appearance/README.md +95 -584
- package/src/domains/appearance/hooks/README.md +95 -303
- package/src/domains/appearance/infrastructure/services/README.md +83 -397
- package/src/domains/appearance/presentation/components/README.md +95 -489
- package/src/domains/cloud-sync/README.md +73 -439
- package/src/domains/cloud-sync/presentation/components/README.md +95 -493
- package/src/domains/dev/README.md +71 -457
- package/src/domains/disclaimer/README.md +77 -411
- package/src/domains/disclaimer/presentation/components/README.md +95 -392
- package/src/domains/faqs/README.md +86 -574
- package/src/domains/feedback/README.md +79 -553
- package/src/domains/feedback/presentation/hooks/README.md +93 -426
- package/src/domains/legal/README.md +88 -537
- package/src/domains/rating/README.md +73 -440
- package/src/domains/rating/presentation/components/README.md +95 -475
- package/src/domains/video-tutorials/README.md +77 -470
- package/src/domains/video-tutorials/presentation/components/README.md +95 -431
- package/src/infrastructure/README.md +78 -425
- package/src/infrastructure/repositories/README.md +88 -420
- package/src/infrastructure/services/README.md +74 -460
- package/src/presentation/components/README.md +97 -480
- package/src/presentation/components/SettingsErrorBoundary/README.md +48 -436
- package/src/presentation/components/SettingsFooter/README.md +48 -427
- package/src/presentation/components/SettingsItemCard/README.md +152 -391
- package/src/presentation/components/SettingsItemCard/STRATEGY.md +164 -0
- package/src/presentation/components/SettingsSection/README.md +47 -401
- package/src/presentation/hooks/README.md +95 -389
- package/src/presentation/hooks/mutations/README.md +99 -376
- package/src/presentation/hooks/queries/README.md +111 -353
- package/src/presentation/navigation/README.md +70 -502
- package/src/presentation/navigation/SettingsStackNavigator.tsx +2 -0
- package/src/presentation/navigation/components/README.md +70 -295
- package/src/presentation/navigation/components/wrappers/SettingsScreenWrapper.tsx +3 -0
- package/src/presentation/navigation/hooks/README.md +75 -367
- package/src/presentation/navigation/types.ts +1 -0
- package/src/presentation/navigation/utils/README.md +100 -380
- package/src/presentation/screens/README.md +53 -504
- package/src/presentation/screens/SettingsScreen.tsx +4 -2
- package/src/presentation/screens/components/SettingsContent/README.md +53 -382
- package/src/presentation/screens/components/SettingsHeader/README.md +48 -303
- package/src/presentation/screens/components/sections/CustomSettingsList/README.md +47 -359
- package/src/presentation/screens/components/sections/FeatureSettingsSection/README.md +81 -176
- package/src/presentation/screens/components/sections/IdentitySettingsSection/README.md +40 -297
- package/src/presentation/screens/components/sections/ProfileSectionLoader/README.md +47 -451
- package/src/presentation/screens/components/sections/SupportSettingsSection/README.md +45 -361
- package/src/presentation/screens/hooks/README.md +64 -354
- package/src/presentation/screens/types/README.md +79 -409
- package/src/presentation/screens/utils/README.md +65 -255
|
@@ -1,475 +1,82 @@
|
|
|
1
1
|
# Video Tutorials Domain
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
##
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const tutorial = {
|
|
81
|
-
id: '1',
|
|
82
|
-
title: 'Tutorial Title',
|
|
83
|
-
description: 'Tutorial description',
|
|
84
|
-
thumbnailUrl: 'https://example.com/thumb.jpg',
|
|
85
|
-
videoUrl: 'https://youtube.com/watch?v=xxx',
|
|
86
|
-
duration: '10:25',
|
|
87
|
-
views: 1500,
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
return (
|
|
91
|
-
<VideoTutorialCard
|
|
92
|
-
tutorial={tutorial}
|
|
93
|
-
onPress={() => console.log('Play video')}
|
|
94
|
-
/>
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
#### Props
|
|
100
|
-
|
|
101
|
-
| Prop | Type | Default | Description |
|
|
102
|
-
|------|------|---------|-------------|
|
|
103
|
-
| `tutorial` | `VideoTutorial` | **Required** | Tutorial data |
|
|
104
|
-
| `onPress` | `() => void` | **Required** | Press handler |
|
|
105
|
-
| `horizontal` | `boolean` | `false` | Horizontal card variant |
|
|
106
|
-
|
|
107
|
-
### VideoTutorialSection
|
|
108
|
-
|
|
109
|
-
Section component for grouping tutorials by category.
|
|
110
|
-
|
|
111
|
-
```tsx
|
|
112
|
-
import { VideoTutorialSection } from '@umituz/react-native-settings';
|
|
113
|
-
|
|
114
|
-
function MyTutorialSection() {
|
|
115
|
-
const tutorials = [ /* tutorial data */ ];
|
|
116
|
-
|
|
117
|
-
return (
|
|
118
|
-
<VideoTutorialSection
|
|
119
|
-
title="Getting Started"
|
|
120
|
-
tutorials={tutorials}
|
|
121
|
-
onTutorialPress={(tutorial) => playVideo(tutorial)}
|
|
122
|
-
/>
|
|
123
|
-
);
|
|
124
|
-
}
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
#### Props
|
|
128
|
-
|
|
129
|
-
| Prop | Type | Default | Description |
|
|
130
|
-
|------|------|---------|-------------|
|
|
131
|
-
| `title` | `string` | **Required** | Section title |
|
|
132
|
-
| `tutorials` | `VideoTutorial[]` | **Required** | Tutorials in section |
|
|
133
|
-
| `onTutorialPress` | `(tutorial) => void` | **Required** | Tutorial press handler |
|
|
134
|
-
|
|
135
|
-
## Types
|
|
136
|
-
|
|
137
|
-
### VideoTutorial
|
|
138
|
-
|
|
139
|
-
```typescript
|
|
140
|
-
interface VideoTutorial {
|
|
141
|
-
id: string;
|
|
142
|
-
title: string;
|
|
143
|
-
description?: string;
|
|
144
|
-
thumbnailUrl?: string;
|
|
145
|
-
videoUrl: string;
|
|
146
|
-
duration?: string;
|
|
147
|
-
views?: number;
|
|
148
|
-
category?: string;
|
|
149
|
-
publishedAt?: string;
|
|
150
|
-
author?: string;
|
|
151
|
-
}
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
## Examples
|
|
155
|
-
|
|
156
|
-
### Basic Video Tutorials Screen
|
|
157
|
-
|
|
158
|
-
```tsx
|
|
159
|
-
import React from 'react';
|
|
160
|
-
import { VideoTutorialsScreen } from '@umituz/react-native-settings';
|
|
161
|
-
|
|
162
|
-
const TUTORIALS = [
|
|
163
|
-
{
|
|
164
|
-
id: '1',
|
|
165
|
-
title: 'Introduction to the App',
|
|
166
|
-
description: 'Learn the basic features',
|
|
167
|
-
thumbnailUrl: 'https://picsum.photos/300/200?random=1',
|
|
168
|
-
videoUrl: 'https://youtube.com/watch?v=abc123',
|
|
169
|
-
duration: '5:30',
|
|
170
|
-
category: 'Getting Started',
|
|
171
|
-
views: 12500,
|
|
172
|
-
},
|
|
173
|
-
{
|
|
174
|
-
id: '2',
|
|
175
|
-
title: 'Advanced Features',
|
|
176
|
-
description: 'Master advanced functionality',
|
|
177
|
-
thumbnailUrl: 'https://picsum.photos/300/200?random=2',
|
|
178
|
-
videoUrl: 'https://youtube.com/watch?v=def456',
|
|
179
|
-
duration: '12:45',
|
|
180
|
-
category: 'Advanced',
|
|
181
|
-
views: 8300,
|
|
182
|
-
},
|
|
183
|
-
{
|
|
184
|
-
id: '3',
|
|
185
|
-
title: 'Tips and Tricks',
|
|
186
|
-
description: 'Helpful tips for power users',
|
|
187
|
-
thumbnailUrl: 'https://picsum.photos/300/200?random=3',
|
|
188
|
-
videoUrl: 'https://youtube.com/watch?v=ghi789',
|
|
189
|
-
duration: '8:15',
|
|
190
|
-
category: 'Tips',
|
|
191
|
-
views: 15600,
|
|
192
|
-
},
|
|
193
|
-
];
|
|
194
|
-
|
|
195
|
-
export default function TutorialsScreen() {
|
|
196
|
-
return (
|
|
197
|
-
<VideoTutorialsScreen
|
|
198
|
-
tutorials={TUTORIALS}
|
|
199
|
-
featuredTutorials={TUTORIALS.slice(0, 2)}
|
|
200
|
-
title="Help & Tutorials"
|
|
201
|
-
featuredTitle="Featured Videos"
|
|
202
|
-
allTutorialsTitle="All Tutorials"
|
|
203
|
-
onTutorialPress={(tutorial) => {
|
|
204
|
-
// Open in WebView or navigate to video player
|
|
205
|
-
navigation.navigate('VideoPlayer', { tutorial });
|
|
206
|
-
}}
|
|
207
|
-
/>
|
|
208
|
-
);
|
|
209
|
-
}
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
### With Loading State
|
|
213
|
-
|
|
214
|
-
```tsx
|
|
215
|
-
function TutorialsScreenWithLoading() {
|
|
216
|
-
const [tutorials, setTutorials] = useState([]);
|
|
217
|
-
const [loading, setLoading] = useState(true);
|
|
218
|
-
|
|
219
|
-
useEffect(() => {
|
|
220
|
-
loadTutorials();
|
|
221
|
-
}, []);
|
|
222
|
-
|
|
223
|
-
const loadTutorials = async () => {
|
|
224
|
-
try {
|
|
225
|
-
const data = await api.fetchTutorials();
|
|
226
|
-
setTutorials(data);
|
|
227
|
-
} catch (error) {
|
|
228
|
-
console.error('Failed to load tutorials:', error);
|
|
229
|
-
} finally {
|
|
230
|
-
setLoading(false);
|
|
231
|
-
}
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
return (
|
|
235
|
-
<VideoTutorialsScreen
|
|
236
|
-
tutorials={tutorials}
|
|
237
|
-
isLoading={loading}
|
|
238
|
-
onTutorialPress={handleTutorialPress}
|
|
239
|
-
/>
|
|
240
|
-
);
|
|
241
|
-
}
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
### Custom Empty State
|
|
245
|
-
|
|
246
|
-
```tsx
|
|
247
|
-
function EmptyTutorialsScreen() {
|
|
248
|
-
return (
|
|
249
|
-
<VideoTutorialsScreen
|
|
250
|
-
tutorials={[]}
|
|
251
|
-
emptyMessage="No tutorials available right now. Check back later!"
|
|
252
|
-
onTutorialPress={() => {}}
|
|
253
|
-
/>
|
|
254
|
-
);
|
|
255
|
-
}
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
### With Video Player Integration
|
|
259
|
-
|
|
260
|
-
```tsx
|
|
261
|
-
import { VideoTutorialsScreen } from '@umituz/react-native-settings';
|
|
262
|
-
import { WebView } from 'react-native-webview';
|
|
263
|
-
|
|
264
|
-
function TutorialsWithPlayer() {
|
|
265
|
-
const [selectedTutorial, setSelectedTutorial] = useState(null);
|
|
266
|
-
|
|
267
|
-
if (selectedTutorial) {
|
|
268
|
-
return (
|
|
269
|
-
<WebView
|
|
270
|
-
source={{ uri: selectedTutorial.videoUrl }}
|
|
271
|
-
style={{ flex: 1 }}
|
|
272
|
-
/>
|
|
273
|
-
);
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
return (
|
|
277
|
-
<VideoTutorialsScreen
|
|
278
|
-
tutorials={TUTORIALS}
|
|
279
|
-
onTutorialPress={setSelectedTutorial}
|
|
280
|
-
/>
|
|
281
|
-
);
|
|
282
|
-
}
|
|
283
|
-
```
|
|
284
|
-
|
|
285
|
-
### Using Tutorial Cards Directly
|
|
286
|
-
|
|
287
|
-
```tsx
|
|
288
|
-
import { VideoTutorialCard } from '@umituz/react-native-settings';
|
|
289
|
-
import { ScrollView } from 'react-native';
|
|
290
|
-
|
|
291
|
-
function CustomTutorialsList() {
|
|
292
|
-
return (
|
|
293
|
-
<ScrollView>
|
|
294
|
-
{TUTORIALS.map((tutorial) => (
|
|
295
|
-
<VideoTutorialCard
|
|
296
|
-
key={tutorial.id}
|
|
297
|
-
tutorial={tutorial}
|
|
298
|
-
onPress={() => playVideo(tutorial)}
|
|
299
|
-
/>
|
|
300
|
-
))}
|
|
301
|
-
</ScrollView>
|
|
302
|
-
);
|
|
303
|
-
}
|
|
304
|
-
```
|
|
305
|
-
|
|
306
|
-
### Horizontal Featured Section
|
|
307
|
-
|
|
308
|
-
```tsx
|
|
309
|
-
function FeaturedSection() {
|
|
310
|
-
const featuredTutorials = TUTORIALS.filter(t => t.featured);
|
|
311
|
-
|
|
312
|
-
return (
|
|
313
|
-
<View>
|
|
314
|
-
<Text style={{ fontSize: 20, fontWeight: 'bold', marginBottom: 12 }}>
|
|
315
|
-
Featured Tutorials
|
|
316
|
-
</Text>
|
|
317
|
-
<ScrollView horizontal showsHorizontalScrollIndicator={false}>
|
|
318
|
-
{featuredTutorials.map((tutorial) => (
|
|
319
|
-
<View key={tutorial.id} style={{ marginRight: 12 }}>
|
|
320
|
-
<VideoTutorialCard
|
|
321
|
-
tutorial={tutorial}
|
|
322
|
-
horizontal={true}
|
|
323
|
-
onPress={() => playVideo(tutorial)}
|
|
324
|
-
/>
|
|
325
|
-
</View>
|
|
326
|
-
))}
|
|
327
|
-
</ScrollView>
|
|
328
|
-
</View>
|
|
329
|
-
);
|
|
330
|
-
}
|
|
331
|
-
```
|
|
332
|
-
|
|
333
|
-
### Categorized Tutorials
|
|
334
|
-
|
|
335
|
-
```tsx
|
|
336
|
-
function CategorizedTutorialsScreen() {
|
|
337
|
-
const categories = {
|
|
338
|
-
'Getting Started': TUTORIALS.filter(t => t.category === 'Getting Started'),
|
|
339
|
-
'Advanced': TUTORIALS.filter(t => t.category === 'Advanced'),
|
|
340
|
-
'Tips': TUTORIALS.filter(t => t.category === 'Tips'),
|
|
341
|
-
};
|
|
342
|
-
|
|
343
|
-
return (
|
|
344
|
-
<ScrollView>
|
|
345
|
-
{Object.entries(categories).map(([category, tutorials]) => (
|
|
346
|
-
<VideoTutorialSection
|
|
347
|
-
key={category}
|
|
348
|
-
title={category}
|
|
349
|
-
tutorials={tutorials}
|
|
350
|
-
onTutorialPress={playVideo}
|
|
351
|
-
/>
|
|
352
|
-
))}
|
|
353
|
-
</ScrollView>
|
|
354
|
-
);
|
|
355
|
-
}
|
|
356
|
-
```
|
|
357
|
-
|
|
358
|
-
### With Search
|
|
359
|
-
|
|
360
|
-
```tsx
|
|
361
|
-
function SearchableTutorials() {
|
|
362
|
-
const [searchQuery, setSearchQuery] = useState('');
|
|
363
|
-
const [filteredTutorials, setFilteredTutorials] = useState(TUTORIALS);
|
|
364
|
-
|
|
365
|
-
useEffect(() => {
|
|
366
|
-
if (searchQuery.trim() === '') {
|
|
367
|
-
setFilteredTutorials(TUTORIALS);
|
|
368
|
-
} else {
|
|
369
|
-
const filtered = TUTORIALS.filter(t =>
|
|
370
|
-
t.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
|
371
|
-
t.description?.toLowerCase().includes(searchQuery.toLowerCase())
|
|
372
|
-
);
|
|
373
|
-
setFilteredTutorials(filtered);
|
|
374
|
-
}
|
|
375
|
-
}, [searchQuery]);
|
|
376
|
-
|
|
377
|
-
return (
|
|
378
|
-
<View>
|
|
379
|
-
<TextInput
|
|
380
|
-
value={searchQuery}
|
|
381
|
-
onChangeText={setSearchQuery}
|
|
382
|
-
placeholder="Search tutorials..."
|
|
383
|
-
style={{ padding: 12, backgroundColor: '#FFF' }}
|
|
384
|
-
/>
|
|
385
|
-
|
|
386
|
-
<VideoTutorialsScreen
|
|
387
|
-
tutorials={filteredTutorials}
|
|
388
|
-
onTutorialPress={playVideo}
|
|
389
|
-
/>
|
|
390
|
-
</View>
|
|
391
|
-
);
|
|
392
|
-
}
|
|
393
|
-
```
|
|
394
|
-
|
|
395
|
-
## Architecture
|
|
396
|
-
|
|
397
|
-
```
|
|
398
|
-
src/domains/video-tutorials/
|
|
399
|
-
├── types/
|
|
400
|
-
│ └── index.ts # VideoTutorial types
|
|
401
|
-
├── presentation/
|
|
402
|
-
│ ├── screens/
|
|
403
|
-
│ │ └── VideoTutorialsScreen.tsx
|
|
404
|
-
│ └── components/
|
|
405
|
-
│ ├── VideoTutorialCard.tsx
|
|
406
|
-
│ └── VideoTutorialSection.tsx
|
|
407
|
-
└── index.ts # Public API exports
|
|
408
|
-
```
|
|
409
|
-
|
|
410
|
-
## Best Practices
|
|
411
|
-
|
|
412
|
-
1. **Quality Thumbnails**: Use high-quality, consistent thumbnail sizes
|
|
413
|
-
2. **Accurate Metadata**: Keep duration and view counts up to date
|
|
414
|
-
3. **Categorization**: Organize tutorials logically for easy browsing
|
|
415
|
-
4. **Featured Content**: Highlight important or new tutorials
|
|
416
|
-
5. **Loading States**: Show proper loading indicators for better UX
|
|
417
|
-
6. **Error Handling**: Handle video playback errors gracefully
|
|
418
|
-
7. **Offline Support**: Consider caching video information for offline viewing
|
|
419
|
-
8. **Progress Tracking**: Track which tutorials users have watched
|
|
420
|
-
|
|
421
|
-
## Testing
|
|
422
|
-
|
|
423
|
-
```tsx
|
|
424
|
-
import { render, fireEvent } from '@testing-library/react-native';
|
|
425
|
-
import { VideoTutorialsScreen } from '@umituz/react-native-settings';
|
|
426
|
-
|
|
427
|
-
describe('VideoTutorialsScreen', () => {
|
|
428
|
-
const tutorials = [
|
|
429
|
-
{
|
|
430
|
-
id: '1',
|
|
431
|
-
title: 'Test Tutorial',
|
|
432
|
-
videoUrl: 'https://youtube.com/watch?v=test',
|
|
433
|
-
},
|
|
434
|
-
];
|
|
435
|
-
|
|
436
|
-
it('renders tutorials list', () => {
|
|
437
|
-
const { getByText } = render(
|
|
438
|
-
<VideoTutorialsScreen
|
|
439
|
-
tutorials={tutorials}
|
|
440
|
-
onTutorialPress={() => {}}
|
|
441
|
-
/>
|
|
442
|
-
);
|
|
443
|
-
|
|
444
|
-
expect(getByText('Test Tutorial')).toBeTruthy();
|
|
445
|
-
});
|
|
446
|
-
|
|
447
|
-
it('calls onTutorialPress when tutorial is pressed', () => {
|
|
448
|
-
const mockPress = jest.fn();
|
|
449
|
-
const { getByText } = render(
|
|
450
|
-
<VideoTutorialsScreen
|
|
451
|
-
tutorials={tutorials}
|
|
452
|
-
onTutorialPress={mockPress}
|
|
453
|
-
/>
|
|
454
|
-
);
|
|
455
|
-
|
|
456
|
-
fireEvent.press(getByText('Test Tutorial'));
|
|
457
|
-
expect(mockPress).toHaveBeenCalledWith(tutorials[0]);
|
|
458
|
-
});
|
|
459
|
-
|
|
460
|
-
it('shows empty state when no tutorials', () => {
|
|
461
|
-
const { getByText } = render(
|
|
462
|
-
<VideoTutorialsScreen
|
|
463
|
-
tutorials={[]}
|
|
464
|
-
emptyMessage="No tutorials found"
|
|
465
|
-
onTutorialPress={() => {}}
|
|
466
|
-
/>
|
|
467
|
-
);
|
|
468
|
-
|
|
469
|
-
expect(getByText('No tutorials found')).toBeTruthy();
|
|
470
|
-
});
|
|
471
|
-
});
|
|
472
|
-
```
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Provides components for displaying and managing video tutorials with featured sections, categorized lists, thumbnails, and external video linking.
|
|
6
|
+
|
|
7
|
+
## File Paths
|
|
8
|
+
|
|
9
|
+
**Screens:**
|
|
10
|
+
- `/Users/umituz/Desktop/github/umituz/apps/artificial_intelligence/npm-packages/react-native-settings/src/domains/video-tutorials/presentation/screens/VideoTutorialsScreen.tsx`
|
|
11
|
+
|
|
12
|
+
**Components:**
|
|
13
|
+
- `/Users/umituz/Desktop/github/umituz/apps/artificial_intelligence/npm-packages/react-native-settings/src/domains/video-tutorials/presentation/components/VideoTutorialCard.tsx`
|
|
14
|
+
- `/Users/umituz/Desktop/github/umituz/apps/artificial_intelligence/npm-packages/react-native-settings/src/domains/video-tutorials/presentation/components/VideoTutorialSection.tsx`
|
|
15
|
+
|
|
16
|
+
**Types:**
|
|
17
|
+
- `/Users/umituz/Desktop/github/umituz/apps/artificial_intelligence/npm-packages/react-native-settings/src/domains/video-tutorials/types/index.ts`
|
|
18
|
+
|
|
19
|
+
**Index:**
|
|
20
|
+
- `/Users/umituz/Desktop/github/umituz/apps/artificial_intelligence/npm-packages/react-native-settings/src/domains/video-tutorials/index.ts`
|
|
21
|
+
|
|
22
|
+
## Strategy
|
|
23
|
+
|
|
24
|
+
1. **Featured Content**: Display featured tutorials in horizontal scrolling section for prominence
|
|
25
|
+
2. **Categorization**: Organize tutorials by category for better navigation
|
|
26
|
+
3. **Rich Metadata**: Include thumbnails, duration, views, and descriptions for better UX
|
|
27
|
+
4. **External Linking**: Support linking to YouTube, Vimeo, and other platforms
|
|
28
|
+
5. **Loading States**: Show proper loading and empty states for better UX
|
|
29
|
+
|
|
30
|
+
## Restrictions (Forbidden)
|
|
31
|
+
|
|
32
|
+
### DO NOT
|
|
33
|
+
- ❌ DO NOT use VideoTutorialsScreen without providing tutorials array
|
|
34
|
+
- ❌ DO NOT display tutorials without proper thumbnails
|
|
35
|
+
- ❌ DO NOT bypass loading states when tutorials are being fetched
|
|
36
|
+
- ❌ DO NOT mix video tutorial logic with other business logic
|
|
37
|
+
|
|
38
|
+
### NEVER
|
|
39
|
+
- ❌ NEVER use VideoTutorialCard without required tutorial data (id, title, videoUrl)
|
|
40
|
+
- ❌ NEVER embed video players directly - link to external platforms
|
|
41
|
+
- ❌ NEVER show tutorials without proper error handling
|
|
42
|
+
- ❌ NEVER create custom tutorial card components when VideoTutorialCard exists
|
|
43
|
+
|
|
44
|
+
### AVOID
|
|
45
|
+
- ❌ AVOID hardcoding tutorial data in components - always pass as props
|
|
46
|
+
- ❌ AVOID using inconsistent thumbnail sizes
|
|
47
|
+
- ❌ AVOID creating custom tutorial lists when VideoTutorialsScreen can be configured
|
|
48
|
+
- ❌ AVOID mixing video playback logic with tutorial display logic
|
|
49
|
+
|
|
50
|
+
## Rules
|
|
51
|
+
|
|
52
|
+
### ALWAYS
|
|
53
|
+
- ✅ ALWAYS provide tutorials array with at least id, title, and videoUrl
|
|
54
|
+
- ✅ ALWAYS provide onTutorialPress handler for tutorial cards
|
|
55
|
+
- ✅ ALWAYS handle loading states with isLoading prop
|
|
56
|
+
- ✅ ALWAYS provide empty state message when no tutorials available
|
|
57
|
+
- ✅ ALWAYS use consistent thumbnail sizes across all tutorials
|
|
58
|
+
|
|
59
|
+
### MUST
|
|
60
|
+
- ✅ MUST provide unique id for each tutorial
|
|
61
|
+
- ✅ MUST include videoUrl for all tutorials
|
|
62
|
+
- ✅ MUST provide proper metadata (thumbnailUrl, duration, views, category)
|
|
63
|
+
- ✅ MUST handle video playback errors gracefully
|
|
64
|
+
- ✅ MUST use VideoTutorial types for type safety
|
|
65
|
+
|
|
66
|
+
### SHOULD
|
|
67
|
+
- ✅ SHOULD use high-quality, consistent thumbnail sizes
|
|
68
|
+
- ✅ SHOULD keep metadata accurate and up to date
|
|
69
|
+
- ✅ SHOULD organize tutorials logically by category
|
|
70
|
+
- ✅ SHOULD highlight important or new tutorials in featured section
|
|
71
|
+
- ✅ SHOULD support offline viewing by caching tutorial information
|
|
72
|
+
|
|
73
|
+
## AI Agent Guidelines
|
|
74
|
+
|
|
75
|
+
1. **Component Selection**: Use VideoTutorialsScreen for full screens, VideoTutorialCard for individual cards, VideoTutorialSection for categorized sections
|
|
76
|
+
2. **Data Structure**: Always structure tutorial data with id, title, videoUrl, and optional metadata
|
|
77
|
+
3. **External Playback**: Always link to external platforms (YouTube, Vimeo) - never embed players directly
|
|
78
|
+
4. **Loading States**: Always show proper loading indicators when fetching tutorials
|
|
79
|
+
5. **Metadata**: Always include rich metadata (thumbnails, duration, views) for better UX
|
|
473
80
|
|
|
474
81
|
## Related
|
|
475
82
|
|