@umituz/react-native-design-system 4.23.97 → 4.23.101

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 (77) hide show
  1. package/package.json +1 -1
  2. package/src/atoms/AtomicInput.tsx +0 -2
  3. package/src/atoms/button/AtomicButton.tsx +7 -0
  4. package/src/atoms/button/types/index.ts +4 -0
  5. package/src/atoms/input/hooks/useInputState.ts +3 -7
  6. package/src/haptics/infrastructure/services/HapticService.ts +1 -1
  7. package/src/media/domain/entities/{MultimediaFlashcardTypes.ts → MediaAttachments.ts} +13 -32
  8. package/src/media/index.ts +24 -23
  9. package/src/media/{presentation/hooks/useCardMediaGeneration.ts → infrastructure/hooks/useGenericMediaGeneration.ts} +77 -31
  10. package/src/media/infrastructure/services/MediaGenerationService.ts +1 -1
  11. package/src/media/infrastructure/services/MediaOptimizerService.ts +1 -1
  12. package/src/media/infrastructure/services/MediaUploadService.ts +1 -1
  13. package/src/media/infrastructure/services/MediaValidationService.ts +1 -1
  14. package/src/media/infrastructure/services/MultimediaFlashcardService.ts +1 -1
  15. package/src/media/infrastructure/utils/PermissionManager.ts +1 -1
  16. package/src/media/infrastructure/utils/media-collection-utils.ts +4 -2
  17. package/src/media/infrastructure/utils/mediaPickerMappers.ts +1 -1
  18. package/src/media/presentation/hooks/multimedia.types.ts +1 -1
  19. package/src/media/presentation/hooks/useCardMultimediaFlashcard.ts +4 -4
  20. package/src/media/presentation/hooks/useMedia.ts +2 -2
  21. package/src/media/presentation/hooks/useMediaGeneration.ts +5 -88
  22. package/src/media/presentation/hooks/useMediaUpload.ts +1 -1
  23. package/src/media/presentation/hooks/useMediaValidation.ts +1 -1
  24. package/src/media/presentation/hooks/useMultimediaFlashcard.ts +1 -1
  25. package/src/molecules/navigation/components/NavigationHeader.tsx +3 -3
  26. package/src/molecules/navigation/utils/AppNavigation.ts +3 -3
  27. package/src/offline/index.ts +1 -0
  28. package/src/offline/infrastructure/storage/OfflineConfigStore.ts +34 -0
  29. package/src/offline/presentation/hooks/useOffline.ts +8 -4
  30. package/src/storage/domain/utils/devUtils.ts +0 -24
  31. package/src/storage/index.ts +1 -1
  32. package/src/storage/infrastructure/adapters/StorageService.ts +5 -10
  33. package/src/storage/infrastructure/repositories/BaseStorageOperations.ts +5 -8
  34. package/src/storage/presentation/hooks/CacheStorageOperations.ts +5 -11
  35. package/src/storage/presentation/hooks/useStore.ts +13 -5
  36. package/src/utilities/sharing/presentation/hooks/useSharing.ts +3 -3
  37. package/src/layouts/ScreenLayout/ScreenLayout.example.tsx +0 -92
  38. package/src/media/domain/entities/CardMultimedia.types.README.md +0 -129
  39. package/src/media/domain/entities/CardMultimedia.types.ts +0 -120
  40. package/src/media/domain/entities/Media.README.md +0 -80
  41. package/src/media/domain/entities/MultimediaFlashcardTypes.README.md +0 -144
  42. package/src/media/domain/utils/MediaUtils.README.md +0 -178
  43. package/src/media/index.ts.README.md +0 -191
  44. package/src/media/infrastructure/services/CardMediaGenerationService.README.md +0 -99
  45. package/src/media/infrastructure/services/CardMediaGenerationService.ts +0 -101
  46. package/src/media/infrastructure/services/CardMediaOptimizerService.README.md +0 -167
  47. package/src/media/infrastructure/services/CardMediaOptimizerService.ts +0 -36
  48. package/src/media/infrastructure/services/CardMediaUploadService.README.md +0 -123
  49. package/src/media/infrastructure/services/CardMediaUploadService.ts +0 -62
  50. package/src/media/infrastructure/services/CardMediaValidationService.README.md +0 -134
  51. package/src/media/infrastructure/services/CardMediaValidationService.ts +0 -81
  52. package/src/media/infrastructure/services/CardMultimediaService.README.md +0 -176
  53. package/src/media/infrastructure/services/CardMultimediaService.ts +0 -98
  54. package/src/media/infrastructure/services/MediaGenerationService.README.md +0 -142
  55. package/src/media/infrastructure/services/MediaOptimizerService.README.md +0 -145
  56. package/src/media/infrastructure/services/MediaPickerService.README.md +0 -106
  57. package/src/media/infrastructure/services/MediaSaveService.README.md +0 -120
  58. package/src/media/infrastructure/services/MediaUploadService.README.md +0 -135
  59. package/src/media/infrastructure/services/MediaValidationService.README.md +0 -135
  60. package/src/media/infrastructure/services/MultimediaFlashcardService.README.md +0 -142
  61. package/src/media/infrastructure/utils/mediaHelpers.README.md +0 -96
  62. package/src/media/infrastructure/utils/mediaPickerMappers.README.md +0 -129
  63. package/src/media/presentation/hooks/card-multimedia.types.README.md +0 -177
  64. package/src/media/presentation/hooks/card-multimedia.types.ts +0 -53
  65. package/src/media/presentation/hooks/multimedia.types.README.md +0 -201
  66. package/src/media/presentation/hooks/useCardMediaGeneration.README.md +0 -164
  67. package/src/media/presentation/hooks/useCardMediaUpload.README.md +0 -153
  68. package/src/media/presentation/hooks/useCardMediaUpload.ts +0 -84
  69. package/src/media/presentation/hooks/useCardMediaValidation.README.md +0 -176
  70. package/src/media/presentation/hooks/useCardMediaValidation.ts +0 -101
  71. package/src/media/presentation/hooks/useCardMultimediaFlashcard.README.md +0 -158
  72. package/src/media/presentation/hooks/useMedia.README.md +0 -94
  73. package/src/media/presentation/hooks/useMediaGeneration.README.md +0 -118
  74. package/src/media/presentation/hooks/useMediaUpload.README.md +0 -108
  75. package/src/media/presentation/hooks/useMediaValidation.README.md +0 -134
  76. package/src/media/presentation/hooks/useMultimediaFlashcard.README.md +0 -141
  77. package/src/storage/domain/utils/__tests__/devUtils.test.ts +0 -97
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-design-system",
3
- "version": "4.23.97",
3
+ "version": "4.23.101",
4
4
  "description": "Universal design system for React Native apps - Consolidated package with atoms, molecules, organisms, theme, typography, responsive, safe area, exception, infinite scroll, UUID, image, timezone, offline, onboarding, and loading utilities",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -57,9 +57,7 @@ export const AtomicInput = React.forwardRef<React.ElementRef<typeof TextInput>,
57
57
  value,
58
58
  onChangeText,
59
59
  secureTextEntry,
60
- showPasswordToggle,
61
60
  maxLength,
62
- showCharacterCount,
63
61
  });
64
62
 
65
63
  const isDisabled = state === 'disabled' || disabled;
@@ -29,6 +29,9 @@ export const AtomicButton: React.FC<AtomicButtonProps> = React.memo(({
29
29
  textStyle,
30
30
  activeOpacity = 0.8,
31
31
  testID,
32
+ accessibilityLabel,
33
+ accessibilityHint,
34
+ accessibilityRole = 'button',
32
35
  }) => {
33
36
  const tokens = useAppDesignTokens();
34
37
 
@@ -80,6 +83,10 @@ export const AtomicButton: React.FC<AtomicButtonProps> = React.memo(({
80
83
  activeOpacity={activeOpacity}
81
84
  disabled={isDisabled}
82
85
  testID={testID}
86
+ accessibilityRole={accessibilityRole}
87
+ accessibilityLabel={accessibilityLabel || title || (typeof children === 'string' ? children : 'Button')}
88
+ accessibilityHint={accessibilityHint}
89
+ accessibilityState={{ disabled: isDisabled, busy: loading }}
83
90
  >
84
91
  {loading ? (
85
92
  <AtomicSpinner
@@ -24,6 +24,10 @@ export interface AtomicButtonProps {
24
24
  readonly textStyle?: StyleProp<TextStyle>;
25
25
  readonly activeOpacity?: number;
26
26
  readonly testID?: string;
27
+ // Accessibility props
28
+ readonly accessibilityLabel?: string;
29
+ readonly accessibilityHint?: string;
30
+ readonly accessibilityRole?: 'button' | 'link';
27
31
  }
28
32
 
29
33
  export interface ButtonSizeConfig {
@@ -1,12 +1,10 @@
1
- import { useState, useCallback, useEffect } from 'react';
1
+ import { useState, useCallback, useEffect, useMemo } from 'react';
2
2
 
3
3
  interface UseInputStateProps {
4
4
  value?: string;
5
5
  onChangeText?: (text: string) => void;
6
6
  secureTextEntry?: boolean;
7
- showPasswordToggle?: boolean;
8
7
  maxLength?: number;
9
- showCharacterCount?: boolean;
10
8
  }
11
9
 
12
10
  interface UseInputStateReturn {
@@ -24,9 +22,7 @@ export const useInputState = ({
24
22
  value = '',
25
23
  onChangeText,
26
24
  secureTextEntry = false,
27
- showPasswordToggle: _showPasswordToggle = false,
28
25
  maxLength,
29
- showCharacterCount: _showCharacterCount = false,
30
26
  }: UseInputStateProps = {}): UseInputStateReturn => {
31
27
  const [localValue, setLocalValue] = useState(value);
32
28
  const [isFocused, setIsFocused] = useState(false);
@@ -49,7 +45,7 @@ export const useInputState = ({
49
45
  const characterCount = localValue.length;
50
46
  const isAtMaxLength = maxLength ? characterCount >= maxLength : false;
51
47
 
52
- return {
48
+ return useMemo(() => ({
53
49
  localValue,
54
50
  isFocused,
55
51
  isPasswordVisible,
@@ -58,5 +54,5 @@ export const useInputState = ({
58
54
  setIsFocused,
59
55
  handleTextChange,
60
56
  togglePasswordVisibility,
61
- };
57
+ }), [localValue, isFocused, isPasswordVisible, characterCount, isAtMaxLength, handleTextChange, togglePasswordVisibility]);
62
58
  };
@@ -15,7 +15,7 @@ import type { ImpactStyle, NotificationType, HapticPattern } from '../../domain/
15
15
  * Log error in development mode only
16
16
  */
17
17
  function logError(method: string, error: unknown): void {
18
- if (process.env.NODE_ENV === 'development') {
18
+ if (__DEV__) {
19
19
  console.error(`[DesignSystem] HapticService.${method} error:`, error);
20
20
  }
21
21
  }
@@ -1,22 +1,22 @@
1
1
  /**
2
- * Multimedia Flashcard Types
3
- * Extended media types for flashcard support
2
+ * Media Attachments Types
3
+ * Types for media attachments in flashcards and content
4
4
  */
5
5
 
6
- export type MediaType = "image" | "audio" | "video";
6
+ export type MediaAttachmentType = "image" | "audio" | "video";
7
7
  export type MediaPosition = "front" | "back" | "both";
8
8
 
9
9
  export interface MediaAttachment {
10
10
  id: string;
11
- type: MediaType;
11
+ type: MediaAttachmentType;
12
12
  position: MediaPosition;
13
13
  url: string;
14
14
  localPath?: string;
15
15
  filename: string;
16
16
  fileSize: number;
17
17
  mimeType: string;
18
- duration?: number; // For audio/video in seconds
19
- thumbnailUrl?: string; // For videos
18
+ duration?: number;
19
+ thumbnailUrl?: string;
20
20
  caption?: string;
21
21
  isDownloaded: boolean;
22
22
  createdAt: string;
@@ -30,12 +30,11 @@ export interface MultimediaFlashcard {
30
30
  tags: string[];
31
31
  createdAt?: string;
32
32
  updatedAt?: string;
33
- // Extended properties for multimedia support
34
33
  media: MediaAttachment[];
35
- hasMedia: boolean; // Computed property
36
- mediaType: MediaType[]; // Array of media types present
37
- isDownloaded: boolean; // All media downloaded?
38
- estimatedSize: number; // Total size in bytes
34
+ hasMedia: boolean;
35
+ mediaType: MediaAttachmentType[];
36
+ isDownloaded: boolean;
37
+ estimatedSize: number;
39
38
  }
40
39
 
41
40
  export interface MediaGenerationRequest {
@@ -65,17 +64,17 @@ export interface MediaGenerationResult {
65
64
 
66
65
  export interface MediaUploadProgress {
67
66
  fileId: string;
68
- progress: number; // 0-100
67
+ progress: number;
69
68
  status: "uploading" | "processing" | "completed" | "error";
70
69
  error?: string;
71
70
  url?: string;
72
71
  }
73
72
 
74
73
  export interface MediaCompressionOptions {
75
- quality: number; // 0.1 - 1.0
74
+ quality: number;
76
75
  maxWidth?: number;
77
76
  maxHeight?: number;
78
- maxFileSize?: number; // bytes
77
+ maxFileSize?: number;
79
78
  format?: "jpeg" | "png" | "webp";
80
79
  }
81
80
 
@@ -100,21 +99,3 @@ export interface MediaValidation {
100
99
  warnings: string[];
101
100
  recommendations: string[];
102
101
  }
103
-
104
- export interface MultimediaFlashcardService {
105
- uploadMedia(
106
- file: MediaFile,
107
- options?: MediaCompressionOptions,
108
- ): Promise<MediaAttachment>;
109
- generateMedia(
110
- request: MediaGenerationRequest,
111
- ): Promise<MediaGenerationResult>;
112
- validateMedia(file: MediaFile): Promise<MediaValidation>;
113
- optimizeMedia(
114
- attachment: MediaAttachment,
115
- options: MediaCompressionOptions,
116
- ): Promise<MediaAttachment>;
117
- deleteMedia(attachmentId: string): Promise<void>;
118
- getMediaUrl(attachmentId: string): Promise<string>;
119
- downloadMedia(attachmentId: string): Promise<string>; // Returns local path
120
- }
@@ -91,28 +91,29 @@ export {
91
91
  type SaveToGalleryResult,
92
92
  } from "./infrastructure/utils/file-media-utils";
93
93
 
94
- // Multimedia Flashcard Support
94
+ // Media Attachment Types (Clean, no aliases)
95
95
  export type {
96
- CardMediaType,
97
- CardMediaPosition,
98
- CardMediaAttachment,
99
- CardMultimediaFlashcard,
100
- CardMediaGenerationRequest,
101
- CardMediaGenerationResult,
102
- CardMediaUploadProgress,
103
- CardMediaCompressionOptions,
104
- CardMediaValidation,
105
- } from "./domain/entities/CardMultimedia.types";
96
+ MediaAttachmentType,
97
+ MediaPosition,
98
+ MediaAttachment,
99
+ MultimediaFlashcard,
100
+ MediaGenerationRequest,
101
+ MediaGenerationResult,
102
+ MediaUploadProgress,
103
+ MediaCompressionOptions,
104
+ MediaValidation,
105
+ MediaFile,
106
+ CreateMultimediaCardData,
107
+ } from "./domain/entities/MediaAttachments";
106
108
 
107
- export { CardMultimediaFlashcardService } from "./infrastructure/services/CardMultimediaService";
108
-
109
- export {
110
- useCardMediaUpload,
111
- useCardMediaGeneration,
112
- useCardMediaValidation,
113
- useCardMultimediaFlashcard,
114
- type UseCardMediaUploadResult,
115
- type UseCardMediaGenerationResult,
116
- type UseCardMediaValidationResult,
117
- type UseCardMultimediaFlashcardResult,
118
- } from "./presentation/hooks/useCardMultimediaFlashcard";
109
+ // Media Hooks
110
+ export { useMediaUpload } from "./presentation/hooks/useMediaUpload";
111
+ export { useMediaGeneration } from "./presentation/hooks/useMediaGeneration";
112
+ export { useMediaValidation } from "./presentation/hooks/useMediaValidation";
113
+ export { useMultimediaFlashcard } from "./presentation/hooks/useMultimediaFlashcard";
114
+ export type {
115
+ UseMediaUploadResult,
116
+ UseMediaGenerationResult,
117
+ UseMediaValidationResult,
118
+ UseMultimediaFlashcardResult,
119
+ } from "./presentation/hooks/multimedia.types";
@@ -1,26 +1,75 @@
1
1
  /**
2
- * Card Media Generation Hook
3
- * Hook for generating card media with AI
2
+ * Generic Media Generation Hook
3
+ * Shared implementation for both Media and CardMedia generation
4
+ * Eliminates ~600 LOC duplication
4
5
  */
5
6
 
6
7
  import { useState, useCallback } from "react";
7
- import type { UseCardMediaGenerationResult } from "./card-multimedia.types";
8
- import type {
9
- CardMediaAttachment,
10
- CardMediaGenerationRequest,
11
- CardMediaGenerationResult,
12
- } from "../../domain/entities/CardMultimedia.types";
13
-
14
- export const useCardMediaGeneration = (): UseCardMediaGenerationResult => {
8
+
9
+ interface GenericMediaAttachment {
10
+ id: string;
11
+ type: string;
12
+ position: string;
13
+ url: string;
14
+ filename: string;
15
+ fileSize: number;
16
+ mimeType: string;
17
+ duration?: number;
18
+ thumbnailUrl?: string;
19
+ caption?: string;
20
+ isDownloaded: boolean;
21
+ createdAt: string;
22
+ }
23
+
24
+ interface GenericMediaGenerationRequest {
25
+ type: "text_to_image" | "text_to_audio" | "image_search";
26
+ input: {
27
+ text?: string;
28
+ prompt?: string;
29
+ language?: string;
30
+ voice?: "male" | "female" | "neutral";
31
+ style?: "realistic" | "cartoon" | "artistic";
32
+ };
33
+ options: {
34
+ maxResults?: number;
35
+ quality?: "low" | "medium" | "high";
36
+ format?: "jpeg" | "png" | "mp3" | "wav";
37
+ };
38
+ }
39
+
40
+ interface GenericMediaGenerationResult<TAttachment> {
41
+ success: boolean;
42
+ attachments: TAttachment[];
43
+ creditsUsed: number;
44
+ processingTime: number;
45
+ error?: string;
46
+ requestId: string;
47
+ }
48
+
49
+ export interface UseGenericMediaGenerationResult<TAttachment, TRequest> {
50
+ generateMedia: (request: TRequest) => Promise<GenericMediaGenerationResult<TAttachment>>;
51
+ isGenerating: boolean;
52
+ generationResult: GenericMediaGenerationResult<TAttachment> | null;
53
+ error: string | null;
54
+ }
55
+
56
+ /**
57
+ * Generic implementation of media generation logic
58
+ * Type-safe through attachment factory pattern
59
+ */
60
+ export function useGenericMediaGeneration<
61
+ TAttachment extends GenericMediaAttachment,
62
+ TRequest extends GenericMediaGenerationRequest
63
+ >(
64
+ attachmentFactory: (baseAttachment: GenericMediaAttachment) => TAttachment
65
+ ): UseGenericMediaGenerationResult<TAttachment, TRequest> {
15
66
  const [isGenerating, setIsGenerating] = useState(false);
16
67
  const [generationResult, setGenerationResult] =
17
- useState<CardMediaGenerationResult | null>(null);
68
+ useState<GenericMediaGenerationResult<TAttachment> | null>(null);
18
69
  const [error, setError] = useState<string | null>(null);
19
70
 
20
71
  const generateMedia = useCallback(
21
- async (
22
- request: CardMediaGenerationRequest,
23
- ): Promise<CardMediaGenerationResult> => {
72
+ async (request: TRequest): Promise<GenericMediaGenerationResult<TAttachment>> => {
24
73
  try {
25
74
  setIsGenerating(true);
26
75
  setError(null);
@@ -28,18 +77,18 @@ export const useCardMediaGeneration = (): UseCardMediaGenerationResult => {
28
77
  // Simulate generation
29
78
  await new Promise((resolve) => setTimeout(resolve, 3000));
30
79
 
31
- const attachments: CardMediaAttachment[] = [];
80
+ const baseAttachments: GenericMediaAttachment[] = [];
32
81
 
33
82
  switch (request.type) {
34
83
  case "text_to_image":
35
84
  for (let i = 0; i < (request.options.maxResults || 1); i++) {
36
- attachments.push({
85
+ baseAttachments.push({
37
86
  id: `ai_img_${Date.now()}_${i}`,
38
87
  type: "image",
39
88
  position: "both",
40
89
  url: `https://picsum.photos/400/300?random=${Date.now() + i}`,
41
90
  filename: `ai_generated_${i}.jpg`,
42
- fileSize: 150000, // 150KB
91
+ fileSize: 150000,
43
92
  mimeType: "image/jpeg",
44
93
  isDownloaded: false,
45
94
  createdAt: new Date().toISOString(),
@@ -48,15 +97,15 @@ export const useCardMediaGeneration = (): UseCardMediaGenerationResult => {
48
97
  break;
49
98
 
50
99
  case "text_to_audio":
51
- attachments.push({
100
+ baseAttachments.push({
52
101
  id: `ai_audio_${Date.now()}`,
53
102
  type: "audio",
54
103
  position: "back",
55
104
  url: `https://example.com/audio_${Date.now()}.mp3`,
56
105
  filename: `ai_generated_${Date.now()}.mp3`,
57
- fileSize: 80000, // 80KB
106
+ fileSize: 80000,
58
107
  mimeType: "audio/mp3",
59
- duration: 10, // 10 seconds
108
+ duration: 10,
60
109
  isDownloaded: false,
61
110
  createdAt: new Date().toISOString(),
62
111
  });
@@ -64,13 +113,13 @@ export const useCardMediaGeneration = (): UseCardMediaGenerationResult => {
64
113
 
65
114
  case "image_search":
66
115
  for (let i = 0; i < (request.options.maxResults || 5); i++) {
67
- attachments.push({
116
+ baseAttachments.push({
68
117
  id: `search_img_${Date.now()}_${i}`,
69
118
  type: "image",
70
119
  position: "both",
71
120
  url: `https://picsum.photos/400/300?random=${Date.now() + i}`,
72
121
  filename: `search_result_${i}.jpg`,
73
- fileSize: 120000, // 120KB
122
+ fileSize: 120000,
74
123
  mimeType: "image/jpeg",
75
124
  isDownloaded: false,
76
125
  createdAt: new Date().toISOString(),
@@ -79,15 +128,12 @@ export const useCardMediaGeneration = (): UseCardMediaGenerationResult => {
79
128
  break;
80
129
  }
81
130
 
82
- const result: CardMediaGenerationResult = {
131
+ const attachments = baseAttachments.map(attachmentFactory);
132
+
133
+ const result: GenericMediaGenerationResult<TAttachment> = {
83
134
  success: true,
84
135
  attachments,
85
- creditsUsed:
86
- request.type === "text_to_image"
87
- ? 5
88
- : request.type === "text_to_audio"
89
- ? 3
90
- : 2,
136
+ creditsUsed: request.type === "text_to_image" ? 5 : request.type === "text_to_audio" ? 3 : 2,
91
137
  processingTime: 3000,
92
138
  requestId: `req_${Date.now()}`,
93
139
  };
@@ -112,7 +158,7 @@ export const useCardMediaGeneration = (): UseCardMediaGenerationResult => {
112
158
  setIsGenerating(false);
113
159
  }
114
160
  },
115
- [],
161
+ [attachmentFactory],
116
162
  );
117
163
 
118
164
  return {
@@ -121,4 +167,4 @@ export const useCardMediaGeneration = (): UseCardMediaGenerationResult => {
121
167
  generationResult,
122
168
  error,
123
169
  };
124
- };
170
+ }
@@ -9,7 +9,7 @@ import type {
9
9
  MediaGenerationResult,
10
10
  MediaType,
11
11
  MediaPosition,
12
- } from "../../domain/entities/MultimediaFlashcardTypes";
12
+ } from "../../domain/entities/MediaAttachments";
13
13
 
14
14
  export class MediaGenerationService {
15
15
  /**
@@ -6,7 +6,7 @@
6
6
  import type {
7
7
  MediaAttachment,
8
8
  MediaCompressionOptions,
9
- } from "../../domain/entities/MultimediaFlashcardTypes";
9
+ } from "../../domain/entities/MediaAttachments";
10
10
 
11
11
  export class MediaOptimizerService {
12
12
  /**
@@ -7,7 +7,7 @@ import type {
7
7
  MediaAttachment,
8
8
  MediaCompressionOptions,
9
9
  MediaFile,
10
- } from "../../domain/entities/MultimediaFlashcardTypes";
10
+ } from "../../domain/entities/MediaAttachments";
11
11
  import { generateThumbnail, getMediaDuration } from "../utils/file-media-utils";
12
12
  import { getMediaTypeFromMime } from "../utils/mime-type-detector";
13
13
 
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import { formatFileSize } from "../utils/media-collection-utils";
7
- import type { MediaValidation, MediaFile } from "../../domain/entities/MultimediaFlashcardTypes";
7
+ import type { MediaValidation, MediaFile } from "../../domain/entities/MediaAttachments";
8
8
 
9
9
  export class MediaValidationService {
10
10
  /**
@@ -10,7 +10,7 @@ import type {
10
10
  MediaGenerationResult,
11
11
  MediaCompressionOptions,
12
12
  MediaValidation,
13
- } from "../../domain/entities/MultimediaFlashcardTypes";
13
+ } from "../../domain/entities/MediaAttachments";
14
14
  import { MediaUploadService } from "./MediaUploadService";
15
15
  import { MediaGenerationService } from "./MediaGenerationService";
16
16
  import { MediaValidationService } from "./MediaValidationService";
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  import * as ImagePicker from "expo-image-picker";
8
- import { MediaLibraryPermission } from "../../domain/entities/Media";
8
+ import { MediaLibraryPermission } from "../../domain/entities/MediaAttachments";
9
9
  import { mapPermissionStatus } from "./mediaPickerMappers";
10
10
 
11
11
  /**
@@ -1,5 +1,7 @@
1
- import type { CardMediaAttachment } from "../../domain/entities/CardMultimedia.types";
2
- import type { MediaAttachment } from "../../domain/entities/MultimediaFlashcardTypes";
1
+ import type { MediaAttachment } from "../../domain/entities/MediaAttachments";
2
+
3
+ // CardMediaAttachment is an alias of MediaAttachment
4
+ type CardMediaAttachment = MediaAttachment;
3
5
 
4
6
  type MediaType = "image" | "audio" | "video";
5
7
 
@@ -9,7 +9,7 @@ import {
9
9
  MediaType,
10
10
  type MediaAsset,
11
11
  type MediaPickerResult,
12
- } from "../../domain/entities/Media";
12
+ } from "../../domain/entities/MediaAttachments";
13
13
 
14
14
  /**
15
15
  * Map expo-image-picker permission status to MediaLibraryPermission
@@ -13,7 +13,7 @@ import type {
13
13
  MediaUploadProgress,
14
14
  MultimediaFlashcard,
15
15
  CreateMultimediaCardData,
16
- } from "../../domain/entities/MultimediaFlashcardTypes";
16
+ } from "../../domain/entities/MediaAttachments";
17
17
 
18
18
  export interface UseMediaUploadResult {
19
19
  uploadMedia: (
@@ -7,10 +7,10 @@ import { useState, useCallback } from "react";
7
7
  import { calculateTotalSize, extractMediaTypes } from "../../infrastructure/utils/media-collection-utils";
8
8
  import type { UseCardMultimediaFlashcardResult } from "./card-multimedia.types";
9
9
  import type {
10
- CardMediaAttachment,
11
- CardMultimediaFlashcard,
12
- CreateCardMultimediaData,
13
- } from "../../domain/entities/CardMultimedia.types";
10
+ MediaAttachment as CardMediaAttachment,
11
+ MultimediaFlashcard as CardMultimediaFlashcard,
12
+ CreateMultimediaCardData as CreateCardMultimediaData,
13
+ } from "../../domain/entities/MediaAttachments";
14
14
 
15
15
  // Export individual hooks
16
16
  export { useCardMediaUpload } from "./useCardMediaUpload";
@@ -12,8 +12,8 @@ import type {
12
12
  MediaPickerOptions,
13
13
  MediaPickerResult,
14
14
  CameraOptions,
15
- } from "../../domain/entities/Media";
16
- import { MediaLibraryPermission } from "../../domain/entities/Media";
15
+ } from "../../domain/entities/MediaAttachments";
16
+ import { MediaLibraryPermission } from "../../domain/entities/MediaAttachments";
17
17
 
18
18
  /**
19
19
  * useMedia hook for complete media workflow
@@ -1,101 +1,18 @@
1
1
  /**
2
2
  * Media Generation Hook
3
3
  * Hook for generating media with AI
4
+ * Now a thin wrapper around useGenericMediaGeneration
4
5
  */
5
6
 
6
- import { useState, useCallback } from "react";
7
+ import { useGenericMediaGeneration } from "../../infrastructure/hooks/useGenericMediaGeneration";
7
8
  import type { UseMediaGenerationResult } from "./multimedia.types";
8
9
  import type {
9
10
  MediaAttachment,
10
11
  MediaGenerationRequest,
11
- MediaGenerationResult,
12
- } from "../../domain/entities/MultimediaFlashcardTypes";
12
+ } from "../../domain/entities/MediaAttachments";
13
13
 
14
14
  export const useMediaGeneration = (): UseMediaGenerationResult => {
15
- const [isGenerating, setIsGenerating] = useState(false);
16
- const [generationResult, setGenerationResult] =
17
- useState<MediaGenerationResult | null>(null);
18
- const [error, setError] = useState<string | null>(null);
19
-
20
- const generateMedia = 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
- [],
15
+ return useGenericMediaGeneration<MediaAttachment, MediaGenerationRequest>(
16
+ (baseAttachment) => baseAttachment as MediaAttachment
93
17
  );
94
-
95
- return {
96
- generateMedia,
97
- isGenerating,
98
- generationResult,
99
- error,
100
- };
101
18
  };
@@ -12,7 +12,7 @@ import type {
12
12
  MediaCompressionOptions,
13
13
  MediaFile,
14
14
  MediaUploadProgress,
15
- } from "../../domain/entities/MultimediaFlashcardTypes";
15
+ } from "../../domain/entities/MediaAttachments";
16
16
 
17
17
  export const useMediaUpload = (): UseMediaUploadResult => {
18
18
  const [isUploading, setIsUploading] = useState(false);