@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,120 @@
|
|
|
1
|
+
# MediaSaveService
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
Handles saving image and video files to the device's photo gallery, including album management and permission handling.
|
|
5
|
+
|
|
6
|
+
## File Location
|
|
7
|
+
`/Users/umituz/Desktop/github/umituz/apps/artificial_intelligence/npm-packages/react-native-media/src/infrastructure/services/MediaSaveService`
|
|
8
|
+
|
|
9
|
+
## Strategy
|
|
10
|
+
|
|
11
|
+
### Core Purpose
|
|
12
|
+
- Save media files to device gallery
|
|
13
|
+
- Create and manage custom albums
|
|
14
|
+
- Handle platform-specific save requirements
|
|
15
|
+
- Manage write permissions for media library
|
|
16
|
+
|
|
17
|
+
### Usage Scenarios
|
|
18
|
+
- Saving downloaded images to gallery
|
|
19
|
+
- Creating app-specific albums
|
|
20
|
+
- Saving captured media to gallery
|
|
21
|
+
- Organizing media into custom collections
|
|
22
|
+
- Backup workflows
|
|
23
|
+
|
|
24
|
+
### Integration Points
|
|
25
|
+
- After media download completes
|
|
26
|
+
- After media generation/creation
|
|
27
|
+
- User-initiated save actions
|
|
28
|
+
- Batch media save operations
|
|
29
|
+
|
|
30
|
+
## Forbidden
|
|
31
|
+
|
|
32
|
+
### MUST NOT
|
|
33
|
+
- Save files without proper write permissions
|
|
34
|
+
- Assume album creation always succeeds
|
|
35
|
+
- Create duplicate albums with same name
|
|
36
|
+
- Overwrite existing media without user consent
|
|
37
|
+
- Save invalid or corrupted media files
|
|
38
|
+
- Ignore save operation results
|
|
39
|
+
|
|
40
|
+
### MUST NEVER
|
|
41
|
+
- Attempt to save when permission is denied
|
|
42
|
+
- Assume save operation is instant
|
|
43
|
+
- Save to private app storage using this service
|
|
44
|
+
- Modify saved media after save operation completes
|
|
45
|
+
- Bypass platform-specific save restrictions
|
|
46
|
+
|
|
47
|
+
## Rules
|
|
48
|
+
|
|
49
|
+
### Permission Management
|
|
50
|
+
- MUST request write permission before saving
|
|
51
|
+
- MUST check permission status before operations
|
|
52
|
+
- MUST handle permission denial gracefully
|
|
53
|
+
- MUST provide clear error messages for permission issues
|
|
54
|
+
- MUST respect user's permission decisions
|
|
55
|
+
|
|
56
|
+
### Save Operations
|
|
57
|
+
- MUST validate file URI/path before saving
|
|
58
|
+
- MUST determine media type (image/video) correctly
|
|
59
|
+
- MUST handle save failures appropriately
|
|
60
|
+
- MUST return success/failure status
|
|
61
|
+
- MUST include asset ID in successful results
|
|
62
|
+
|
|
63
|
+
### Album Management
|
|
64
|
+
- MUST create album automatically if it doesn't exist
|
|
65
|
+
- MUST NOT create duplicate albums with same name
|
|
66
|
+
- MUST save to default gallery if no album specified
|
|
67
|
+
- MUST handle album creation failures
|
|
68
|
+
- MUST validate album names
|
|
69
|
+
|
|
70
|
+
### Error Handling
|
|
71
|
+
- MUST catch and report save failures
|
|
72
|
+
- MUST handle invalid file paths
|
|
73
|
+
- MUST handle insufficient storage scenarios
|
|
74
|
+
- MUST provide meaningful error messages
|
|
75
|
+
- MUST allow retry after permission grant
|
|
76
|
+
|
|
77
|
+
### Platform Considerations
|
|
78
|
+
- MUST handle iOS save requirements
|
|
79
|
+
- MUST handle Android scoped storage (API 10+)
|
|
80
|
+
- MUST account for platform-specific restrictions
|
|
81
|
+
- MUST test on both platforms
|
|
82
|
+
|
|
83
|
+
## AI Agent Guidelines
|
|
84
|
+
|
|
85
|
+
### When Implementing Save Operations
|
|
86
|
+
1. Always check permissions before attempting save
|
|
87
|
+
2. Validate file URI/path exists and is accessible
|
|
88
|
+
3. Determine correct media type for the file
|
|
89
|
+
4. Handle both success and failure cases
|
|
90
|
+
5. Provide user feedback for save operations
|
|
91
|
+
|
|
92
|
+
### When Working with Albums
|
|
93
|
+
- Check if album exists before creating
|
|
94
|
+
- Use consistent album naming
|
|
95
|
+
- Handle album creation failures gracefully
|
|
96
|
+
- Allow saving to default gallery as fallback
|
|
97
|
+
|
|
98
|
+
### When Adding Features
|
|
99
|
+
- Add new media types with proper validation
|
|
100
|
+
- Extend save options without breaking changes
|
|
101
|
+
- Maintain backward compatibility
|
|
102
|
+
- Add error handling for new edge cases
|
|
103
|
+
|
|
104
|
+
### When Refactoring
|
|
105
|
+
- Keep public API stable
|
|
106
|
+
- Preserve permission handling logic
|
|
107
|
+
- Maintain platform-specific behavior
|
|
108
|
+
- Don't remove existing save methods without deprecation
|
|
109
|
+
|
|
110
|
+
### Common Patterns to Follow
|
|
111
|
+
- Request permission -> Check status -> Validate file -> Save
|
|
112
|
+
- Handle result -> Check success -> Return asset ID or error
|
|
113
|
+
- Always wrap in try-catch for unexpected errors
|
|
114
|
+
- Provide user feedback for save status
|
|
115
|
+
|
|
116
|
+
## Dependencies
|
|
117
|
+
|
|
118
|
+
- Domain types: MediaType, MediaLibraryPermission from Media
|
|
119
|
+
- External libraries: expo-media-library
|
|
120
|
+
- No internal utility dependencies
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Media Save Service
|
|
3
|
+
* Save images and videos to device gallery
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as MediaLibrary from "expo-media-library";
|
|
7
|
+
import { MediaType, MediaLibraryPermission } from "../../domain/entities/Media";
|
|
8
|
+
|
|
9
|
+
export interface SaveResult {
|
|
10
|
+
success: boolean;
|
|
11
|
+
assetId?: string;
|
|
12
|
+
error?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface SaveOptions {
|
|
16
|
+
album?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Service for saving media to gallery
|
|
21
|
+
*/
|
|
22
|
+
export class MediaSaveService {
|
|
23
|
+
/**
|
|
24
|
+
* Request media library write permission
|
|
25
|
+
*/
|
|
26
|
+
static async requestPermission(): Promise<MediaLibraryPermission> {
|
|
27
|
+
try {
|
|
28
|
+
const { status } = await MediaLibrary.requestPermissionsAsync();
|
|
29
|
+
return MediaSaveService.mapPermissionStatus(status);
|
|
30
|
+
} catch {
|
|
31
|
+
return MediaLibraryPermission.DENIED;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Get current permission status
|
|
37
|
+
*/
|
|
38
|
+
static async getPermissionStatus(): Promise<MediaLibraryPermission> {
|
|
39
|
+
try {
|
|
40
|
+
const { status } = await MediaLibrary.getPermissionsAsync();
|
|
41
|
+
return MediaSaveService.mapPermissionStatus(status);
|
|
42
|
+
} catch {
|
|
43
|
+
return MediaLibraryPermission.DENIED;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Save image to gallery
|
|
49
|
+
*/
|
|
50
|
+
static async saveImage(
|
|
51
|
+
uri: string,
|
|
52
|
+
options?: SaveOptions
|
|
53
|
+
): Promise<SaveResult> {
|
|
54
|
+
return MediaSaveService.saveToGallery(uri, MediaType.IMAGE, options);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Save video to gallery
|
|
59
|
+
*/
|
|
60
|
+
static async saveVideo(
|
|
61
|
+
uri: string,
|
|
62
|
+
options?: SaveOptions
|
|
63
|
+
): Promise<SaveResult> {
|
|
64
|
+
return MediaSaveService.saveToGallery(uri, MediaType.VIDEO, options);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Save media (image or video) to gallery
|
|
69
|
+
*/
|
|
70
|
+
static async saveToGallery(
|
|
71
|
+
uri: string,
|
|
72
|
+
_mediaType: MediaType = MediaType.ALL,
|
|
73
|
+
options?: SaveOptions
|
|
74
|
+
): Promise<SaveResult> {
|
|
75
|
+
try {
|
|
76
|
+
const permission = await MediaSaveService.requestPermission();
|
|
77
|
+
|
|
78
|
+
if (permission === MediaLibraryPermission.DENIED) {
|
|
79
|
+
return {
|
|
80
|
+
success: false,
|
|
81
|
+
error: "Permission denied to save media",
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const asset = await MediaLibrary.createAssetAsync(uri);
|
|
86
|
+
|
|
87
|
+
if (options?.album) {
|
|
88
|
+
const album = await MediaSaveService.getOrCreateAlbum(options.album);
|
|
89
|
+
if (album) {
|
|
90
|
+
await MediaLibrary.addAssetsToAlbumAsync([asset], album, false);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
success: true,
|
|
96
|
+
assetId: asset.id,
|
|
97
|
+
};
|
|
98
|
+
} catch (error) {
|
|
99
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
100
|
+
return {
|
|
101
|
+
success: false,
|
|
102
|
+
error: `Failed to save media: ${message}`,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Get or create album
|
|
109
|
+
*/
|
|
110
|
+
private static async getOrCreateAlbum(
|
|
111
|
+
albumName: string
|
|
112
|
+
): Promise<MediaLibrary.Album | null> {
|
|
113
|
+
try {
|
|
114
|
+
const albums = await MediaLibrary.getAlbumsAsync();
|
|
115
|
+
const existingAlbum = albums.find((album) => album.title === albumName);
|
|
116
|
+
|
|
117
|
+
if (existingAlbum) {
|
|
118
|
+
return existingAlbum;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const asset = await MediaLibrary.getAssetsAsync({ first: 1 });
|
|
122
|
+
if (asset.assets.length > 0) {
|
|
123
|
+
const newAlbum = await MediaLibrary.createAlbumAsync(
|
|
124
|
+
albumName,
|
|
125
|
+
asset.assets[0],
|
|
126
|
+
false
|
|
127
|
+
);
|
|
128
|
+
return newAlbum;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return null;
|
|
132
|
+
} catch {
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Map permission status
|
|
139
|
+
*/
|
|
140
|
+
private static mapPermissionStatus(
|
|
141
|
+
status: MediaLibrary.PermissionStatus
|
|
142
|
+
): MediaLibraryPermission {
|
|
143
|
+
switch (status) {
|
|
144
|
+
case MediaLibrary.PermissionStatus.GRANTED:
|
|
145
|
+
return MediaLibraryPermission.GRANTED;
|
|
146
|
+
case MediaLibrary.PermissionStatus.DENIED:
|
|
147
|
+
return MediaLibraryPermission.DENIED;
|
|
148
|
+
case MediaLibrary.PermissionStatus.UNDETERMINED:
|
|
149
|
+
return MediaLibraryPermission.DENIED;
|
|
150
|
+
default:
|
|
151
|
+
return MediaLibraryPermission.DENIED;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# MediaUploadService
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
Manages media file uploads to remote servers, including compression, URL management, and download functionality.
|
|
5
|
+
|
|
6
|
+
## File Location
|
|
7
|
+
`/Users/umituz/Desktop/github/umituz/apps/artificial_intelligence/npm-packages/react-native-media/src/infrastructure/services/MediaUploadService`
|
|
8
|
+
|
|
9
|
+
## Strategy
|
|
10
|
+
|
|
11
|
+
### Core Purpose
|
|
12
|
+
- Upload media files to remote storage
|
|
13
|
+
- Generate and manage media URLs
|
|
14
|
+
- Support compression during upload
|
|
15
|
+
- Download media to local storage
|
|
16
|
+
- Generate thumbnails automatically
|
|
17
|
+
|
|
18
|
+
### Usage Scenarios
|
|
19
|
+
- User-generated content uploads
|
|
20
|
+
- Profile picture uploads
|
|
21
|
+
- Document/image sharing
|
|
22
|
+
- Media backup workflows
|
|
23
|
+
- Content delivery networks integration
|
|
24
|
+
|
|
25
|
+
### Integration Points
|
|
26
|
+
- Form submissions with media attachments
|
|
27
|
+
- Social media sharing features
|
|
28
|
+
- Cloud storage synchronization
|
|
29
|
+
- Content management systems
|
|
30
|
+
- Media delivery pipelines
|
|
31
|
+
|
|
32
|
+
## Forbidden
|
|
33
|
+
|
|
34
|
+
### MUST NOT
|
|
35
|
+
- Upload invalid or corrupted files
|
|
36
|
+
- Assume network is always available
|
|
37
|
+
- Upload without file size limits
|
|
38
|
+
- Ignore authentication requirements
|
|
39
|
+
- Store sensitive credentials in service
|
|
40
|
+
- Generate duplicate URLs for same media
|
|
41
|
+
|
|
42
|
+
### MUST NEVER
|
|
43
|
+
- Upload without proper error handling
|
|
44
|
+
- Assume upload progress is always available
|
|
45
|
+
- Retry failed uploads indefinitely
|
|
46
|
+
- Expose sensitive upload endpoints
|
|
47
|
+
- Upload without user consent
|
|
48
|
+
- Ignore network timeout scenarios
|
|
49
|
+
|
|
50
|
+
## Rules
|
|
51
|
+
|
|
52
|
+
### Upload Operations
|
|
53
|
+
- MUST validate file before upload
|
|
54
|
+
- MUST handle network errors gracefully
|
|
55
|
+
- MUST support compression options
|
|
56
|
+
- MUST return unique media ID
|
|
57
|
+
- MUST provide upload progress when possible
|
|
58
|
+
- MUST handle timeout scenarios
|
|
59
|
+
|
|
60
|
+
### Compression Options
|
|
61
|
+
- MUST support quality adjustment (0-1)
|
|
62
|
+
- MUST support max width/height constraints
|
|
63
|
+
- MUST support format conversion (jpeg/png)
|
|
64
|
+
- MUST validate compression parameters
|
|
65
|
+
- MUST apply compression before upload
|
|
66
|
+
|
|
67
|
+
### URL Management
|
|
68
|
+
- MUST generate unique URLs for each media
|
|
69
|
+
- MUST support URL retrieval by media ID
|
|
70
|
+
- MUST handle invalid media IDs
|
|
71
|
+
- MUST maintain URL consistency
|
|
72
|
+
- MUST support URL expiration if required
|
|
73
|
+
|
|
74
|
+
### Download Operations
|
|
75
|
+
- MUST validate media ID before download
|
|
76
|
+
- MUST handle download failures
|
|
77
|
+
- MUST return local file path
|
|
78
|
+
- MUST manage storage space
|
|
79
|
+
- MUST support large file downloads
|
|
80
|
+
|
|
81
|
+
### Return Values
|
|
82
|
+
- MUST include media metadata (type, size, MIME)
|
|
83
|
+
- MUST include unique identifier
|
|
84
|
+
- MUST include URL (full or relative)
|
|
85
|
+
- MUST include thumbnail for applicable types
|
|
86
|
+
- MUST include duration for audio/video
|
|
87
|
+
|
|
88
|
+
### Error Handling
|
|
89
|
+
- MUST catch network errors
|
|
90
|
+
- MUST handle authentication failures
|
|
91
|
+
- MUST handle storage quota exceeded
|
|
92
|
+
- MUST provide meaningful error messages
|
|
93
|
+
- MUST allow retry after failure
|
|
94
|
+
|
|
95
|
+
## AI Agent Guidelines
|
|
96
|
+
|
|
97
|
+
### When Implementing Upload Features
|
|
98
|
+
1. Always validate file metadata before upload
|
|
99
|
+
2. Apply compression options if specified
|
|
100
|
+
3. Generate unique media identifier
|
|
101
|
+
4. Handle network failures gracefully
|
|
102
|
+
5. Return complete media attachment object
|
|
103
|
+
|
|
104
|
+
### When Working with URLs
|
|
105
|
+
- Generate unique, predictable URLs
|
|
106
|
+
- Support both absolute and relative URLs
|
|
107
|
+
- Include media ID in URL structure
|
|
108
|
+
- Handle URL generation failures
|
|
109
|
+
|
|
110
|
+
### When Adding Features
|
|
111
|
+
- Add new media types with validation
|
|
112
|
+
- Extend compression options carefully
|
|
113
|
+
- Maintain backward compatibility
|
|
114
|
+
- Add progress tracking for large files
|
|
115
|
+
- Support batch uploads if needed
|
|
116
|
+
|
|
117
|
+
### When Refactoring
|
|
118
|
+
- Keep upload API stable
|
|
119
|
+
- Preserve media ID generation logic
|
|
120
|
+
- Maintain URL structure consistency
|
|
121
|
+
- Don't change return value structure
|
|
122
|
+
- Add deprecation warnings for breaking changes
|
|
123
|
+
|
|
124
|
+
### Common Patterns to Follow
|
|
125
|
+
- Validate file -> Apply compression -> Upload -> Return attachment
|
|
126
|
+
- Handle network errors -> Retry if appropriate -> Return error
|
|
127
|
+
- Generate URL -> Store mapping -> Return URL
|
|
128
|
+
- Always wrap network operations in try-catch
|
|
129
|
+
- Provide user feedback for upload progress
|
|
130
|
+
|
|
131
|
+
## Dependencies
|
|
132
|
+
|
|
133
|
+
- Domain types: MediaAttachment, MediaCompressionOptions from MultimediaFlashcardTypes
|
|
134
|
+
- Internal utilities: mediaHelpers (generateThumbnail, getMediaDuration, getMediaType)
|
|
135
|
+
- No external library dependencies (uses native APIs and fetch)
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Media Upload Service
|
|
3
|
+
* Handles media upload, download, and URL operations
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type {
|
|
7
|
+
MediaAttachment,
|
|
8
|
+
MediaCompressionOptions,
|
|
9
|
+
} from "../../domain/entities/MultimediaFlashcardTypes";
|
|
10
|
+
import {
|
|
11
|
+
generateThumbnail,
|
|
12
|
+
getMediaDuration,
|
|
13
|
+
getMediaType,
|
|
14
|
+
} from "../utils/mediaHelpers";
|
|
15
|
+
|
|
16
|
+
export class MediaUploadService {
|
|
17
|
+
/**
|
|
18
|
+
* Upload media file with optional compression
|
|
19
|
+
*/
|
|
20
|
+
async uploadMedia(
|
|
21
|
+
file: any,
|
|
22
|
+
_options?: MediaCompressionOptions,
|
|
23
|
+
): Promise<MediaAttachment> {
|
|
24
|
+
try {
|
|
25
|
+
// Simulate upload process
|
|
26
|
+
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
27
|
+
|
|
28
|
+
const attachment: MediaAttachment = {
|
|
29
|
+
id: `media_${Date.now()}`,
|
|
30
|
+
type: getMediaType(file.type),
|
|
31
|
+
position: "both",
|
|
32
|
+
url: `https://storage.example.com/media/${Date.now()}_${file.name}`,
|
|
33
|
+
filename: file.name,
|
|
34
|
+
fileSize: file.size || 100000,
|
|
35
|
+
mimeType: file.type,
|
|
36
|
+
duration: await getMediaDuration(file),
|
|
37
|
+
thumbnailUrl: generateThumbnail(file),
|
|
38
|
+
caption: "",
|
|
39
|
+
isDownloaded: true,
|
|
40
|
+
createdAt: new Date().toISOString(),
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
return attachment;
|
|
44
|
+
} catch (error) {
|
|
45
|
+
throw new Error(`Failed to upload media: ${error}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Get media URL
|
|
51
|
+
*/
|
|
52
|
+
async getMediaUrl(attachmentId: string): Promise<string> {
|
|
53
|
+
return `https://storage.example.com/media/${attachmentId}`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Download media to local storage
|
|
58
|
+
*/
|
|
59
|
+
async downloadMedia(attachmentId: string): Promise<string> {
|
|
60
|
+
return `/local/storage/${attachmentId}`;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# MediaValidationService
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
Validates media files before upload by checking file size, type, and other properties to ensure compatibility and performance.
|
|
5
|
+
|
|
6
|
+
## File Location
|
|
7
|
+
`/Users/umituz/Desktop/github/umituz/apps/artificial_intelligence/npm-packages/react-native-media/src/infrastructure/services/MediaValidationService`
|
|
8
|
+
|
|
9
|
+
## Strategy
|
|
10
|
+
|
|
11
|
+
### Core Purpose
|
|
12
|
+
- Validate media files before upload
|
|
13
|
+
- Check file size constraints
|
|
14
|
+
- Verify supported file types
|
|
15
|
+
- Provide actionable feedback (errors, warnings, recommendations)
|
|
16
|
+
- Prevent upload of invalid or problematic files
|
|
17
|
+
|
|
18
|
+
### Usage Scenarios
|
|
19
|
+
- Pre-upload validation checks
|
|
20
|
+
- Form submission workflows
|
|
21
|
+
- File selection validation
|
|
22
|
+
- User feedback on file issues
|
|
23
|
+
- Quality control processes
|
|
24
|
+
|
|
25
|
+
### Integration Points
|
|
26
|
+
- Before upload operations
|
|
27
|
+
- After file selection
|
|
28
|
+
- In form validation workflows
|
|
29
|
+
- User input feedback loops
|
|
30
|
+
- File processing pipelines
|
|
31
|
+
|
|
32
|
+
## Forbidden
|
|
33
|
+
|
|
34
|
+
### MUST NOT
|
|
35
|
+
- Allow uploads of files exceeding size limits
|
|
36
|
+
- Accept unsupported file types
|
|
37
|
+
- Ignore validation results
|
|
38
|
+
- Proceed with upload when isValid is false
|
|
39
|
+
- Assume all files are valid
|
|
40
|
+
- Skip validation for performance
|
|
41
|
+
|
|
42
|
+
### MUST NEVER
|
|
43
|
+
- Upload files with errors
|
|
44
|
+
- Modify files during validation
|
|
45
|
+
- Cache validation results indefinitely
|
|
46
|
+
- Assume synchronous validation
|
|
47
|
+
- Ignore platform-specific constraints
|
|
48
|
+
- Allow bypass of critical validation rules
|
|
49
|
+
|
|
50
|
+
## Rules
|
|
51
|
+
|
|
52
|
+
### Validation Rules
|
|
53
|
+
- MUST check file size (max 50 MB)
|
|
54
|
+
- MUST check file type against supported formats
|
|
55
|
+
- MUST return validation result with isValid boolean
|
|
56
|
+
- MUST provide errors for upload-blocking issues
|
|
57
|
+
- MUST provide warnings for performance concerns
|
|
58
|
+
- MUST provide recommendations for improvements
|
|
59
|
+
|
|
60
|
+
### File Size Limits
|
|
61
|
+
- MUST reject files over 50 MB (error)
|
|
62
|
+
- MUST warn on files over 10 MB
|
|
63
|
+
- MUST recommend compression for large files
|
|
64
|
+
- MUST format file sizes for readability
|
|
65
|
+
- MUST consider media type for limits
|
|
66
|
+
|
|
67
|
+
### Supported File Types
|
|
68
|
+
- Images: JPEG, PNG, WebP
|
|
69
|
+
- Audio: MP3, WAV, M4A
|
|
70
|
+
- Video: MP4, MOV
|
|
71
|
+
- MUST validate MIME types
|
|
72
|
+
- MUST reject unsupported types with clear error
|
|
73
|
+
|
|
74
|
+
### Validation Results
|
|
75
|
+
- MUST include isValid boolean
|
|
76
|
+
- MUST include errors array (upload blockers)
|
|
77
|
+
- MUST include warnings array (performance impacts)
|
|
78
|
+
- MUST include recommendations array (improvements)
|
|
79
|
+
- MUST be serializable for transport
|
|
80
|
+
|
|
81
|
+
### Error Handling
|
|
82
|
+
- MUST handle missing file metadata
|
|
83
|
+
- MUST handle invalid file structures
|
|
84
|
+
- MUST handle async validation operations
|
|
85
|
+
- MUST provide specific error messages
|
|
86
|
+
- MUST support batch validation
|
|
87
|
+
|
|
88
|
+
### Feedback Levels
|
|
89
|
+
- Errors: Critical issues that prevent upload
|
|
90
|
+
- Warnings: Non-critical but impactful issues
|
|
91
|
+
- Recommendations: Suggestions for optimization
|
|
92
|
+
- MUST clearly distinguish between levels
|
|
93
|
+
|
|
94
|
+
## AI Agent Guidelines
|
|
95
|
+
|
|
96
|
+
### When Implementing Validation
|
|
97
|
+
1. Always check file metadata completeness
|
|
98
|
+
2. Validate size limits before processing
|
|
99
|
+
3. Check MIME type against allowed list
|
|
100
|
+
4. Provide specific, actionable error messages
|
|
101
|
+
5. Return structured validation result
|
|
102
|
+
|
|
103
|
+
### When Working with Validation Results
|
|
104
|
+
- Check isValid flag before proceeding
|
|
105
|
+
- Display errors to user (block upload)
|
|
106
|
+
- Show warnings to user (allow upload)
|
|
107
|
+
- Present recommendations as optional
|
|
108
|
+
- Format messages for user understanding
|
|
109
|
+
|
|
110
|
+
### When Adding Validation Rules
|
|
111
|
+
- Add new size limits with clear thresholds
|
|
112
|
+
- Add new file types with MIME validation
|
|
113
|
+
- Add custom rules for specific use cases
|
|
114
|
+
- Maintain backward compatibility
|
|
115
|
+
- Document rule changes
|
|
116
|
+
|
|
117
|
+
### When Refactoring
|
|
118
|
+
- Keep validation API stable
|
|
119
|
+
- Preserve error message format
|
|
120
|
+
- Maintain validation logic flow
|
|
121
|
+
- Don't change result structure
|
|
122
|
+
- Add deprecation warnings for breaking changes
|
|
123
|
+
|
|
124
|
+
### Common Patterns to Follow
|
|
125
|
+
- Receive file -> Check metadata -> Validate rules -> Return result
|
|
126
|
+
- Check isValid -> If false, show errors -> If true, proceed
|
|
127
|
+
- Check size -> If large, warn and recommend compression
|
|
128
|
+
- Check type -> If invalid, error with supported types
|
|
129
|
+
- Always handle async validation properly
|
|
130
|
+
|
|
131
|
+
## Dependencies
|
|
132
|
+
|
|
133
|
+
- Domain types: MediaValidation from MultimediaFlashcardTypes
|
|
134
|
+
- Internal utilities: mediaHelpers (formatFileSize)
|
|
135
|
+
- No external library dependencies (uses native File API)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Media Validation Service
|
|
3
|
+
* Handles media file validation before upload
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { formatFileSize } from "../utils/mediaHelpers";
|
|
7
|
+
import type { MediaValidation } from "../../domain/entities/MultimediaFlashcardTypes";
|
|
8
|
+
|
|
9
|
+
export class MediaValidationService {
|
|
10
|
+
/**
|
|
11
|
+
* Validate media file before upload
|
|
12
|
+
*/
|
|
13
|
+
async validateMedia(file: any): Promise<MediaValidation> {
|
|
14
|
+
try {
|
|
15
|
+
const errors: string[] = [];
|
|
16
|
+
const warnings: string[] = [];
|
|
17
|
+
const recommendations: string[] = [];
|
|
18
|
+
|
|
19
|
+
// File size validation
|
|
20
|
+
const maxSize = 50 * 1024 * 1024; // 50MB
|
|
21
|
+
if (file.size > maxSize) {
|
|
22
|
+
errors.push(
|
|
23
|
+
`File size (${formatFileSize(file.size)}) exceeds maximum allowed size (${formatFileSize(maxSize)})`,
|
|
24
|
+
);
|
|
25
|
+
} else if (file.size > 10 * 1024 * 1024) {
|
|
26
|
+
warnings.push(`Large file size may impact performance`);
|
|
27
|
+
recommendations.push("Consider compressing file");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// File type validation
|
|
31
|
+
const supportedTypes = [
|
|
32
|
+
"image/jpeg",
|
|
33
|
+
"image/png",
|
|
34
|
+
"image/webp",
|
|
35
|
+
"audio/mp3",
|
|
36
|
+
"audio/wav",
|
|
37
|
+
"audio/m4a",
|
|
38
|
+
"video/mp4",
|
|
39
|
+
"video/mov",
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
if (!supportedTypes.includes(file.type)) {
|
|
43
|
+
errors.push(`Unsupported file type: ${file.type}`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
isValid: errors.length === 0,
|
|
48
|
+
errors,
|
|
49
|
+
warnings,
|
|
50
|
+
recommendations,
|
|
51
|
+
};
|
|
52
|
+
} catch (error) {
|
|
53
|
+
return {
|
|
54
|
+
isValid: false,
|
|
55
|
+
errors: [error instanceof Error ? error.message : "Validation failed"],
|
|
56
|
+
warnings: [],
|
|
57
|
+
recommendations: [],
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|