@umituz/react-native-ai-generation-content 1.54.0 → 1.56.0
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/domains/generation/wizard/presentation/components/WizardFlowContent.tsx +2 -1
- package/src/domains/generation/wizard/presentation/hooks/generation-result.utils.ts +41 -0
- package/src/domains/generation/wizard/presentation/hooks/useVideoQueueGeneration.ts +18 -3
- package/src/domains/generation/wizard/presentation/hooks/useWizardFlowHandlers.ts +27 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-ai-generation-content",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.56.0",
|
|
4
4
|
"description": "Provider-agnostic AI generation orchestration for React Native with result preview components",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "src/index.ts",
|
|
@@ -121,6 +121,7 @@ export const WizardFlowContent: React.FC<WizardFlowContentProps> = (props) => {
|
|
|
121
121
|
setShowRatingPicker,
|
|
122
122
|
onGenerationStart,
|
|
123
123
|
onGenerationComplete,
|
|
124
|
+
onGenerationError,
|
|
124
125
|
onBack,
|
|
125
126
|
});
|
|
126
127
|
|
|
@@ -132,7 +133,7 @@ export const WizardFlowContent: React.FC<WizardFlowContentProps> = (props) => {
|
|
|
132
133
|
alertMessages,
|
|
133
134
|
creditCost,
|
|
134
135
|
onSuccess: handlers.handleGenerationComplete,
|
|
135
|
-
onError:
|
|
136
|
+
onError: handlers.handleGenerationError,
|
|
136
137
|
onCreditsExhausted,
|
|
137
138
|
});
|
|
138
139
|
|
|
@@ -3,11 +3,20 @@
|
|
|
3
3
|
* Shared utilities for extracting and processing generation results
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
export interface FalErrorDetail {
|
|
7
|
+
msg?: string;
|
|
8
|
+
type?: string;
|
|
9
|
+
loc?: string[];
|
|
10
|
+
input?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
6
13
|
export interface FalResult {
|
|
7
14
|
video?: { url?: string };
|
|
8
15
|
output?: string;
|
|
9
16
|
images?: Array<{ url?: string }>;
|
|
10
17
|
image?: { url?: string };
|
|
18
|
+
detail?: FalErrorDetail[];
|
|
19
|
+
error?: string;
|
|
11
20
|
}
|
|
12
21
|
|
|
13
22
|
export interface GenerationUrls {
|
|
@@ -15,11 +24,43 @@ export interface GenerationUrls {
|
|
|
15
24
|
videoUrl?: string;
|
|
16
25
|
}
|
|
17
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Check if result contains an error and throw with appropriate message
|
|
29
|
+
*/
|
|
30
|
+
function checkForErrors(result: FalResult): void {
|
|
31
|
+
// Check for FAL API error format: {detail: [{msg, type}]}
|
|
32
|
+
if (result.detail && Array.isArray(result.detail) && result.detail.length > 0) {
|
|
33
|
+
const firstError = result.detail[0];
|
|
34
|
+
const errorType = firstError?.type || "unknown";
|
|
35
|
+
const errorMsg = firstError?.msg || "Generation failed";
|
|
36
|
+
|
|
37
|
+
// Map error type to translation key
|
|
38
|
+
if (errorType === "content_policy_violation") {
|
|
39
|
+
throw new Error("error.generation.content_policy");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (errorType.includes("validation")) {
|
|
43
|
+
throw new Error("error.generation.validation");
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
throw new Error(errorMsg);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Check for simple error field
|
|
50
|
+
if (result.error) {
|
|
51
|
+
throw new Error(result.error);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
18
55
|
/**
|
|
19
56
|
* Extracts image/video URL from FAL result
|
|
20
57
|
* Handles various result formats from different FAL models
|
|
58
|
+
* Throws error if result contains error information
|
|
21
59
|
*/
|
|
22
60
|
export function extractResultUrl(result: FalResult): GenerationUrls {
|
|
61
|
+
// First check for errors in the result
|
|
62
|
+
checkForErrors(result);
|
|
63
|
+
|
|
23
64
|
// Video result
|
|
24
65
|
if (result.video?.url) {
|
|
25
66
|
return { videoUrl: result.video.url };
|
|
@@ -109,14 +109,29 @@ export function useVideoQueueGeneration(
|
|
|
109
109
|
if (status.status === QUEUE_STATUS.COMPLETED || status.status === QUEUE_STATUS.FAILED) {
|
|
110
110
|
if (pollingRef.current) { clearInterval(pollingRef.current); pollingRef.current = null; }
|
|
111
111
|
if (status.status === QUEUE_STATUS.COMPLETED) {
|
|
112
|
-
|
|
113
|
-
|
|
112
|
+
try {
|
|
113
|
+
const result = await provider.getJobResult<FalResult>(model, requestId);
|
|
114
|
+
await handleComplete(extractResultUrl(result));
|
|
115
|
+
} catch (resultErr) {
|
|
116
|
+
// Handle errors when getting/extracting result (e.g., ValidationError, content policy)
|
|
117
|
+
const errorMessage = resultErr instanceof Error ? resultErr.message : "Generation failed";
|
|
118
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
119
|
+
console.error("[VideoQueueGeneration] Result error:", errorMessage);
|
|
120
|
+
}
|
|
121
|
+
await handleError(errorMessage);
|
|
122
|
+
}
|
|
114
123
|
} else {
|
|
115
124
|
await handleError("Generation failed");
|
|
116
125
|
}
|
|
117
126
|
}
|
|
118
127
|
} catch (err) {
|
|
119
|
-
|
|
128
|
+
// Handle polling errors - stop polling and show error to user
|
|
129
|
+
if (pollingRef.current) { clearInterval(pollingRef.current); pollingRef.current = null; }
|
|
130
|
+
const errorMessage = err instanceof Error ? err.message : "Generation failed";
|
|
131
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
132
|
+
console.error("[VideoQueueGeneration] Poll error:", errorMessage);
|
|
133
|
+
}
|
|
134
|
+
await handleError(errorMessage);
|
|
120
135
|
}
|
|
121
136
|
}, [handleComplete, handleError]);
|
|
122
137
|
|
|
@@ -29,6 +29,7 @@ export interface UseWizardFlowHandlersProps {
|
|
|
29
29
|
readonly setShowRatingPicker: (show: boolean) => void;
|
|
30
30
|
readonly onGenerationStart?: (data: Record<string, unknown>, proceed: () => void) => void;
|
|
31
31
|
readonly onGenerationComplete?: (result: unknown) => void;
|
|
32
|
+
readonly onGenerationError?: (error: string) => void;
|
|
32
33
|
readonly onBack?: () => void;
|
|
33
34
|
}
|
|
34
35
|
|
|
@@ -51,6 +52,7 @@ export function useWizardFlowHandlers(props: UseWizardFlowHandlersProps) {
|
|
|
51
52
|
setShowRatingPicker,
|
|
52
53
|
onGenerationStart,
|
|
53
54
|
onGenerationComplete,
|
|
55
|
+
onGenerationError,
|
|
54
56
|
onBack,
|
|
55
57
|
} = props;
|
|
56
58
|
|
|
@@ -69,6 +71,30 @@ export function useWizardFlowHandlers(props: UseWizardFlowHandlersProps) {
|
|
|
69
71
|
[setResult, setCurrentCreation, nextStep, onGenerationComplete, skipResultStep],
|
|
70
72
|
);
|
|
71
73
|
|
|
74
|
+
const handleGenerationError = useCallback(
|
|
75
|
+
(errorMessage: string) => {
|
|
76
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
77
|
+
console.log("[WizardFlowHandlers] Generation error:", errorMessage);
|
|
78
|
+
}
|
|
79
|
+
// Translate error key if it looks like a translation key
|
|
80
|
+
const displayMessage = errorMessage.startsWith("error.")
|
|
81
|
+
? t(errorMessage)
|
|
82
|
+
: errorMessage;
|
|
83
|
+
// Show error alert to user
|
|
84
|
+
alert.show(
|
|
85
|
+
AlertType.ERROR,
|
|
86
|
+
AlertMode.MODAL,
|
|
87
|
+
t("common.error"),
|
|
88
|
+
displayMessage,
|
|
89
|
+
);
|
|
90
|
+
// Notify parent component
|
|
91
|
+
onGenerationError?.(errorMessage);
|
|
92
|
+
// Close the wizard
|
|
93
|
+
onBack?.();
|
|
94
|
+
},
|
|
95
|
+
[alert, t, onGenerationError, onBack],
|
|
96
|
+
);
|
|
97
|
+
|
|
72
98
|
const handleDismissGenerating = useCallback(() => {
|
|
73
99
|
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
74
100
|
console.log("[WizardFlowHandlers] Dismissing - generation continues");
|
|
@@ -124,6 +150,7 @@ export function useWizardFlowHandlers(props: UseWizardFlowHandlersProps) {
|
|
|
124
150
|
|
|
125
151
|
return {
|
|
126
152
|
handleGenerationComplete,
|
|
153
|
+
handleGenerationError,
|
|
127
154
|
handleDismissGenerating,
|
|
128
155
|
handleBack,
|
|
129
156
|
handleNextStep,
|