@umituz/react-native-ai-generation-content 1.82.6 → 1.82.7

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-ai-generation-content",
3
- "version": "1.82.6",
3
+ "version": "1.82.7",
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",
@@ -85,7 +85,8 @@ export function useProcessingJobsPoller(
85
85
  try {
86
86
  await repository.update(userId, creation.id, {
87
87
  status: CREATION_STATUS.FAILED,
88
- metadata: { error: "Generation timed out" },
88
+ metadata: { ...creation.metadata, error: "Generation timed out" },
89
+ completedAt: new Date(),
89
90
  });
90
91
  } catch (e) {
91
92
  if (typeof __DEV__ !== "undefined" && __DEV__) {
@@ -129,7 +130,8 @@ export function useProcessingJobsPoller(
129
130
  }
130
131
  await repository.update(userId, creation.id, {
131
132
  status: CREATION_STATUS.FAILED,
132
- metadata: { error: "No valid result URL received" },
133
+ metadata: { ...creation.metadata, error: "No valid result URL received" },
134
+ completedAt: new Date(),
133
135
  });
134
136
  return;
135
137
  }
@@ -143,6 +145,7 @@ export function useProcessingJobsPoller(
143
145
  status: CREATION_STATUS.COMPLETED,
144
146
  uri,
145
147
  output,
148
+ completedAt: new Date(),
146
149
  });
147
150
  } else if (status.status === QUEUE_STATUS.FAILED) {
148
151
  if (typeof __DEV__ !== "undefined" && __DEV__) console.log("[ProcessingJobsPoller] Failed:", creation.id);
@@ -151,7 +154,8 @@ export function useProcessingJobsPoller(
151
154
 
152
155
  await repository.update(userId, creation.id, {
153
156
  status: CREATION_STATUS.FAILED,
154
- metadata: { error: "Generation failed" },
157
+ metadata: { ...creation.metadata, error: "Generation failed" },
158
+ completedAt: new Date(),
155
159
  });
156
160
  }
157
161
  } catch (error) {
@@ -25,13 +25,16 @@ export function useVideoQueueGeneration(props: UseVideoQueueGenerationProps): Us
25
25
  const consecutiveErrorsRef = useRef(0);
26
26
  const [isGenerating, setIsGenerating] = useState(false);
27
27
 
28
+ const clearPolling = useCallback(() => {
29
+ if (pollingRef.current) {
30
+ clearInterval(pollingRef.current);
31
+ pollingRef.current = null;
32
+ }
33
+ }, []);
34
+
28
35
  useEffect(() => {
29
36
  return () => {
30
- if (pollingRef.current) {
31
- clearInterval(pollingRef.current);
32
- pollingRef.current = null;
33
- }
34
- // Reset all refs on unmount
37
+ clearPolling();
35
38
  isGeneratingRef.current = false;
36
39
  isPollingRef.current = false;
37
40
  consecutiveErrorsRef.current = 0;
@@ -40,9 +43,10 @@ export function useVideoQueueGeneration(props: UseVideoQueueGenerationProps): Us
40
43
  modelRef.current = null;
41
44
  setIsGenerating(false);
42
45
  };
43
- }, []);
46
+ }, [clearPolling]);
44
47
 
45
48
  const resetRefs = useCallback(() => {
49
+ clearPolling();
46
50
  creationIdRef.current = null;
47
51
  requestIdRef.current = null;
48
52
  modelRef.current = null;
@@ -50,10 +54,13 @@ export function useVideoQueueGeneration(props: UseVideoQueueGenerationProps): Us
50
54
  isPollingRef.current = false;
51
55
  consecutiveErrorsRef.current = 0;
52
56
  setIsGenerating(false);
53
- }, []);
57
+ }, [clearPolling]);
54
58
 
55
59
  const handleComplete = useCallback(
56
60
  async (urls: GenerationUrls) => {
61
+ // Stop polling immediately on completion
62
+ clearPolling();
63
+
57
64
  const creationId = creationIdRef.current;
58
65
  const uri = (urls.videoUrl || urls.imageUrl) ?? "";
59
66
 
@@ -72,9 +79,12 @@ export function useVideoQueueGeneration(props: UseVideoQueueGenerationProps): Us
72
79
  if (typeof __DEV__ !== "undefined" && __DEV__) {
73
80
  console.error("[VideoQueue] ❌ Invalid completion data:", { creationId, userId, uri });
74
81
  }
82
+ resetRefs();
83
+ onError?.("Invalid completion data - no valid URL received");
75
84
  return;
76
85
  }
77
86
 
87
+ let persistenceSucceeded = true;
78
88
  if (creationId && userId) {
79
89
  try {
80
90
  await persistence.updateToCompleted(userId, creationId, {
@@ -87,27 +97,32 @@ export function useVideoQueueGeneration(props: UseVideoQueueGenerationProps): Us
87
97
  console.log("[VideoQueue] ✅ Updated completion status in Firestore");
88
98
  }
89
99
  } catch (error) {
100
+ persistenceSucceeded = false;
90
101
  if (typeof __DEV__ !== "undefined" && __DEV__) {
91
102
  console.error("[VideoQueue] ❌ Failed to update completion status:", error);
92
103
  }
93
104
  }
94
105
  }
95
106
 
107
+ resetRefs();
108
+
109
+ // Still call onSuccess even if persistence failed - the generation itself succeeded
110
+ // The video/image URL is valid, user should still see the result
96
111
  if (typeof __DEV__ !== "undefined" && __DEV__) {
97
- console.log("[VideoQueue] 🎯 Calling onSuccess callback now...");
112
+ console.log("[VideoQueue] 🎯 Calling onSuccess callback now...", { persistenceSucceeded });
98
113
  }
99
- resetRefs();
100
114
  onSuccess?.(urls);
101
115
 
102
116
  if (typeof __DEV__ !== "undefined" && __DEV__) {
103
117
  console.log("[VideoQueue] ✅ onSuccess callback completed");
104
118
  }
105
119
  },
106
- [userId, persistence, onSuccess, resetRefs],
120
+ [userId, persistence, onSuccess, onError, resetRefs, clearPolling],
107
121
  );
108
122
 
109
123
  const handleError = useCallback(
110
124
  async (errorMsg: string) => {
125
+ clearPolling();
111
126
  const creationId = creationIdRef.current;
112
127
  if (creationId && userId) {
113
128
  try {
@@ -121,7 +136,7 @@ export function useVideoQueueGeneration(props: UseVideoQueueGenerationProps): Us
121
136
  resetRefs();
122
137
  onError?.(errorMsg);
123
138
  },
124
- [userId, persistence, onError, resetRefs],
139
+ [userId, persistence, onError, resetRefs, clearPolling],
125
140
  );
126
141
 
127
142
  const pollStatus = useCallback(async () => {
@@ -129,15 +144,21 @@ export function useVideoQueueGeneration(props: UseVideoQueueGenerationProps): Us
129
144
  const model = modelRef.current;
130
145
  if (!requestId || !model) return;
131
146
 
132
- await pollQueueStatus({
133
- requestId,
134
- model,
135
- isPollingRef,
136
- pollingRef,
137
- consecutiveErrorsRef,
138
- onComplete: handleComplete,
139
- onError: handleError,
140
- });
147
+ try {
148
+ await pollQueueStatus({
149
+ requestId,
150
+ model,
151
+ isPollingRef,
152
+ pollingRef,
153
+ consecutiveErrorsRef,
154
+ onComplete: handleComplete,
155
+ onError: handleError,
156
+ });
157
+ } catch (error) {
158
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
159
+ console.error("[VideoQueue] Unexpected poll error:", error);
160
+ }
161
+ }
141
162
  }, [handleComplete, handleError]);
142
163
 
143
164
  const startGeneration = useCallback(
@@ -176,14 +197,34 @@ export function useVideoQueueGeneration(props: UseVideoQueueGenerationProps): Us
176
197
  if (typeof __DEV__ !== "undefined" && __DEV__) {
177
198
  console.error("[VideoQueue] Failed to save processing creation:", error);
178
199
  }
200
+ // Continue without creation tracking - generation can still proceed
201
+ // The video will be generated but won't appear in gallery history
202
+ }
203
+ }
204
+
205
+ let queueResult;
206
+ try {
207
+ queueResult = await strategy.submitToQueue(input);
208
+ } catch (error) {
209
+ // Queue submission threw - reset state and report error
210
+ if (creationId && userId) {
211
+ try {
212
+ await persistence.updateToFailed(userId, creationId, error instanceof Error ? error.message : "Queue submission failed");
213
+ } catch { /* best effort */ }
179
214
  }
215
+ isGeneratingRef.current = false;
216
+ setIsGenerating(false);
217
+ onError?.(error instanceof Error ? error.message : "Queue submission failed");
218
+ return;
180
219
  }
181
220
 
182
- const queueResult = await strategy.submitToQueue(input);
183
221
  if (!queueResult.success || !queueResult.requestId || !queueResult.model) {
184
222
  if (creationId && userId) {
185
- await persistence.updateToFailed(userId, creationId, queueResult.error || "Queue submission failed");
223
+ try {
224
+ await persistence.updateToFailed(userId, creationId, queueResult.error || "Queue submission failed");
225
+ } catch { /* best effort */ }
186
226
  }
227
+ isGeneratingRef.current = false;
187
228
  setIsGenerating(false);
188
229
  onError?.(queueResult.error || "Queue submission failed");
189
230
  return;
@@ -205,7 +246,7 @@ export function useVideoQueueGeneration(props: UseVideoQueueGenerationProps): Us
205
246
  pollingRef.current = setInterval(() => void pollStatus(), DEFAULT_POLL_INTERVAL_MS);
206
247
  void pollStatus();
207
248
  },
208
- [userId, scenario, persistence, strategy, pollStatus, onError],
249
+ [userId, scenario, persistence, strategy, creditCost, pollStatus, onError],
209
250
  );
210
251
 
211
252
  return { isGenerating, startGeneration };