@umituz/react-native-ai-generation-content 1.56.3 → 1.57.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-ai-generation-content",
3
- "version": "1.56.3",
3
+ "version": "1.57.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",
@@ -3,9 +3,12 @@
3
3
  * Orchestrates wizard-based generation by delegating to appropriate mode:
4
4
  * - Video: Queue-based generation with background support
5
5
  * - Photo: Blocking execution for quick results
6
+ *
7
+ * Architecture: State machine pattern with useReducer
8
+ * States: IDLE → PREPARING → GENERATING → COMPLETED/ERROR → IDLE
6
9
  */
7
10
 
8
- import { useEffect, useRef, useMemo } from "react";
11
+ import { useEffect, useReducer, useMemo } from "react";
9
12
  import { createWizardStrategy, buildWizardInput } from "../../infrastructure/strategies";
10
13
  import { createCreationPersistence } from "../../infrastructure/utils/creation-persistence.util";
11
14
  import { useVideoQueueGeneration } from "./useVideoQueueGeneration";
@@ -17,6 +20,57 @@ import type {
17
20
 
18
21
  declare const __DEV__: boolean;
19
22
 
23
+ /**
24
+ * Generation orchestration states
25
+ */
26
+ type GenerationStatus =
27
+ | "IDLE" // Not started
28
+ | "PREPARING" // Building input
29
+ | "GENERATING" // Generation in progress
30
+ | "ERROR" // Failed (prevents retry)
31
+ | "COMPLETED"; // Success
32
+
33
+ /**
34
+ * State machine state
35
+ */
36
+ interface GenerationState {
37
+ status: GenerationStatus;
38
+ error?: string;
39
+ }
40
+
41
+ /**
42
+ * State machine actions
43
+ */
44
+ type GenerationAction =
45
+ | { type: "START_PREPARATION" }
46
+ | { type: "START_GENERATION" }
47
+ | { type: "COMPLETE" }
48
+ | { type: "ERROR"; error: string }
49
+ | { type: "RESET" };
50
+
51
+ /**
52
+ * State machine reducer
53
+ */
54
+ const generationReducer = (
55
+ state: GenerationState,
56
+ action: GenerationAction,
57
+ ): GenerationState => {
58
+ switch (action.type) {
59
+ case "START_PREPARATION":
60
+ return { status: "PREPARING" };
61
+ case "START_GENERATION":
62
+ return { status: "GENERATING" };
63
+ case "COMPLETE":
64
+ return { status: "COMPLETED" };
65
+ case "ERROR":
66
+ return { status: "ERROR", error: action.error };
67
+ case "RESET":
68
+ return { status: "IDLE" };
69
+ default:
70
+ return state;
71
+ }
72
+ };
73
+
20
74
  export type {
21
75
  WizardOutputType,
22
76
  WizardScenarioData,
@@ -39,8 +93,8 @@ export const useWizardGeneration = (
39
93
  onCreditsExhausted,
40
94
  } = props;
41
95
 
42
- const hasStarted = useRef(false);
43
- const hasError = useRef(false);
96
+ // State machine: replaces multiple useRef flags
97
+ const [state, dispatch] = useReducer(generationReducer, { status: "IDLE" });
44
98
 
45
99
  const persistence = useMemo(() => createCreationPersistence(), []);
46
100
  const strategy = useMemo(
@@ -76,21 +130,28 @@ export const useWizardGeneration = (
76
130
  useEffect(() => {
77
131
  const isAlreadyGenerating = videoGeneration.isGenerating || photoGeneration.isGenerating;
78
132
 
79
- if (isGeneratingStep && !hasStarted.current && !isAlreadyGenerating && !hasError.current) {
80
- hasStarted.current = true;
133
+ // Start generation: Simple single condition using state machine
134
+ if (isGeneratingStep && state.status === "IDLE" && !isAlreadyGenerating) {
135
+ dispatch({ type: "START_PREPARATION" });
136
+
137
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
138
+ console.log("[WizardGeneration] State: PREPARING");
139
+ }
81
140
 
82
141
  buildWizardInput(wizardData, scenario)
83
142
  .then(async (input) => {
84
143
  if (!input) {
85
- hasStarted.current = false;
86
- hasError.current = true;
144
+ dispatch({ type: "ERROR", error: "Failed to build generation input" });
87
145
  onError?.("Failed to build generation input");
88
146
  return;
89
147
  }
90
148
 
149
+ dispatch({ type: "START_GENERATION" });
150
+
91
151
  const typedInput = input as { prompt?: string };
92
152
 
93
153
  if (typeof __DEV__ !== "undefined" && __DEV__) {
154
+ console.log("[WizardGeneration] State: GENERATING");
94
155
  console.log("[WizardGeneration] Mode:", isVideoMode ? "VIDEO_QUEUE" : "PHOTO_BLOCKING");
95
156
  }
96
157
 
@@ -99,23 +160,28 @@ export const useWizardGeneration = (
99
160
  } else {
100
161
  await photoGeneration.startGeneration(input, typedInput.prompt || "");
101
162
  }
163
+
164
+ dispatch({ type: "COMPLETE" });
102
165
  })
103
166
  .catch((error) => {
104
167
  if (typeof __DEV__ !== "undefined" && __DEV__) {
105
168
  console.error("[WizardGeneration] Build input error:", error.message);
106
169
  }
107
- hasStarted.current = false;
108
- hasError.current = true;
170
+ dispatch({ type: "ERROR", error: error.message });
109
171
  onError?.(error.message);
110
172
  });
111
173
  }
112
174
 
113
- if (!isGeneratingStep) {
114
- hasStarted.current = false;
115
- hasError.current = false;
175
+ // Reset state when leaving generating step
176
+ if (!isGeneratingStep && state.status !== "IDLE") {
177
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
178
+ console.log("[WizardGeneration] State: RESET");
179
+ }
180
+ dispatch({ type: "RESET" });
116
181
  }
117
182
  }, [
118
183
  isGeneratingStep,
184
+ state.status,
119
185
  scenario,
120
186
  wizardData,
121
187
  isVideoMode,