@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,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Media Generation Hook
|
|
3
|
+
* Hook for generating media with AI
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React from "react";
|
|
7
|
+
import type { UseMediaGenerationResult } from "./multimedia.types";
|
|
8
|
+
import type {
|
|
9
|
+
MediaAttachment,
|
|
10
|
+
MediaGenerationRequest,
|
|
11
|
+
MediaGenerationResult,
|
|
12
|
+
} from "../../domain/entities/MultimediaFlashcardTypes";
|
|
13
|
+
|
|
14
|
+
export const useMediaGeneration = (): UseMediaGenerationResult => {
|
|
15
|
+
const [isGenerating, setIsGenerating] = React.useState(false);
|
|
16
|
+
const [generationResult, setGenerationResult] =
|
|
17
|
+
React.useState<MediaGenerationResult | null>(null);
|
|
18
|
+
const [error, setError] = React.useState<string | null>(null);
|
|
19
|
+
|
|
20
|
+
const generateMedia = React.useCallback(
|
|
21
|
+
async (request: MediaGenerationRequest): Promise<MediaGenerationResult> => {
|
|
22
|
+
try {
|
|
23
|
+
setIsGenerating(true);
|
|
24
|
+
setError(null);
|
|
25
|
+
|
|
26
|
+
// Simulate generation
|
|
27
|
+
await new Promise((resolve) => setTimeout(resolve, 3000));
|
|
28
|
+
|
|
29
|
+
const attachments: MediaAttachment[] = [];
|
|
30
|
+
|
|
31
|
+
switch (request.type) {
|
|
32
|
+
case "text_to_image":
|
|
33
|
+
for (let i = 0; i < (request.options.maxResults || 1); i++) {
|
|
34
|
+
attachments.push({
|
|
35
|
+
id: `ai_img_${Date.now()}_${i}`,
|
|
36
|
+
type: "image",
|
|
37
|
+
position: "both",
|
|
38
|
+
url: `https://picsum.photos/400/300?random=${Date.now() + i}`,
|
|
39
|
+
filename: `ai_generated_${i}.jpg`,
|
|
40
|
+
fileSize: 150000, // 150KB
|
|
41
|
+
mimeType: "image/jpeg",
|
|
42
|
+
isDownloaded: false,
|
|
43
|
+
createdAt: new Date().toISOString(),
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
break;
|
|
47
|
+
|
|
48
|
+
case "text_to_audio":
|
|
49
|
+
attachments.push({
|
|
50
|
+
id: `ai_audio_${Date.now()}`,
|
|
51
|
+
type: "audio",
|
|
52
|
+
position: "back",
|
|
53
|
+
url: `https://example.com/audio_${Date.now()}.mp3`,
|
|
54
|
+
filename: `ai_generated_${Date.now()}.mp3`,
|
|
55
|
+
fileSize: 80000, // 80KB
|
|
56
|
+
mimeType: "audio/mp3",
|
|
57
|
+
duration: 10, // 10 seconds
|
|
58
|
+
isDownloaded: false,
|
|
59
|
+
createdAt: new Date().toISOString(),
|
|
60
|
+
});
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const result: MediaGenerationResult = {
|
|
65
|
+
success: true,
|
|
66
|
+
attachments,
|
|
67
|
+
creditsUsed: request.type === "text_to_image" ? 5 : 3,
|
|
68
|
+
processingTime: 3000,
|
|
69
|
+
requestId: `req_${Date.now()}`,
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
setGenerationResult(result);
|
|
73
|
+
return result;
|
|
74
|
+
} catch (err) {
|
|
75
|
+
const errorMessage =
|
|
76
|
+
err instanceof Error ? err.message : "Generation failed";
|
|
77
|
+
setError(errorMessage);
|
|
78
|
+
setIsGenerating(false);
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
success: false,
|
|
82
|
+
attachments: [],
|
|
83
|
+
creditsUsed: 0,
|
|
84
|
+
processingTime: 0,
|
|
85
|
+
error: errorMessage,
|
|
86
|
+
requestId: "",
|
|
87
|
+
};
|
|
88
|
+
} finally {
|
|
89
|
+
setIsGenerating(false);
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
[],
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
generateMedia,
|
|
97
|
+
isGenerating,
|
|
98
|
+
generationResult,
|
|
99
|
+
error,
|
|
100
|
+
};
|
|
101
|
+
};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# useMediaUpload
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
React hook for uploading media files to server with progress tracking and compression support.
|
|
5
|
+
|
|
6
|
+
## File Location
|
|
7
|
+
`src/presentation/hooks/useMediaUpload.ts`
|
|
8
|
+
|
|
9
|
+
## Strategy
|
|
10
|
+
- Provide unified media upload interface with progress tracking
|
|
11
|
+
- Support compression options to optimize file sizes before upload
|
|
12
|
+
- Track upload progress with percentage and status updates
|
|
13
|
+
- Handle upload errors gracefully with proper error propagation
|
|
14
|
+
- Maintain loading state to prevent duplicate uploads
|
|
15
|
+
- Support various media types (image, video, audio)
|
|
16
|
+
- Generate automatic thumbnails for media files
|
|
17
|
+
|
|
18
|
+
## Forbidden
|
|
19
|
+
- **DO NOT** start new upload while previous upload is in progress
|
|
20
|
+
- **DO NOT** ignore compression options - always apply before upload
|
|
21
|
+
- **DO NOT** upload files without validation (use useMediaValidation first)
|
|
22
|
+
- **DO NOT** mock upload process in production without integration
|
|
23
|
+
- **DO NOT** modify file during upload (compression happens before)
|
|
24
|
+
- **DO NOT** assume upload will succeed - always handle errors
|
|
25
|
+
- **DO NOT** use hardcoded API endpoints - must be configurable
|
|
26
|
+
- **DO NOT** bypass progress tracking for async uploads
|
|
27
|
+
- **DO NOT** store upload results permanently in hook state
|
|
28
|
+
|
|
29
|
+
## Rules
|
|
30
|
+
1. Always validate files before uploading (use useMediaValidation hook)
|
|
31
|
+
2. Compression quality must be in 0-1 range
|
|
32
|
+
3. Dimensions must be in pixels (maxWidth, maxHeight)
|
|
33
|
+
4. Progress updates must be emitted every 10% or on status change
|
|
34
|
+
5. Upload state must be cleared on error or completion
|
|
35
|
+
6. Return complete MediaAttachment object on success
|
|
36
|
+
7. Generate thumbnail URL automatically for visual media
|
|
37
|
+
8. Calculate duration for audio/video files
|
|
38
|
+
9. Update progress status: uploading -> completed or error
|
|
39
|
+
10. Include unique fileId in progress tracking
|
|
40
|
+
|
|
41
|
+
## AI Agent Guidelines
|
|
42
|
+
|
|
43
|
+
When working with useMediaUpload hook:
|
|
44
|
+
|
|
45
|
+
1. **Pre-upload Validation**: Always use useMediaValidation before calling uploadMedia
|
|
46
|
+
2. **Progress Tracking**: Monitor uploadProgress state for real-time updates
|
|
47
|
+
3. **Compression**: Apply appropriate compression based on use case
|
|
48
|
+
4. **Error Recovery**: Handle upload errors and allow retry logic
|
|
49
|
+
5. **File Size**: Consider file size when choosing compression settings
|
|
50
|
+
|
|
51
|
+
### Upload Workflow
|
|
52
|
+
|
|
53
|
+
1. Validate file with useMediaValidation hook
|
|
54
|
+
2. Select compression options based on file type and size
|
|
55
|
+
3. Call uploadMedia with file and options
|
|
56
|
+
4. Monitor uploadProgress for status updates
|
|
57
|
+
5. Handle completion (success or error)
|
|
58
|
+
6. Process returned MediaAttachment object
|
|
59
|
+
|
|
60
|
+
### Compression Guidelines
|
|
61
|
+
|
|
62
|
+
**High Quality** (quality: 0.9, maxWidth: 4096)
|
|
63
|
+
- Use for professional photos, detailed graphics
|
|
64
|
+
- Larger file size, best quality
|
|
65
|
+
|
|
66
|
+
**Medium Quality** (quality: 0.7, maxWidth: 1920) - RECOMMENDED
|
|
67
|
+
- Balanced quality and size
|
|
68
|
+
- Good for most use cases
|
|
69
|
+
|
|
70
|
+
**Low Quality** (quality: 0.5, maxWidth: 1280)
|
|
71
|
+
- Use for thumbnails, previews
|
|
72
|
+
- Smallest file size, reduced quality
|
|
73
|
+
|
|
74
|
+
### Upload Progress States
|
|
75
|
+
|
|
76
|
+
- **uploading**: Upload in progress, progress 0-99%
|
|
77
|
+
- **completed**: Upload finished successfully, progress 100%
|
|
78
|
+
- **error**: Upload failed, error message available
|
|
79
|
+
|
|
80
|
+
### MediaAttachment Structure
|
|
81
|
+
|
|
82
|
+
Returned object includes:
|
|
83
|
+
- id: Unique identifier
|
|
84
|
+
- url: Uploaded file URL
|
|
85
|
+
- type: MediaType (IMAGE, VIDEO, AUDIO)
|
|
86
|
+
- position: MediaPosition (front, back, both)
|
|
87
|
+
- filename: Original filename
|
|
88
|
+
- fileSize: Size in bytes
|
|
89
|
+
- mimeType: MIME type string
|
|
90
|
+
- duration: Audio/video duration in seconds
|
|
91
|
+
- thumbnailUrl: Thumbnail URL for visual media
|
|
92
|
+
- caption: Optional caption text
|
|
93
|
+
- isDownloaded: Download status flag
|
|
94
|
+
- createdAt: ISO timestamp
|
|
95
|
+
|
|
96
|
+
### Integration Requirements
|
|
97
|
+
|
|
98
|
+
- Configure API endpoint for upload service
|
|
99
|
+
- Implement actual upload logic in MediaUploadService
|
|
100
|
+
- Handle authentication tokens for uploads
|
|
101
|
+
- Support retry logic for failed uploads
|
|
102
|
+
- Implement timeout handling for large files
|
|
103
|
+
|
|
104
|
+
## Dependencies
|
|
105
|
+
|
|
106
|
+
- MediaUploadService (infrastructure layer)
|
|
107
|
+
- Domain types: MediaAttachment, MediaCompressionOptions, MediaUploadProgress
|
|
108
|
+
- useMediaValidation (for pre-upload validation)
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Media Upload Hook
|
|
3
|
+
* Hook for uploading media files
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React from "react";
|
|
7
|
+
import {
|
|
8
|
+
generateThumbnail,
|
|
9
|
+
getMediaDuration,
|
|
10
|
+
getMediaType,
|
|
11
|
+
} from "../../infrastructure/utils/mediaHelpers";
|
|
12
|
+
import type { UseMediaUploadResult } from "./multimedia.types";
|
|
13
|
+
import type {
|
|
14
|
+
MediaAttachment,
|
|
15
|
+
MediaCompressionOptions,
|
|
16
|
+
MediaUploadProgress,
|
|
17
|
+
} from "../../domain/entities/MultimediaFlashcardTypes";
|
|
18
|
+
|
|
19
|
+
export const useMediaUpload = (): UseMediaUploadResult => {
|
|
20
|
+
const [isUploading, setIsUploading] = React.useState(false);
|
|
21
|
+
const [uploadProgress, setUploadProgress] =
|
|
22
|
+
React.useState<MediaUploadProgress | null>(null);
|
|
23
|
+
const [error, setError] = React.useState<string | null>(null);
|
|
24
|
+
|
|
25
|
+
const uploadMedia = React.useCallback(
|
|
26
|
+
async (file: any, options?: MediaCompressionOptions) => {
|
|
27
|
+
try {
|
|
28
|
+
setIsUploading(true);
|
|
29
|
+
setError(null);
|
|
30
|
+
|
|
31
|
+
// Simulate upload progress
|
|
32
|
+
setUploadProgress({
|
|
33
|
+
fileId: `upload_${Date.now()}`,
|
|
34
|
+
progress: 0,
|
|
35
|
+
status: "uploading",
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Simulate progress updates
|
|
39
|
+
for (let i = 1; i <= 100; i += 10) {
|
|
40
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
41
|
+
setUploadProgress((prev) => (prev ? { ...prev, progress: i } : null));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const attachment: MediaAttachment = {
|
|
45
|
+
id: `media_${Date.now()}`,
|
|
46
|
+
type: getMediaType(file.type),
|
|
47
|
+
position: "both",
|
|
48
|
+
url: `https://storage.example.com/media/${Date.now()}_${file.name}`,
|
|
49
|
+
filename: file.name,
|
|
50
|
+
fileSize: file.size || 100000,
|
|
51
|
+
mimeType: file.type,
|
|
52
|
+
duration: await getMediaDuration(file),
|
|
53
|
+
thumbnailUrl: generateThumbnail(file),
|
|
54
|
+
caption: "",
|
|
55
|
+
isDownloaded: true,
|
|
56
|
+
createdAt: new Date().toISOString(),
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
setUploadProgress({
|
|
60
|
+
fileId: `upload_${Date.now()}`,
|
|
61
|
+
progress: 100,
|
|
62
|
+
status: "completed",
|
|
63
|
+
url: attachment.url,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
return attachment;
|
|
67
|
+
} catch (err) {
|
|
68
|
+
const errorMessage =
|
|
69
|
+
err instanceof Error ? err.message : "Upload failed";
|
|
70
|
+
setError(errorMessage);
|
|
71
|
+
setIsUploading(false);
|
|
72
|
+
throw err;
|
|
73
|
+
} finally {
|
|
74
|
+
setIsUploading(false);
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
[],
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
uploadMedia,
|
|
82
|
+
isUploading,
|
|
83
|
+
uploadProgress,
|
|
84
|
+
error,
|
|
85
|
+
};
|
|
86
|
+
};
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# useMediaValidation
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
React hook for validating media files before upload, checking file size, type, and providing improvement recommendations.
|
|
5
|
+
|
|
6
|
+
## File Location
|
|
7
|
+
`src/presentation/hooks/useMediaValidation.ts`
|
|
8
|
+
|
|
9
|
+
## Strategy
|
|
10
|
+
- Provide comprehensive media file validation before upload
|
|
11
|
+
- Check file size limits with appropriate warnings
|
|
12
|
+
- Validate MIME types against supported formats
|
|
13
|
+
- Provide three-tier feedback: errors (blocking), warnings (performance), recommendations (improvements)
|
|
14
|
+
- Support validation state management
|
|
15
|
+
- Enable pre-upload validation workflow
|
|
16
|
+
- Return actionable feedback for each validation issue
|
|
17
|
+
|
|
18
|
+
## Forbidden
|
|
19
|
+
- **DO NOT** upload files that fail validation (errors present)
|
|
20
|
+
- **DO NOT** ignore warnings - they indicate performance issues
|
|
21
|
+
- **DO NOT** bypass file type validation
|
|
22
|
+
- **DO NOT** use mock validation in production
|
|
23
|
+
- **DO NOT** allow files exceeding maximum size limits
|
|
24
|
+
- **DO NOT** modify file during validation process
|
|
25
|
+
- **DO NOT** store validation results permanently in hook state
|
|
26
|
+
- **DO NOT** validate empty or missing files
|
|
27
|
+
- **DO NOT** suppress validation errors for user convenience
|
|
28
|
+
|
|
29
|
+
## Rules
|
|
30
|
+
1. Always validate before upload operations
|
|
31
|
+
2. Files over 50 MB must be rejected with error
|
|
32
|
+
3. Files over 10 MB must trigger warning and recommendation
|
|
33
|
+
4. Unsupported MIME types must be rejected
|
|
34
|
+
5. Validation must check file size, type, and format
|
|
35
|
+
6. Return errors array for blocking issues
|
|
36
|
+
7. Return warnings array for performance concerns
|
|
37
|
+
8. Return recommendations array for improvements
|
|
38
|
+
9. Clear validation state on new validation requests
|
|
39
|
+
10. Support synchronous and asynchronous validation
|
|
40
|
+
|
|
41
|
+
## AI Agent Guidelines
|
|
42
|
+
|
|
43
|
+
When working with useMediaValidation hook:
|
|
44
|
+
|
|
45
|
+
1. **Pre-upload Check**: Always validate before useMediaUpload calls
|
|
46
|
+
2. **Three-Tier Feedback**: Distinguish between errors, warnings, recommendations
|
|
47
|
+
3. **User Decision**: Show warnings but allow user to proceed
|
|
48
|
+
4. **File Size**: Be strict with maximum limits, flexible with warnings
|
|
49
|
+
5. **Type Safety**: Validate MIME types against supported formats
|
|
50
|
+
|
|
51
|
+
### Validation Levels
|
|
52
|
+
|
|
53
|
+
**Errors** (Blocking - Must fix before upload):
|
|
54
|
+
- File size exceeds 50 MB
|
|
55
|
+
- Unsupported file type
|
|
56
|
+
- Invalid file format
|
|
57
|
+
- Missing required properties
|
|
58
|
+
|
|
59
|
+
**Warnings** (Performance - Should fix but can proceed):
|
|
60
|
+
- File size over 10 MB (performance impact)
|
|
61
|
+
- Large dimensions (may need optimization)
|
|
62
|
+
- Non-standard format (compatibility issues)
|
|
63
|
+
|
|
64
|
+
**Recommendations** (Improvements - Optional suggestions):
|
|
65
|
+
- Reduce file size for better performance
|
|
66
|
+
- Use recommended format (JPEG for images, MP4 for video)
|
|
67
|
+
- Optimize dimensions for target use case
|
|
68
|
+
- Compress to balance quality and size
|
|
69
|
+
|
|
70
|
+
### Supported File Types
|
|
71
|
+
|
|
72
|
+
**Images:**
|
|
73
|
+
- image/jpeg (JPEG photos)
|
|
74
|
+
- image/png (PNG graphics with transparency)
|
|
75
|
+
- image/webp (WebP format)
|
|
76
|
+
|
|
77
|
+
**Audio:**
|
|
78
|
+
- audio/mp3 (MP3 compressed audio)
|
|
79
|
+
- audio/wav (WAV uncompressed audio)
|
|
80
|
+
- audio/m4a (M4A audio format)
|
|
81
|
+
|
|
82
|
+
**Video:**
|
|
83
|
+
- video/mp4 (MP4 video)
|
|
84
|
+
- video/mov (QuickTime video)
|
|
85
|
+
|
|
86
|
+
### Validation Workflow
|
|
87
|
+
|
|
88
|
+
1. Receive file object with name, type, size, uri
|
|
89
|
+
2. Check file size against limits (50 MB max, 10 MB warning)
|
|
90
|
+
3. Validate MIME type against supported formats
|
|
91
|
+
4. Generate appropriate errors, warnings, recommendations
|
|
92
|
+
5. Return MediaValidation object with results
|
|
93
|
+
6. Display feedback to user for action
|
|
94
|
+
|
|
95
|
+
### Validation State Management
|
|
96
|
+
|
|
97
|
+
- isValid: Boolean (true if no errors)
|
|
98
|
+
- errors: String array (blocking issues)
|
|
99
|
+
- warnings: String array (performance concerns)
|
|
100
|
+
- recommendations: String array (improvement suggestions)
|
|
101
|
+
|
|
102
|
+
### Integration with Upload Flow
|
|
103
|
+
|
|
104
|
+
Typical validation-upload workflow:
|
|
105
|
+
1. Select file from picker or file system
|
|
106
|
+
2. Call validateMedia(file)
|
|
107
|
+
3. Check validation.isValid
|
|
108
|
+
4. If errors: Show to user, block upload
|
|
109
|
+
5. If warnings: Show to user, ask confirmation
|
|
110
|
+
6. If recommendations: Show to user for reference
|
|
111
|
+
7. Proceed to upload if no errors or user confirms warnings
|
|
112
|
+
|
|
113
|
+
### File Size Guidelines
|
|
114
|
+
|
|
115
|
+
**Images:**
|
|
116
|
+
- Optimal: Under 2 MB
|
|
117
|
+
- Warning: 2-10 MB
|
|
118
|
+
- Error: Over 50 MB
|
|
119
|
+
|
|
120
|
+
**Audio:**
|
|
121
|
+
- Optimal: Under 5 MB
|
|
122
|
+
- Warning: 5-10 MB
|
|
123
|
+
- Error: Over 50 MB
|
|
124
|
+
|
|
125
|
+
**Video:**
|
|
126
|
+
- Optimal: Under 10 MB
|
|
127
|
+
- Warning: 10-50 MB
|
|
128
|
+
- Error: Over 50 MB
|
|
129
|
+
|
|
130
|
+
## Dependencies
|
|
131
|
+
|
|
132
|
+
- MediaValidationService (infrastructure layer)
|
|
133
|
+
- Domain types: MediaValidation, file input interfaces
|
|
134
|
+
- Media constants (size limits, supported types)
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Media Validation Hook
|
|
3
|
+
* Hook for validating media files
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React from "react";
|
|
7
|
+
import { formatFileSize } from "../../infrastructure/utils/mediaHelpers";
|
|
8
|
+
import type { UseMediaValidationResult } from "./multimedia.types";
|
|
9
|
+
import type { MediaValidation } from "../../domain/entities/MultimediaFlashcardTypes";
|
|
10
|
+
|
|
11
|
+
export const useMediaValidation = (): UseMediaValidationResult => {
|
|
12
|
+
const [isValidating, setIsValidating] = React.useState(false);
|
|
13
|
+
const [validation, setValidation] = React.useState<MediaValidation | null>(
|
|
14
|
+
null,
|
|
15
|
+
);
|
|
16
|
+
const [error, setError] = React.useState<string | null>(null);
|
|
17
|
+
|
|
18
|
+
const validateMedia = React.useCallback(
|
|
19
|
+
async (file: any): Promise<MediaValidation> => {
|
|
20
|
+
try {
|
|
21
|
+
setIsValidating(true);
|
|
22
|
+
setError(null);
|
|
23
|
+
|
|
24
|
+
// Simulate validation
|
|
25
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
26
|
+
|
|
27
|
+
const errors: string[] = [];
|
|
28
|
+
const warnings: string[] = [];
|
|
29
|
+
const recommendations: string[] = [];
|
|
30
|
+
|
|
31
|
+
// File size validation
|
|
32
|
+
const maxSize = 50 * 1024 * 1024; // 50MB
|
|
33
|
+
if (file.size > maxSize) {
|
|
34
|
+
errors.push(
|
|
35
|
+
`File size (${formatFileSize(file.size)}) exceeds maximum allowed size (${formatFileSize(maxSize)})`,
|
|
36
|
+
);
|
|
37
|
+
} else if (file.size > 10 * 1024 * 1024) {
|
|
38
|
+
// 10MB
|
|
39
|
+
warnings.push(`Large file size may impact performance`);
|
|
40
|
+
recommendations.push("Consider compressing file");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// File type validation
|
|
44
|
+
const supportedTypes = [
|
|
45
|
+
"image/jpeg",
|
|
46
|
+
"image/png",
|
|
47
|
+
"image/webp",
|
|
48
|
+
"audio/mp3",
|
|
49
|
+
"audio/wav",
|
|
50
|
+
"audio/m4a",
|
|
51
|
+
"video/mp4",
|
|
52
|
+
"video/mov",
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
if (!supportedTypes.includes(file.type)) {
|
|
56
|
+
errors.push(`Unsupported file type: ${file.type}`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const result: MediaValidation = {
|
|
60
|
+
isValid: errors.length === 0,
|
|
61
|
+
errors,
|
|
62
|
+
warnings,
|
|
63
|
+
recommendations,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
setValidation(result);
|
|
67
|
+
return result;
|
|
68
|
+
} catch (err) {
|
|
69
|
+
const errorMessage =
|
|
70
|
+
err instanceof Error ? err.message : "Validation failed";
|
|
71
|
+
setError(errorMessage);
|
|
72
|
+
setIsValidating(false);
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
isValid: false,
|
|
76
|
+
errors: [errorMessage],
|
|
77
|
+
warnings: [],
|
|
78
|
+
recommendations: [],
|
|
79
|
+
};
|
|
80
|
+
} finally {
|
|
81
|
+
setIsValidating(false);
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
[],
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
validateMedia,
|
|
89
|
+
isValidating,
|
|
90
|
+
validation,
|
|
91
|
+
error,
|
|
92
|
+
};
|
|
93
|
+
};
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# useMultimediaFlashcard
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
Main hook for creating and managing flashcards with media attachments, providing all multimedia operations in one place.
|
|
5
|
+
|
|
6
|
+
## File Location
|
|
7
|
+
`src/presentation/hooks/useMultimediaFlashcard.ts`
|
|
8
|
+
|
|
9
|
+
## Strategy
|
|
10
|
+
- Provide unified interface for flashcard creation with media support
|
|
11
|
+
- Support adding, updating, and deleting media on flashcards
|
|
12
|
+
- Automatically analyze media composition (types, sizes, positions)
|
|
13
|
+
- Calculate estimated storage requirements
|
|
14
|
+
- Track download status for offline support
|
|
15
|
+
- Enable rich multimedia flashcard experiences
|
|
16
|
+
- Maintain separation between card data and media management
|
|
17
|
+
|
|
18
|
+
## Forbidden
|
|
19
|
+
- **DO NOT** create flashcards without required fields (front, back)
|
|
20
|
+
- **DO NOT** add media without proper validation first
|
|
21
|
+
- **DO NOT** allow duplicate media attachments with same ID
|
|
22
|
+
- **DO NOT** mock card operations in production without backend integration
|
|
23
|
+
- **DO NOT** assume all media is downloaded (check isDownloaded flag)
|
|
24
|
+
- **DO NOT** modify card structure after creation (use update functions)
|
|
25
|
+
- **DO NOT** exceed practical media limits per card (performance)
|
|
26
|
+
- **DO NOT** store large media directly in card object (use references)
|
|
27
|
+
- **DO NOT** bypass media analysis for size estimation
|
|
28
|
+
|
|
29
|
+
## Rules
|
|
30
|
+
1. Always validate media before adding to flashcard
|
|
31
|
+
2. Calculate estimatedSize from all media attachments
|
|
32
|
+
3. Generate unique ID for each flashcard
|
|
33
|
+
4. Analyze media types and populate mediaType array
|
|
34
|
+
5. Set hasMedia flag based on media array length
|
|
35
|
+
6. Set isDownloaded based on all media download status
|
|
36
|
+
7. Support front, back, and both positions for media
|
|
37
|
+
8. Return complete MultimediaFlashcard object
|
|
38
|
+
9. Clear processing state on completion or error
|
|
39
|
+
10. Support empty media array for text-only cards
|
|
40
|
+
|
|
41
|
+
## AI Agent Guidelines
|
|
42
|
+
|
|
43
|
+
When working with useMultimediaFlashcard hook:
|
|
44
|
+
|
|
45
|
+
1. **Media First**: Upload and validate media before creating card
|
|
46
|
+
2. **Size Awareness**: Monitor estimatedSize for performance implications
|
|
47
|
+
3. **Type Analysis**: Use mediaType array to determine card capabilities
|
|
48
|
+
4. **Download Status**: Check isDownloaded before displaying media
|
|
49
|
+
5. **Position Strategy**: Assign appropriate position (front, back, both)
|
|
50
|
+
|
|
51
|
+
### Card Creation Workflow
|
|
52
|
+
|
|
53
|
+
1. Prepare card content (front text, back text)
|
|
54
|
+
2. Upload and validate media files separately
|
|
55
|
+
3. Collect MediaAttachment objects
|
|
56
|
+
4. Call createMultimediaCard with data
|
|
57
|
+
5. Receive complete MultimediaFlashcard object
|
|
58
|
+
6. Use returned card for display and storage
|
|
59
|
+
|
|
60
|
+
### Flashcard Structure
|
|
61
|
+
|
|
62
|
+
MultimediaFlashcard includes:
|
|
63
|
+
- id: Unique card identifier
|
|
64
|
+
- front: Front side content (question/prompt)
|
|
65
|
+
- back: Back side content (answer/explanation)
|
|
66
|
+
- difficulty: easy/medium/hard
|
|
67
|
+
- tags: Array of topic tags
|
|
68
|
+
- media: Array of MediaAttachment objects
|
|
69
|
+
- hasMedia: Boolean flag for media presence
|
|
70
|
+
- mediaType: Array of unique media types present
|
|
71
|
+
- isDownloaded: Boolean (all media downloaded)
|
|
72
|
+
- estimatedSize: Total size in bytes
|
|
73
|
+
- createdAt: ISO timestamp
|
|
74
|
+
|
|
75
|
+
### Media Analysis
|
|
76
|
+
|
|
77
|
+
**hasMedia**: True if media array has items
|
|
78
|
+
**mediaType**: Unique array of media types (image, audio, video)
|
|
79
|
+
**isDownloaded**: True if all media.isDownloaded are true
|
|
80
|
+
**estimatedSize**: Sum of all media.fileSize values
|
|
81
|
+
|
|
82
|
+
### Media Positioning
|
|
83
|
+
|
|
84
|
+
Media can be assigned to:
|
|
85
|
+
- **front**: Displayed on front side of card
|
|
86
|
+
- **back**: Displayed on back side of card
|
|
87
|
+
- **both**: Displayed on both sides
|
|
88
|
+
|
|
89
|
+
### Card Management Operations
|
|
90
|
+
|
|
91
|
+
**createMultimediaCard**: Create new card with media
|
|
92
|
+
- Validates required fields (front, back)
|
|
93
|
+
- Processes media array
|
|
94
|
+
- Generates unique ID
|
|
95
|
+
- Analyzes media composition
|
|
96
|
+
- Calculates estimated size
|
|
97
|
+
|
|
98
|
+
**updateMedia**: Replace media on existing card
|
|
99
|
+
- Updates media array
|
|
100
|
+
- Re-analyzes composition
|
|
101
|
+
- Recalculates size
|
|
102
|
+
- Preserves card ID and metadata
|
|
103
|
+
|
|
104
|
+
**deleteMedia**: Remove specific media attachment
|
|
105
|
+
- Removes from media array by ID
|
|
106
|
+
- Updates analysis
|
|
107
|
+
- Recalculates size
|
|
108
|
+
|
|
109
|
+
### Integration with Other Hooks
|
|
110
|
+
|
|
111
|
+
Typical workflow combining multiple hooks:
|
|
112
|
+
1. useMedia: Select images/videos
|
|
113
|
+
2. useMediaUpload: Upload selected media
|
|
114
|
+
3. useMediaValidation: Validate before upload
|
|
115
|
+
4. useMediaGeneration: Generate AI media (optional)
|
|
116
|
+
5. useMultimediaFlashcard: Create card with media
|
|
117
|
+
|
|
118
|
+
### Performance Considerations
|
|
119
|
+
|
|
120
|
+
- Limit media count per card (recommend 5-10 items)
|
|
121
|
+
- Monitor estimatedSize (warn over 25 MB)
|
|
122
|
+
- Use thumbnails for previews
|
|
123
|
+
- Lazy load media when displaying cards
|
|
124
|
+
- Cache cards with downloaded media
|
|
125
|
+
|
|
126
|
+
### Best Practices
|
|
127
|
+
|
|
128
|
+
1. Always validate media before adding to cards
|
|
129
|
+
2. Use descriptive tags for card organization
|
|
130
|
+
3. Set appropriate difficulty levels
|
|
131
|
+
4. Balance media types (don't overload with videos)
|
|
132
|
+
5. Consider offline usage (isDownloaded flag)
|
|
133
|
+
6. Provide captions for accessibility
|
|
134
|
+
|
|
135
|
+
## Dependencies
|
|
136
|
+
|
|
137
|
+
- MultimediaFlashcardService (infrastructure layer)
|
|
138
|
+
- Domain types: MultimediaFlashcard, MediaAttachment
|
|
139
|
+
- useMediaUpload (for media upload)
|
|
140
|
+
- useMediaValidation (for media validation)
|
|
141
|
+
- useMediaGeneration (for AI media generation)
|