@umituz/react-native-ai-generation-content 1.61.25 → 1.61.26

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 (35) hide show
  1. package/package.json +1 -1
  2. package/src/core/types/error.types.ts +3 -30
  3. package/src/core/types/provider.types.ts +35 -188
  4. package/src/core/types/result.types.ts +12 -96
  5. package/src/domain/entities/flow-config.types.ts +2 -2
  6. package/src/domains/generation/domain/generation.types.ts +4 -7
  7. package/src/domains/generation/index.ts +1 -1
  8. package/src/domains/generation/presentation/useAIGeneration.hook.ts +3 -15
  9. package/src/domains/generation/wizard/presentation/hooks/usePhotoBlockingGeneration.ts +1 -1
  10. package/src/features/image-to-video/infrastructure/services/image-to-video-executor.ts +10 -37
  11. package/src/features/image-to-video/presentation/hooks/image-to-video-feature.types.ts +2 -12
  12. package/src/features/image-to-video/presentation/hooks/useImageToVideoFeature.ts +24 -13
  13. package/src/features/text-to-video/infrastructure/services/text-to-video-executor.ts +5 -37
  14. package/src/features/text-to-video/presentation/hooks/useTextToVideoFeature.ts +26 -26
  15. package/src/infrastructure/orchestration/GenerationOrchestrator.ts +17 -14
  16. package/src/infrastructure/orchestration/orchestrator.types.ts +2 -5
  17. package/src/infrastructure/services/generation-orchestrator.service.ts +6 -6
  18. package/src/infrastructure/utils/README.md +7 -7
  19. package/src/infrastructure/utils/base64.util.ts +15 -0
  20. package/src/infrastructure/utils/error-classifier.util.ts +27 -10
  21. package/src/infrastructure/utils/error-message-extractor.util.ts +3 -3
  22. package/src/infrastructure/utils/error-patterns.constants.ts +21 -8
  23. package/src/infrastructure/utils/id-generator.util.ts +11 -0
  24. package/src/infrastructure/utils/index.ts +3 -0
  25. package/src/infrastructure/utils/provider-validator.util.ts +2 -2
  26. package/src/infrastructure/utils/video-result-extractor.util.ts +38 -0
  27. package/src/presentation/constants/alert-messages.ts +14 -0
  28. package/src/presentation/hooks/generation/errors.ts +5 -1
  29. package/src/presentation/hooks/generation/useImageGeneration.ts +6 -2
  30. package/src/presentation/hooks/generation/useVideoGeneration.ts +6 -2
  31. package/src/presentation/hooks/useGenerationFlow.ts +18 -23
  32. package/src/presentation/layouts/DualImageFeatureLayout.tsx +0 -1
  33. package/src/presentation/layouts/DualImageVideoFeatureLayout.tsx +1 -1
  34. package/src/presentation/layouts/SingleImageFeatureLayout.tsx +1 -1
  35. package/src/presentation/layouts/SingleImageWithPromptFeatureLayout.tsx +1 -1
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Video Result Extractor Utility
3
+ * Shared extractor for video generation results
4
+ */
5
+
6
+ export interface ExtractedVideoResult {
7
+ videoUrl?: string;
8
+ thumbnailUrl?: string;
9
+ }
10
+
11
+ /**
12
+ * Default extractor for video generation results.
13
+ * Handles common provider response formats.
14
+ */
15
+ export function defaultExtractVideoResult(
16
+ result: unknown,
17
+ ): ExtractedVideoResult | undefined {
18
+ if (typeof result !== "object" || result === null) return undefined;
19
+
20
+ const r = result as Record<string, unknown>;
21
+
22
+ if (typeof r.video === "string") {
23
+ return { videoUrl: r.video };
24
+ }
25
+
26
+ if (r.video && typeof r.video === "object") {
27
+ const video = r.video as Record<string, unknown>;
28
+ if (typeof video.url === "string") {
29
+ return {
30
+ videoUrl: video.url,
31
+ thumbnailUrl:
32
+ typeof r.thumbnail === "string" ? r.thumbnail : undefined,
33
+ };
34
+ }
35
+ }
36
+
37
+ return undefined;
38
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Default Alert Messages
3
+ * Shared constant for generation error messages
4
+ */
5
+
6
+ import type { AlertMessages } from "../hooks/generation/types";
7
+
8
+ export const DEFAULT_ALERT_MESSAGES: AlertMessages = {
9
+ networkError: "No internet connection. Please check your network.",
10
+ policyViolation: "Content not allowed. Please try again.",
11
+ saveFailed: "Failed to save. Please try again.",
12
+ creditFailed: "Credit operation failed. Please try again.",
13
+ unknown: "An error occurred. Please try again.",
14
+ };
@@ -58,11 +58,15 @@ export const parseError = (err: unknown): GenerationError => {
58
58
  return createGenerationError("unknown", "Generation failed");
59
59
  };
60
60
 
61
+ const VALID_ERROR_TYPES: readonly string[] = ["network", "credits", "policy", "save", "unknown"];
62
+
61
63
  const isGenerationError = (err: unknown): err is GenerationError => {
62
64
  return (
63
65
  typeof err === "object" &&
64
66
  err !== null &&
65
67
  "type" in err &&
66
- "message" in err
68
+ "message" in err &&
69
+ typeof (err as GenerationError).type === "string" &&
70
+ VALID_ERROR_TYPES.includes((err as GenerationError).type)
67
71
  );
68
72
  };
@@ -4,7 +4,7 @@
4
4
  * Uses centralized orchestrator for credit/error handling
5
5
  */
6
6
 
7
- import { useMemo, useCallback } from "react";
7
+ import { useMemo, useCallback, useRef } from "react";
8
8
  import { useGenerationOrchestrator } from "./orchestrator";
9
9
  import type { GenerationStrategy, AlertMessages } from "./types";
10
10
  import { executeImageFeature } from "../../../infrastructure/services";
@@ -105,9 +105,13 @@ export const useImageGeneration = <
105
105
  [],
106
106
  );
107
107
 
108
+ const lastInputRef = useRef<TInput | null>(null);
109
+
108
110
  const strategy: GenerationStrategy<TInput, TResult> = useMemo(
109
111
  () => ({
110
112
  execute: async (input) => {
113
+ lastInputRef.current = input;
114
+
111
115
  // Build executor input
112
116
  const executorInput = buildExecutorInput
113
117
  ? buildExecutorInput(input)
@@ -129,7 +133,7 @@ export const useImageGeneration = <
129
133
  getCreditCost: () => creditCost,
130
134
  save: buildCreation
131
135
  ? async (result, uid) => {
132
- const creation = buildCreation(result, {} as TInput);
136
+ const creation = buildCreation(result, lastInputRef.current ?? {} as TInput);
133
137
  if (creation) {
134
138
  await repository.create(uid, creation);
135
139
  }
@@ -4,7 +4,7 @@
4
4
  * Uses centralized orchestrator for credit/error handling
5
5
  */
6
6
 
7
- import { useMemo, useCallback } from "react";
7
+ import { useMemo, useCallback, useRef } from "react";
8
8
  import { useGenerationOrchestrator } from "./orchestrator";
9
9
  import type { GenerationStrategy, AlertMessages } from "./types";
10
10
  import { executeVideoFeature } from "../../../infrastructure/services";
@@ -60,9 +60,13 @@ export const useVideoGeneration = <TResult>(
60
60
  [],
61
61
  );
62
62
 
63
+ const lastInputRef = useRef<DualImageVideoInput | null>(null);
64
+
63
65
  const strategy: GenerationStrategy<DualImageVideoInput, TResult> = useMemo(
64
66
  () => ({
65
67
  execute: async (input) => {
68
+ lastInputRef.current = input;
69
+
66
70
  const result = await executeVideoFeature(
67
71
  featureType,
68
72
  {
@@ -81,7 +85,7 @@ export const useVideoGeneration = <TResult>(
81
85
  getCreditCost: () => creditCost,
82
86
  save: buildCreation
83
87
  ? async (result, uid) => {
84
- const creation = buildCreation(result, {} as DualImageVideoInput);
88
+ const creation = buildCreation(result, lastInputRef.current ?? {} as DualImageVideoInput);
85
89
  if (creation) {
86
90
  await repository.create(uid, creation);
87
91
  }
@@ -84,29 +84,26 @@ export const useGenerationFlow = ({
84
84
  const goNext = useCallback(() => {
85
85
  if (!canGoNext) return;
86
86
 
87
- setState((prev) => {
88
- const nextIndex = prev.currentStepIndex + 1;
89
-
90
- if (nextIndex >= config.photoSteps.length) {
91
- const newState = { ...prev, isComplete: true };
92
- onComplete?.(newState);
93
- return newState;
94
- }
87
+ const nextIndex = state.currentStepIndex + 1;
88
+ const isLastStep = nextIndex >= config.photoSteps.length;
95
89
 
90
+ if (isLastStep) {
91
+ const newState = { ...state, isComplete: true };
92
+ setState(newState);
93
+ onComplete?.(newState);
94
+ } else {
95
+ setState((prev) => ({ ...prev, currentStepIndex: nextIndex }));
96
96
  onStepChange?.(nextIndex, config.photoSteps[nextIndex]);
97
- return { ...prev, currentStepIndex: nextIndex };
98
- });
99
- }, [canGoNext, config.photoSteps, onComplete, onStepChange]);
97
+ }
98
+ }, [canGoNext, state, config.photoSteps, onComplete, onStepChange]);
100
99
 
101
100
  const goBack = useCallback(() => {
102
101
  if (!canGoBack) return;
103
102
 
104
- setState((prev) => {
105
- const prevIndex = prev.currentStepIndex - 1;
106
- onStepChange?.(prevIndex, config.photoSteps[prevIndex]);
107
- return { ...prev, currentStepIndex: prevIndex, isComplete: false };
108
- });
109
- }, [canGoBack, config.photoSteps, onStepChange]);
103
+ const prevIndex = state.currentStepIndex - 1;
104
+ setState((prev) => ({ ...prev, currentStepIndex: prevIndex, isComplete: false }));
105
+ onStepChange?.(prevIndex, config.photoSteps[prevIndex]);
106
+ }, [canGoBack, state.currentStepIndex, config.photoSteps, onStepChange]);
110
107
 
111
108
  const updatePhoto = useCallback((imageUri: string, previewUrl?: string) => {
112
109
  setState((prev) =>
@@ -159,12 +156,10 @@ export const useGenerationFlow = ({
159
156
  }, [config]);
160
157
 
161
158
  const complete = useCallback(() => {
162
- setState((prev) => {
163
- const newState = { ...prev, isComplete: true };
164
- onComplete?.(newState);
165
- return newState;
166
- });
167
- }, [onComplete]);
159
+ const newState = { ...state, isComplete: true };
160
+ setState(newState);
161
+ onComplete?.(newState);
162
+ }, [state, onComplete]);
168
163
 
169
164
  return {
170
165
  state,
@@ -122,7 +122,6 @@ export const DualImageFeatureLayout: React.FC<DualImageFeatureLayoutProps> = ({
122
122
  onGenerate={handleProcess}
123
123
  isGenerating={feature.isProcessing}
124
124
  isDisabled={!feature.sourceImageUri || !feature.targetImageUri}
125
- progress={feature.progress}
126
125
  translations={{
127
126
  generateButton: translations.processButtonText,
128
127
  generatingButton: translations.processingText,
@@ -115,7 +115,7 @@ export const DualImageVideoFeatureLayout: React.FC<DualImageVideoFeatureLayoutPr
115
115
  <AIGenerationForm
116
116
  onGenerate={handleProcess}
117
117
  isGenerating={feature.isProcessing}
118
- progress={feature.progress}
118
+ isDisabled={!feature.sourceImageUri || !feature.targetImageUri}
119
119
  translations={{
120
120
  generateButton: translations.processButtonText,
121
121
  generatingButton: translations.processingText,
@@ -138,7 +138,7 @@ export const SingleImageFeatureLayout: React.FC<SingleImageFeatureLayoutProps> =
138
138
  <AIGenerationForm
139
139
  onGenerate={handleProcess}
140
140
  isGenerating={feature.isProcessing}
141
- progress={feature.progress}
141
+ isDisabled={!feature.imageUri}
142
142
  translations={{
143
143
  generateButton: translations.processButtonText,
144
144
  generatingButton: translations.processingText,
@@ -125,7 +125,7 @@ export const SingleImageWithPromptFeatureLayout: React.FC<SingleImageWithPromptF
125
125
  <AIGenerationForm
126
126
  onGenerate={handleProcess}
127
127
  isGenerating={feature.isProcessing}
128
- progress={feature.progress}
128
+ isDisabled={!feature.imageUri}
129
129
  translations={{
130
130
  generateButton: translations.processButtonText,
131
131
  generatingButton: translations.processingText,