@umituz/react-native-ai-generation-content 1.61.62 → 1.61.64

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 (121) hide show
  1. package/package.json +1 -1
  2. package/src/core/index.ts +1 -1
  3. package/src/domain/entities/index.ts +1 -1
  4. package/src/domain/interfaces/ai-provider.interface.ts +1 -1
  5. package/src/domain/interfaces/index.ts +1 -1
  6. package/src/domains/background/domain/entities/index.ts +1 -0
  7. package/src/domains/background/domain/interfaces/index.ts +1 -0
  8. package/src/{domain → domains/background/domain}/interfaces/provider-job-manager.interface.ts +1 -1
  9. package/src/domains/background/domain/types/background-generation.types.ts +28 -0
  10. package/src/domains/background/infrastructure/executors/backgroundJobExecutor.ts +105 -0
  11. package/src/{infrastructure → domains/background/infrastructure}/services/job-poller-factory.ts +1 -1
  12. package/src/{infrastructure → domains/background/infrastructure}/services/job-poller.service.ts +1 -1
  13. package/src/{infrastructure → domains/background/infrastructure}/services/job-poller.types.ts +2 -2
  14. package/src/{infrastructure → domains/background/infrastructure}/utils/polling-interval.util.ts +1 -1
  15. package/src/{infrastructure → domains/background/infrastructure}/utils/status-checker.util.ts +1 -1
  16. package/src/domains/background/presentation/hooks/use-background-generation.ts +97 -0
  17. package/src/domains/creations/presentation/components/PendingJobsSection.tsx +1 -1
  18. package/src/domains/generation/wizard/presentation/hooks/generationExecutor.ts +65 -0
  19. package/src/domains/generation/wizard/presentation/hooks/generationStateMachine.ts +35 -0
  20. package/src/domains/generation/wizard/presentation/hooks/typeGuards.ts +13 -0
  21. package/src/domains/generation/wizard/presentation/hooks/useVideoQueueGeneration.ts +34 -71
  22. package/src/domains/generation/wizard/presentation/hooks/useWizardFlowHandlers.ts +6 -84
  23. package/src/domains/generation/wizard/presentation/hooks/useWizardGeneration.ts +19 -131
  24. package/src/domains/generation/wizard/presentation/hooks/videoQueuePoller.ts +59 -0
  25. package/src/domains/image-to-video/presentation/hooks/imageToVideoStrategy.ts +77 -0
  26. package/src/domains/image-to-video/presentation/hooks/useImageToVideoFeature.ts +102 -0
  27. package/src/domains/scenarios/presentation/containers/CategoryNavigationContainer.tsx +4 -80
  28. package/src/{features → domains}/text-to-image/infrastructure/services/text-to-image-executor.ts +2 -82
  29. package/src/domains/text-to-image/infrastructure/utils/imageResultExtractor.ts +58 -0
  30. package/src/domains/text-to-video/presentation/hooks/textToVideoStrategy.ts +75 -0
  31. package/src/domains/text-to-video/presentation/hooks/useTextToVideoFeature.ts +120 -0
  32. package/src/exports/features.ts +12 -12
  33. package/src/presentation/components/PendingJobCard.tsx +1 -1
  34. package/src/features/image-to-video/presentation/hooks/useImageToVideoFeature.ts +0 -186
  35. package/src/features/text-to-video/presentation/hooks/useTextToVideoFeature.ts +0 -186
  36. package/src/presentation/hooks/use-background-generation.ts +0 -185
  37. /package/src/{domain → domains/background/domain}/entities/job.types.ts +0 -0
  38. /package/src/{infrastructure → domains/background/infrastructure}/utils/result-validator.util.ts +0 -0
  39. /package/src/{presentation → domains/background/presentation}/hooks/use-pending-jobs.ts +0 -0
  40. /package/src/{features → domains}/image-to-video/README.md +0 -0
  41. /package/src/{features → domains}/image-to-video/domain/constants/animation.constants.ts +0 -0
  42. /package/src/{features → domains}/image-to-video/domain/constants/duration.constants.ts +0 -0
  43. /package/src/{features → domains}/image-to-video/domain/constants/form.constants.ts +0 -0
  44. /package/src/{features → domains}/image-to-video/domain/constants/index.ts +0 -0
  45. /package/src/{features → domains}/image-to-video/domain/constants/music.constants.ts +0 -0
  46. /package/src/{features → domains}/image-to-video/domain/index.ts +0 -0
  47. /package/src/{features → domains}/image-to-video/domain/types/animation.types.ts +0 -0
  48. /package/src/{features → domains}/image-to-video/domain/types/config.types.ts +0 -0
  49. /package/src/{features → domains}/image-to-video/domain/types/duration.types.ts +0 -0
  50. /package/src/{features → domains}/image-to-video/domain/types/form.types.ts +0 -0
  51. /package/src/{features → domains}/image-to-video/domain/types/image-to-video.types.ts +0 -0
  52. /package/src/{features → domains}/image-to-video/domain/types/index.ts +0 -0
  53. /package/src/{features → domains}/image-to-video/domain/types/music.types.ts +0 -0
  54. /package/src/{features → domains}/image-to-video/index.ts +0 -0
  55. /package/src/{features → domains}/image-to-video/infrastructure/index.ts +0 -0
  56. /package/src/{features → domains}/image-to-video/infrastructure/services/image-to-video-executor.ts +0 -0
  57. /package/src/{features → domains}/image-to-video/infrastructure/services/index.ts +0 -0
  58. /package/src/{features → domains}/image-to-video/presentation/components/AddMoreCard.tsx +0 -0
  59. /package/src/{features → domains}/image-to-video/presentation/components/AnimationStyleSelector.tsx +0 -0
  60. /package/src/{features → domains}/image-to-video/presentation/components/DurationSelector.tsx +0 -0
  61. /package/src/{features → domains}/image-to-video/presentation/components/EmptyGridState.tsx +0 -0
  62. /package/src/{features → domains}/image-to-video/presentation/components/GridImageItem.tsx +0 -0
  63. /package/src/{features → domains}/image-to-video/presentation/components/ImageSelectionGrid.styles.ts +0 -0
  64. /package/src/{features → domains}/image-to-video/presentation/components/ImageSelectionGrid.tsx +0 -0
  65. /package/src/{features → domains}/image-to-video/presentation/components/ImageSelectionGrid.types.ts +0 -0
  66. /package/src/{features → domains}/image-to-video/presentation/components/MusicMoodSelector.tsx +0 -0
  67. /package/src/{features → domains}/image-to-video/presentation/components/index.ts +0 -0
  68. /package/src/{features → domains}/image-to-video/presentation/hooks/image-to-video-feature.types.ts +0 -0
  69. /package/src/{features → domains}/image-to-video/presentation/hooks/index.ts +0 -0
  70. /package/src/{features → domains}/image-to-video/presentation/hooks/useFormState.ts +0 -0
  71. /package/src/{features → domains}/image-to-video/presentation/hooks/useGeneration.ts +0 -0
  72. /package/src/{features → domains}/image-to-video/presentation/hooks/useImageToVideoForm.ts +0 -0
  73. /package/src/{features → domains}/image-to-video/presentation/index.ts +0 -0
  74. /package/src/{features → domains}/image-to-video/presentation/screens/ImageToVideoWizardFlow.tsx +0 -0
  75. /package/src/{features → domains}/shared/index.ts +0 -0
  76. /package/src/{features → domains}/shared/presentation/components/AutoSkipPreview.tsx +0 -0
  77. /package/src/{features → domains}/shared/presentation/components/index.ts +0 -0
  78. /package/src/{features → domains}/shared/presentation/utils/index.ts +0 -0
  79. /package/src/{features → domains}/shared/presentation/utils/wizard-flow.utils.ts +0 -0
  80. /package/src/{features → domains}/text-to-image/README.md +0 -0
  81. /package/src/{features → domains}/text-to-image/domain/constants/index.ts +0 -0
  82. /package/src/{features → domains}/text-to-image/domain/constants/options.constants.ts +0 -0
  83. /package/src/{features → domains}/text-to-image/domain/constants/styles.constants.ts +0 -0
  84. /package/src/{features → domains}/text-to-image/domain/index.ts +0 -0
  85. /package/src/{features → domains}/text-to-image/domain/types/config.types.ts +0 -0
  86. /package/src/{features → domains}/text-to-image/domain/types/form.types.ts +0 -0
  87. /package/src/{features → domains}/text-to-image/domain/types/index.ts +0 -0
  88. /package/src/{features → domains}/text-to-image/domain/types/text-to-image.types.ts +0 -0
  89. /package/src/{features → domains}/text-to-image/index.ts +0 -0
  90. /package/src/{features → domains}/text-to-image/infrastructure/index.ts +0 -0
  91. /package/src/{features → domains}/text-to-image/infrastructure/services/index.ts +0 -0
  92. /package/src/{features → domains}/text-to-image/presentation/components/index.ts +0 -0
  93. /package/src/{features → domains}/text-to-image/presentation/hooks/index.ts +0 -0
  94. /package/src/{features → domains}/text-to-image/presentation/hooks/useFormState.ts +0 -0
  95. /package/src/{features → domains}/text-to-image/presentation/hooks/useGeneration.ts +0 -0
  96. /package/src/{features → domains}/text-to-image/presentation/hooks/useTextToImageForm.ts +0 -0
  97. /package/src/{features → domains}/text-to-image/presentation/index.ts +0 -0
  98. /package/src/{features → domains}/text-to-image/presentation/screens/TextToImageWizardFlow.tsx +0 -0
  99. /package/src/{features → domains}/text-to-image/presentation/screens/TextToImageWizardFlow.types.ts +0 -0
  100. /package/src/{features → domains}/text-to-video/README.md +0 -0
  101. /package/src/{features → domains}/text-to-video/domain/index.ts +0 -0
  102. /package/src/{features → domains}/text-to-video/domain/types/callback.types.ts +0 -0
  103. /package/src/{features → domains}/text-to-video/domain/types/component.types.ts +0 -0
  104. /package/src/{features → domains}/text-to-video/domain/types/config.types.ts +0 -0
  105. /package/src/{features → domains}/text-to-video/domain/types/index.ts +0 -0
  106. /package/src/{features → domains}/text-to-video/domain/types/request.types.ts +0 -0
  107. /package/src/{features → domains}/text-to-video/domain/types/state.types.ts +0 -0
  108. /package/src/{features → domains}/text-to-video/index.ts +0 -0
  109. /package/src/{features → domains}/text-to-video/infrastructure/index.ts +0 -0
  110. /package/src/{features → domains}/text-to-video/infrastructure/services/index.ts +0 -0
  111. /package/src/{features → domains}/text-to-video/infrastructure/services/text-to-video-executor.ts +0 -0
  112. /package/src/{features → domains}/text-to-video/presentation/components/FrameSelector.tsx +0 -0
  113. /package/src/{features → domains}/text-to-video/presentation/components/GenerationTabs.tsx +0 -0
  114. /package/src/{features → domains}/text-to-video/presentation/components/HeroSection.tsx +0 -0
  115. /package/src/{features → domains}/text-to-video/presentation/components/HintCarousel.tsx +0 -0
  116. /package/src/{features → domains}/text-to-video/presentation/components/OptionsPanel.tsx +0 -0
  117. /package/src/{features → domains}/text-to-video/presentation/components/index.ts +0 -0
  118. /package/src/{features → domains}/text-to-video/presentation/hooks/index.ts +0 -0
  119. /package/src/{features → domains}/text-to-video/presentation/hooks/useTextToVideoForm.ts +0 -0
  120. /package/src/{features → domains}/text-to-video/presentation/index.ts +0 -0
  121. /package/src/{features → domains}/text-to-video/presentation/screens/TextToVideoWizardFlow.tsx +0 -0
@@ -4,7 +4,7 @@
4
4
  * Main Category → Sub Category → Scenario List
5
5
  */
6
6
 
7
- import React, { useState, useCallback, useEffect } from "react";
7
+ import React, { useState, useCallback } from "react";
8
8
  import type { ScenarioData } from "../../domain/scenario.types";
9
9
  import type { MainCategory, SubCategory } from "../../domain/category.types";
10
10
  import { MainCategoryScreen } from "../screens/MainCategoryScreen";
@@ -48,88 +48,34 @@ export const CategoryNavigationContainer: React.FC<
48
48
  const [selectedMainCategoryId, setSelectedMainCategoryId] = useState<string | null>(null);
49
49
  const [selectedSubCategoryId, setSelectedSubCategoryId] = useState<string | null>(null);
50
50
 
51
- // Debug: Initial mount
52
- useEffect(() => {
53
- if (typeof __DEV__ !== "undefined" && __DEV__) {
54
- console.log("[CategoryNavigationContainer] Mounted", {
55
- mainCategoriesCount: mainCategories.length,
56
- subCategoriesCount: subCategories.length,
57
- scenariosCount: scenarios.length,
58
- currentStep,
59
- });
60
- }
61
- }, []);
62
-
63
- // Debug: Step changes
64
- useEffect(() => {
65
- if (typeof __DEV__ !== "undefined" && __DEV__) {
66
- console.log("[CategoryNavigationContainer] Step changed", {
67
- currentStep,
68
- selectedMainCategoryId,
69
- selectedSubCategoryId,
70
- });
71
- }
72
- }, [currentStep, selectedMainCategoryId, selectedSubCategoryId]);
73
-
74
51
  const handleSelectMainCategory = useCallback((categoryId: string) => {
75
- if (typeof __DEV__ !== "undefined" && __DEV__) {
76
- console.log("[CategoryNavigationContainer] Main category selected", {
77
- categoryId,
78
- });
79
- }
80
52
  setSelectedMainCategoryId(categoryId);
81
53
  setCurrentStep("sub_category");
82
- if (onSelectMainCategory) {
83
- onSelectMainCategory(categoryId);
84
- }
54
+ onSelectMainCategory?.(categoryId);
85
55
  }, [onSelectMainCategory]);
86
56
 
87
57
  const handleSelectSubCategory = useCallback((subCategoryId: string) => {
88
- if (typeof __DEV__ !== "undefined" && __DEV__) {
89
- console.log("[CategoryNavigationContainer] Sub category selected", {
90
- subCategoryId,
91
- });
92
- }
93
58
  setSelectedSubCategoryId(subCategoryId);
94
59
  setCurrentStep("scenario_list");
95
- if (onSelectSubCategory) {
96
- onSelectSubCategory(subCategoryId);
97
- }
60
+ onSelectSubCategory?.(subCategoryId);
98
61
  }, [onSelectSubCategory]);
99
62
 
100
63
  const handleBackFromSubCategory = useCallback(() => {
101
- if (typeof __DEV__ !== "undefined" && __DEV__) {
102
- console.log("[CategoryNavigationContainer] Back from sub category");
103
- }
104
64
  setSelectedMainCategoryId(null);
105
65
  setCurrentStep("main_category");
106
66
  }, []);
107
67
 
108
68
  const handleBackFromScenarioList = useCallback(() => {
109
- if (typeof __DEV__ !== "undefined" && __DEV__) {
110
- console.log("[CategoryNavigationContainer] Back from scenario list");
111
- }
112
69
  setSelectedSubCategoryId(null);
113
70
  setCurrentStep("sub_category");
114
71
  }, []);
115
72
 
116
- const handleBackFromMainCategory = useCallback(() => {
117
- if (onBack) {
118
- onBack();
119
- }
120
- }, [onBack]);
121
-
122
73
  if (currentStep === "main_category") {
123
- if (typeof __DEV__ !== "undefined" && __DEV__) {
124
- console.log("[CategoryNavigationContainer] Rendering MainCategoryScreen", {
125
- mainCategoriesCount: mainCategories.length,
126
- });
127
- }
128
74
  return (
129
75
  <MainCategoryScreen
130
76
  mainCategories={mainCategories}
131
77
  onSelectCategory={handleSelectMainCategory}
132
- onBack={onBack ? handleBackFromMainCategory : undefined}
78
+ onBack={onBack}
133
79
  t={t}
134
80
  headerTitle={headerTitle}
135
81
  headerDescription={headerDescription}
@@ -139,14 +85,6 @@ export const CategoryNavigationContainer: React.FC<
139
85
 
140
86
  if (currentStep === "sub_category" && selectedMainCategoryId) {
141
87
  const selectedMainCategory = mainCategories.find(c => c.id === selectedMainCategoryId);
142
-
143
- if (typeof __DEV__ !== "undefined" && __DEV__) {
144
- console.log("[CategoryNavigationContainer] Rendering SubCategoryScreen", {
145
- selectedMainCategoryId,
146
- subCategoriesCount: subCategories.length,
147
- mainCategoryTitle: selectedMainCategory?.titleKey,
148
- });
149
- }
150
88
  return (
151
89
  <SubCategoryScreen
152
90
  mainCategoryId={selectedMainCategoryId}
@@ -161,12 +99,6 @@ export const CategoryNavigationContainer: React.FC<
161
99
  }
162
100
 
163
101
  if (currentStep === "scenario_list" && selectedSubCategoryId) {
164
- if (typeof __DEV__ !== "undefined" && __DEV__) {
165
- console.log("[CategoryNavigationContainer] Rendering HierarchicalScenarioListScreen", {
166
- selectedSubCategoryId,
167
- scenariosCount: scenarios.length,
168
- });
169
- }
170
102
  return (
171
103
  <HierarchicalScenarioListScreen
172
104
  subCategoryId={selectedSubCategoryId}
@@ -181,13 +113,5 @@ export const CategoryNavigationContainer: React.FC<
181
113
  );
182
114
  }
183
115
 
184
- if (typeof __DEV__ !== "undefined" && __DEV__) {
185
- console.log("[CategoryNavigationContainer] Rendering NULL - no matching condition", {
186
- currentStep,
187
- selectedMainCategoryId,
188
- selectedSubCategoryId,
189
- });
190
- }
191
-
192
116
  return null;
193
117
  };
@@ -12,10 +12,8 @@ import type {
12
12
  TextToImageInputBuilder,
13
13
  TextToImageResultExtractor,
14
14
  } from "../../domain/types";
15
+ import { defaultExtractImageResult, type ExtractedImageResult } from "../utils/imageResultExtractor";
15
16
 
16
- /**
17
- * Options for text-to-image execution
18
- */
19
17
  export interface ExecuteTextToImageOptions {
20
18
  model: string;
21
19
  buildInput: TextToImageInputBuilder;
@@ -23,84 +21,6 @@ export interface ExecuteTextToImageOptions {
23
21
  onProgress?: (progress: number) => void;
24
22
  }
25
23
 
26
- /**
27
- * Extracted result structure from provider response
28
- */
29
- interface ExtractedImageResult {
30
- imageUrl?: string;
31
- imageUrls?: string[];
32
- }
33
-
34
- /**
35
- * Extract images from provider response object
36
- */
37
- function extractImagesFromObject(
38
- obj: Record<string, unknown>,
39
- ): string[] | null {
40
- // Direct images array
41
- if (Array.isArray(obj.images)) {
42
- const urls = obj.images
43
- .map((img) => {
44
- if (typeof img === "string") return img;
45
- if (img && typeof img === "object" && "url" in img) {
46
- return (img as { url: string }).url;
47
- }
48
- return null;
49
- })
50
- .filter((url): url is string => url !== null);
51
-
52
- if (urls.length > 0) return urls;
53
- }
54
- return null;
55
- }
56
-
57
- /**
58
- * Default extractor for text-to-image results
59
- */
60
- function defaultExtractResult(
61
- result: unknown,
62
- ): ExtractedImageResult | undefined {
63
- if (typeof result !== "object" || result === null) {
64
- return undefined;
65
- }
66
-
67
- const r = result as Record<string, unknown>;
68
-
69
- // Check nested 'data' object first (common API wrapper format)
70
- if (r.data && typeof r.data === "object") {
71
- const dataObj = r.data as Record<string, unknown>;
72
- const urls = extractImagesFromObject(dataObj);
73
- if (urls) {
74
- return { imageUrl: urls[0], imageUrls: urls };
75
- }
76
- }
77
-
78
- // Check direct 'images' array
79
- const directUrls = extractImagesFromObject(r);
80
- if (directUrls) {
81
- return { imageUrl: directUrls[0], imageUrls: directUrls };
82
- }
83
-
84
- // Check for imageUrl (data URL)
85
- if (typeof r.imageUrl === "string") {
86
- return { imageUrl: r.imageUrl, imageUrls: [r.imageUrl] };
87
- }
88
-
89
- // Fallback: construct data URL from imageBase64
90
- if (typeof r.imageBase64 === "string") {
91
- const mimeType = typeof r.mimeType === "string" ? r.mimeType : "image/png";
92
- const dataUrl = `data:${mimeType};base64,${r.imageBase64}`;
93
- return { imageUrl: dataUrl, imageUrls: [dataUrl] };
94
- }
95
-
96
- // Check for 'image' field
97
- if (typeof r.image === "string") {
98
- return { imageUrl: r.image, imageUrls: [r.image] };
99
- }
100
-
101
- return undefined;
102
- }
103
-
104
24
  /**
105
25
  * Text-to-Image Executor using Template Method pattern
106
26
  * Eliminates code duplication through BaseExecutor
@@ -151,7 +71,7 @@ class TextToImageExecutor extends BaseExecutor<
151
71
  protected getDefaultExtractor(): (
152
72
  result: unknown,
153
73
  ) => ExtractedImageResult | undefined {
154
- return defaultExtractResult;
74
+ return defaultExtractImageResult;
155
75
  }
156
76
  }
157
77
 
@@ -0,0 +1,58 @@
1
+ export interface ExtractedImageResult {
2
+ imageUrl?: string;
3
+ imageUrls?: string[];
4
+ }
5
+
6
+ function extractImagesFromObject(obj: Record<string, unknown>): string[] | null {
7
+ if (Array.isArray(obj.images)) {
8
+ const urls = obj.images
9
+ .map((img) => {
10
+ if (typeof img === "string") return img;
11
+ if (img && typeof img === "object" && "url" in img) {
12
+ return (img as { url: string }).url;
13
+ }
14
+ return null;
15
+ })
16
+ .filter((url): url is string => url !== null);
17
+
18
+ if (urls.length > 0) return urls;
19
+ }
20
+ return null;
21
+ }
22
+
23
+ export function defaultExtractImageResult(result: unknown): ExtractedImageResult | undefined {
24
+ if (typeof result !== "object" || result === null) {
25
+ return undefined;
26
+ }
27
+
28
+ const r = result as Record<string, unknown>;
29
+
30
+ if (r.data && typeof r.data === "object") {
31
+ const dataObj = r.data as Record<string, unknown>;
32
+ const urls = extractImagesFromObject(dataObj);
33
+ if (urls) {
34
+ return { imageUrl: urls[0], imageUrls: urls };
35
+ }
36
+ }
37
+
38
+ const directUrls = extractImagesFromObject(r);
39
+ if (directUrls) {
40
+ return { imageUrl: directUrls[0], imageUrls: directUrls };
41
+ }
42
+
43
+ if (typeof r.imageUrl === "string") {
44
+ return { imageUrl: r.imageUrl, imageUrls: [r.imageUrl] };
45
+ }
46
+
47
+ if (typeof r.imageBase64 === "string") {
48
+ const mimeType = typeof r.mimeType === "string" ? r.mimeType : "image/png";
49
+ const dataUrl = `data:${mimeType};base64,${r.imageBase64}`;
50
+ return { imageUrl: dataUrl, imageUrls: [dataUrl] };
51
+ }
52
+
53
+ if (typeof r.image === "string") {
54
+ return { imageUrl: r.image, imageUrls: [r.image] };
55
+ }
56
+
57
+ return undefined;
58
+ }
@@ -0,0 +1,75 @@
1
+ import { executeTextToVideo } from "../../infrastructure/services";
2
+ import type { GenerationStrategy } from "../../../../presentation/hooks/generation";
3
+ import type {
4
+ TextToVideoConfig,
5
+ TextToVideoCallbacks,
6
+ TextToVideoResult,
7
+ TextToVideoOptions,
8
+ TextToVideoInputBuilder,
9
+ TextToVideoResultExtractor,
10
+ } from "../../domain/types";
11
+
12
+ interface VideoGenerationInput {
13
+ prompt: string;
14
+ options?: TextToVideoOptions;
15
+ creationId: string;
16
+ }
17
+
18
+ interface CreateStrategyParams {
19
+ config: TextToVideoConfig;
20
+ callbacks: TextToVideoCallbacks;
21
+ buildInput: TextToVideoInputBuilder;
22
+ extractResult?: TextToVideoResultExtractor;
23
+ userId: string;
24
+ currentPrompt: string;
25
+ creationIdRef: React.MutableRefObject<string>;
26
+ updateState: (videoUrl: string | null, thumbnailUrl: string | null) => void;
27
+ }
28
+
29
+ export const createTextToVideoStrategy = (
30
+ params: CreateStrategyParams,
31
+ ): GenerationStrategy<VideoGenerationInput, TextToVideoResult> => {
32
+ const { config, callbacks, buildInput, extractResult, userId, currentPrompt, creationIdRef, updateState } = params;
33
+
34
+ return {
35
+ execute: async (input) => {
36
+ creationIdRef.current = input.creationId;
37
+
38
+ callbacks.onGenerationStart?.({
39
+ creationId: input.creationId,
40
+ type: "text-to-video",
41
+ prompt: input.prompt,
42
+ metadata: input.options as Record<string, unknown> | undefined,
43
+ }).catch(() => {});
44
+
45
+ const result = await executeTextToVideo(
46
+ { prompt: input.prompt, userId, options: input.options },
47
+ { model: config.model, buildInput, extractResult },
48
+ );
49
+
50
+ if (!result.success || !result.videoUrl) {
51
+ throw new Error(result.error || "Generation failed");
52
+ }
53
+
54
+ updateState(result.videoUrl ?? null, result.thumbnailUrl ?? null);
55
+
56
+ return {
57
+ success: true,
58
+ videoUrl: result.videoUrl,
59
+ thumbnailUrl: result.thumbnailUrl,
60
+ };
61
+ },
62
+ getCreditCost: () => config.creditCost,
63
+ save: async (result) => {
64
+ if (result.success && result.videoUrl && creationIdRef.current) {
65
+ await callbacks.onCreationSave?.({
66
+ creationId: creationIdRef.current,
67
+ type: "text-to-video",
68
+ videoUrl: result.videoUrl,
69
+ thumbnailUrl: result.thumbnailUrl,
70
+ prompt: currentPrompt,
71
+ });
72
+ }
73
+ },
74
+ };
75
+ };
@@ -0,0 +1,120 @@
1
+ import { useState, useCallback, useMemo, useRef } from "react";
2
+ import { useGenerationOrchestrator } from "../../../../presentation/hooks/generation";
3
+ import { DEFAULT_ALERT_MESSAGES } from "../../../../presentation/constants/alert-messages";
4
+ import { generateCreationId } from "../../../../infrastructure/utils/id-generator.util";
5
+ import { createTextToVideoStrategy } from "./textToVideoStrategy";
6
+ import type {
7
+ TextToVideoFeatureState,
8
+ TextToVideoConfig,
9
+ TextToVideoCallbacks,
10
+ TextToVideoResult,
11
+ TextToVideoOptions,
12
+ TextToVideoInputBuilder,
13
+ TextToVideoResultExtractor,
14
+ } from "../../domain/types";
15
+
16
+ export interface UseTextToVideoFeatureProps {
17
+ config: TextToVideoConfig;
18
+ callbacks: TextToVideoCallbacks;
19
+ userId: string;
20
+ buildInput: TextToVideoInputBuilder;
21
+ extractResult?: TextToVideoResultExtractor;
22
+ }
23
+
24
+ export interface TextToVideoGenerateParams extends TextToVideoOptions {
25
+ prompt?: string;
26
+ }
27
+
28
+ export interface UseTextToVideoFeatureReturn {
29
+ state: TextToVideoFeatureState;
30
+ setPrompt: (prompt: string) => void;
31
+ generate: (params?: TextToVideoGenerateParams) => Promise<TextToVideoResult>;
32
+ reset: () => void;
33
+ isReady: boolean;
34
+ canGenerate: boolean;
35
+ }
36
+
37
+ const INITIAL_STATE: TextToVideoFeatureState = {
38
+ prompt: "",
39
+ videoUrl: null,
40
+ thumbnailUrl: null,
41
+ isProcessing: false,
42
+ progress: 0,
43
+ error: null,
44
+ };
45
+
46
+ export function useTextToVideoFeature(props: UseTextToVideoFeatureProps): UseTextToVideoFeatureReturn {
47
+ const { config, callbacks, userId, buildInput, extractResult } = props;
48
+ const [state, setState] = useState<TextToVideoFeatureState>(INITIAL_STATE);
49
+ const creationIdRef = useRef("");
50
+
51
+ const updateState = useCallback((videoUrl: string | null, thumbnailUrl: string | null) => {
52
+ setState((prev) => ({ ...prev, videoUrl, thumbnailUrl }));
53
+ }, []);
54
+
55
+ const strategy = useMemo(
56
+ () =>
57
+ createTextToVideoStrategy({
58
+ config,
59
+ callbacks,
60
+ buildInput,
61
+ extractResult,
62
+ userId,
63
+ currentPrompt: state.prompt,
64
+ creationIdRef,
65
+ updateState,
66
+ }),
67
+ [config, callbacks, buildInput, extractResult, userId, state.prompt, updateState],
68
+ );
69
+
70
+ const orchestrator = useGenerationOrchestrator(strategy, {
71
+ userId,
72
+ alertMessages: DEFAULT_ALERT_MESSAGES,
73
+ onCreditsExhausted: () => callbacks.onShowPaywall?.(config.creditCost),
74
+ onSuccess: (result) => callbacks.onGenerate?.(result as TextToVideoResult),
75
+ onError: (err) => callbacks.onError?.(err.message),
76
+ });
77
+
78
+ const setPrompt = useCallback((prompt: string) => {
79
+ setState((prev) => ({ ...prev, prompt, error: null }));
80
+ }, []);
81
+
82
+ const generate = useCallback(
83
+ async (params?: TextToVideoGenerateParams): Promise<TextToVideoResult> => {
84
+ const prompt = params?.prompt || state.prompt;
85
+ if (!prompt.trim()) {
86
+ const error = "Prompt is required";
87
+ setState((prev) => ({ ...prev, error }));
88
+ return { success: false, error };
89
+ }
90
+
91
+ setState((prev) => ({ ...prev, isProcessing: true, error: null, progress: 0 }));
92
+
93
+ try {
94
+ const result = await orchestrator.generate({
95
+ prompt: prompt.trim(),
96
+ options: params,
97
+ creationId: generateCreationId("text-to-video"),
98
+ });
99
+ setState((prev) => ({ ...prev, isProcessing: false }));
100
+ return { success: true, videoUrl: (result as TextToVideoResult)?.videoUrl };
101
+ } catch (error) {
102
+ const message = error instanceof Error ? error.message : "Generation failed";
103
+ setState((prev) => ({ ...prev, isProcessing: false, error: message }));
104
+ return { success: false, error: message };
105
+ }
106
+ },
107
+ [state.prompt, orchestrator],
108
+ );
109
+
110
+ const reset = useCallback(() => setState(INITIAL_STATE), []);
111
+
112
+ return {
113
+ state,
114
+ setPrompt,
115
+ generate,
116
+ reset,
117
+ isReady: !orchestrator.isGenerating && !state.isProcessing,
118
+ canGenerate: !orchestrator.isGenerating && !state.isProcessing && state.prompt.trim().length > 0,
119
+ };
120
+ }
@@ -18,7 +18,7 @@ export type {
18
18
  UseTextToImageFormOptions, UseTextToImageFormReturn,
19
19
  TextToImagePromptInputProps, TextToImageExamplePromptsProps, TextToImageStyleSelectorProps,
20
20
  TextToImageAspectRatioSelectorProps, TextToImageGenerateButtonProps, TextToImageSettingsSheetProps,
21
- } from "../features/text-to-image";
21
+ } from "../domains/text-to-image";
22
22
  export {
23
23
  DEFAULT_IMAGE_STYLES, DEFAULT_NUM_IMAGES_OPTIONS, ASPECT_RATIO_VALUES, IMAGE_SIZE_VALUES,
24
24
  OUTPUT_FORMAT_VALUES, DEFAULT_FORM_VALUES, DEFAULT_TEXT_TO_IMAGE_PROMPTS, DEFAULT_TEXT_TO_VOICE_PROMPTS,
@@ -29,7 +29,7 @@ export {
29
29
  TextToImagePromptInput, TextToImageExamplePrompts, TextToImageNumImagesSelector,
30
30
  TextToImageStyleSelector, TextToImageAspectRatioSelector, TextToImageSizeSelector,
31
31
  TextToImageOutputFormatSelector, TextToImageGenerateButton, TextToImageSettingsSheet,
32
- } from "../features/text-to-image";
32
+ } from "../domains/text-to-image";
33
33
 
34
34
  // Text-to-Video Feature
35
35
  export type {
@@ -45,13 +45,13 @@ export type {
45
45
  ExamplePrompt,
46
46
  UseTextToVideoFeatureProps, UseTextToVideoFeatureReturn, TextToVideoGenerateParams,
47
47
  UseTextToVideoFormProps, UseTextToVideoFormReturn, ExecuteTextToVideoOptions,
48
- } from "../features/text-to-video";
48
+ } from "../domains/text-to-video";
49
49
  export {
50
50
  INITIAL_FORM_STATE, INITIAL_GENERATION_STATE,
51
51
  executeTextToVideo, hasTextToVideoSupport,
52
52
  useTextToVideoFeature, useTextToVideoForm,
53
53
  GenerationTabs, FrameSelector, OptionsPanel, HeroSection, HintCarousel,
54
- } from "../features/text-to-video";
54
+ } from "../domains/text-to-video";
55
55
 
56
56
  // Image-to-Video Feature
57
57
  export type {
@@ -70,7 +70,7 @@ export type {
70
70
  ImageToVideoAnimationStyleSelectorProps, ImageToVideoDurationSelectorProps,
71
71
  ImageToVideoMusicMoodSelectorProps, ImageToVideoSelectionGridProps,
72
72
  ImageToVideoSelectionGridTranslations, ImageToVideoGenerateButtonProps,
73
- } from "../features/image-to-video";
73
+ } from "../domains/image-to-video";
74
74
  export {
75
75
  IMAGE_TO_VIDEO_ANIMATION_STYLES, IMAGE_TO_VIDEO_DEFAULT_ANIMATION,
76
76
  IMAGE_TO_VIDEO_MUSIC_MOODS, IMAGE_TO_VIDEO_DEFAULT_MUSIC,
@@ -80,12 +80,12 @@ export {
80
80
  useImageToVideoFormState, useImageToVideoGeneration, useImageToVideoForm, useImageToVideoFeature,
81
81
  ImageToVideoAnimationStyleSelector, ImageToVideoDurationSelector,
82
82
  ImageToVideoMusicMoodSelector, ImageToVideoSelectionGrid, ImageToVideoGenerateButton,
83
- } from "../features/image-to-video";
83
+ } from "../domains/image-to-video";
84
84
 
85
85
  // Wizard Flows
86
- export { TextToImageWizardFlow } from "../features/text-to-image/presentation/screens/TextToImageWizardFlow";
87
- export type { TextToImageWizardFlowProps } from "../features/text-to-image/presentation/screens/TextToImageWizardFlow";
88
- export { TextToVideoWizardFlow } from "../features/text-to-video/presentation/screens/TextToVideoWizardFlow";
89
- export type { TextToVideoWizardFlowProps } from "../features/text-to-video/presentation/screens/TextToVideoWizardFlow";
90
- export { ImageToVideoWizardFlow } from "../features/image-to-video/presentation/screens/ImageToVideoWizardFlow";
91
- export type { ImageToVideoWizardFlowProps } from "../features/image-to-video/presentation/screens/ImageToVideoWizardFlow";
86
+ export { TextToImageWizardFlow } from "../domains/text-to-image/presentation/screens/TextToImageWizardFlow";
87
+ export type { TextToImageWizardFlowProps } from "../domains/text-to-image/presentation/screens/TextToImageWizardFlow";
88
+ export { TextToVideoWizardFlow } from "../domains/text-to-video/presentation/screens/TextToVideoWizardFlow";
89
+ export type { TextToVideoWizardFlowProps } from "../domains/text-to-video/presentation/screens/TextToVideoWizardFlow";
90
+ export { ImageToVideoWizardFlow } from "../domains/image-to-video/presentation/screens/ImageToVideoWizardFlow";
91
+ export type { ImageToVideoWizardFlowProps } from "../domains/image-to-video/presentation/screens/ImageToVideoWizardFlow";
@@ -6,7 +6,7 @@
6
6
  import React from "react";
7
7
  import { View, StyleSheet } from "react-native";
8
8
  import { AtomicText, AtomicSpinner, useAppDesignTokens } from "@umituz/react-native-design-system";
9
- import type { BackgroundJob } from "../../domain/entities/job.types";
9
+ import type { BackgroundJob } from "../../domains/background/domain/entities/job.types";
10
10
  import { PendingJobProgressBar } from "./PendingJobProgressBar";
11
11
  import { PendingJobCardActions } from "./PendingJobCardActions";
12
12