@umituz/react-native-design-system 4.23.101 → 4.23.102
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 +1 -1
- package/src/media/index.ts +4 -1
- package/src/media/infrastructure/utils/PermissionManager.ts +1 -1
- package/src/media/infrastructure/utils/mediaPickerMappers.ts +1 -1
- package/src/storage/infrastructure/repositories/BaseStorageOperations.ts +4 -4
- package/src/media/domain/entities/MediaAttachments.ts +0 -101
- package/src/media/infrastructure/services/MediaGenerationService.ts +0 -80
- package/src/media/infrastructure/services/MediaOptimizerService.ts +0 -32
- package/src/media/infrastructure/services/MediaPickerService.ts +0 -157
- package/src/media/infrastructure/services/MediaSaveService.ts +0 -97
- package/src/media/infrastructure/services/MediaUploadService.ts +0 -60
- package/src/media/infrastructure/services/MediaValidationService.ts +0 -61
- package/src/media/infrastructure/services/MultimediaFlashcardService.ts +0 -96
- package/src/media/presentation/hooks/multimedia.types.ts +0 -53
- package/src/media/presentation/hooks/useCardMultimediaFlashcard.ts +0 -102
- package/src/media/presentation/hooks/useMedia.ts +0 -190
- package/src/media/presentation/hooks/useMediaGeneration.ts +0 -18
- package/src/media/presentation/hooks/useMediaUpload.ts +0 -84
- package/src/media/presentation/hooks/useMediaValidation.ts +0 -93
- package/src/media/presentation/hooks/useMultimediaFlashcard.ts +0 -101
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Multimedia Flashcard Service
|
|
3
|
-
* Media attachments for flashcards - Main entry point
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type {
|
|
7
|
-
MediaAttachment,
|
|
8
|
-
MediaFile,
|
|
9
|
-
MediaGenerationRequest,
|
|
10
|
-
MediaGenerationResult,
|
|
11
|
-
MediaCompressionOptions,
|
|
12
|
-
MediaValidation,
|
|
13
|
-
} from "../../domain/entities/MediaAttachments";
|
|
14
|
-
import { MediaUploadService } from "./MediaUploadService";
|
|
15
|
-
import { MediaGenerationService } from "./MediaGenerationService";
|
|
16
|
-
import { MediaValidationService } from "./MediaValidationService";
|
|
17
|
-
import { MediaOptimizerService } from "./MediaOptimizerService";
|
|
18
|
-
|
|
19
|
-
export class MultimediaFlashcardService {
|
|
20
|
-
private static instance: MultimediaFlashcardService;
|
|
21
|
-
private uploadService: MediaUploadService;
|
|
22
|
-
private generationService: MediaGenerationService;
|
|
23
|
-
private validationService: MediaValidationService;
|
|
24
|
-
private optimizerService: MediaOptimizerService;
|
|
25
|
-
|
|
26
|
-
private constructor() {
|
|
27
|
-
this.uploadService = new MediaUploadService();
|
|
28
|
-
this.generationService = new MediaGenerationService();
|
|
29
|
-
this.validationService = new MediaValidationService();
|
|
30
|
-
this.optimizerService = new MediaOptimizerService();
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
static getInstance(): MultimediaFlashcardService {
|
|
34
|
-
if (!MultimediaFlashcardService.instance) {
|
|
35
|
-
MultimediaFlashcardService.instance = new MultimediaFlashcardService();
|
|
36
|
-
}
|
|
37
|
-
return MultimediaFlashcardService.instance;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Upload media file with optional compression
|
|
42
|
-
*/
|
|
43
|
-
async uploadMedia(
|
|
44
|
-
file: MediaFile,
|
|
45
|
-
options?: MediaCompressionOptions,
|
|
46
|
-
): Promise<MediaAttachment> {
|
|
47
|
-
return this.uploadService.uploadMedia(file, options);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Generate media from AI (text-to-image, text-to-audio, etc.)
|
|
52
|
-
*/
|
|
53
|
-
async generateMedia(
|
|
54
|
-
request: MediaGenerationRequest,
|
|
55
|
-
): Promise<MediaGenerationResult> {
|
|
56
|
-
return this.generationService.generateMedia(request);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Validate media file before upload
|
|
61
|
-
*/
|
|
62
|
-
async validateMedia(file: MediaFile): Promise<MediaValidation> {
|
|
63
|
-
return this.validationService.validateMedia(file);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Optimize media file
|
|
68
|
-
*/
|
|
69
|
-
async optimizeMedia(
|
|
70
|
-
attachment: MediaAttachment,
|
|
71
|
-
options: MediaCompressionOptions,
|
|
72
|
-
): Promise<MediaAttachment> {
|
|
73
|
-
return this.optimizerService.optimizeMedia(attachment, options);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Delete media attachment
|
|
78
|
-
*/
|
|
79
|
-
async deleteMedia(attachmentId: string): Promise<void> {
|
|
80
|
-
return this.optimizerService.deleteMedia(attachmentId);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Get media URL
|
|
85
|
-
*/
|
|
86
|
-
async getMediaUrl(attachmentId: string): Promise<string> {
|
|
87
|
-
return this.uploadService.getMediaUrl(attachmentId);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Download media to local storage
|
|
92
|
-
*/
|
|
93
|
-
async downloadMedia(attachmentId: string): Promise<string> {
|
|
94
|
-
return this.uploadService.downloadMedia(attachmentId);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Multimedia Flashcard Hook Types
|
|
3
|
-
* Type definitions for multimedia hooks
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type {
|
|
7
|
-
MediaAttachment,
|
|
8
|
-
MediaFile,
|
|
9
|
-
MediaGenerationRequest,
|
|
10
|
-
MediaGenerationResult,
|
|
11
|
-
MediaCompressionOptions,
|
|
12
|
-
MediaValidation,
|
|
13
|
-
MediaUploadProgress,
|
|
14
|
-
MultimediaFlashcard,
|
|
15
|
-
CreateMultimediaCardData,
|
|
16
|
-
} from "../../domain/entities/MediaAttachments";
|
|
17
|
-
|
|
18
|
-
export interface UseMediaUploadResult {
|
|
19
|
-
uploadMedia: (
|
|
20
|
-
file: MediaFile,
|
|
21
|
-
options?: MediaCompressionOptions,
|
|
22
|
-
) => Promise<MediaAttachment>;
|
|
23
|
-
isUploading: boolean;
|
|
24
|
-
uploadProgress: MediaUploadProgress | null;
|
|
25
|
-
error: string | null;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export interface UseMediaGenerationResult {
|
|
29
|
-
generateMedia: (
|
|
30
|
-
request: MediaGenerationRequest,
|
|
31
|
-
) => Promise<MediaGenerationResult>;
|
|
32
|
-
isGenerating: boolean;
|
|
33
|
-
generationResult: MediaGenerationResult | null;
|
|
34
|
-
error: string | null;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface UseMediaValidationResult {
|
|
38
|
-
validateMedia: (file: MediaFile) => Promise<MediaValidation>;
|
|
39
|
-
isValidating: boolean;
|
|
40
|
-
validation: MediaValidation | null;
|
|
41
|
-
error: string | null;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export interface UseMultimediaFlashcardResult {
|
|
45
|
-
createMultimediaCard: (cardData: CreateMultimediaCardData) => Promise<MultimediaFlashcard>;
|
|
46
|
-
updateMedia: (
|
|
47
|
-
cardId: string,
|
|
48
|
-
media: MediaAttachment[],
|
|
49
|
-
) => Promise<MultimediaFlashcard>;
|
|
50
|
-
deleteMedia: (attachmentId: string) => Promise<void>;
|
|
51
|
-
isProcessing: boolean;
|
|
52
|
-
error: string | null;
|
|
53
|
-
}
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Card Multimedia Flashcard Hooks
|
|
3
|
-
* Main hook and exports for card multimedia functionality
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { useState, useCallback } from "react";
|
|
7
|
-
import { calculateTotalSize, extractMediaTypes } from "../../infrastructure/utils/media-collection-utils";
|
|
8
|
-
import type { UseCardMultimediaFlashcardResult } from "./card-multimedia.types";
|
|
9
|
-
import type {
|
|
10
|
-
MediaAttachment as CardMediaAttachment,
|
|
11
|
-
MultimediaFlashcard as CardMultimediaFlashcard,
|
|
12
|
-
CreateMultimediaCardData as CreateCardMultimediaData,
|
|
13
|
-
} from "../../domain/entities/MediaAttachments";
|
|
14
|
-
|
|
15
|
-
// Export individual hooks
|
|
16
|
-
export { useCardMediaUpload } from "./useCardMediaUpload";
|
|
17
|
-
export { useCardMediaGeneration } from "./useCardMediaGeneration";
|
|
18
|
-
export { useCardMediaValidation } from "./useCardMediaValidation";
|
|
19
|
-
|
|
20
|
-
// Export types
|
|
21
|
-
export type {
|
|
22
|
-
UseCardMediaUploadResult,
|
|
23
|
-
UseCardMediaGenerationResult,
|
|
24
|
-
UseCardMediaValidationResult,
|
|
25
|
-
UseCardMultimediaFlashcardResult,
|
|
26
|
-
} from "./card-multimedia.types";
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Main hook for card multimedia flashcard operations
|
|
30
|
-
*/
|
|
31
|
-
export const useCardMultimediaFlashcard =
|
|
32
|
-
(): UseCardMultimediaFlashcardResult => {
|
|
33
|
-
const [isProcessing, setIsProcessing] = useState(false);
|
|
34
|
-
const [error, setError] = useState<string | null>(null);
|
|
35
|
-
|
|
36
|
-
const createCardMultimedia = useCallback(
|
|
37
|
-
async (cardData: CreateCardMultimediaData): Promise<CardMultimediaFlashcard> => {
|
|
38
|
-
try {
|
|
39
|
-
setIsProcessing(true);
|
|
40
|
-
setError(null);
|
|
41
|
-
|
|
42
|
-
// Simulate card creation
|
|
43
|
-
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
44
|
-
|
|
45
|
-
const card: CardMultimediaFlashcard = {
|
|
46
|
-
id: `card_multimedia_${Date.now()}`,
|
|
47
|
-
front: cardData.front || "",
|
|
48
|
-
back: cardData.back || "",
|
|
49
|
-
difficulty: cardData.difficulty || "medium",
|
|
50
|
-
tags: cardData.tags || [],
|
|
51
|
-
media: cardData.media || [],
|
|
52
|
-
hasMedia: (cardData.media || []).length > 0,
|
|
53
|
-
mediaType: extractMediaTypes(cardData.media || []),
|
|
54
|
-
isDownloaded: (cardData.media || []).every(
|
|
55
|
-
(m: CardMediaAttachment) => m.isDownloaded,
|
|
56
|
-
),
|
|
57
|
-
estimatedSize: calculateTotalSize(cardData.media || []),
|
|
58
|
-
createdAt: new Date().toISOString(),
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
return card;
|
|
62
|
-
} catch (err) {
|
|
63
|
-
const errorMessage =
|
|
64
|
-
err instanceof Error ? err.message : "Card creation failed";
|
|
65
|
-
setError(errorMessage);
|
|
66
|
-
setIsProcessing(false);
|
|
67
|
-
throw err;
|
|
68
|
-
} finally {
|
|
69
|
-
setIsProcessing(false);
|
|
70
|
-
}
|
|
71
|
-
},
|
|
72
|
-
[],
|
|
73
|
-
);
|
|
74
|
-
|
|
75
|
-
const updateCardMedia = useCallback(
|
|
76
|
-
async (
|
|
77
|
-
_cardId: string,
|
|
78
|
-
_media: CardMediaAttachment[],
|
|
79
|
-
): Promise<CardMultimediaFlashcard> => {
|
|
80
|
-
// Mock implementation
|
|
81
|
-
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
82
|
-
return {} as CardMultimediaFlashcard;
|
|
83
|
-
},
|
|
84
|
-
[],
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
const deleteCardMedia = useCallback(
|
|
88
|
-
async (_attachmentId: string): Promise<void> => {
|
|
89
|
-
// Mock implementation
|
|
90
|
-
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
91
|
-
},
|
|
92
|
-
[],
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
return {
|
|
96
|
-
createCardMultimedia,
|
|
97
|
-
updateCardMedia,
|
|
98
|
-
deleteCardMedia,
|
|
99
|
-
isProcessing,
|
|
100
|
-
error,
|
|
101
|
-
};
|
|
102
|
-
};
|
|
@@ -1,190 +0,0 @@
|
|
|
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 { PermissionManager } from "../../infrastructure/utils/PermissionManager";
|
|
11
|
-
import type {
|
|
12
|
-
MediaPickerOptions,
|
|
13
|
-
MediaPickerResult,
|
|
14
|
-
CameraOptions,
|
|
15
|
-
} from "../../domain/entities/MediaAttachments";
|
|
16
|
-
import { MediaLibraryPermission } from "../../domain/entities/MediaAttachments";
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* useMedia hook for complete media workflow
|
|
20
|
-
*
|
|
21
|
-
* USAGE:
|
|
22
|
-
* ```typescript
|
|
23
|
-
* const {
|
|
24
|
-
* pickImage,
|
|
25
|
-
* pickMultipleImages,
|
|
26
|
-
* launchCamera,
|
|
27
|
-
* isLoading,
|
|
28
|
-
* error,
|
|
29
|
-
* } = useMedia();
|
|
30
|
-
*
|
|
31
|
-
* const handlePickImage = async () => {
|
|
32
|
-
* const result = await pickImage({ allowsEditing: true });
|
|
33
|
-
* if (!result.canceled && result.assets) {
|
|
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
|
-
// Set error from validation result if present
|
|
49
|
-
if (result.errorMessage) {
|
|
50
|
-
setError(result.errorMessage);
|
|
51
|
-
}
|
|
52
|
-
return result;
|
|
53
|
-
} catch (err) {
|
|
54
|
-
const errorMessage =
|
|
55
|
-
err instanceof Error ? err.message : "Failed to pick image";
|
|
56
|
-
setError(errorMessage);
|
|
57
|
-
return { canceled: true };
|
|
58
|
-
} finally {
|
|
59
|
-
setIsLoading(false);
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
|
-
[]
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
const pickMultipleImages = useCallback(
|
|
66
|
-
async (options?: MediaPickerOptions): Promise<MediaPickerResult> => {
|
|
67
|
-
setIsLoading(true);
|
|
68
|
-
setError(null);
|
|
69
|
-
try {
|
|
70
|
-
const result = await MediaPickerService.pickMultipleImages(options);
|
|
71
|
-
return result;
|
|
72
|
-
} catch (err) {
|
|
73
|
-
const errorMessage =
|
|
74
|
-
err instanceof Error ? err.message : "Failed to pick images";
|
|
75
|
-
setError(errorMessage);
|
|
76
|
-
return { canceled: true };
|
|
77
|
-
} finally {
|
|
78
|
-
setIsLoading(false);
|
|
79
|
-
}
|
|
80
|
-
},
|
|
81
|
-
[]
|
|
82
|
-
);
|
|
83
|
-
|
|
84
|
-
const pickVideo = useCallback(
|
|
85
|
-
async (options?: MediaPickerOptions): Promise<MediaPickerResult> => {
|
|
86
|
-
setIsLoading(true);
|
|
87
|
-
setError(null);
|
|
88
|
-
try {
|
|
89
|
-
const result = await MediaPickerService.pickVideo(options);
|
|
90
|
-
return result;
|
|
91
|
-
} catch (err) {
|
|
92
|
-
const errorMessage =
|
|
93
|
-
err instanceof Error ? err.message : "Failed to pick video";
|
|
94
|
-
setError(errorMessage);
|
|
95
|
-
return { canceled: true };
|
|
96
|
-
} finally {
|
|
97
|
-
setIsLoading(false);
|
|
98
|
-
}
|
|
99
|
-
},
|
|
100
|
-
[]
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
const launchCamera = useCallback(
|
|
104
|
-
async (options?: CameraOptions): Promise<MediaPickerResult> => {
|
|
105
|
-
setIsLoading(true);
|
|
106
|
-
setError(null);
|
|
107
|
-
try {
|
|
108
|
-
const result = await MediaPickerService.launchCamera(options);
|
|
109
|
-
return result;
|
|
110
|
-
} catch (err) {
|
|
111
|
-
const errorMessage =
|
|
112
|
-
err instanceof Error ? err.message : "Failed to launch camera";
|
|
113
|
-
setError(errorMessage);
|
|
114
|
-
return { canceled: true };
|
|
115
|
-
} finally {
|
|
116
|
-
setIsLoading(false);
|
|
117
|
-
}
|
|
118
|
-
},
|
|
119
|
-
[]
|
|
120
|
-
);
|
|
121
|
-
|
|
122
|
-
const launchCameraForVideo = useCallback(
|
|
123
|
-
async (options?: CameraOptions): Promise<MediaPickerResult> => {
|
|
124
|
-
setIsLoading(true);
|
|
125
|
-
setError(null);
|
|
126
|
-
try {
|
|
127
|
-
const result = await MediaPickerService.launchCameraForVideo(options);
|
|
128
|
-
return result;
|
|
129
|
-
} catch (err) {
|
|
130
|
-
const errorMessage =
|
|
131
|
-
err instanceof Error ? err.message : "Failed to record video";
|
|
132
|
-
setError(errorMessage);
|
|
133
|
-
return { canceled: true };
|
|
134
|
-
} finally {
|
|
135
|
-
setIsLoading(false);
|
|
136
|
-
}
|
|
137
|
-
},
|
|
138
|
-
[]
|
|
139
|
-
);
|
|
140
|
-
|
|
141
|
-
const requestCameraPermission =
|
|
142
|
-
useCallback(async (): Promise<MediaLibraryPermission> => {
|
|
143
|
-
try {
|
|
144
|
-
return await PermissionManager.requestCameraPermission();
|
|
145
|
-
} catch {
|
|
146
|
-
return MediaLibraryPermission.DENIED;
|
|
147
|
-
}
|
|
148
|
-
}, []);
|
|
149
|
-
|
|
150
|
-
const requestMediaLibraryPermission =
|
|
151
|
-
useCallback(async (): Promise<MediaLibraryPermission> => {
|
|
152
|
-
try {
|
|
153
|
-
return await PermissionManager.requestMediaLibraryPermission();
|
|
154
|
-
} catch {
|
|
155
|
-
return MediaLibraryPermission.DENIED;
|
|
156
|
-
}
|
|
157
|
-
}, []);
|
|
158
|
-
|
|
159
|
-
const getCameraPermissionStatus =
|
|
160
|
-
useCallback(async (): Promise<MediaLibraryPermission> => {
|
|
161
|
-
try {
|
|
162
|
-
return await PermissionManager.getCameraPermissionStatus();
|
|
163
|
-
} catch {
|
|
164
|
-
return MediaLibraryPermission.DENIED;
|
|
165
|
-
}
|
|
166
|
-
}, []);
|
|
167
|
-
|
|
168
|
-
const getMediaLibraryPermissionStatus =
|
|
169
|
-
useCallback(async (): Promise<MediaLibraryPermission> => {
|
|
170
|
-
try {
|
|
171
|
-
return await PermissionManager.getMediaLibraryPermissionStatus();
|
|
172
|
-
} catch {
|
|
173
|
-
return MediaLibraryPermission.DENIED;
|
|
174
|
-
}
|
|
175
|
-
}, []);
|
|
176
|
-
|
|
177
|
-
return {
|
|
178
|
-
pickImage,
|
|
179
|
-
pickMultipleImages,
|
|
180
|
-
pickVideo,
|
|
181
|
-
launchCamera,
|
|
182
|
-
launchCameraForVideo,
|
|
183
|
-
requestCameraPermission,
|
|
184
|
-
requestMediaLibraryPermission,
|
|
185
|
-
getCameraPermissionStatus,
|
|
186
|
-
getMediaLibraryPermissionStatus,
|
|
187
|
-
isLoading,
|
|
188
|
-
error,
|
|
189
|
-
};
|
|
190
|
-
};
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Media Generation Hook
|
|
3
|
-
* Hook for generating media with AI
|
|
4
|
-
* Now a thin wrapper around useGenericMediaGeneration
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { useGenericMediaGeneration } from "../../infrastructure/hooks/useGenericMediaGeneration";
|
|
8
|
-
import type { UseMediaGenerationResult } from "./multimedia.types";
|
|
9
|
-
import type {
|
|
10
|
-
MediaAttachment,
|
|
11
|
-
MediaGenerationRequest,
|
|
12
|
-
} from "../../domain/entities/MediaAttachments";
|
|
13
|
-
|
|
14
|
-
export const useMediaGeneration = (): UseMediaGenerationResult => {
|
|
15
|
-
return useGenericMediaGeneration<MediaAttachment, MediaGenerationRequest>(
|
|
16
|
-
(baseAttachment) => baseAttachment as MediaAttachment
|
|
17
|
-
);
|
|
18
|
-
};
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Media Upload Hook
|
|
3
|
-
* Hook for uploading media files
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { useState, useCallback } from "react";
|
|
7
|
-
import { generateThumbnail, getMediaDuration } from "../../infrastructure/utils/file-media-utils";
|
|
8
|
-
import { getMediaTypeFromMime } from "../../infrastructure/utils/mime-type-detector";
|
|
9
|
-
import type { UseMediaUploadResult } from "./multimedia.types";
|
|
10
|
-
import type {
|
|
11
|
-
MediaAttachment,
|
|
12
|
-
MediaCompressionOptions,
|
|
13
|
-
MediaFile,
|
|
14
|
-
MediaUploadProgress,
|
|
15
|
-
} from "../../domain/entities/MediaAttachments";
|
|
16
|
-
|
|
17
|
-
export const useMediaUpload = (): UseMediaUploadResult => {
|
|
18
|
-
const [isUploading, setIsUploading] = useState(false);
|
|
19
|
-
const [uploadProgress, setUploadProgress] =
|
|
20
|
-
useState<MediaUploadProgress | null>(null);
|
|
21
|
-
const [error, setError] = useState<string | null>(null);
|
|
22
|
-
|
|
23
|
-
const uploadMedia = useCallback(
|
|
24
|
-
async (file: MediaFile, _options?: MediaCompressionOptions) => {
|
|
25
|
-
try {
|
|
26
|
-
setIsUploading(true);
|
|
27
|
-
setError(null);
|
|
28
|
-
|
|
29
|
-
// Simulate upload progress
|
|
30
|
-
setUploadProgress({
|
|
31
|
-
fileId: `upload_${Date.now()}`,
|
|
32
|
-
progress: 0,
|
|
33
|
-
status: "uploading",
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
// Simulate progress updates
|
|
37
|
-
for (let i = 1; i <= 100; i += 10) {
|
|
38
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
39
|
-
setUploadProgress((prev) => (prev ? { ...prev, progress: i } : null));
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const attachment: MediaAttachment = {
|
|
43
|
-
id: `media_${Date.now()}`,
|
|
44
|
-
type: getMediaTypeFromMime(file.type),
|
|
45
|
-
position: "both",
|
|
46
|
-
url: `https://storage.example.com/media/${Date.now()}_${file.name}`,
|
|
47
|
-
filename: file.name,
|
|
48
|
-
fileSize: file.size || 100000,
|
|
49
|
-
mimeType: file.type,
|
|
50
|
-
duration: await getMediaDuration(file),
|
|
51
|
-
thumbnailUrl: generateThumbnail(file),
|
|
52
|
-
caption: "",
|
|
53
|
-
isDownloaded: true,
|
|
54
|
-
createdAt: new Date().toISOString(),
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
setUploadProgress({
|
|
58
|
-
fileId: `upload_${Date.now()}`,
|
|
59
|
-
progress: 100,
|
|
60
|
-
status: "completed",
|
|
61
|
-
url: attachment.url,
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
return attachment;
|
|
65
|
-
} catch (err) {
|
|
66
|
-
const errorMessage =
|
|
67
|
-
err instanceof Error ? err.message : "Upload failed";
|
|
68
|
-
setError(errorMessage);
|
|
69
|
-
setIsUploading(false);
|
|
70
|
-
throw err;
|
|
71
|
-
} finally {
|
|
72
|
-
setIsUploading(false);
|
|
73
|
-
}
|
|
74
|
-
},
|
|
75
|
-
[],
|
|
76
|
-
);
|
|
77
|
-
|
|
78
|
-
return {
|
|
79
|
-
uploadMedia,
|
|
80
|
-
isUploading,
|
|
81
|
-
uploadProgress,
|
|
82
|
-
error,
|
|
83
|
-
};
|
|
84
|
-
};
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Media Validation Hook
|
|
3
|
-
* Hook for validating media files
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { useState, useCallback } from "react";
|
|
7
|
-
import { formatFileSize } from "../../infrastructure/utils/media-collection-utils";
|
|
8
|
-
import type { UseMediaValidationResult } from "./multimedia.types";
|
|
9
|
-
import type { MediaValidation, MediaFile } from "../../domain/entities/MediaAttachments";
|
|
10
|
-
|
|
11
|
-
export const useMediaValidation = (): UseMediaValidationResult => {
|
|
12
|
-
const [isValidating, setIsValidating] = useState(false);
|
|
13
|
-
const [validation, setValidation] = useState<MediaValidation | null>(
|
|
14
|
-
null,
|
|
15
|
-
);
|
|
16
|
-
const [error, setError] = useState<string | null>(null);
|
|
17
|
-
|
|
18
|
-
const validateMedia = useCallback(
|
|
19
|
-
async (file: MediaFile): Promise<MediaValidation> => {
|
|
20
|
-
try {
|
|
21
|
-
setIsValidating(true);
|
|
22
|
-
setError(null);
|
|
23
|
-
|
|
24
|
-
// Simulate validation
|
|
25
|
-
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
26
|
-
|
|
27
|
-
const errors: string[] = [];
|
|
28
|
-
const warnings: string[] = [];
|
|
29
|
-
const recommendations: string[] = [];
|
|
30
|
-
|
|
31
|
-
// File size validation
|
|
32
|
-
const maxSize = 50 * 1024 * 1024; // 50MB
|
|
33
|
-
if (file.size > maxSize) {
|
|
34
|
-
errors.push(
|
|
35
|
-
`File size (${formatFileSize(file.size)}) exceeds maximum allowed size (${formatFileSize(maxSize)})`,
|
|
36
|
-
);
|
|
37
|
-
} else if (file.size > 10 * 1024 * 1024) {
|
|
38
|
-
// 10MB
|
|
39
|
-
warnings.push(`Large file size may impact performance`);
|
|
40
|
-
recommendations.push("Consider compressing file");
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// File type validation
|
|
44
|
-
const supportedTypes = [
|
|
45
|
-
"image/jpeg",
|
|
46
|
-
"image/png",
|
|
47
|
-
"image/webp",
|
|
48
|
-
"audio/mp3",
|
|
49
|
-
"audio/wav",
|
|
50
|
-
"audio/m4a",
|
|
51
|
-
"video/mp4",
|
|
52
|
-
"video/mov",
|
|
53
|
-
];
|
|
54
|
-
|
|
55
|
-
if (!supportedTypes.includes(file.type)) {
|
|
56
|
-
errors.push(`Unsupported file type: ${file.type}`);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const result: MediaValidation = {
|
|
60
|
-
isValid: errors.length === 0,
|
|
61
|
-
errors,
|
|
62
|
-
warnings,
|
|
63
|
-
recommendations,
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
setValidation(result);
|
|
67
|
-
return result;
|
|
68
|
-
} catch (err) {
|
|
69
|
-
const errorMessage =
|
|
70
|
-
err instanceof Error ? err.message : "Validation failed";
|
|
71
|
-
setError(errorMessage);
|
|
72
|
-
setIsValidating(false);
|
|
73
|
-
|
|
74
|
-
return {
|
|
75
|
-
isValid: false,
|
|
76
|
-
errors: [errorMessage],
|
|
77
|
-
warnings: [],
|
|
78
|
-
recommendations: [],
|
|
79
|
-
};
|
|
80
|
-
} finally {
|
|
81
|
-
setIsValidating(false);
|
|
82
|
-
}
|
|
83
|
-
},
|
|
84
|
-
[],
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
return {
|
|
88
|
-
validateMedia,
|
|
89
|
-
isValidating,
|
|
90
|
-
validation,
|
|
91
|
-
error,
|
|
92
|
-
};
|
|
93
|
-
};
|