@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.
Files changed (189) hide show
  1. package/package.json +10 -6
  2. package/src/device/infrastructure/repositories/LegacyDeviceIdRepository.ts +1 -1
  3. package/src/device/infrastructure/services/DeviceFeatureService.ts +1 -1
  4. package/src/exception/infrastructure/services/ExceptionLogger.ts +1 -1
  5. package/src/exception/infrastructure/storage/ExceptionStore.ts +1 -1
  6. package/src/exports/filesystem.ts +1 -0
  7. package/src/exports/media.ts +1 -0
  8. package/src/exports/storage.ts +1 -0
  9. package/src/filesystem/domain/constants/FileConstants.ts +20 -0
  10. package/src/filesystem/domain/entities/File.ts +20 -0
  11. package/src/filesystem/domain/types/FileTypes.ts +43 -0
  12. package/src/filesystem/domain/utils/FileUtils.ts +86 -0
  13. package/src/filesystem/index.ts +23 -0
  14. package/src/filesystem/infrastructure/services/FileSystemService.ts +45 -0
  15. package/src/filesystem/infrastructure/services/cache.service.ts +48 -0
  16. package/src/filesystem/infrastructure/services/directory.service.ts +66 -0
  17. package/src/filesystem/infrastructure/services/download.constants.ts +6 -0
  18. package/src/filesystem/infrastructure/services/download.service.ts +74 -0
  19. package/src/filesystem/infrastructure/services/download.types.ts +7 -0
  20. package/src/filesystem/infrastructure/services/encoding.service.ts +25 -0
  21. package/src/filesystem/infrastructure/services/file-info.service.ts +52 -0
  22. package/src/filesystem/infrastructure/services/file-manager.service.ts +81 -0
  23. package/src/filesystem/infrastructure/services/file-path.service.ts +22 -0
  24. package/src/filesystem/infrastructure/services/file-reader.service.ts +52 -0
  25. package/src/filesystem/infrastructure/services/file-writer.service.ts +32 -0
  26. package/src/filesystem/infrastructure/utils/blob.utils.ts +20 -0
  27. package/src/image/infrastructure/services/ImageStorageService.ts +1 -1
  28. package/src/index.ts +14 -0
  29. package/src/media/domain/entities/CardMultimedia.types.README.md +129 -0
  30. package/src/media/domain/entities/CardMultimedia.types.ts +105 -0
  31. package/src/media/domain/entities/Media.README.md +80 -0
  32. package/src/media/domain/entities/Media.ts +139 -0
  33. package/src/media/domain/entities/MultimediaFlashcardTypes.README.md +144 -0
  34. package/src/media/domain/entities/MultimediaFlashcardTypes.ts +105 -0
  35. package/src/media/domain/utils/MediaUtils.README.md +178 -0
  36. package/src/media/domain/utils/MediaUtils.ts +82 -0
  37. package/src/media/index.ts +70 -0
  38. package/src/media/index.ts.README.md +191 -0
  39. package/src/media/infrastructure/services/CardMediaGenerationService.README.md +99 -0
  40. package/src/media/infrastructure/services/CardMediaGenerationService.ts +101 -0
  41. package/src/media/infrastructure/services/CardMediaOptimizerService.README.md +167 -0
  42. package/src/media/infrastructure/services/CardMediaOptimizerService.ts +36 -0
  43. package/src/media/infrastructure/services/CardMediaUploadService.README.md +123 -0
  44. package/src/media/infrastructure/services/CardMediaUploadService.ts +67 -0
  45. package/src/media/infrastructure/services/CardMediaValidationService.README.md +134 -0
  46. package/src/media/infrastructure/services/CardMediaValidationService.ts +81 -0
  47. package/src/media/infrastructure/services/CardMultimediaService.README.md +176 -0
  48. package/src/media/infrastructure/services/CardMultimediaService.ts +97 -0
  49. package/src/media/infrastructure/services/MediaGenerationService.README.md +142 -0
  50. package/src/media/infrastructure/services/MediaGenerationService.ts +80 -0
  51. package/src/media/infrastructure/services/MediaOptimizerService.README.md +145 -0
  52. package/src/media/infrastructure/services/MediaOptimizerService.ts +32 -0
  53. package/src/media/infrastructure/services/MediaPickerService.README.md +106 -0
  54. package/src/media/infrastructure/services/MediaPickerService.ts +173 -0
  55. package/src/media/infrastructure/services/MediaSaveService.README.md +120 -0
  56. package/src/media/infrastructure/services/MediaSaveService.ts +154 -0
  57. package/src/media/infrastructure/services/MediaUploadService.README.md +135 -0
  58. package/src/media/infrastructure/services/MediaUploadService.ts +62 -0
  59. package/src/media/infrastructure/services/MediaValidationService.README.md +135 -0
  60. package/src/media/infrastructure/services/MediaValidationService.ts +61 -0
  61. package/src/media/infrastructure/services/MultimediaFlashcardService.README.md +142 -0
  62. package/src/media/infrastructure/services/MultimediaFlashcardService.ts +95 -0
  63. package/src/media/infrastructure/utils/mediaHelpers.README.md +96 -0
  64. package/src/media/infrastructure/utils/mediaHelpers.ts +82 -0
  65. package/src/media/infrastructure/utils/mediaPickerMappers.README.md +129 -0
  66. package/src/media/infrastructure/utils/mediaPickerMappers.ts +76 -0
  67. package/src/media/presentation/hooks/card-multimedia.types.README.md +177 -0
  68. package/src/media/presentation/hooks/card-multimedia.types.ts +51 -0
  69. package/src/media/presentation/hooks/multimedia.types.README.md +201 -0
  70. package/src/media/presentation/hooks/multimedia.types.ts +51 -0
  71. package/src/media/presentation/hooks/useCardMediaGeneration.README.md +164 -0
  72. package/src/media/presentation/hooks/useCardMediaGeneration.ts +124 -0
  73. package/src/media/presentation/hooks/useCardMediaUpload.README.md +153 -0
  74. package/src/media/presentation/hooks/useCardMediaUpload.ts +86 -0
  75. package/src/media/presentation/hooks/useCardMediaValidation.README.md +176 -0
  76. package/src/media/presentation/hooks/useCardMediaValidation.ts +101 -0
  77. package/src/media/presentation/hooks/useCardMultimediaFlashcard.README.md +158 -0
  78. package/src/media/presentation/hooks/useCardMultimediaFlashcard.ts +104 -0
  79. package/src/media/presentation/hooks/useMedia.README.md +94 -0
  80. package/src/media/presentation/hooks/useMedia.ts +186 -0
  81. package/src/media/presentation/hooks/useMediaGeneration.README.md +118 -0
  82. package/src/media/presentation/hooks/useMediaGeneration.ts +101 -0
  83. package/src/media/presentation/hooks/useMediaUpload.README.md +108 -0
  84. package/src/media/presentation/hooks/useMediaUpload.ts +86 -0
  85. package/src/media/presentation/hooks/useMediaValidation.README.md +134 -0
  86. package/src/media/presentation/hooks/useMediaValidation.ts +93 -0
  87. package/src/media/presentation/hooks/useMultimediaFlashcard.README.md +141 -0
  88. package/src/media/presentation/hooks/useMultimediaFlashcard.ts +103 -0
  89. package/src/molecules/alerts/AlertStore.ts +1 -1
  90. package/src/molecules/calendar/infrastructure/storage/EventActions.ts +1 -1
  91. package/src/molecules/calendar/infrastructure/stores/storageAdapter.ts +1 -1
  92. package/src/offline/infrastructure/storage/OfflineStore.ts +1 -1
  93. package/src/onboarding/infrastructure/storage/OnboardingStore.ts +2 -2
  94. package/src/onboarding/infrastructure/storage/__tests__/OnboardingStore.test.ts +1 -1
  95. package/src/onboarding/infrastructure/storage/actions/answerActions.ts +1 -1
  96. package/src/onboarding/infrastructure/storage/actions/storageHelpers.ts +1 -1
  97. package/src/storage/README.md +185 -0
  98. package/src/storage/__tests__/integration.test.ts +391 -0
  99. package/src/storage/__tests__/mocks/asyncStorage.mock.ts +52 -0
  100. package/src/storage/__tests__/performance.test.tsx +352 -0
  101. package/src/storage/__tests__/setup.ts +63 -0
  102. package/src/storage/application/README.md +158 -0
  103. package/src/storage/application/ports/IStorageRepository.ts +61 -0
  104. package/src/storage/application/ports/README.md +127 -0
  105. package/src/storage/cache/README.md +154 -0
  106. package/src/storage/cache/__tests__/PerformanceAndMemory.test.ts +387 -0
  107. package/src/storage/cache/__tests__/setup.ts +19 -0
  108. package/src/storage/cache/domain/Cache.ts +146 -0
  109. package/src/storage/cache/domain/CacheManager.md +83 -0
  110. package/src/storage/cache/domain/CacheManager.ts +48 -0
  111. package/src/storage/cache/domain/CacheStatsTracker.md +169 -0
  112. package/src/storage/cache/domain/CacheStatsTracker.ts +49 -0
  113. package/src/storage/cache/domain/CachedValue.md +97 -0
  114. package/src/storage/cache/domain/ErrorHandler.md +99 -0
  115. package/src/storage/cache/domain/ErrorHandler.ts +42 -0
  116. package/src/storage/cache/domain/PatternMatcher.md +122 -0
  117. package/src/storage/cache/domain/PatternMatcher.ts +30 -0
  118. package/src/storage/cache/domain/README.md +118 -0
  119. package/src/storage/cache/domain/__tests__/Cache.test.ts +293 -0
  120. package/src/storage/cache/domain/__tests__/CacheManager.test.ts +276 -0
  121. package/src/storage/cache/domain/__tests__/ErrorHandler.test.ts +303 -0
  122. package/src/storage/cache/domain/__tests__/PatternMatcher.test.ts +261 -0
  123. package/src/storage/cache/domain/strategies/EvictionStrategy.ts +9 -0
  124. package/src/storage/cache/domain/strategies/FIFOStrategy.ts +12 -0
  125. package/src/storage/cache/domain/strategies/LFUStrategy.ts +22 -0
  126. package/src/storage/cache/domain/strategies/LRUStrategy.ts +22 -0
  127. package/src/storage/cache/domain/strategies/README.md +117 -0
  128. package/src/storage/cache/domain/strategies/TTLStrategy.ts +23 -0
  129. package/src/storage/cache/domain/strategies/__tests__/EvictionStrategies.test.ts +293 -0
  130. package/src/storage/cache/domain/types/Cache.ts +28 -0
  131. package/src/storage/cache/domain/types/README.md +107 -0
  132. package/src/storage/cache/index.ts +28 -0
  133. package/src/storage/cache/infrastructure/README.md +126 -0
  134. package/src/storage/cache/infrastructure/TTLCache.ts +103 -0
  135. package/src/storage/cache/infrastructure/__tests__/TTLCache.test.ts +303 -0
  136. package/src/storage/cache/presentation/README.md +123 -0
  137. package/src/storage/cache/presentation/__tests__/ReactHooks.test.ts +514 -0
  138. package/src/storage/cache/presentation/useCache.ts +76 -0
  139. package/src/storage/cache/presentation/useCachedValue.ts +88 -0
  140. package/src/storage/cache/types.d.ts +3 -0
  141. package/src/storage/domain/README.md +128 -0
  142. package/src/storage/domain/constants/CacheDefaults.ts +64 -0
  143. package/src/storage/domain/constants/README.md +105 -0
  144. package/src/storage/domain/entities/CachedValue.ts +86 -0
  145. package/src/storage/domain/entities/README.md +109 -0
  146. package/src/storage/domain/entities/StorageResult.ts +75 -0
  147. package/src/storage/domain/entities/__tests__/CachedValue.test.ts +149 -0
  148. package/src/storage/domain/entities/__tests__/StorageResult.test.ts +122 -0
  149. package/src/storage/domain/errors/README.md +126 -0
  150. package/src/storage/domain/errors/StorageError.ts +81 -0
  151. package/src/storage/domain/errors/__tests__/StorageError.test.ts +127 -0
  152. package/src/storage/domain/factories/README.md +138 -0
  153. package/src/storage/domain/factories/StoreFactory.ts +59 -0
  154. package/src/storage/domain/types/README.md +522 -0
  155. package/src/storage/domain/types/Store.ts +44 -0
  156. package/src/storage/domain/utils/CacheKeyGenerator.ts +66 -0
  157. package/src/storage/domain/utils/README.md +127 -0
  158. package/src/storage/domain/utils/__tests__/devUtils.test.ts +97 -0
  159. package/src/storage/domain/utils/devUtils.ts +37 -0
  160. package/src/storage/domain/value-objects/README.md +120 -0
  161. package/src/storage/domain/value-objects/StorageKey.ts +60 -0
  162. package/src/storage/index.ts +175 -0
  163. package/src/storage/infrastructure/README.md +165 -0
  164. package/src/storage/infrastructure/adapters/README.md +175 -0
  165. package/src/storage/infrastructure/adapters/StorageService.md +103 -0
  166. package/src/storage/infrastructure/adapters/StorageService.ts +49 -0
  167. package/src/storage/infrastructure/repositories/AsyncStorageRepository.ts +98 -0
  168. package/src/storage/infrastructure/repositories/BaseStorageOperations.ts +100 -0
  169. package/src/storage/infrastructure/repositories/BatchStorageOperations.ts +42 -0
  170. package/src/storage/infrastructure/repositories/README.md +121 -0
  171. package/src/storage/infrastructure/repositories/StringStorageOperations.ts +44 -0
  172. package/src/storage/infrastructure/repositories/__tests__/AsyncStorageRepository.test.ts +170 -0
  173. package/src/storage/infrastructure/repositories/__tests__/BaseStorageOperations.test.ts +201 -0
  174. package/src/storage/presentation/README.md +181 -0
  175. package/src/storage/presentation/hooks/CacheStorageOperations.ts +94 -0
  176. package/src/storage/presentation/hooks/README.md +128 -0
  177. package/src/storage/presentation/hooks/__tests__/usePersistentCache.test.ts +405 -0
  178. package/src/storage/presentation/hooks/__tests__/useStorage.test.ts +247 -0
  179. package/src/storage/presentation/hooks/__tests__/useStorageState.test.ts +293 -0
  180. package/src/storage/presentation/hooks/useCacheState.ts +53 -0
  181. package/src/storage/presentation/hooks/usePersistentCache.ts +154 -0
  182. package/src/storage/presentation/hooks/useStorage.ts +102 -0
  183. package/src/storage/presentation/hooks/useStorageState.ts +71 -0
  184. package/src/storage/presentation/hooks/useStore.ts +15 -0
  185. package/src/storage/types/README.md +103 -0
  186. package/src/theme/infrastructure/globalThemeStore.ts +1 -1
  187. package/src/theme/infrastructure/storage/ThemeStorage.ts +1 -1
  188. package/src/theme/infrastructure/stores/themeStore.ts +1 -1
  189. 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
+ };