@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,104 @@
1
+ /**
2
+ * Card Multimedia Flashcard Hooks
3
+ * Main hook and exports for card multimedia functionality
4
+ */
5
+
6
+ import React from "react";
7
+ import {
8
+ calculateTotalSize,
9
+ extractMediaTypes,
10
+ } from "../../infrastructure/utils/mediaHelpers";
11
+ import type { UseCardMultimediaFlashcardResult } from "./card-multimedia.types";
12
+ import type {
13
+ CardMediaAttachment,
14
+ CardMultimediaFlashcard,
15
+ } from "../../domain/entities/CardMultimedia.types";
16
+
17
+ // Export individual hooks
18
+ export { useCardMediaUpload } from "./useCardMediaUpload";
19
+ export { useCardMediaGeneration } from "./useCardMediaGeneration";
20
+ export { useCardMediaValidation } from "./useCardMediaValidation";
21
+
22
+ // Export types
23
+ export type {
24
+ UseCardMediaUploadResult,
25
+ UseCardMediaGenerationResult,
26
+ UseCardMediaValidationResult,
27
+ UseCardMultimediaFlashcardResult,
28
+ } from "./card-multimedia.types";
29
+
30
+ /**
31
+ * Main hook for card multimedia flashcard operations
32
+ */
33
+ export const useCardMultimediaFlashcard =
34
+ (): UseCardMultimediaFlashcardResult => {
35
+ const [isProcessing, setIsProcessing] = React.useState(false);
36
+ const [error, setError] = React.useState<string | null>(null);
37
+
38
+ const createCardMultimedia = React.useCallback(
39
+ async (cardData: any): Promise<CardMultimediaFlashcard> => {
40
+ try {
41
+ setIsProcessing(true);
42
+ setError(null);
43
+
44
+ // Simulate card creation
45
+ await new Promise((resolve) => setTimeout(resolve, 1000));
46
+
47
+ const card: CardMultimediaFlashcard = {
48
+ id: `card_multimedia_${Date.now()}`,
49
+ front: cardData.front || "",
50
+ back: cardData.back || "",
51
+ difficulty: cardData.difficulty || "medium",
52
+ tags: cardData.tags || [],
53
+ media: cardData.media || [],
54
+ hasMedia: (cardData.media || []).length > 0,
55
+ mediaType: extractMediaTypes(cardData.media || []),
56
+ isDownloaded: (cardData.media || []).every(
57
+ (m: any) => m.isDownloaded,
58
+ ),
59
+ estimatedSize: calculateTotalSize(cardData.media || []),
60
+ createdAt: new Date().toISOString(),
61
+ };
62
+
63
+ return card;
64
+ } catch (err) {
65
+ const errorMessage =
66
+ err instanceof Error ? err.message : "Card creation failed";
67
+ setError(errorMessage);
68
+ setIsProcessing(false);
69
+ throw err;
70
+ } finally {
71
+ setIsProcessing(false);
72
+ }
73
+ },
74
+ [],
75
+ );
76
+
77
+ const updateCardMedia = React.useCallback(
78
+ async (
79
+ cardId: string,
80
+ media: CardMediaAttachment[],
81
+ ): Promise<CardMultimediaFlashcard> => {
82
+ // Mock implementation
83
+ await new Promise((resolve) => setTimeout(resolve, 500));
84
+ return {} as CardMultimediaFlashcard;
85
+ },
86
+ [],
87
+ );
88
+
89
+ const deleteCardMedia = React.useCallback(
90
+ async (attachmentId: string): Promise<void> => {
91
+ // Mock implementation
92
+ await new Promise((resolve) => setTimeout(resolve, 500));
93
+ },
94
+ [],
95
+ );
96
+
97
+ return {
98
+ createCardMultimedia,
99
+ updateCardMedia,
100
+ deleteCardMedia,
101
+ isProcessing,
102
+ error,
103
+ };
104
+ };
@@ -0,0 +1,94 @@
1
+ # useMedia
2
+
3
+ ## Purpose
4
+ Core React hook for media selection operations (image/video picking, camera access) in React Native applications.
5
+
6
+ ## File Location
7
+ `src/presentation/hooks/useMedia.ts`
8
+
9
+ ## Strategy
10
+ - Provide unified interface for media picker and camera operations
11
+ - Abstract expo-image-picker complexity from components
12
+ - Centralize permission management logic
13
+ - Maintain consistent state management across media operations
14
+ - Enable type-safe media operations with proper TypeScript interfaces
15
+ - Support single and multiple media selection workflows
16
+ - Handle loading states and error propagation
17
+
18
+ ## Forbidden
19
+ - **DO NOT** expose expo-image-picker implementation details to consumers
20
+ - **DO NOT** automatically request permissions without explicit user action
21
+ - **DO NOT** mix camera and library picker logic in single operations
22
+ - **DO NOT** assume permission states - always check before operations
23
+ - **DO NOT** bypass error handling or loading states
24
+ - **DO NOT** use mock implementations in production without clear warnings
25
+ - **DO NOT** allow operations while previous operation is in progress
26
+ - **DO NOT** modify media assets after selection
27
+ - **DO NOT** store selected media permanently in hook state
28
+
29
+ ## Rules
30
+ 1. Always check permission status before camera/library operations
31
+ 2. All picker operations must return MediaPickerResult with canceled flag
32
+ 3. Loading state must be true during async operations
33
+ 4. Error state must be cleared on new operation attempts
34
+ 5. Permission requests must be explicit, not automatic
35
+ 6. Selected media must be validated against type definitions
36
+ 7. Quality parameters must be in 0-1 range
37
+ 8. Aspect ratio must be [width, height] tuple
38
+ 9. File size must be included when available from picker
39
+ 10. Support both single and multiple selection based on function used
40
+
41
+ ## AI Agent Guidelines
42
+
43
+ When working with useMedia hook:
44
+
45
+ 1. **Permission First**: Always request/check permissions before calling picker or camera functions
46
+ 2. **State Management**: Use isLoading to prevent duplicate operations during active calls
47
+ 3. **Error Handling**: Always check error state and handle user cancellation (canceled: true)
48
+ 4. **Type Safety**: Use MediaPickerOptions and CameraOptions interfaces for configuration
49
+ 5. **Validation**: Validate returned assets before processing (check if assets array exists)
50
+
51
+ ### Key Functions
52
+
53
+ - **pickImage**: Single image selection from library with optional editing
54
+ - **pickMultipleImages**: Multiple image selection with selection limit
55
+ - **pickVideo**: Video selection from library
56
+ - **launchCamera**: Photo capture via device camera
57
+ - **launchCameraForVideo**: Video recording via device camera
58
+ - **requestCameraPermission**: Request camera access permission
59
+ - **requestMediaLibraryPermission**: Request photo library access permission
60
+ - **getCameraPermissionStatus**: Check current camera permission state
61
+ - **getMediaLibraryPermissionStatus**: Check current library permission state
62
+
63
+ ### Media Selection Workflow
64
+
65
+ 1. Check permission status before operation
66
+ 2. Request permission if not granted
67
+ 3. Call appropriate picker/camera function with options
68
+ 4. Check canceled flag before processing assets
69
+ 5. Validate assets array exists and has items
70
+ 6. Process first asset (or all for multiple selection)
71
+
72
+ ### Quality Guidelines
73
+
74
+ - HIGH (1.0): Original quality, largest file size
75
+ - MEDIUM (0.7): Balanced quality and size (recommended)
76
+ - LOW (0.3): Smallest file size, reduced quality
77
+
78
+ ### Platform Requirements
79
+
80
+ - **iOS**: Add NSCameraUsageDescription and NSPhotoLibraryUsageDescription to Info.plist
81
+ - **Android**: Add CAMERA and READ_EXTERNAL_STORAGE permissions to AndroidManifest.xml
82
+
83
+ ### State Management
84
+
85
+ - **isLoading**: True during any async picker/camera operation
86
+ - **error**: String error message or null, cleared on new operations
87
+ - **MediaPickerResult.canceled**: True when user cancels operation
88
+ - **MediaPickerResult.assets**: Array of selected media or undefined
89
+
90
+ ## Dependencies
91
+
92
+ - MediaPickerService (infrastructure layer)
93
+ - Domain types: MediaAsset, MediaPickerResult, MediaPickerOptions, CameraOptions
94
+ - expo-image-picker (via service layer)
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Media Domain - useMedia Hook
3
+ *
4
+ * React hook for media picking operations (images, videos).
5
+ * Provides camera, gallery picking functionality.
6
+ */
7
+
8
+ import { useState, useCallback } from "react";
9
+ import { MediaPickerService } from "../../infrastructure/services/MediaPickerService";
10
+ import type {
11
+ MediaPickerOptions,
12
+ MediaPickerResult,
13
+ CameraOptions,
14
+ } from "../../domain/entities/Media";
15
+ import { MediaLibraryPermission } from "../../domain/entities/Media";
16
+
17
+ /**
18
+ * useMedia hook for complete media workflow
19
+ *
20
+ * USAGE:
21
+ * ```typescript
22
+ * const {
23
+ * pickImage,
24
+ * pickMultipleImages,
25
+ * launchCamera,
26
+ * isLoading,
27
+ * error,
28
+ * } = useMedia();
29
+ *
30
+ * const handlePickImage = async () => {
31
+ * const result = await pickImage({ allowsEditing: true });
32
+ * if (!result.canceled && result.assets) {
33
+ * console.log('Picked:', result.assets[0].uri);
34
+ * }
35
+ * };
36
+ * ```
37
+ */
38
+ export const useMedia = () => {
39
+ const [isLoading, setIsLoading] = useState(false);
40
+ const [error, setError] = useState<string | null>(null);
41
+
42
+ const pickImage = useCallback(
43
+ async (options?: MediaPickerOptions): Promise<MediaPickerResult> => {
44
+ setIsLoading(true);
45
+ setError(null);
46
+ try {
47
+ const result = await MediaPickerService.pickSingleImage(options);
48
+ return result;
49
+ } catch (err) {
50
+ const errorMessage =
51
+ err instanceof Error ? err.message : "Failed to pick image";
52
+ setError(errorMessage);
53
+ return { canceled: true };
54
+ } finally {
55
+ setIsLoading(false);
56
+ }
57
+ },
58
+ []
59
+ );
60
+
61
+ const pickMultipleImages = useCallback(
62
+ async (options?: MediaPickerOptions): Promise<MediaPickerResult> => {
63
+ setIsLoading(true);
64
+ setError(null);
65
+ try {
66
+ const result = await MediaPickerService.pickMultipleImages(options);
67
+ return result;
68
+ } catch (err) {
69
+ const errorMessage =
70
+ err instanceof Error ? err.message : "Failed to pick images";
71
+ setError(errorMessage);
72
+ return { canceled: true };
73
+ } finally {
74
+ setIsLoading(false);
75
+ }
76
+ },
77
+ []
78
+ );
79
+
80
+ const pickVideo = useCallback(
81
+ async (options?: MediaPickerOptions): Promise<MediaPickerResult> => {
82
+ setIsLoading(true);
83
+ setError(null);
84
+ try {
85
+ const result = await MediaPickerService.pickVideo(options);
86
+ return result;
87
+ } catch (err) {
88
+ const errorMessage =
89
+ err instanceof Error ? err.message : "Failed to pick video";
90
+ setError(errorMessage);
91
+ return { canceled: true };
92
+ } finally {
93
+ setIsLoading(false);
94
+ }
95
+ },
96
+ []
97
+ );
98
+
99
+ const launchCamera = useCallback(
100
+ async (options?: CameraOptions): Promise<MediaPickerResult> => {
101
+ setIsLoading(true);
102
+ setError(null);
103
+ try {
104
+ const result = await MediaPickerService.launchCamera(options);
105
+ return result;
106
+ } catch (err) {
107
+ const errorMessage =
108
+ err instanceof Error ? err.message : "Failed to launch camera";
109
+ setError(errorMessage);
110
+ return { canceled: true };
111
+ } finally {
112
+ setIsLoading(false);
113
+ }
114
+ },
115
+ []
116
+ );
117
+
118
+ const launchCameraForVideo = useCallback(
119
+ async (options?: CameraOptions): Promise<MediaPickerResult> => {
120
+ setIsLoading(true);
121
+ setError(null);
122
+ try {
123
+ const result = await MediaPickerService.launchCameraForVideo(options);
124
+ return result;
125
+ } catch (err) {
126
+ const errorMessage =
127
+ err instanceof Error ? err.message : "Failed to record video";
128
+ setError(errorMessage);
129
+ return { canceled: true };
130
+ } finally {
131
+ setIsLoading(false);
132
+ }
133
+ },
134
+ []
135
+ );
136
+
137
+ const requestCameraPermission =
138
+ useCallback(async (): Promise<MediaLibraryPermission> => {
139
+ try {
140
+ return await MediaPickerService.requestCameraPermission();
141
+ } catch {
142
+ return MediaLibraryPermission.DENIED;
143
+ }
144
+ }, []);
145
+
146
+ const requestMediaLibraryPermission =
147
+ useCallback(async (): Promise<MediaLibraryPermission> => {
148
+ try {
149
+ return await MediaPickerService.requestMediaLibraryPermission();
150
+ } catch {
151
+ return MediaLibraryPermission.DENIED;
152
+ }
153
+ }, []);
154
+
155
+ const getCameraPermissionStatus =
156
+ useCallback(async (): Promise<MediaLibraryPermission> => {
157
+ try {
158
+ return await MediaPickerService.getCameraPermissionStatus();
159
+ } catch {
160
+ return MediaLibraryPermission.DENIED;
161
+ }
162
+ }, []);
163
+
164
+ const getMediaLibraryPermissionStatus =
165
+ useCallback(async (): Promise<MediaLibraryPermission> => {
166
+ try {
167
+ return await MediaPickerService.getMediaLibraryPermissionStatus();
168
+ } catch {
169
+ return MediaLibraryPermission.DENIED;
170
+ }
171
+ }, []);
172
+
173
+ return {
174
+ pickImage,
175
+ pickMultipleImages,
176
+ pickVideo,
177
+ launchCamera,
178
+ launchCameraForVideo,
179
+ requestCameraPermission,
180
+ requestMediaLibraryPermission,
181
+ getCameraPermissionStatus,
182
+ getMediaLibraryPermissionStatus,
183
+ isLoading,
184
+ error,
185
+ };
186
+ };
@@ -0,0 +1,118 @@
1
+ # useMediaGeneration
2
+
3
+ ## Purpose
4
+ React hook for AI-powered media generation (text-to-image, text-to-audio) with result tracking.
5
+
6
+ ## File Location
7
+ `src/presentation/hooks/useMediaGeneration.ts`
8
+
9
+ ## Strategy
10
+ - Provide unified interface for AI media generation operations
11
+ - Support multiple generation types (text-to-image, text-to-audio)
12
+ - Track generation status and progress
13
+ - Manage credit usage and balance tracking
14
+ - Handle generation errors gracefully
15
+ - Return structured results with metadata
16
+ - Support customizable generation options
17
+
18
+ ## Forbidden
19
+ - **DO NOT** start new generation while previous is in progress
20
+ - **DO NOT** ignore credit costs before generation
21
+ - **DO NOT** mock generation process in production without API integration
22
+ - **DO NOT** assume generation will succeed - always check result.success
23
+ - **DO NOT** expose API keys or AI service implementation details
24
+ - **DO NOT** allow unlimited concurrent generations
25
+ - **DO NOT** bypass generation timeout handling
26
+ - **DO NOT** store large generation results permanently in hook state
27
+ - **DO NOT** use empty or invalid prompts for generation
28
+
29
+ ## Rules
30
+ 1. Always validate prompt text before generation
31
+ 2. Check credit availability before generation operations
32
+ 3. Track processing time for each generation request
33
+ 4. Return unique requestId for each generation
34
+ 5. Support maxResults parameter for multiple outputs
35
+ 6. Generation state must be cleared on new operations
36
+ 7. Include creditsUsed in result metadata
37
+ 8. Handle both success and failure in result object
38
+ 9. Support language and voice options for audio generation
39
+ 10. Support style options for image generation
40
+
41
+ ## AI Agent Guidelines
42
+
43
+ When working with useMediaGeneration hook:
44
+
45
+ 1. **Prompt Quality**: Use descriptive, specific prompts for better results
46
+ 2. **Credit Management**: Track credit costs and balance before operations
47
+ 3. **Error Handling**: Always check result.success field
48
+ 4. **Result Processing**: Validate attachments array before use
49
+ 5. **Options**: Use appropriate options for generation type
50
+
51
+ ### Generation Types
52
+
53
+ **Text-to-Image** (type: 'text_to_image')
54
+ - Generates images from text descriptions
55
+ - Credit cost: 5 per generation
56
+ - Default maxResults: 1
57
+ - Supports style customization
58
+
59
+ **Text-to-Audio** (type: 'text_to_audio')
60
+ - Generates audio from text (text-to-speech)
61
+ - Credit cost: 3 per generation
62
+ - Default duration: 10 seconds
63
+ - Supports voice, language, speed options
64
+
65
+ ### Generation Workflow
66
+
67
+ 1. Validate prompt text quality and length
68
+ 2. Check available credits
69
+ 3. Configure generation options
70
+ 4. Call generateMedia with request
71
+ 5. Monitor isGenerating state
72
+ 6. Process generationResult on completion
73
+ 7. Handle errors with user feedback
74
+
75
+ ### Result Structure
76
+
77
+ GenerationResult includes:
78
+ - success: Boolean indicating success/failure
79
+ - attachments: Array of generated MediaAttachment
80
+ - creditsUsed: Number of credits consumed
81
+ - processingTime: Duration in milliseconds
82
+ - requestId: Unique request identifier
83
+ - error: Error message if failed
84
+
85
+ ### Generation Options
86
+
87
+ **Image Options:**
88
+ - maxResults: Number of images to generate (default: 1)
89
+ - style: Image style preset
90
+
91
+ **Audio Options:**
92
+ - voice: Voice type (male/female)
93
+ - language: Language code (e.g., 'tr-TR', 'en-US')
94
+ - speed: Playback speed (default: 1.0)
95
+
96
+ ### Integration Requirements
97
+
98
+ - Configure AI API endpoints
99
+ - Implement authentication for AI services
100
+ - Handle rate limiting and quotas
101
+ - Implement retry logic for failed generations
102
+ - Cache generation results when appropriate
103
+ - Monitor credit balance and usage
104
+
105
+ ### Error Scenarios
106
+
107
+ - Insufficient credits: Check balance before generation
108
+ - Invalid prompt: Validate text quality and length
109
+ - API timeout: Implement retry with exponential backoff
110
+ - Content policy violations: Filter and validate prompts
111
+ - Service unavailable: Graceful degradation with error message
112
+
113
+ ## Dependencies
114
+
115
+ - MediaGenerationService (infrastructure layer)
116
+ - Domain types: MediaGenerationRequest, MediaGenerationResult, MediaAttachment
117
+ - Credit/balance tracking system
118
+ - AI service APIs (text-to-image, text-to-speech)
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Media Generation Hook
3
+ * Hook for generating media with AI
4
+ */
5
+
6
+ import React from "react";
7
+ import type { UseMediaGenerationResult } from "./multimedia.types";
8
+ import type {
9
+ MediaAttachment,
10
+ MediaGenerationRequest,
11
+ MediaGenerationResult,
12
+ } from "../../domain/entities/MultimediaFlashcardTypes";
13
+
14
+ export const useMediaGeneration = (): UseMediaGenerationResult => {
15
+ const [isGenerating, setIsGenerating] = React.useState(false);
16
+ const [generationResult, setGenerationResult] =
17
+ React.useState<MediaGenerationResult | null>(null);
18
+ const [error, setError] = React.useState<string | null>(null);
19
+
20
+ const generateMedia = React.useCallback(
21
+ async (request: MediaGenerationRequest): Promise<MediaGenerationResult> => {
22
+ try {
23
+ setIsGenerating(true);
24
+ setError(null);
25
+
26
+ // Simulate generation
27
+ await new Promise((resolve) => setTimeout(resolve, 3000));
28
+
29
+ const attachments: MediaAttachment[] = [];
30
+
31
+ switch (request.type) {
32
+ case "text_to_image":
33
+ for (let i = 0; i < (request.options.maxResults || 1); i++) {
34
+ attachments.push({
35
+ id: `ai_img_${Date.now()}_${i}`,
36
+ type: "image",
37
+ position: "both",
38
+ url: `https://picsum.photos/400/300?random=${Date.now() + i}`,
39
+ filename: `ai_generated_${i}.jpg`,
40
+ fileSize: 150000, // 150KB
41
+ mimeType: "image/jpeg",
42
+ isDownloaded: false,
43
+ createdAt: new Date().toISOString(),
44
+ });
45
+ }
46
+ break;
47
+
48
+ case "text_to_audio":
49
+ attachments.push({
50
+ id: `ai_audio_${Date.now()}`,
51
+ type: "audio",
52
+ position: "back",
53
+ url: `https://example.com/audio_${Date.now()}.mp3`,
54
+ filename: `ai_generated_${Date.now()}.mp3`,
55
+ fileSize: 80000, // 80KB
56
+ mimeType: "audio/mp3",
57
+ duration: 10, // 10 seconds
58
+ isDownloaded: false,
59
+ createdAt: new Date().toISOString(),
60
+ });
61
+ break;
62
+ }
63
+
64
+ const result: MediaGenerationResult = {
65
+ success: true,
66
+ attachments,
67
+ creditsUsed: request.type === "text_to_image" ? 5 : 3,
68
+ processingTime: 3000,
69
+ requestId: `req_${Date.now()}`,
70
+ };
71
+
72
+ setGenerationResult(result);
73
+ return result;
74
+ } catch (err) {
75
+ const errorMessage =
76
+ err instanceof Error ? err.message : "Generation failed";
77
+ setError(errorMessage);
78
+ setIsGenerating(false);
79
+
80
+ return {
81
+ success: false,
82
+ attachments: [],
83
+ creditsUsed: 0,
84
+ processingTime: 0,
85
+ error: errorMessage,
86
+ requestId: "",
87
+ };
88
+ } finally {
89
+ setIsGenerating(false);
90
+ }
91
+ },
92
+ [],
93
+ );
94
+
95
+ return {
96
+ generateMedia,
97
+ isGenerating,
98
+ generationResult,
99
+ error,
100
+ };
101
+ };