@umituz/react-native-ai-generation-content 1.37.13 → 1.37.14

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.37.13",
3
+ "version": "1.37.14",
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",
@@ -80,11 +80,14 @@ function applyStyleEnhancements(prompt: string, wizardData: Record<string, unkno
80
80
  // Strategy Factory
81
81
  // ============================================================================
82
82
 
83
+ declare const __DEV__: boolean;
84
+
83
85
  export function createImageStrategy(options: CreateImageStrategyOptions): WizardStrategy {
84
86
  const { scenario, collectionName = "creations" } = options;
85
87
  const repository = createCreationsRepository(collectionName);
86
88
 
87
89
  let lastInputRef: WizardImageInput | null = null;
90
+ let processingCreationId: string | null = null;
88
91
 
89
92
  return {
90
93
  execute: async (input: unknown) => {
@@ -106,28 +109,63 @@ export function createImageStrategy(options: CreateImageStrategyOptions): Wizard
106
109
 
107
110
  getCreditCost: () => 1,
108
111
 
109
- save: async (result: unknown, uid) => {
110
- const input = lastInputRef;
111
- const imageResult = result as { imageUrl?: string };
112
- if (!input || !scenario?.id || !imageResult.imageUrl) return;
112
+ saveAsProcessing: async (uid: string, input: unknown) => {
113
+ const imageInput = input as WizardImageInput;
114
+ const creationId = `${scenario.id}_${Date.now()}`;
115
+ processingCreationId = creationId;
113
116
 
114
- const creation = {
115
- id: `${scenario.id}_${Date.now()}`,
116
- uri: imageResult.imageUrl,
117
+ await repository.create(uid, {
118
+ id: creationId,
119
+ uri: "",
117
120
  type: scenario.id,
118
- prompt: input.prompt,
119
- status: "completed" as const,
121
+ prompt: imageInput.prompt,
122
+ status: "processing" as const,
120
123
  createdAt: new Date(),
121
124
  isShared: false,
122
125
  isFavorite: false,
123
- metadata: {
124
- scenarioId: scenario.id,
125
- scenarioTitle: scenario.title,
126
- },
127
- output: { imageUrl: imageResult.imageUrl },
128
- };
129
-
130
- await repository.create(uid, creation);
126
+ metadata: { scenarioId: scenario.id, scenarioTitle: scenario.title },
127
+ });
128
+
129
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
130
+ console.log("[ImageStrategy] Saved as processing", { creationId });
131
+ }
132
+
133
+ return creationId;
134
+ },
135
+
136
+ save: async (result: unknown, uid: string, creationId?: string) => {
137
+ const input = lastInputRef;
138
+ const imageResult = result as { imageUrl?: string };
139
+ if (!input || !scenario?.id || !imageResult.imageUrl) return;
140
+
141
+ const idToUpdate = creationId || processingCreationId;
142
+
143
+ if (idToUpdate) {
144
+ // Update existing processing creation to completed
145
+ await repository.update(uid, idToUpdate, {
146
+ uri: imageResult.imageUrl,
147
+ status: "completed" as const,
148
+ output: { imageUrl: imageResult.imageUrl },
149
+ });
150
+
151
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
152
+ console.log("[ImageStrategy] Updated to completed", { creationId: idToUpdate });
153
+ }
154
+ } else {
155
+ // Fallback: create new (shouldn't happen normally)
156
+ await repository.create(uid, {
157
+ id: `${scenario.id}_${Date.now()}`,
158
+ uri: imageResult.imageUrl,
159
+ type: scenario.id,
160
+ prompt: input.prompt,
161
+ status: "completed" as const,
162
+ createdAt: new Date(),
163
+ isShared: false,
164
+ isFavorite: false,
165
+ metadata: { scenarioId: scenario.id, scenarioTitle: scenario.title },
166
+ output: { imageUrl: imageResult.imageUrl },
167
+ });
168
+ }
131
169
  },
132
170
  };
133
171
  }
@@ -76,6 +76,7 @@ export function createVideoStrategy(options: CreateVideoStrategyOptions): Wizard
76
76
  const videoFeatureType = getVideoFeatureType(scenario.id);
77
77
 
78
78
  let lastInputRef: WizardVideoInput | null = null;
79
+ let processingCreationId: string | null = null;
79
80
 
80
81
  return {
81
82
  execute: async (input: unknown) => {
@@ -102,23 +103,63 @@ export function createVideoStrategy(options: CreateVideoStrategyOptions): Wizard
102
103
 
103
104
  getCreditCost: () => 1,
104
105
 
105
- save: async (result: unknown, uid) => {
106
- const input = lastInputRef;
107
- const videoResult = result as { videoUrl?: string };
108
- if (!input || !scenario?.id || !videoResult.videoUrl) return;
106
+ saveAsProcessing: async (uid: string, input: unknown) => {
107
+ const videoInput = input as WizardVideoInput;
108
+ const creationId = `${scenario.id}_${Date.now()}`;
109
+ processingCreationId = creationId;
109
110
 
110
111
  await repository.create(uid, {
111
- id: `${scenario.id}_${Date.now()}`,
112
- uri: videoResult.videoUrl,
112
+ id: creationId,
113
+ uri: "",
113
114
  type: scenario.id,
114
- prompt: input.prompt,
115
- status: "completed" as const,
115
+ prompt: videoInput.prompt,
116
+ status: "processing" as const,
116
117
  createdAt: new Date(),
117
118
  isShared: false,
118
119
  isFavorite: false,
119
120
  metadata: { scenarioId: scenario.id, scenarioTitle: scenario.title },
120
- output: { videoUrl: videoResult.videoUrl },
121
121
  });
122
+
123
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
124
+ console.log("[VideoStrategy] Saved as processing", { creationId });
125
+ }
126
+
127
+ return creationId;
128
+ },
129
+
130
+ save: async (result: unknown, uid: string, creationId?: string) => {
131
+ const input = lastInputRef;
132
+ const videoResult = result as { videoUrl?: string };
133
+ if (!input || !scenario?.id || !videoResult.videoUrl) return;
134
+
135
+ const idToUpdate = creationId || processingCreationId;
136
+
137
+ if (idToUpdate) {
138
+ // Update existing processing creation to completed
139
+ await repository.update(uid, idToUpdate, {
140
+ uri: videoResult.videoUrl,
141
+ status: "completed" as const,
142
+ output: { videoUrl: videoResult.videoUrl },
143
+ });
144
+
145
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
146
+ console.log("[VideoStrategy] Updated to completed", { creationId: idToUpdate });
147
+ }
148
+ } else {
149
+ // Fallback: create new (shouldn't happen normally)
150
+ await repository.create(uid, {
151
+ id: `${scenario.id}_${Date.now()}`,
152
+ uri: videoResult.videoUrl,
153
+ type: scenario.id,
154
+ prompt: input.prompt,
155
+ status: "completed" as const,
156
+ createdAt: new Date(),
157
+ isShared: false,
158
+ isFavorite: false,
159
+ metadata: { scenarioId: scenario.id, scenarioTitle: scenario.title },
160
+ output: { videoUrl: videoResult.videoUrl },
161
+ });
162
+ }
122
163
  },
123
164
  };
124
165
  }
@@ -6,5 +6,8 @@
6
6
  export interface WizardStrategy {
7
7
  execute: (input: unknown) => Promise<{ imageUrl?: string; videoUrl?: string }>;
8
8
  getCreditCost: () => number;
9
- save?: (result: unknown, userId: string) => Promise<void>;
9
+ /** Save as processing when generation starts - returns creation ID */
10
+ saveAsProcessing?: (userId: string, input: unknown) => Promise<string>;
11
+ /** Update to completed when generation finishes */
12
+ save?: (result: unknown, userId: string, creationId?: string) => Promise<void>;
10
13
  }
@@ -1,12 +1,11 @@
1
1
  /**
2
2
  * useWizardGeneration Hook
3
3
  * Wizard generation using orchestrator + strategy factory pattern
4
- * Includes background job tracking for CreationsGallery display
4
+ * Saves to Firestore with status="processing" at start for gallery display
5
5
  */
6
6
 
7
7
  import { useEffect, useRef, useMemo, useCallback } from "react";
8
8
  import { useGenerationOrchestrator } from "../../../../../presentation/hooks/generation";
9
- import { usePendingJobs } from "../../../../../presentation/hooks/use-pending-jobs";
10
9
  import { createWizardStrategy, buildWizardInput } from "../../infrastructure/strategies";
11
10
  import type {
12
11
  UseWizardGenerationProps,
@@ -34,23 +33,19 @@ export const useWizardGeneration = (
34
33
  onSuccess,
35
34
  onError,
36
35
  onCreditsExhausted,
37
- trackAsBackgroundJob = true,
38
36
  } = props;
39
37
 
40
38
  const hasStarted = useRef(false);
41
- const currentJobIdRef = useRef<string | null>(null);
42
-
43
- const { addJob, updateJob, removeJob } = usePendingJobs();
39
+ const currentCreationIdRef = useRef<string | null>(null);
44
40
 
45
41
  useEffect(() => {
46
42
  if (typeof __DEV__ !== "undefined" && __DEV__) {
47
43
  console.log("[useWizardGeneration] Initialized", {
48
44
  scenarioId: scenario.id,
49
45
  outputType: scenario.outputType,
50
- trackAsBackgroundJob,
51
46
  });
52
47
  }
53
- }, [scenario.id, scenario.outputType, trackAsBackgroundJob]);
48
+ }, [scenario.id, scenario.outputType]);
54
49
 
55
50
  const strategy = useMemo(() => {
56
51
  return createWizardStrategy({
@@ -62,17 +57,14 @@ export const useWizardGeneration = (
62
57
  const handleSuccess = useCallback(
63
58
  (result: unknown) => {
64
59
  if (typeof __DEV__ !== "undefined" && __DEV__) {
65
- console.log("[useWizardGeneration] Success");
66
- }
67
-
68
- if (trackAsBackgroundJob && currentJobIdRef.current) {
69
- removeJob(currentJobIdRef.current);
70
- currentJobIdRef.current = null;
60
+ console.log("[useWizardGeneration] Success", {
61
+ creationId: currentCreationIdRef.current,
62
+ });
71
63
  }
72
-
64
+ currentCreationIdRef.current = null;
73
65
  onSuccess?.(result);
74
66
  },
75
- [trackAsBackgroundJob, removeJob, onSuccess],
67
+ [onSuccess],
76
68
  );
77
69
 
78
70
  const handleError = useCallback(
@@ -80,17 +72,11 @@ export const useWizardGeneration = (
80
72
  if (typeof __DEV__ !== "undefined" && __DEV__) {
81
73
  console.log("[useWizardGeneration] Error:", err.message);
82
74
  }
83
-
84
- if (trackAsBackgroundJob && currentJobIdRef.current) {
85
- updateJob({
86
- id: currentJobIdRef.current,
87
- updates: { status: "failed", error: err.message, progress: 0 },
88
- });
89
- }
90
-
75
+ // Note: Failed status update is handled by orchestrator via strategy
76
+ currentCreationIdRef.current = null;
91
77
  onError?.(err.message);
92
78
  },
93
- [trackAsBackgroundJob, updateJob, onError],
79
+ [onError],
94
80
  );
95
81
 
96
82
  const { generate, isGenerating } = useGenerationOrchestrator(strategy, {
@@ -113,31 +99,27 @@ export const useWizardGeneration = (
113
99
  hasStarted.current = true;
114
100
 
115
101
  buildWizardInput(wizardData, scenario)
116
- .then((input) => {
102
+ .then(async (input) => {
117
103
  if (!input) {
118
104
  hasStarted.current = false;
119
105
  onError?.("Failed to build generation input");
120
106
  return;
121
107
  }
122
108
 
123
- if (trackAsBackgroundJob && scenario.outputType) {
124
- const jobId = `wizard-${scenario.id}-${Date.now()}`;
125
- currentJobIdRef.current = jobId;
126
-
127
- addJob({
128
- id: jobId,
129
- input: {
130
- scenarioId: scenario.id,
131
- scenarioTitle: scenario.title,
132
- outputType: scenario.outputType,
133
- },
134
- type: scenario.outputType,
135
- status: "processing",
136
- progress: 10,
137
- });
138
-
139
- if (typeof __DEV__ !== "undefined" && __DEV__) {
140
- console.log("[useWizardGeneration] Created background job:", jobId);
109
+ // Save to Firestore with status="processing" BEFORE starting generation
110
+ if (strategy.saveAsProcessing && userId) {
111
+ try {
112
+ const creationId = await strategy.saveAsProcessing(userId, input);
113
+ currentCreationIdRef.current = creationId;
114
+
115
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
116
+ console.log("[useWizardGeneration] Saved as processing:", creationId);
117
+ }
118
+ } catch (err) {
119
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
120
+ console.error("[useWizardGeneration] saveAsProcessing error:", err);
121
+ }
122
+ // Continue with generation even if save fails
141
123
  }
142
124
  }
143
125
 
@@ -162,8 +144,8 @@ export const useWizardGeneration = (
162
144
  isGenerating,
163
145
  generate,
164
146
  onError,
165
- trackAsBackgroundJob,
166
- addJob,
147
+ strategy,
148
+ userId,
167
149
  ]);
168
150
 
169
151
  return { isGenerating };