@umituz/react-native-design-system 2.8.8 → 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 +6 -1
- package/src/exports/media.ts +1 -0
- package/src/index.ts +5 -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/storage/infrastructure/repositories/__tests__/AsyncStorageRepository.test.ts +1 -1
- package/src/storage/infrastructure/repositories/__tests__/BaseStorageOperations.test.ts +1 -1
|
@@ -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
|
+
}
|
|
@@ -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
|