@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.
Files changed (65) hide show
  1. package/package.json +6 -1
  2. package/src/exports/media.ts +1 -0
  3. package/src/index.ts +5 -0
  4. package/src/media/domain/entities/CardMultimedia.types.README.md +129 -0
  5. package/src/media/domain/entities/CardMultimedia.types.ts +105 -0
  6. package/src/media/domain/entities/Media.README.md +80 -0
  7. package/src/media/domain/entities/Media.ts +139 -0
  8. package/src/media/domain/entities/MultimediaFlashcardTypes.README.md +144 -0
  9. package/src/media/domain/entities/MultimediaFlashcardTypes.ts +105 -0
  10. package/src/media/domain/utils/MediaUtils.README.md +178 -0
  11. package/src/media/domain/utils/MediaUtils.ts +82 -0
  12. package/src/media/index.ts +70 -0
  13. package/src/media/index.ts.README.md +191 -0
  14. package/src/media/infrastructure/services/CardMediaGenerationService.README.md +99 -0
  15. package/src/media/infrastructure/services/CardMediaGenerationService.ts +101 -0
  16. package/src/media/infrastructure/services/CardMediaOptimizerService.README.md +167 -0
  17. package/src/media/infrastructure/services/CardMediaOptimizerService.ts +36 -0
  18. package/src/media/infrastructure/services/CardMediaUploadService.README.md +123 -0
  19. package/src/media/infrastructure/services/CardMediaUploadService.ts +67 -0
  20. package/src/media/infrastructure/services/CardMediaValidationService.README.md +134 -0
  21. package/src/media/infrastructure/services/CardMediaValidationService.ts +81 -0
  22. package/src/media/infrastructure/services/CardMultimediaService.README.md +176 -0
  23. package/src/media/infrastructure/services/CardMultimediaService.ts +97 -0
  24. package/src/media/infrastructure/services/MediaGenerationService.README.md +142 -0
  25. package/src/media/infrastructure/services/MediaGenerationService.ts +80 -0
  26. package/src/media/infrastructure/services/MediaOptimizerService.README.md +145 -0
  27. package/src/media/infrastructure/services/MediaOptimizerService.ts +32 -0
  28. package/src/media/infrastructure/services/MediaPickerService.README.md +106 -0
  29. package/src/media/infrastructure/services/MediaPickerService.ts +173 -0
  30. package/src/media/infrastructure/services/MediaSaveService.README.md +120 -0
  31. package/src/media/infrastructure/services/MediaSaveService.ts +154 -0
  32. package/src/media/infrastructure/services/MediaUploadService.README.md +135 -0
  33. package/src/media/infrastructure/services/MediaUploadService.ts +62 -0
  34. package/src/media/infrastructure/services/MediaValidationService.README.md +135 -0
  35. package/src/media/infrastructure/services/MediaValidationService.ts +61 -0
  36. package/src/media/infrastructure/services/MultimediaFlashcardService.README.md +142 -0
  37. package/src/media/infrastructure/services/MultimediaFlashcardService.ts +95 -0
  38. package/src/media/infrastructure/utils/mediaHelpers.README.md +96 -0
  39. package/src/media/infrastructure/utils/mediaHelpers.ts +82 -0
  40. package/src/media/infrastructure/utils/mediaPickerMappers.README.md +129 -0
  41. package/src/media/infrastructure/utils/mediaPickerMappers.ts +76 -0
  42. package/src/media/presentation/hooks/card-multimedia.types.README.md +177 -0
  43. package/src/media/presentation/hooks/card-multimedia.types.ts +51 -0
  44. package/src/media/presentation/hooks/multimedia.types.README.md +201 -0
  45. package/src/media/presentation/hooks/multimedia.types.ts +51 -0
  46. package/src/media/presentation/hooks/useCardMediaGeneration.README.md +164 -0
  47. package/src/media/presentation/hooks/useCardMediaGeneration.ts +124 -0
  48. package/src/media/presentation/hooks/useCardMediaUpload.README.md +153 -0
  49. package/src/media/presentation/hooks/useCardMediaUpload.ts +86 -0
  50. package/src/media/presentation/hooks/useCardMediaValidation.README.md +176 -0
  51. package/src/media/presentation/hooks/useCardMediaValidation.ts +101 -0
  52. package/src/media/presentation/hooks/useCardMultimediaFlashcard.README.md +158 -0
  53. package/src/media/presentation/hooks/useCardMultimediaFlashcard.ts +104 -0
  54. package/src/media/presentation/hooks/useMedia.README.md +94 -0
  55. package/src/media/presentation/hooks/useMedia.ts +186 -0
  56. package/src/media/presentation/hooks/useMediaGeneration.README.md +118 -0
  57. package/src/media/presentation/hooks/useMediaGeneration.ts +101 -0
  58. package/src/media/presentation/hooks/useMediaUpload.README.md +108 -0
  59. package/src/media/presentation/hooks/useMediaUpload.ts +86 -0
  60. package/src/media/presentation/hooks/useMediaValidation.README.md +134 -0
  61. package/src/media/presentation/hooks/useMediaValidation.ts +93 -0
  62. package/src/media/presentation/hooks/useMultimediaFlashcard.README.md +141 -0
  63. package/src/media/presentation/hooks/useMultimediaFlashcard.ts +103 -0
  64. package/src/storage/infrastructure/repositories/__tests__/AsyncStorageRepository.test.ts +1 -1
  65. package/src/storage/infrastructure/repositories/__tests__/BaseStorageOperations.test.ts +1 -1
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Multimedia Flashcard Service
3
+ * Media attachments for flashcards - Main entry point
4
+ */
5
+
6
+ import type {
7
+ MediaAttachment,
8
+ MediaGenerationRequest,
9
+ MediaGenerationResult,
10
+ MediaCompressionOptions,
11
+ MediaValidation,
12
+ } from "../../domain/entities/MultimediaFlashcardTypes";
13
+ import { MediaUploadService } from "./MediaUploadService";
14
+ import { MediaGenerationService } from "./MediaGenerationService";
15
+ import { MediaValidationService } from "./MediaValidationService";
16
+ import { MediaOptimizerService } from "./MediaOptimizerService";
17
+
18
+ export class MultimediaFlashcardService {
19
+ private static instance: MultimediaFlashcardService;
20
+ private uploadService: MediaUploadService;
21
+ private generationService: MediaGenerationService;
22
+ private validationService: MediaValidationService;
23
+ private optimizerService: MediaOptimizerService;
24
+
25
+ private constructor() {
26
+ this.uploadService = new MediaUploadService();
27
+ this.generationService = new MediaGenerationService();
28
+ this.validationService = new MediaValidationService();
29
+ this.optimizerService = new MediaOptimizerService();
30
+ }
31
+
32
+ static getInstance(): MultimediaFlashcardService {
33
+ if (!MultimediaFlashcardService.instance) {
34
+ MultimediaFlashcardService.instance = new MultimediaFlashcardService();
35
+ }
36
+ return MultimediaFlashcardService.instance;
37
+ }
38
+
39
+ /**
40
+ * Upload media file with optional compression
41
+ */
42
+ async uploadMedia(
43
+ file: any,
44
+ options?: MediaCompressionOptions,
45
+ ): Promise<MediaAttachment> {
46
+ return this.uploadService.uploadMedia(file, options);
47
+ }
48
+
49
+ /**
50
+ * Generate media from AI (text-to-image, text-to-audio, etc.)
51
+ */
52
+ async generateMedia(
53
+ request: MediaGenerationRequest,
54
+ ): Promise<MediaGenerationResult> {
55
+ return this.generationService.generateMedia(request);
56
+ }
57
+
58
+ /**
59
+ * Validate media file before upload
60
+ */
61
+ async validateMedia(file: any): Promise<MediaValidation> {
62
+ return this.validationService.validateMedia(file);
63
+ }
64
+
65
+ /**
66
+ * Optimize media file
67
+ */
68
+ async optimizeMedia(
69
+ attachment: MediaAttachment,
70
+ options: MediaCompressionOptions,
71
+ ): Promise<MediaAttachment> {
72
+ return this.optimizerService.optimizeMedia(attachment, options);
73
+ }
74
+
75
+ /**
76
+ * Delete media attachment
77
+ */
78
+ async deleteMedia(attachmentId: string): Promise<void> {
79
+ return this.optimizerService.deleteMedia(attachmentId);
80
+ }
81
+
82
+ /**
83
+ * Get media URL
84
+ */
85
+ async getMediaUrl(attachmentId: string): Promise<string> {
86
+ return this.uploadService.getMediaUrl(attachmentId);
87
+ }
88
+
89
+ /**
90
+ * Download media to local storage
91
+ */
92
+ async downloadMedia(attachmentId: string): Promise<string> {
93
+ return this.uploadService.downloadMedia(attachmentId);
94
+ }
95
+ }
@@ -0,0 +1,96 @@
1
+ # Media Helper Utilities
2
+
3
+ ## Purpose
4
+ Core utility functions for media type detection, duration calculation, thumbnail generation, and file size operations.
5
+
6
+ ## File Location
7
+ `src/infrastructure/utils/mediaHelpers.ts`
8
+
9
+ ## Strategy
10
+ - Provide pure utility functions for common media operations
11
+ - Enable media type classification from MIME types
12
+ - Support file size calculations and formatting
13
+ - Generate thumbnails for video files
14
+ - Extract metadata from media collections
15
+ - Maintain framework-agnostic approach where possible
16
+
17
+ ## Forbidden
18
+ - **DO NOT** add business logic to utility functions
19
+ - **DO NOT** make network calls or API requests
20
+ - **DO NOT** modify input parameters (pure functions)
21
+ - **DO NOT** store state or cache results globally
22
+ - **DO NOT** depend on React or UI frameworks
23
+ - **DO NOT** throw exceptions without clear error messages
24
+ - **DO NOT** use locale-specific string formatting
25
+
26
+ ## Rules
27
+ 1. All functions must be pure (same input = same output)
28
+ 2. File size calculations must use bytes as the base unit
29
+ 3. Media type detection must use MIME type patterns
30
+ 4. Duration calculation must return seconds (or undefined for non-audio/video)
31
+ 5. Thumbnail generation must only return URLs for video files
32
+ 6. Type extraction must remove duplicates and preserve order
33
+ 7. Size formatting must use appropriate units (Bytes/KB/MB/GB)
34
+ 8. All functions must handle edge cases (empty arrays, null values)
35
+ 9. Must support both CardMediaAttachment and MediaAttachment types
36
+ 10. Must return fallback values for invalid inputs
37
+
38
+ ## AI Agent Guidelines
39
+
40
+ When working with media helper utilities:
41
+
42
+ 1. **Type Detection**: Always use `getCardMediaType()` for consistent type classification from MIME types
43
+ 2. **Size Calculations**: Use `calculateTotalSize()` for aggregating file sizes, never sum manually
44
+ 3. **Duration Handling**: Check for undefined return value from `getMediaDuration()` for non-audio/video files
45
+ 4. **Thumbnail Generation**: Only videos return thumbnail URLs; images return undefined
46
+ 5. **Type Extraction**: Use `extractMediaTypes()` to get unique media types from collections
47
+ 6. **Size Formatting**: Always use `formatFileSize()` for user-facing size displays
48
+ 7. **Null Safety**: Always handle null/undefined returns appropriately
49
+ 8. **Collection Operations**: Use provided utilities instead of manual array operations
50
+
51
+ ### Media Type Classification
52
+
53
+ - **Supported Types**: "image", "audio", "video"
54
+ - **Detection Method**: MIME type pattern matching
55
+ - **Default Behavior**: Unknown types default to "image"
56
+ - **Common Patterns**:
57
+ - Images: image/jpeg, image/png, image/gif, image/webp
58
+ - Audio: audio/mp3, audio/wav, audio/mpeg, audio/aac
59
+ - Video: video/mp4, video/quicktime, video/x-msvideo
60
+
61
+ ### File Size Operations
62
+
63
+ 1. **Aggregation**: `calculateTotalSize()` - Sum all file sizes in bytes
64
+ 2. **Formatting**: `formatFileSize()` - Convert bytes to readable format
65
+ 3. **Unit Selection**: Automatically chooses appropriate unit (Bytes/KB/MB/GB)
66
+ 4. **Rounding**: Rounds to 2 decimal places for KB and above
67
+
68
+ ### Duration and Metadata
69
+
70
+ 1. **Duration**: Returns seconds for audio/video, undefined for images
71
+ 2. **Thumbnails**: Only generated for video files using external service
72
+ 3. **Type Extraction**: Returns unique types in order of appearance
73
+ 4. **Media Support**: Works with both CardMediaAttachment and MediaAttachment
74
+
75
+ ### Error Handling
76
+
77
+ 1. Handle undefined returns from `getMediaDuration()` for images
78
+ 2. Handle undefined returns from `generateThumbnail()` for non-videos
79
+ 3. Validate MIME type strings before type detection
80
+ 4. Handle empty arrays in collection operations
81
+ 5. Always check for null/undefined file objects
82
+
83
+ ### Usage Patterns
84
+
85
+ 1. **Media Analysis**: Combine multiple utilities for comprehensive file analysis
86
+ 2. **Validation**: Use type detection and size calculation for pre-upload validation
87
+ 3. **Statistics**: Aggregate collection data using type extraction and size calculation
88
+ 4. **Display**: Format sizes for user interfaces using formatFileSize
89
+ 5. **Filtering**: Use extracted types for conditional logic and filtering
90
+
91
+ ## Dependencies
92
+
93
+ - Domain layer types (MediaAttachment, CardMediaAttachment)
94
+ - No external libraries
95
+ - No framework dependencies
96
+ - Pure TypeScript/JavaScript utilities
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Media Helper Utilities
3
+ * Shared helper functions for media operations
4
+ */
5
+
6
+ import type {
7
+ CardMediaAttachment,
8
+ CardMediaType,
9
+ } from "../../domain/entities/CardMultimedia.types";
10
+ import type { MediaAttachment } from "../../domain/entities/MultimediaFlashcardTypes";
11
+
12
+ /**
13
+ * Get media type from MIME type for CardMedia
14
+ */
15
+ export const getCardMediaType = (mimeType: string): CardMediaType => {
16
+ if (mimeType.startsWith("image/")) return "image";
17
+ if (mimeType.startsWith("audio/")) return "audio";
18
+ if (mimeType.startsWith("video/")) return "video";
19
+ return "image";
20
+ };
21
+
22
+ /**
23
+ * Get media type from MIME type for Media
24
+ */
25
+ export const getMediaType = (mimeType: string): "image" | "audio" | "video" => {
26
+ if (mimeType.startsWith("image/")) return "image";
27
+ if (mimeType.startsWith("audio/")) return "audio";
28
+ if (mimeType.startsWith("video/")) return "video";
29
+ return "image";
30
+ };
31
+
32
+ /**
33
+ * Get media duration for audio/video files
34
+ */
35
+ export const getMediaDuration = async (
36
+ file: any
37
+ ): Promise<number | undefined> => {
38
+ if (file.type.startsWith("audio/") || file.type.startsWith("video/")) {
39
+ return Math.floor(Math.random() * 60) + 10;
40
+ }
41
+ return undefined;
42
+ };
43
+
44
+ /**
45
+ * Generate thumbnail URL for video files
46
+ */
47
+ export const generateThumbnail = (file: any): string | undefined => {
48
+ if (file.type.startsWith("video/")) {
49
+ return `https://picsum.photos/200/150?random=${Date.now()}`;
50
+ }
51
+ return undefined;
52
+ };
53
+
54
+ /**
55
+ * Extract unique media types from attachments
56
+ */
57
+ export const extractMediaTypes = (
58
+ media: CardMediaAttachment[] | MediaAttachment[]
59
+ ): ("image" | "audio" | "video")[] => {
60
+ const types: Set<string> = new Set();
61
+ media.forEach((m) => types.add(m.type));
62
+ return Array.from(types) as ("image" | "audio" | "video")[];
63
+ };
64
+
65
+ /**
66
+ * Calculate total file size of media attachments
67
+ */
68
+ export const calculateTotalSize = (
69
+ media: CardMediaAttachment[] | MediaAttachment[]
70
+ ): number => {
71
+ return media.reduce((total, m) => total + m.fileSize, 0);
72
+ };
73
+
74
+ /**
75
+ * Format bytes to human-readable file size
76
+ */
77
+ export const formatFileSize = (bytes: number): string => {
78
+ const sizes = ["Bytes", "KB", "MB", "GB"];
79
+ if (bytes === 0) return "0 Bytes";
80
+ const i = Math.floor(Math.log(bytes) / Math.log(1024));
81
+ return Math.round((bytes / Math.pow(1024, i)) * 100) / 100 + " " + sizes[i];
82
+ };
@@ -0,0 +1,129 @@
1
+ # Media Picker Mappers
2
+
3
+ ## Purpose
4
+ Mapper functions to convert between expo-image-picker types and domain types, maintaining abstraction layer.
5
+
6
+ ## File Location
7
+ `src/infrastructure/utils/mediaPickerMappers.ts`
8
+
9
+ ## Strategy
10
+ - Isolate expo-image-picker dependency to infrastructure layer
11
+ - Provide clean mapping between external and domain types
12
+ - Handle permission status conversion
13
+ - Convert media type enums to library-specific formats
14
+ - Transform picker results to domain entities
15
+ - Maintain compatibility with expo-image-picker API changes
16
+
17
+ ## Forbidden
18
+ - **DO NOT** import expo-image-picker outside infrastructure layer
19
+ - **DO NOT** add business logic to mapping functions
20
+ - **DO NOT** modify input parameters during mapping
21
+ - **DO NOT** throw exceptions for invalid inputs (use defaults)
22
+ - **DO NOT** add side effects to mapping functions
23
+ - **DO NOT** directly use mapped types in domain or presentation layers
24
+ - **DO NOT** create circular dependencies with picker implementation
25
+
26
+ ## Rules
27
+ 1. All mapping functions must be pure transformations
28
+ 2. Permission status must map UNDETERMINED to DENIED
29
+ 3. MediaType must convert to array format for expo-image-picker
30
+ 4. Asset properties must use fallback values for undefined fields
31
+ 5. All mappers must handle null/undefined inputs gracefully
32
+ 6. Mapped types must match domain type contracts exactly
33
+ 7. Must preserve all original data during transformation
34
+ 8. Type conversion must be reversible where possible
35
+ 9. Must handle all enum values explicitly
36
+ 10. Default values must be documented
37
+
38
+ ## AI Agent Guidelines
39
+
40
+ When working with media picker mappers:
41
+
42
+ 1. **Layer Isolation**: Only use mappers in infrastructure layer, never in domain/presentation
43
+ 2. **Type Conversion**: Always use provided mappers, never manually convert types
44
+ 3. **Permission Handling**: Check mapped permission status, not raw expo-image-picker values
45
+ 4. **Media Types**: Use domain MediaType enum, then map to expo format when calling picker
46
+ 5. **Result Processing**: Always map picker results before passing to other layers
47
+ 6. **Fallback Values**: Be aware that asset properties may have default values
48
+ 7. **Null Safety**: Handle undefined optional properties in mapped results
49
+ 8. **Version Compatibility**: Update mappers when upgrading expo-image-picker
50
+
51
+ ### Permission Status Mapping
52
+
53
+ - **GRANTED** → GRANTED (full access)
54
+ - **DENIED** → DENIED (no access)
55
+ - **UNDETERMINED** → DENIED (treat as denied, request again)
56
+
57
+ **Strategy**: Convert undetermined to denied to force explicit permission request
58
+
59
+ ### MediaType Mapping
60
+
61
+ | Domain MediaType | expo-image-picker Format |
62
+ |-----------------|------------------------|
63
+ | IMAGE | ["images"] |
64
+ | VIDEO | ["videos"] |
65
+ | ALL | ["images", "videos"] |
66
+ | undefined | ["images"] (default) |
67
+
68
+ **Strategy**: Convert domain enum to array format required by library
69
+
70
+ ### Asset Transformation
71
+
72
+ All asset fields are mapped with fallback values:
73
+ - **uri**: Required, no fallback
74
+ - **width**: Number, fallback 0
75
+ - **height**: Number, fallback 0
76
+ - **type**: MediaType enum (IMAGE or VIDEO)
77
+ - **fileSize**: Number, fallback 0
78
+ - **fileName**: String or undefined
79
+ - **duration**: Number or undefined (video only)
80
+ - **base64**: String or undefined (only when requested)
81
+ - **mimeType**: String or undefined
82
+
83
+ ### Picker Result Structure
84
+
85
+ **Input Structure (expo-image-picker)**:
86
+ - A boolean `canceled` field indicating whether the user cancelled the operation
87
+ - An optional `assets` array containing Asset objects from expo-image-picker
88
+
89
+ **Output Structure (MediaPickerResult)**:
90
+ - A boolean `canceled` field (same as input)
91
+ - An optional `assets` array containing MediaAsset domain objects
92
+ - All Asset fields are transformed to MediaAsset fields with appropriate fallback values
93
+
94
+ ### Integration Patterns
95
+
96
+ 1. **Before Picker**: Convert domain types to picker types
97
+ 2. **After Picker**: Convert picker results to domain types
98
+ 3. **Permission Check**: Map permission status before domain layer access
99
+ 4. **Error Handling**: Check canceled flag before processing assets
100
+ 5. **Type Safety**: Use domain types throughout application logic
101
+
102
+ ### Common Workflows
103
+
104
+ 1. **Permission Request**: Check status → Map → Request → Map result
105
+ 2. **Media Selection**: Map MediaType → Launch picker → Map result
106
+ 3. **Multiple Selection**: Handle array of assets in mapper
107
+ 4. **Camera vs Library**: Use same mappers for both picker types
108
+
109
+ ### Validation Rules
110
+
111
+ 1. Always check `canceled` flag before accessing assets
112
+ 2. Validate assets array exists and has length > 0
113
+ 3. Handle undefined optional properties gracefully
114
+ 4. Check permission status before launching picker
115
+ 5. Handle null asset properties with fallback values
116
+
117
+ ### Error Handling
118
+
119
+ 1. Cancelled operations return `{ canceled: true }`
120
+ 2. Missing assets return empty array or undefined
121
+ 3. Invalid types use default fallback values
122
+ 4. Permission denied operations should be handled at application level
123
+ 5. Never throw exceptions from mapping functions
124
+
125
+ ## Dependencies
126
+
127
+ - expo-image-picker (external library)
128
+ - Domain layer types (MediaAsset, MediaPickerResult, MediaType, MediaLibraryPermission)
129
+ - Infrastructure layer only
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Media Picker Mapper Utilities
3
+ * Mapping functions for media picker operations
4
+ */
5
+
6
+ import * as ImagePicker from "expo-image-picker";
7
+ import {
8
+ MediaLibraryPermission,
9
+ MediaType,
10
+ type MediaAsset,
11
+ type MediaPickerResult,
12
+ } from "../../domain/entities/Media";
13
+
14
+ /**
15
+ * Map expo-image-picker permission status to MediaLibraryPermission
16
+ */
17
+ export const mapPermissionStatus = (
18
+ status: ImagePicker.PermissionStatus
19
+ ): MediaLibraryPermission => {
20
+ switch (status) {
21
+ case ImagePicker.PermissionStatus.GRANTED:
22
+ return MediaLibraryPermission.GRANTED;
23
+ case ImagePicker.PermissionStatus.DENIED:
24
+ return MediaLibraryPermission.DENIED;
25
+ case ImagePicker.PermissionStatus.UNDETERMINED:
26
+ return MediaLibraryPermission.DENIED;
27
+ default:
28
+ return MediaLibraryPermission.DENIED;
29
+ }
30
+ };
31
+
32
+ /**
33
+ * Map MediaType to expo-image-picker media types
34
+ */
35
+ export const mapMediaType = (
36
+ type?: MediaType
37
+ ): ImagePicker.MediaType[] => {
38
+ switch (type) {
39
+ case MediaType.IMAGE:
40
+ return ["images"];
41
+ case MediaType.VIDEO:
42
+ return ["videos"];
43
+ case MediaType.ALL:
44
+ return ["images", "videos"];
45
+ default:
46
+ return ["images"];
47
+ }
48
+ };
49
+
50
+ /**
51
+ * Map expo-image-picker result to MediaPickerResult
52
+ */
53
+ export const mapPickerResult = (
54
+ result: ImagePicker.ImagePickerResult
55
+ ): MediaPickerResult => {
56
+ if (result.canceled) {
57
+ return { canceled: true };
58
+ }
59
+
60
+ const assets: MediaAsset[] = result.assets.map((asset) => ({
61
+ uri: asset.uri,
62
+ width: asset.width,
63
+ height: asset.height,
64
+ type: asset.type === "video" ? MediaType.VIDEO : MediaType.IMAGE,
65
+ fileSize: asset.fileSize,
66
+ fileName: asset.fileName ?? undefined,
67
+ duration: asset.duration ?? undefined,
68
+ base64: asset.base64 ?? undefined,
69
+ mimeType: asset.mimeType ?? undefined,
70
+ }));
71
+
72
+ return {
73
+ canceled: false,
74
+ assets,
75
+ };
76
+ };
@@ -0,0 +1,177 @@
1
+ # Card Multimedia Hook Types
2
+
3
+ ## Purpose
4
+ TypeScript return type interfaces for card-specific multimedia hooks in the presentation layer.
5
+
6
+ ## File Location
7
+ `src/presentation/hooks/card-multimedia.types.ts`
8
+
9
+ ## Strategy
10
+ - Define contracts for card multimedia hook implementations
11
+ - Ensure type safety across card media operations
12
+ - Provide consistent return types for upload, generation, and validation
13
+ - Support card-specific media operations (including image search)
14
+ - Enable proper error handling and loading states
15
+ - Maintain separation between card and general multimedia types
16
+
17
+ ## Forbidden
18
+ - **DO NOT** import implementation details or hooks in type files
19
+ - **DO NOT** mix CardMediaAttachment and MediaAttachment types
20
+ - **DO NOT** add business logic to type definitions
21
+ - **DO NOT** use `any` type for function parameters or returns
22
+ - **DO NOT** create circular dependencies with domain types
23
+ - **DO NOT** export implementation-specific types
24
+ - **DO NOT** modify these types without updating all hook implementations
25
+
26
+ ## Rules
27
+ 1. All hook returns must include loading state, error state, and operation function
28
+ 2. Async operations must return Promise with appropriate type
29
+ 3. Error states must be string | null (not Error objects)
30
+ 4. Progress/results must be null when not active
31
+ 5. Boolean states must clearly indicate operation in progress
32
+ 6. All interfaces must be exported and public
33
+ 7. Type names must follow Use*Result pattern
34
+ 8. Functions must accept domain types, not external types
35
+ 9. Optional parameters must be clearly marked
36
+ 10. Return types must match hook implementations exactly
37
+
38
+ ## AI Agent Guidelines
39
+
40
+ When working with card multimedia hook types:
41
+
42
+ 1. **Type Imports**: Always import types from this file for card multimedia hooks
43
+ 2. **Hook Implementation**: Implement hooks that return these exact interfaces
44
+ 3. **Card vs General**: Use Card* types for card-specific operations, Media* for general
45
+ 4. **Error Handling**: Always check error state before using results
46
+ 5. **Loading States**: Respect loading states to prevent race conditions
47
+ 6. **Progress Tracking**: Use progress objects for upload operations
48
+ 7. **Type Safety**: Use these types for all card multimedia hook return values
49
+ 8. **Testing**: Mock these interfaces when testing card media operations
50
+
51
+ ### Hook Return Type Structure
52
+
53
+ All card multimedia hook returns follow this consistent pattern:
54
+
55
+ **Core Components**:
56
+ - **operationFunction**: An async function that accepts parameters and returns a Promise with the result type
57
+ - **isOperationInProgress**: A boolean flag indicating whether the operation is currently running
58
+ - **operationResult**: The result object or null when no operation is active
59
+ - **error**: A string containing error messages or null when no error exists
60
+
61
+ ### UseCardMediaUploadResult
62
+
63
+ **Purpose**: Card media upload operations with compression options
64
+
65
+ **Key Features**:
66
+ - Upload function accepts file and compression options
67
+ - Tracks upload progress
68
+ - Returns CardMediaAttachment
69
+ - Handles upload errors
70
+
71
+ **Usage Pattern**:
72
+ 1. Check `isUploading` before calling
73
+ 2. Call `uploadMedia()` with file and optional compression
74
+ 3. Monitor `uploadProgress` during upload
75
+ 4. Check `error` state on completion
76
+ 5. Use returned CardMediaAttachment on success
77
+
78
+ ### UseCardMediaGenerationResult
79
+
80
+ **Purpose**: Card media generation (AI-based generation, image search)
81
+
82
+ **Key Features**:
83
+ - Generation function accepts request parameters
84
+ - Tracks generation status
85
+ - Returns CardMediaGenerationResult
86
+ - Supports multiple generation methods
87
+
88
+ **Usage Pattern**:
89
+ 1. Prepare CardMediaGenerationRequest
90
+ 2. Check `isGenerating` before calling
91
+ 3. Call `generateMedia()` with request
92
+ 4. Access `generationResult` when complete
93
+ 5. Handle `error` if generation fails
94
+
95
+ ### UseCardMediaValidationResult
96
+
97
+ **Purpose**: Card media validation before upload or processing
98
+
99
+ **Key Features**:
100
+ - Validation function accepts file
101
+ - Tracks validation status
102
+ - Returns CardMediaValidation result
103
+ - Provides detailed validation errors
104
+
105
+ **Usage Pattern**:
106
+ 1. Check `isValidating` before calling
107
+ 2. Call `validateMedia()` with file
108
+ 3. Access `validation` result for validity check
109
+ 4. Use `validation.errors` array for error details
110
+ 5. Check `error` state for validation failures
111
+
112
+ ### UseCardMultimediaFlashcardResult
113
+
114
+ **Purpose**: Card flashcard CRUD operations
115
+
116
+ **Key Features**:
117
+ - Create card with multimedia
118
+ - Update card media
119
+ - Delete specific media attachment
120
+ - Tracks processing state
121
+ - Returns CardMultimediaFlashcard
122
+
123
+ **Usage Pattern**:
124
+ 1. Create: Call `createCardMultimedia()` with card data
125
+ 2. Update: Call `updateCardMedia()` with cardId and media array
126
+ 3. Delete: Call `deleteCardMedia()` with attachmentId
127
+ 4. Check `isProcessing` before operations
128
+ 5. Handle `error` state for failures
129
+
130
+ ### Card vs General Multimedia Types
131
+
132
+ | Operation | Card Types | General Types | Key Difference |
133
+ |-----------|-----------|---------------|----------------|
134
+ | Upload | CardMediaAttachment | MediaAttachment | Card-specific metadata |
135
+ | Generation | CardMediaGenerationRequest | MediaGenerationRequest | Cards include image search |
136
+ | Validation | CardMediaValidation | MediaValidation | Card-specific rules |
137
+ | Flashcard | CardMultimediaFlashcard | MultimediaFlashcard | Different entity types |
138
+
139
+ ### Type Guards and Validation
140
+
141
+ 1. **Upload Hook**: Check for `uploadMedia` function and `isUploading` boolean
142
+ 2. **Generation Hook**: Check for `generateMedia` function and `isGenerating` boolean
143
+ 3. **Validation Hook**: Check for `validateMedia` function and `isValidating` boolean
144
+ 4. **Flashcard Hook**: Check for all three CRUD functions and `isProcessing` boolean
145
+
146
+ ### Error Handling Patterns
147
+
148
+ 1. Always check if `error !== null` before using results
149
+ 2. Errors are strings, not Error objects
150
+ 3. Clear error before starting new operation
151
+ 4. Show user-friendly error messages
152
+ 5. Handle null states for progress/results
153
+
154
+ ### Async Operation Patterns
155
+
156
+ 1. **Before Call**: Check loading state to prevent concurrent calls
157
+ 2. **During Call**: Show loading indicator based on boolean state
158
+ 3. **After Call**: Check error state, then use result
159
+ 4. **Error Case**: Display error, reset loading state
160
+ 5. **Success Case**: Use result, clear error
161
+
162
+ ### Related Domain Types
163
+
164
+ These interfaces use domain types:
165
+ - CardMediaAttachment
166
+ - CardMediaGenerationRequest
167
+ - CardMediaGenerationResult
168
+ - CardMediaCompressionOptions
169
+ - CardMediaValidation
170
+ - CardMediaUploadProgress
171
+ - CardMultimediaFlashcard
172
+
173
+ ## Dependencies
174
+
175
+ - Domain layer types (Card* entities)
176
+ - Presentation layer hooks
177
+ - No external dependencies