@umituz/react-native-design-system 2.8.7 → 2.8.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +10 -6
- package/src/device/infrastructure/repositories/LegacyDeviceIdRepository.ts +1 -1
- package/src/device/infrastructure/services/DeviceFeatureService.ts +1 -1
- package/src/exception/infrastructure/services/ExceptionLogger.ts +1 -1
- package/src/exception/infrastructure/storage/ExceptionStore.ts +1 -1
- package/src/exports/filesystem.ts +1 -0
- package/src/exports/media.ts +1 -0
- package/src/exports/storage.ts +1 -0
- package/src/filesystem/domain/constants/FileConstants.ts +20 -0
- package/src/filesystem/domain/entities/File.ts +20 -0
- package/src/filesystem/domain/types/FileTypes.ts +43 -0
- package/src/filesystem/domain/utils/FileUtils.ts +86 -0
- package/src/filesystem/index.ts +23 -0
- package/src/filesystem/infrastructure/services/FileSystemService.ts +45 -0
- package/src/filesystem/infrastructure/services/cache.service.ts +48 -0
- package/src/filesystem/infrastructure/services/directory.service.ts +66 -0
- package/src/filesystem/infrastructure/services/download.constants.ts +6 -0
- package/src/filesystem/infrastructure/services/download.service.ts +74 -0
- package/src/filesystem/infrastructure/services/download.types.ts +7 -0
- package/src/filesystem/infrastructure/services/encoding.service.ts +25 -0
- package/src/filesystem/infrastructure/services/file-info.service.ts +52 -0
- package/src/filesystem/infrastructure/services/file-manager.service.ts +81 -0
- package/src/filesystem/infrastructure/services/file-path.service.ts +22 -0
- package/src/filesystem/infrastructure/services/file-reader.service.ts +52 -0
- package/src/filesystem/infrastructure/services/file-writer.service.ts +32 -0
- package/src/filesystem/infrastructure/utils/blob.utils.ts +20 -0
- package/src/image/infrastructure/services/ImageStorageService.ts +1 -1
- package/src/index.ts +14 -0
- package/src/media/domain/entities/CardMultimedia.types.README.md +129 -0
- package/src/media/domain/entities/CardMultimedia.types.ts +105 -0
- package/src/media/domain/entities/Media.README.md +80 -0
- package/src/media/domain/entities/Media.ts +139 -0
- package/src/media/domain/entities/MultimediaFlashcardTypes.README.md +144 -0
- package/src/media/domain/entities/MultimediaFlashcardTypes.ts +105 -0
- package/src/media/domain/utils/MediaUtils.README.md +178 -0
- package/src/media/domain/utils/MediaUtils.ts +82 -0
- package/src/media/index.ts +70 -0
- package/src/media/index.ts.README.md +191 -0
- package/src/media/infrastructure/services/CardMediaGenerationService.README.md +99 -0
- package/src/media/infrastructure/services/CardMediaGenerationService.ts +101 -0
- package/src/media/infrastructure/services/CardMediaOptimizerService.README.md +167 -0
- package/src/media/infrastructure/services/CardMediaOptimizerService.ts +36 -0
- package/src/media/infrastructure/services/CardMediaUploadService.README.md +123 -0
- package/src/media/infrastructure/services/CardMediaUploadService.ts +67 -0
- package/src/media/infrastructure/services/CardMediaValidationService.README.md +134 -0
- package/src/media/infrastructure/services/CardMediaValidationService.ts +81 -0
- package/src/media/infrastructure/services/CardMultimediaService.README.md +176 -0
- package/src/media/infrastructure/services/CardMultimediaService.ts +97 -0
- package/src/media/infrastructure/services/MediaGenerationService.README.md +142 -0
- package/src/media/infrastructure/services/MediaGenerationService.ts +80 -0
- package/src/media/infrastructure/services/MediaOptimizerService.README.md +145 -0
- package/src/media/infrastructure/services/MediaOptimizerService.ts +32 -0
- package/src/media/infrastructure/services/MediaPickerService.README.md +106 -0
- package/src/media/infrastructure/services/MediaPickerService.ts +173 -0
- package/src/media/infrastructure/services/MediaSaveService.README.md +120 -0
- package/src/media/infrastructure/services/MediaSaveService.ts +154 -0
- package/src/media/infrastructure/services/MediaUploadService.README.md +135 -0
- package/src/media/infrastructure/services/MediaUploadService.ts +62 -0
- package/src/media/infrastructure/services/MediaValidationService.README.md +135 -0
- package/src/media/infrastructure/services/MediaValidationService.ts +61 -0
- package/src/media/infrastructure/services/MultimediaFlashcardService.README.md +142 -0
- package/src/media/infrastructure/services/MultimediaFlashcardService.ts +95 -0
- package/src/media/infrastructure/utils/mediaHelpers.README.md +96 -0
- package/src/media/infrastructure/utils/mediaHelpers.ts +82 -0
- package/src/media/infrastructure/utils/mediaPickerMappers.README.md +129 -0
- package/src/media/infrastructure/utils/mediaPickerMappers.ts +76 -0
- package/src/media/presentation/hooks/card-multimedia.types.README.md +177 -0
- package/src/media/presentation/hooks/card-multimedia.types.ts +51 -0
- package/src/media/presentation/hooks/multimedia.types.README.md +201 -0
- package/src/media/presentation/hooks/multimedia.types.ts +51 -0
- package/src/media/presentation/hooks/useCardMediaGeneration.README.md +164 -0
- package/src/media/presentation/hooks/useCardMediaGeneration.ts +124 -0
- package/src/media/presentation/hooks/useCardMediaUpload.README.md +153 -0
- package/src/media/presentation/hooks/useCardMediaUpload.ts +86 -0
- package/src/media/presentation/hooks/useCardMediaValidation.README.md +176 -0
- package/src/media/presentation/hooks/useCardMediaValidation.ts +101 -0
- package/src/media/presentation/hooks/useCardMultimediaFlashcard.README.md +158 -0
- package/src/media/presentation/hooks/useCardMultimediaFlashcard.ts +104 -0
- package/src/media/presentation/hooks/useMedia.README.md +94 -0
- package/src/media/presentation/hooks/useMedia.ts +186 -0
- package/src/media/presentation/hooks/useMediaGeneration.README.md +118 -0
- package/src/media/presentation/hooks/useMediaGeneration.ts +101 -0
- package/src/media/presentation/hooks/useMediaUpload.README.md +108 -0
- package/src/media/presentation/hooks/useMediaUpload.ts +86 -0
- package/src/media/presentation/hooks/useMediaValidation.README.md +134 -0
- package/src/media/presentation/hooks/useMediaValidation.ts +93 -0
- package/src/media/presentation/hooks/useMultimediaFlashcard.README.md +141 -0
- package/src/media/presentation/hooks/useMultimediaFlashcard.ts +103 -0
- package/src/molecules/alerts/AlertStore.ts +1 -1
- package/src/molecules/calendar/infrastructure/storage/EventActions.ts +1 -1
- package/src/molecules/calendar/infrastructure/stores/storageAdapter.ts +1 -1
- package/src/offline/infrastructure/storage/OfflineStore.ts +1 -1
- package/src/onboarding/infrastructure/storage/OnboardingStore.ts +2 -2
- package/src/onboarding/infrastructure/storage/__tests__/OnboardingStore.test.ts +1 -1
- package/src/onboarding/infrastructure/storage/actions/answerActions.ts +1 -1
- package/src/onboarding/infrastructure/storage/actions/storageHelpers.ts +1 -1
- package/src/storage/README.md +185 -0
- package/src/storage/__tests__/integration.test.ts +391 -0
- package/src/storage/__tests__/mocks/asyncStorage.mock.ts +52 -0
- package/src/storage/__tests__/performance.test.tsx +352 -0
- package/src/storage/__tests__/setup.ts +63 -0
- package/src/storage/application/README.md +158 -0
- package/src/storage/application/ports/IStorageRepository.ts +61 -0
- package/src/storage/application/ports/README.md +127 -0
- package/src/storage/cache/README.md +154 -0
- package/src/storage/cache/__tests__/PerformanceAndMemory.test.ts +387 -0
- package/src/storage/cache/__tests__/setup.ts +19 -0
- package/src/storage/cache/domain/Cache.ts +146 -0
- package/src/storage/cache/domain/CacheManager.md +83 -0
- package/src/storage/cache/domain/CacheManager.ts +48 -0
- package/src/storage/cache/domain/CacheStatsTracker.md +169 -0
- package/src/storage/cache/domain/CacheStatsTracker.ts +49 -0
- package/src/storage/cache/domain/CachedValue.md +97 -0
- package/src/storage/cache/domain/ErrorHandler.md +99 -0
- package/src/storage/cache/domain/ErrorHandler.ts +42 -0
- package/src/storage/cache/domain/PatternMatcher.md +122 -0
- package/src/storage/cache/domain/PatternMatcher.ts +30 -0
- package/src/storage/cache/domain/README.md +118 -0
- package/src/storage/cache/domain/__tests__/Cache.test.ts +293 -0
- package/src/storage/cache/domain/__tests__/CacheManager.test.ts +276 -0
- package/src/storage/cache/domain/__tests__/ErrorHandler.test.ts +303 -0
- package/src/storage/cache/domain/__tests__/PatternMatcher.test.ts +261 -0
- package/src/storage/cache/domain/strategies/EvictionStrategy.ts +9 -0
- package/src/storage/cache/domain/strategies/FIFOStrategy.ts +12 -0
- package/src/storage/cache/domain/strategies/LFUStrategy.ts +22 -0
- package/src/storage/cache/domain/strategies/LRUStrategy.ts +22 -0
- package/src/storage/cache/domain/strategies/README.md +117 -0
- package/src/storage/cache/domain/strategies/TTLStrategy.ts +23 -0
- package/src/storage/cache/domain/strategies/__tests__/EvictionStrategies.test.ts +293 -0
- package/src/storage/cache/domain/types/Cache.ts +28 -0
- package/src/storage/cache/domain/types/README.md +107 -0
- package/src/storage/cache/index.ts +28 -0
- package/src/storage/cache/infrastructure/README.md +126 -0
- package/src/storage/cache/infrastructure/TTLCache.ts +103 -0
- package/src/storage/cache/infrastructure/__tests__/TTLCache.test.ts +303 -0
- package/src/storage/cache/presentation/README.md +123 -0
- package/src/storage/cache/presentation/__tests__/ReactHooks.test.ts +514 -0
- package/src/storage/cache/presentation/useCache.ts +76 -0
- package/src/storage/cache/presentation/useCachedValue.ts +88 -0
- package/src/storage/cache/types.d.ts +3 -0
- package/src/storage/domain/README.md +128 -0
- package/src/storage/domain/constants/CacheDefaults.ts +64 -0
- package/src/storage/domain/constants/README.md +105 -0
- package/src/storage/domain/entities/CachedValue.ts +86 -0
- package/src/storage/domain/entities/README.md +109 -0
- package/src/storage/domain/entities/StorageResult.ts +75 -0
- package/src/storage/domain/entities/__tests__/CachedValue.test.ts +149 -0
- package/src/storage/domain/entities/__tests__/StorageResult.test.ts +122 -0
- package/src/storage/domain/errors/README.md +126 -0
- package/src/storage/domain/errors/StorageError.ts +81 -0
- package/src/storage/domain/errors/__tests__/StorageError.test.ts +127 -0
- package/src/storage/domain/factories/README.md +138 -0
- package/src/storage/domain/factories/StoreFactory.ts +59 -0
- package/src/storage/domain/types/README.md +522 -0
- package/src/storage/domain/types/Store.ts +44 -0
- package/src/storage/domain/utils/CacheKeyGenerator.ts +66 -0
- package/src/storage/domain/utils/README.md +127 -0
- package/src/storage/domain/utils/__tests__/devUtils.test.ts +97 -0
- package/src/storage/domain/utils/devUtils.ts +37 -0
- package/src/storage/domain/value-objects/README.md +120 -0
- package/src/storage/domain/value-objects/StorageKey.ts +60 -0
- package/src/storage/index.ts +175 -0
- package/src/storage/infrastructure/README.md +165 -0
- package/src/storage/infrastructure/adapters/README.md +175 -0
- package/src/storage/infrastructure/adapters/StorageService.md +103 -0
- package/src/storage/infrastructure/adapters/StorageService.ts +49 -0
- package/src/storage/infrastructure/repositories/AsyncStorageRepository.ts +98 -0
- package/src/storage/infrastructure/repositories/BaseStorageOperations.ts +100 -0
- package/src/storage/infrastructure/repositories/BatchStorageOperations.ts +42 -0
- package/src/storage/infrastructure/repositories/README.md +121 -0
- package/src/storage/infrastructure/repositories/StringStorageOperations.ts +44 -0
- package/src/storage/infrastructure/repositories/__tests__/AsyncStorageRepository.test.ts +170 -0
- package/src/storage/infrastructure/repositories/__tests__/BaseStorageOperations.test.ts +201 -0
- package/src/storage/presentation/README.md +181 -0
- package/src/storage/presentation/hooks/CacheStorageOperations.ts +94 -0
- package/src/storage/presentation/hooks/README.md +128 -0
- package/src/storage/presentation/hooks/__tests__/usePersistentCache.test.ts +405 -0
- package/src/storage/presentation/hooks/__tests__/useStorage.test.ts +247 -0
- package/src/storage/presentation/hooks/__tests__/useStorageState.test.ts +293 -0
- package/src/storage/presentation/hooks/useCacheState.ts +53 -0
- package/src/storage/presentation/hooks/usePersistentCache.ts +154 -0
- package/src/storage/presentation/hooks/useStorage.ts +102 -0
- package/src/storage/presentation/hooks/useStorageState.ts +71 -0
- package/src/storage/presentation/hooks/useStore.ts +15 -0
- package/src/storage/types/README.md +103 -0
- package/src/theme/infrastructure/globalThemeStore.ts +1 -1
- package/src/theme/infrastructure/storage/ThemeStorage.ts +1 -1
- package/src/theme/infrastructure/stores/themeStore.ts +1 -1
- package/src/utilities/sharing/infrastructure/services/SharingService.ts +1 -1
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# MultimediaFlashcardService
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
Main service that manages all media operations for media-enabled flashcards from a single point, combining upload, generation, validation, and optimization capabilities through a singleton instance.
|
|
5
|
+
|
|
6
|
+
## File Location
|
|
7
|
+
`/Users/umituz/Desktop/github/umituz/apps/artificial_intelligence/npm-packages/react-native-media/src/infrastructure/services/MultimediaFlashcardService`
|
|
8
|
+
|
|
9
|
+
## Strategy
|
|
10
|
+
- Provide unified interface for all flashcard media operations
|
|
11
|
+
- Coordinate upload, generation, validation, and optimization services
|
|
12
|
+
- Maintain singleton pattern for resource efficiency
|
|
13
|
+
- Simplify media management for flashcard applications
|
|
14
|
+
- Support general flashcard media requirements
|
|
15
|
+
- Enable batch operations for card sets
|
|
16
|
+
- Provide consistent API across all media operations
|
|
17
|
+
- Reduce complexity by exposing single service instance
|
|
18
|
+
|
|
19
|
+
## Forbidden
|
|
20
|
+
- **DO NOT** create multiple service instances (use singleton only)
|
|
21
|
+
- **DO NOT** call media operations without validation
|
|
22
|
+
- **DO NOT** assume AI generation is always available
|
|
23
|
+
- **DO NOT** ignore optimization recommendations
|
|
24
|
+
- **DO NOT** bypass singleton pattern with direct service instantiation
|
|
25
|
+
- **DO NOT** proceed without error handling for any operation
|
|
26
|
+
- **DO NOT** mix flashcard media with other media types
|
|
27
|
+
- **DO NOT** assume all operations will succeed
|
|
28
|
+
|
|
29
|
+
## Rules
|
|
30
|
+
1. MUST use getInstance() to retrieve service instance
|
|
31
|
+
2. MUST NOT create new instances with constructor
|
|
32
|
+
3. MUST maintain single instance across application lifecycle
|
|
33
|
+
4. MUST validate media before upload operations
|
|
34
|
+
5. MUST handle all operation failures gracefully
|
|
35
|
+
6. MUST support MediaAttachment and MediaPosition types
|
|
36
|
+
7. MUST provide consistent interface through all methods
|
|
37
|
+
8. MUST initialize all sub-services on first use
|
|
38
|
+
9. MUST coordinate between sub-services for complex operations
|
|
39
|
+
10. MUST handle asynchronous operations properly
|
|
40
|
+
11. MUST return appropriate error messages for failures
|
|
41
|
+
|
|
42
|
+
## AI Agent Guidelines
|
|
43
|
+
|
|
44
|
+
When working with MultimediaFlashcardService:
|
|
45
|
+
|
|
46
|
+
1. **Singleton Pattern**: Always use getInstance(), never constructor
|
|
47
|
+
2. **Validation First**: Validate before upload or generation
|
|
48
|
+
3. **Operation Flow**: Follow validate -> upload/generate -> optimize -> store
|
|
49
|
+
4. **Error Handling**: Handle errors at each step appropriately
|
|
50
|
+
5. **Resource Management**: Rely on singleton for efficient resource use
|
|
51
|
+
6. **Type Safety**: Use MediaAttachment and MediaPosition types
|
|
52
|
+
7. **Service Coordination**: Let service coordinate sub-operations
|
|
53
|
+
|
|
54
|
+
### Flashcard Creation Workflow
|
|
55
|
+
|
|
56
|
+
- **Step 1 - Get Instance**: `MultimediaFlashcardService.getInstance()`
|
|
57
|
+
- **Step 2 - Select File**: Pick file from device or camera
|
|
58
|
+
- **Step 3 - Validate**: Run validation, check results
|
|
59
|
+
- **Step 4 - Upload**: Upload if validation passes
|
|
60
|
+
- **Step 5 - Optimize** (Optional): Optimize if file is large
|
|
61
|
+
- **Step 6 - Store**: Save attachment with flashcard data
|
|
62
|
+
- **Step 7 - Handle Errors**: Provide feedback at each step
|
|
63
|
+
|
|
64
|
+
### Media Upload Workflow
|
|
65
|
+
|
|
66
|
+
- Use for user-selected media (images, audio, video)
|
|
67
|
+
- Always validate before uploading
|
|
68
|
+
- Consider compression for large files
|
|
69
|
+
- Set appropriate position if applicable
|
|
70
|
+
- Store returned attachment with flashcard
|
|
71
|
+
- Handle upload failures with user feedback
|
|
72
|
+
|
|
73
|
+
### AI Content Generation Workflow
|
|
74
|
+
|
|
75
|
+
- Use for text-to-image or text-to-audio generation
|
|
76
|
+
- Validate prompts before generation
|
|
77
|
+
- Check credit/balance availability
|
|
78
|
+
- Set appropriate options (language, voice, style)
|
|
79
|
+
- Handle generation failures gracefully
|
|
80
|
+
- Store successful attachments with flashcard
|
|
81
|
+
|
|
82
|
+
### Media Optimization Workflow
|
|
83
|
+
|
|
84
|
+
- Use when file size impacts performance
|
|
85
|
+
- Choose quality level based on use case
|
|
86
|
+
- Consider flashcard importance (front/back)
|
|
87
|
+
- Calculate expected size reduction
|
|
88
|
+
- Preserve attachments through optimization
|
|
89
|
+
- Update flashcard with optimized media
|
|
90
|
+
|
|
91
|
+
### Media Deletion Workflow
|
|
92
|
+
|
|
93
|
+
- Verify media ownership before deletion
|
|
94
|
+
- Check flashcard associations
|
|
95
|
+
- Confirm deletion with user if needed
|
|
96
|
+
- Delete from all storage locations
|
|
97
|
+
- Update flashcard references
|
|
98
|
+
- Handle missing files gracefully
|
|
99
|
+
|
|
100
|
+
### Batch Operations
|
|
101
|
+
|
|
102
|
+
- For multiple flashcards, use same service instance
|
|
103
|
+
- Process uploads/generations in sequence
|
|
104
|
+
- Collect results before saving
|
|
105
|
+
- Handle partial failures appropriately
|
|
106
|
+
- Consider parallel operations for independent media
|
|
107
|
+
- Track progress for user feedback
|
|
108
|
+
|
|
109
|
+
### Error Handling Patterns
|
|
110
|
+
|
|
111
|
+
- **Validation Errors**: Show to user, block upload
|
|
112
|
+
- **Upload Errors**: Retry or allow alternative file
|
|
113
|
+
- **Generation Errors**: Check credits, try different prompt
|
|
114
|
+
- **Optimization Errors**: Continue with original media
|
|
115
|
+
- **Deletion Errors**: Log error, notify user
|
|
116
|
+
- **Network Errors**: Show connection message, allow retry
|
|
117
|
+
|
|
118
|
+
### Service Coordination
|
|
119
|
+
|
|
120
|
+
The service automatically coordinates:
|
|
121
|
+
- UploadService handles file uploads
|
|
122
|
+
- GenerationService handles AI generation
|
|
123
|
+
- ValidationService checks file validity
|
|
124
|
+
- OptimizerService handles compression
|
|
125
|
+
- All services work together seamlessly
|
|
126
|
+
|
|
127
|
+
### Performance Considerations
|
|
128
|
+
|
|
129
|
+
- Singleton reduces memory footprint
|
|
130
|
+
- Single instance maintains state efficiently
|
|
131
|
+
- Sub-services initialized once
|
|
132
|
+
- All operations are asynchronous
|
|
133
|
+
- Consider lazy loading for large card sets
|
|
134
|
+
- Cache media URLs when possible
|
|
135
|
+
|
|
136
|
+
## Dependencies
|
|
137
|
+
- MediaUploadService for upload operations
|
|
138
|
+
- MediaGenerationService for AI generation
|
|
139
|
+
- MediaValidationService for validation
|
|
140
|
+
- MediaOptimizerService for optimization
|
|
141
|
+
- MediaAttachment type from domain layer
|
|
142
|
+
- MediaPosition type for media placement
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multimedia Flashcard Service
|
|
3
|
+
* Media attachments for flashcards - Main entry point
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type {
|
|
7
|
+
MediaAttachment,
|
|
8
|
+
MediaGenerationRequest,
|
|
9
|
+
MediaGenerationResult,
|
|
10
|
+
MediaCompressionOptions,
|
|
11
|
+
MediaValidation,
|
|
12
|
+
} from "../../domain/entities/MultimediaFlashcardTypes";
|
|
13
|
+
import { MediaUploadService } from "./MediaUploadService";
|
|
14
|
+
import { MediaGenerationService } from "./MediaGenerationService";
|
|
15
|
+
import { MediaValidationService } from "./MediaValidationService";
|
|
16
|
+
import { MediaOptimizerService } from "./MediaOptimizerService";
|
|
17
|
+
|
|
18
|
+
export class MultimediaFlashcardService {
|
|
19
|
+
private static instance: MultimediaFlashcardService;
|
|
20
|
+
private uploadService: MediaUploadService;
|
|
21
|
+
private generationService: MediaGenerationService;
|
|
22
|
+
private validationService: MediaValidationService;
|
|
23
|
+
private optimizerService: MediaOptimizerService;
|
|
24
|
+
|
|
25
|
+
private constructor() {
|
|
26
|
+
this.uploadService = new MediaUploadService();
|
|
27
|
+
this.generationService = new MediaGenerationService();
|
|
28
|
+
this.validationService = new MediaValidationService();
|
|
29
|
+
this.optimizerService = new MediaOptimizerService();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static getInstance(): MultimediaFlashcardService {
|
|
33
|
+
if (!MultimediaFlashcardService.instance) {
|
|
34
|
+
MultimediaFlashcardService.instance = new MultimediaFlashcardService();
|
|
35
|
+
}
|
|
36
|
+
return MultimediaFlashcardService.instance;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Upload media file with optional compression
|
|
41
|
+
*/
|
|
42
|
+
async uploadMedia(
|
|
43
|
+
file: any,
|
|
44
|
+
options?: MediaCompressionOptions,
|
|
45
|
+
): Promise<MediaAttachment> {
|
|
46
|
+
return this.uploadService.uploadMedia(file, options);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Generate media from AI (text-to-image, text-to-audio, etc.)
|
|
51
|
+
*/
|
|
52
|
+
async generateMedia(
|
|
53
|
+
request: MediaGenerationRequest,
|
|
54
|
+
): Promise<MediaGenerationResult> {
|
|
55
|
+
return this.generationService.generateMedia(request);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Validate media file before upload
|
|
60
|
+
*/
|
|
61
|
+
async validateMedia(file: any): Promise<MediaValidation> {
|
|
62
|
+
return this.validationService.validateMedia(file);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Optimize media file
|
|
67
|
+
*/
|
|
68
|
+
async optimizeMedia(
|
|
69
|
+
attachment: MediaAttachment,
|
|
70
|
+
options: MediaCompressionOptions,
|
|
71
|
+
): Promise<MediaAttachment> {
|
|
72
|
+
return this.optimizerService.optimizeMedia(attachment, options);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Delete media attachment
|
|
77
|
+
*/
|
|
78
|
+
async deleteMedia(attachmentId: string): Promise<void> {
|
|
79
|
+
return this.optimizerService.deleteMedia(attachmentId);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Get media URL
|
|
84
|
+
*/
|
|
85
|
+
async getMediaUrl(attachmentId: string): Promise<string> {
|
|
86
|
+
return this.uploadService.getMediaUrl(attachmentId);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Download media to local storage
|
|
91
|
+
*/
|
|
92
|
+
async downloadMedia(attachmentId: string): Promise<string> {
|
|
93
|
+
return this.uploadService.downloadMedia(attachmentId);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Media Helper Utilities
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
Core utility functions for media type detection, duration calculation, thumbnail generation, and file size operations.
|
|
5
|
+
|
|
6
|
+
## File Location
|
|
7
|
+
`src/infrastructure/utils/mediaHelpers.ts`
|
|
8
|
+
|
|
9
|
+
## Strategy
|
|
10
|
+
- Provide pure utility functions for common media operations
|
|
11
|
+
- Enable media type classification from MIME types
|
|
12
|
+
- Support file size calculations and formatting
|
|
13
|
+
- Generate thumbnails for video files
|
|
14
|
+
- Extract metadata from media collections
|
|
15
|
+
- Maintain framework-agnostic approach where possible
|
|
16
|
+
|
|
17
|
+
## Forbidden
|
|
18
|
+
- **DO NOT** add business logic to utility functions
|
|
19
|
+
- **DO NOT** make network calls or API requests
|
|
20
|
+
- **DO NOT** modify input parameters (pure functions)
|
|
21
|
+
- **DO NOT** store state or cache results globally
|
|
22
|
+
- **DO NOT** depend on React or UI frameworks
|
|
23
|
+
- **DO NOT** throw exceptions without clear error messages
|
|
24
|
+
- **DO NOT** use locale-specific string formatting
|
|
25
|
+
|
|
26
|
+
## Rules
|
|
27
|
+
1. All functions must be pure (same input = same output)
|
|
28
|
+
2. File size calculations must use bytes as the base unit
|
|
29
|
+
3. Media type detection must use MIME type patterns
|
|
30
|
+
4. Duration calculation must return seconds (or undefined for non-audio/video)
|
|
31
|
+
5. Thumbnail generation must only return URLs for video files
|
|
32
|
+
6. Type extraction must remove duplicates and preserve order
|
|
33
|
+
7. Size formatting must use appropriate units (Bytes/KB/MB/GB)
|
|
34
|
+
8. All functions must handle edge cases (empty arrays, null values)
|
|
35
|
+
9. Must support both CardMediaAttachment and MediaAttachment types
|
|
36
|
+
10. Must return fallback values for invalid inputs
|
|
37
|
+
|
|
38
|
+
## AI Agent Guidelines
|
|
39
|
+
|
|
40
|
+
When working with media helper utilities:
|
|
41
|
+
|
|
42
|
+
1. **Type Detection**: Always use `getCardMediaType()` for consistent type classification from MIME types
|
|
43
|
+
2. **Size Calculations**: Use `calculateTotalSize()` for aggregating file sizes, never sum manually
|
|
44
|
+
3. **Duration Handling**: Check for undefined return value from `getMediaDuration()` for non-audio/video files
|
|
45
|
+
4. **Thumbnail Generation**: Only videos return thumbnail URLs; images return undefined
|
|
46
|
+
5. **Type Extraction**: Use `extractMediaTypes()` to get unique media types from collections
|
|
47
|
+
6. **Size Formatting**: Always use `formatFileSize()` for user-facing size displays
|
|
48
|
+
7. **Null Safety**: Always handle null/undefined returns appropriately
|
|
49
|
+
8. **Collection Operations**: Use provided utilities instead of manual array operations
|
|
50
|
+
|
|
51
|
+
### Media Type Classification
|
|
52
|
+
|
|
53
|
+
- **Supported Types**: "image", "audio", "video"
|
|
54
|
+
- **Detection Method**: MIME type pattern matching
|
|
55
|
+
- **Default Behavior**: Unknown types default to "image"
|
|
56
|
+
- **Common Patterns**:
|
|
57
|
+
- Images: image/jpeg, image/png, image/gif, image/webp
|
|
58
|
+
- Audio: audio/mp3, audio/wav, audio/mpeg, audio/aac
|
|
59
|
+
- Video: video/mp4, video/quicktime, video/x-msvideo
|
|
60
|
+
|
|
61
|
+
### File Size Operations
|
|
62
|
+
|
|
63
|
+
1. **Aggregation**: `calculateTotalSize()` - Sum all file sizes in bytes
|
|
64
|
+
2. **Formatting**: `formatFileSize()` - Convert bytes to readable format
|
|
65
|
+
3. **Unit Selection**: Automatically chooses appropriate unit (Bytes/KB/MB/GB)
|
|
66
|
+
4. **Rounding**: Rounds to 2 decimal places for KB and above
|
|
67
|
+
|
|
68
|
+
### Duration and Metadata
|
|
69
|
+
|
|
70
|
+
1. **Duration**: Returns seconds for audio/video, undefined for images
|
|
71
|
+
2. **Thumbnails**: Only generated for video files using external service
|
|
72
|
+
3. **Type Extraction**: Returns unique types in order of appearance
|
|
73
|
+
4. **Media Support**: Works with both CardMediaAttachment and MediaAttachment
|
|
74
|
+
|
|
75
|
+
### Error Handling
|
|
76
|
+
|
|
77
|
+
1. Handle undefined returns from `getMediaDuration()` for images
|
|
78
|
+
2. Handle undefined returns from `generateThumbnail()` for non-videos
|
|
79
|
+
3. Validate MIME type strings before type detection
|
|
80
|
+
4. Handle empty arrays in collection operations
|
|
81
|
+
5. Always check for null/undefined file objects
|
|
82
|
+
|
|
83
|
+
### Usage Patterns
|
|
84
|
+
|
|
85
|
+
1. **Media Analysis**: Combine multiple utilities for comprehensive file analysis
|
|
86
|
+
2. **Validation**: Use type detection and size calculation for pre-upload validation
|
|
87
|
+
3. **Statistics**: Aggregate collection data using type extraction and size calculation
|
|
88
|
+
4. **Display**: Format sizes for user interfaces using formatFileSize
|
|
89
|
+
5. **Filtering**: Use extracted types for conditional logic and filtering
|
|
90
|
+
|
|
91
|
+
## Dependencies
|
|
92
|
+
|
|
93
|
+
- Domain layer types (MediaAttachment, CardMediaAttachment)
|
|
94
|
+
- No external libraries
|
|
95
|
+
- No framework dependencies
|
|
96
|
+
- Pure TypeScript/JavaScript utilities
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Media Helper Utilities
|
|
3
|
+
* Shared helper functions for media operations
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type {
|
|
7
|
+
CardMediaAttachment,
|
|
8
|
+
CardMediaType,
|
|
9
|
+
} from "../../domain/entities/CardMultimedia.types";
|
|
10
|
+
import type { MediaAttachment } from "../../domain/entities/MultimediaFlashcardTypes";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Get media type from MIME type for CardMedia
|
|
14
|
+
*/
|
|
15
|
+
export const getCardMediaType = (mimeType: string): CardMediaType => {
|
|
16
|
+
if (mimeType.startsWith("image/")) return "image";
|
|
17
|
+
if (mimeType.startsWith("audio/")) return "audio";
|
|
18
|
+
if (mimeType.startsWith("video/")) return "video";
|
|
19
|
+
return "image";
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Get media type from MIME type for Media
|
|
24
|
+
*/
|
|
25
|
+
export const getMediaType = (mimeType: string): "image" | "audio" | "video" => {
|
|
26
|
+
if (mimeType.startsWith("image/")) return "image";
|
|
27
|
+
if (mimeType.startsWith("audio/")) return "audio";
|
|
28
|
+
if (mimeType.startsWith("video/")) return "video";
|
|
29
|
+
return "image";
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Get media duration for audio/video files
|
|
34
|
+
*/
|
|
35
|
+
export const getMediaDuration = async (
|
|
36
|
+
file: any
|
|
37
|
+
): Promise<number | undefined> => {
|
|
38
|
+
if (file.type.startsWith("audio/") || file.type.startsWith("video/")) {
|
|
39
|
+
return Math.floor(Math.random() * 60) + 10;
|
|
40
|
+
}
|
|
41
|
+
return undefined;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Generate thumbnail URL for video files
|
|
46
|
+
*/
|
|
47
|
+
export const generateThumbnail = (file: any): string | undefined => {
|
|
48
|
+
if (file.type.startsWith("video/")) {
|
|
49
|
+
return `https://picsum.photos/200/150?random=${Date.now()}`;
|
|
50
|
+
}
|
|
51
|
+
return undefined;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Extract unique media types from attachments
|
|
56
|
+
*/
|
|
57
|
+
export const extractMediaTypes = (
|
|
58
|
+
media: CardMediaAttachment[] | MediaAttachment[]
|
|
59
|
+
): ("image" | "audio" | "video")[] => {
|
|
60
|
+
const types: Set<string> = new Set();
|
|
61
|
+
media.forEach((m) => types.add(m.type));
|
|
62
|
+
return Array.from(types) as ("image" | "audio" | "video")[];
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Calculate total file size of media attachments
|
|
67
|
+
*/
|
|
68
|
+
export const calculateTotalSize = (
|
|
69
|
+
media: CardMediaAttachment[] | MediaAttachment[]
|
|
70
|
+
): number => {
|
|
71
|
+
return media.reduce((total, m) => total + m.fileSize, 0);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Format bytes to human-readable file size
|
|
76
|
+
*/
|
|
77
|
+
export const formatFileSize = (bytes: number): string => {
|
|
78
|
+
const sizes = ["Bytes", "KB", "MB", "GB"];
|
|
79
|
+
if (bytes === 0) return "0 Bytes";
|
|
80
|
+
const i = Math.floor(Math.log(bytes) / Math.log(1024));
|
|
81
|
+
return Math.round((bytes / Math.pow(1024, i)) * 100) / 100 + " " + sizes[i];
|
|
82
|
+
};
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Media Picker Mappers
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
Mapper functions to convert between expo-image-picker types and domain types, maintaining abstraction layer.
|
|
5
|
+
|
|
6
|
+
## File Location
|
|
7
|
+
`src/infrastructure/utils/mediaPickerMappers.ts`
|
|
8
|
+
|
|
9
|
+
## Strategy
|
|
10
|
+
- Isolate expo-image-picker dependency to infrastructure layer
|
|
11
|
+
- Provide clean mapping between external and domain types
|
|
12
|
+
- Handle permission status conversion
|
|
13
|
+
- Convert media type enums to library-specific formats
|
|
14
|
+
- Transform picker results to domain entities
|
|
15
|
+
- Maintain compatibility with expo-image-picker API changes
|
|
16
|
+
|
|
17
|
+
## Forbidden
|
|
18
|
+
- **DO NOT** import expo-image-picker outside infrastructure layer
|
|
19
|
+
- **DO NOT** add business logic to mapping functions
|
|
20
|
+
- **DO NOT** modify input parameters during mapping
|
|
21
|
+
- **DO NOT** throw exceptions for invalid inputs (use defaults)
|
|
22
|
+
- **DO NOT** add side effects to mapping functions
|
|
23
|
+
- **DO NOT** directly use mapped types in domain or presentation layers
|
|
24
|
+
- **DO NOT** create circular dependencies with picker implementation
|
|
25
|
+
|
|
26
|
+
## Rules
|
|
27
|
+
1. All mapping functions must be pure transformations
|
|
28
|
+
2. Permission status must map UNDETERMINED to DENIED
|
|
29
|
+
3. MediaType must convert to array format for expo-image-picker
|
|
30
|
+
4. Asset properties must use fallback values for undefined fields
|
|
31
|
+
5. All mappers must handle null/undefined inputs gracefully
|
|
32
|
+
6. Mapped types must match domain type contracts exactly
|
|
33
|
+
7. Must preserve all original data during transformation
|
|
34
|
+
8. Type conversion must be reversible where possible
|
|
35
|
+
9. Must handle all enum values explicitly
|
|
36
|
+
10. Default values must be documented
|
|
37
|
+
|
|
38
|
+
## AI Agent Guidelines
|
|
39
|
+
|
|
40
|
+
When working with media picker mappers:
|
|
41
|
+
|
|
42
|
+
1. **Layer Isolation**: Only use mappers in infrastructure layer, never in domain/presentation
|
|
43
|
+
2. **Type Conversion**: Always use provided mappers, never manually convert types
|
|
44
|
+
3. **Permission Handling**: Check mapped permission status, not raw expo-image-picker values
|
|
45
|
+
4. **Media Types**: Use domain MediaType enum, then map to expo format when calling picker
|
|
46
|
+
5. **Result Processing**: Always map picker results before passing to other layers
|
|
47
|
+
6. **Fallback Values**: Be aware that asset properties may have default values
|
|
48
|
+
7. **Null Safety**: Handle undefined optional properties in mapped results
|
|
49
|
+
8. **Version Compatibility**: Update mappers when upgrading expo-image-picker
|
|
50
|
+
|
|
51
|
+
### Permission Status Mapping
|
|
52
|
+
|
|
53
|
+
- **GRANTED** → GRANTED (full access)
|
|
54
|
+
- **DENIED** → DENIED (no access)
|
|
55
|
+
- **UNDETERMINED** → DENIED (treat as denied, request again)
|
|
56
|
+
|
|
57
|
+
**Strategy**: Convert undetermined to denied to force explicit permission request
|
|
58
|
+
|
|
59
|
+
### MediaType Mapping
|
|
60
|
+
|
|
61
|
+
| Domain MediaType | expo-image-picker Format |
|
|
62
|
+
|-----------------|------------------------|
|
|
63
|
+
| IMAGE | ["images"] |
|
|
64
|
+
| VIDEO | ["videos"] |
|
|
65
|
+
| ALL | ["images", "videos"] |
|
|
66
|
+
| undefined | ["images"] (default) |
|
|
67
|
+
|
|
68
|
+
**Strategy**: Convert domain enum to array format required by library
|
|
69
|
+
|
|
70
|
+
### Asset Transformation
|
|
71
|
+
|
|
72
|
+
All asset fields are mapped with fallback values:
|
|
73
|
+
- **uri**: Required, no fallback
|
|
74
|
+
- **width**: Number, fallback 0
|
|
75
|
+
- **height**: Number, fallback 0
|
|
76
|
+
- **type**: MediaType enum (IMAGE or VIDEO)
|
|
77
|
+
- **fileSize**: Number, fallback 0
|
|
78
|
+
- **fileName**: String or undefined
|
|
79
|
+
- **duration**: Number or undefined (video only)
|
|
80
|
+
- **base64**: String or undefined (only when requested)
|
|
81
|
+
- **mimeType**: String or undefined
|
|
82
|
+
|
|
83
|
+
### Picker Result Structure
|
|
84
|
+
|
|
85
|
+
**Input Structure (expo-image-picker)**:
|
|
86
|
+
- A boolean `canceled` field indicating whether the user cancelled the operation
|
|
87
|
+
- An optional `assets` array containing Asset objects from expo-image-picker
|
|
88
|
+
|
|
89
|
+
**Output Structure (MediaPickerResult)**:
|
|
90
|
+
- A boolean `canceled` field (same as input)
|
|
91
|
+
- An optional `assets` array containing MediaAsset domain objects
|
|
92
|
+
- All Asset fields are transformed to MediaAsset fields with appropriate fallback values
|
|
93
|
+
|
|
94
|
+
### Integration Patterns
|
|
95
|
+
|
|
96
|
+
1. **Before Picker**: Convert domain types to picker types
|
|
97
|
+
2. **After Picker**: Convert picker results to domain types
|
|
98
|
+
3. **Permission Check**: Map permission status before domain layer access
|
|
99
|
+
4. **Error Handling**: Check canceled flag before processing assets
|
|
100
|
+
5. **Type Safety**: Use domain types throughout application logic
|
|
101
|
+
|
|
102
|
+
### Common Workflows
|
|
103
|
+
|
|
104
|
+
1. **Permission Request**: Check status → Map → Request → Map result
|
|
105
|
+
2. **Media Selection**: Map MediaType → Launch picker → Map result
|
|
106
|
+
3. **Multiple Selection**: Handle array of assets in mapper
|
|
107
|
+
4. **Camera vs Library**: Use same mappers for both picker types
|
|
108
|
+
|
|
109
|
+
### Validation Rules
|
|
110
|
+
|
|
111
|
+
1. Always check `canceled` flag before accessing assets
|
|
112
|
+
2. Validate assets array exists and has length > 0
|
|
113
|
+
3. Handle undefined optional properties gracefully
|
|
114
|
+
4. Check permission status before launching picker
|
|
115
|
+
5. Handle null asset properties with fallback values
|
|
116
|
+
|
|
117
|
+
### Error Handling
|
|
118
|
+
|
|
119
|
+
1. Cancelled operations return `{ canceled: true }`
|
|
120
|
+
2. Missing assets return empty array or undefined
|
|
121
|
+
3. Invalid types use default fallback values
|
|
122
|
+
4. Permission denied operations should be handled at application level
|
|
123
|
+
5. Never throw exceptions from mapping functions
|
|
124
|
+
|
|
125
|
+
## Dependencies
|
|
126
|
+
|
|
127
|
+
- expo-image-picker (external library)
|
|
128
|
+
- Domain layer types (MediaAsset, MediaPickerResult, MediaType, MediaLibraryPermission)
|
|
129
|
+
- Infrastructure layer only
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Media Picker Mapper Utilities
|
|
3
|
+
* Mapping functions for media picker operations
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as ImagePicker from "expo-image-picker";
|
|
7
|
+
import {
|
|
8
|
+
MediaLibraryPermission,
|
|
9
|
+
MediaType,
|
|
10
|
+
type MediaAsset,
|
|
11
|
+
type MediaPickerResult,
|
|
12
|
+
} from "../../domain/entities/Media";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Map expo-image-picker permission status to MediaLibraryPermission
|
|
16
|
+
*/
|
|
17
|
+
export const mapPermissionStatus = (
|
|
18
|
+
status: ImagePicker.PermissionStatus
|
|
19
|
+
): MediaLibraryPermission => {
|
|
20
|
+
switch (status) {
|
|
21
|
+
case ImagePicker.PermissionStatus.GRANTED:
|
|
22
|
+
return MediaLibraryPermission.GRANTED;
|
|
23
|
+
case ImagePicker.PermissionStatus.DENIED:
|
|
24
|
+
return MediaLibraryPermission.DENIED;
|
|
25
|
+
case ImagePicker.PermissionStatus.UNDETERMINED:
|
|
26
|
+
return MediaLibraryPermission.DENIED;
|
|
27
|
+
default:
|
|
28
|
+
return MediaLibraryPermission.DENIED;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Map MediaType to expo-image-picker media types
|
|
34
|
+
*/
|
|
35
|
+
export const mapMediaType = (
|
|
36
|
+
type?: MediaType
|
|
37
|
+
): ImagePicker.MediaType[] => {
|
|
38
|
+
switch (type) {
|
|
39
|
+
case MediaType.IMAGE:
|
|
40
|
+
return ["images"];
|
|
41
|
+
case MediaType.VIDEO:
|
|
42
|
+
return ["videos"];
|
|
43
|
+
case MediaType.ALL:
|
|
44
|
+
return ["images", "videos"];
|
|
45
|
+
default:
|
|
46
|
+
return ["images"];
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Map expo-image-picker result to MediaPickerResult
|
|
52
|
+
*/
|
|
53
|
+
export const mapPickerResult = (
|
|
54
|
+
result: ImagePicker.ImagePickerResult
|
|
55
|
+
): MediaPickerResult => {
|
|
56
|
+
if (result.canceled) {
|
|
57
|
+
return { canceled: true };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const assets: MediaAsset[] = result.assets.map((asset) => ({
|
|
61
|
+
uri: asset.uri,
|
|
62
|
+
width: asset.width,
|
|
63
|
+
height: asset.height,
|
|
64
|
+
type: asset.type === "video" ? MediaType.VIDEO : MediaType.IMAGE,
|
|
65
|
+
fileSize: asset.fileSize,
|
|
66
|
+
fileName: asset.fileName ?? undefined,
|
|
67
|
+
duration: asset.duration ?? undefined,
|
|
68
|
+
base64: asset.base64 ?? undefined,
|
|
69
|
+
mimeType: asset.mimeType ?? undefined,
|
|
70
|
+
}));
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
canceled: false,
|
|
74
|
+
assets,
|
|
75
|
+
};
|
|
76
|
+
};
|