@umituz/react-native-ai-generation-content 1.75.1 → 1.75.3

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.75.1",
3
+ "version": "1.75.3",
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",
@@ -70,7 +70,22 @@ export const createFlowStore = (config: FlowStoreConfig) => {
70
70
  nextStep: () => {
71
71
  const { stepDefinitions, currentStepIndex, completedSteps, currentStepId } = get();
72
72
  const nextIndex = currentStepIndex + 1;
73
- if (nextIndex >= stepDefinitions.length) return;
73
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
74
+ console.log("[FlowStore] nextStep called", {
75
+ currentStepIndex,
76
+ nextIndex,
77
+ totalSteps: stepDefinitions.length,
78
+ currentStepId,
79
+ nextStepId: stepDefinitions[nextIndex]?.id,
80
+ nextStepType: stepDefinitions[nextIndex]?.type,
81
+ });
82
+ }
83
+ if (nextIndex >= stepDefinitions.length) {
84
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
85
+ console.log("[FlowStore] nextStep BLOCKED - already at last step");
86
+ }
87
+ return;
88
+ }
74
89
  set({
75
90
  currentStepId: stepDefinitions[nextIndex].id,
76
91
  currentStepIndex: nextIndex,
@@ -2,24 +2,42 @@
2
2
  * Credit Value Extractors
3
3
  * Pure utility functions to extract and normalize values from customData
4
4
  * Single Responsibility: Data transformation for credit calculation
5
+ *
6
+ * Handles both raw values and selection format objects:
7
+ * - Raw: "4s", 4, "480p"
8
+ * - Selection format: { uri: "4s", selection: "4s" | 4, previewUrl: "" }
9
+ */
10
+
11
+ /**
12
+ * Unwrap selection format to get the actual value
13
+ * Selection steps store data as { uri, selection, previewUrl } objects
5
14
  */
15
+ function unwrapSelection(value: unknown): unknown {
16
+ if (typeof value === "object" && value !== null && "selection" in value) {
17
+ return (value as Record<string, unknown>).selection;
18
+ }
19
+ return value;
20
+ }
6
21
 
7
22
  /**
8
23
  * Extract duration value from customData
9
24
  * Handles both number and string formats ("4s", "5s", "6s")
25
+ * Also handles selection format objects from wizard steps
10
26
  *
11
27
  * @param value - Raw value from customData
12
28
  * @returns Normalized duration number, or undefined if invalid
13
29
  */
14
30
  export function extractDuration(value: unknown): number | undefined {
31
+ const unwrapped = unwrapSelection(value);
32
+
15
33
  // Already a number
16
- if (typeof value === "number" && value > 0) {
17
- return value;
34
+ if (typeof unwrapped === "number" && unwrapped > 0) {
35
+ return unwrapped;
18
36
  }
19
37
 
20
38
  // String format: "4s", "5s", "6s" → parse to number
21
- if (typeof value === "string") {
22
- const match = value.match(/^(\d+)s?$/);
39
+ if (typeof unwrapped === "string") {
40
+ const match = unwrapped.match(/^(\d+)s?$/);
23
41
  if (match) {
24
42
  const parsed = parseInt(match[1], 10);
25
43
  return parsed > 0 ? parsed : undefined;
@@ -32,13 +50,16 @@ export function extractDuration(value: unknown): number | undefined {
32
50
  /**
33
51
  * Extract resolution value from customData
34
52
  * Validates against allowed values
53
+ * Also handles selection format objects from wizard steps
35
54
  *
36
55
  * @param value - Raw value from customData
37
56
  * @returns Normalized resolution string, or undefined if invalid
38
57
  */
39
58
  export function extractResolution(value: unknown): "480p" | "720p" | undefined {
40
- if (value === "480p" || value === "720p") {
41
- return value;
59
+ const unwrapped = unwrapSelection(value);
60
+
61
+ if (unwrapped === "480p" || unwrapped === "720p") {
62
+ return unwrapped;
42
63
  }
43
64
  return undefined;
44
65
  }
@@ -2,8 +2,14 @@
2
2
  * Wizard Data Validators
3
3
  * Centralized validation utilities for wizard generation data
4
4
  * DRY: Used across AIGenerateScreen, TextToVideoWizardScreen, ImageToVideoWizardScreen
5
+ *
6
+ * Handles both raw values and selection format objects from wizard steps:
7
+ * - Raw: 4, "480p"
8
+ * - Selection format: { uri: "4s", selection: 4, previewUrl: "" }
5
9
  */
6
10
 
11
+ import { extractDuration, extractResolution } from "./credit-value-extractors";
12
+
7
13
  export interface ValidationResult<T> {
8
14
  value?: T;
9
15
  error?: string;
@@ -18,11 +24,11 @@ export interface ValidationResult<T> {
18
24
  export function validateDuration(
19
25
  data: Record<string, unknown>,
20
26
  ): ValidationResult<number> {
21
- const duration = data.duration as number;
27
+ const duration = extractDuration(data.duration);
22
28
 
23
- if (!duration || typeof duration !== "number" || duration <= 0) {
29
+ if (!duration) {
24
30
  return {
25
- error: `Invalid duration: ${duration}. Must be a positive number.`,
31
+ error: `Invalid duration: ${JSON.stringify(data.duration)}. Must be a positive number.`,
26
32
  };
27
33
  }
28
34
 
@@ -38,24 +44,13 @@ export function validateDuration(
38
44
  export function validateResolution(
39
45
  data: Record<string, unknown>,
40
46
  ): ValidationResult<"480p" | "720p"> {
41
- const resolutionValue = data.resolution as string;
47
+ const resolution = extractResolution(data.resolution);
42
48
 
43
- if (!resolutionValue || typeof resolutionValue !== "string") {
49
+ if (!resolution) {
44
50
  return {
45
- error: `Invalid resolution: ${resolutionValue}. Must be a string.`,
51
+ error: `Invalid resolution: ${JSON.stringify(data.resolution)}. Must be "480p" or "720p".`,
46
52
  };
47
53
  }
48
54
 
49
- // Map resolution - EXACT MATCH ONLY
50
- if (resolutionValue === "480p") {
51
- return { value: "480p" };
52
- }
53
-
54
- if (resolutionValue === "720p") {
55
- return { value: "720p" };
56
- }
57
-
58
- return {
59
- error: `Invalid resolution value: "${resolutionValue}". Must be "480p" or "720p".`,
60
- };
55
+ return { value: resolution };
61
56
  }
@@ -89,6 +89,13 @@ export const WizardFlowContent: React.FC<WizardFlowContentProps> = (props) => {
89
89
  [featureConfig, skipResultStep],
90
90
  );
91
91
 
92
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
93
+ console.log("[WizardFlowContent] flowSteps built", {
94
+ totalSteps: flowSteps.length,
95
+ steps: flowSteps.map((s, i) => `${i}: ${s.id} (${s.type})`),
96
+ });
97
+ }
98
+
92
99
  const flow = useFlow({ steps: flowSteps, initialStepIndex: 0 });
93
100
  const {
94
101
  currentStep,
@@ -26,6 +26,13 @@ export function renderPhotoUploadStep({
26
26
  t,
27
27
  creditCost,
28
28
  }: PhotoUploadStepProps): React.ReactElement {
29
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
30
+ console.log("[renderPhotoUploadStep] Rendering", {
31
+ stepId: step.id,
32
+ hasOnPhotoContinue: !!onPhotoContinue,
33
+ creditCost,
34
+ });
35
+ }
29
36
  const wizardConfig = getWizardStepConfig(step.config);
30
37
  const titleKey = wizardConfig?.titleKey ?? `wizard.steps.${step.id}.title`;
31
38
  const subtitleKey = wizardConfig?.subtitleKey ?? `wizard.steps.${step.id}.subtitle`;
@@ -94,8 +94,11 @@ export function useWizardFlowHandlers(props: UseWizardFlowHandlersProps) {
94
94
  else previousStep();
95
95
  }, [currentStepIndex, previousStep, onBack]);
96
96
 
97
- const handleNextStep = useCallback(() => {
97
+ const handleNextStep = useCallback((additionalData?: Record<string, unknown>) => {
98
98
  const nextStepDef = flowSteps[currentStepIndex + 1];
99
+ // Merge additionalData to avoid stale closure issue
100
+ // When called from handlePhotoContinue, customData in closure may not include the just-set value
101
+ const mergedData = additionalData ? { ...customData, ...additionalData } : customData;
99
102
  if (typeof __DEV__ !== "undefined" && __DEV__) {
100
103
  console.log("[handleNextStep] Called", {
101
104
  currentStepIndex,
@@ -103,14 +106,15 @@ export function useWizardFlowHandlers(props: UseWizardFlowHandlersProps) {
103
106
  nextStepId: nextStepDef?.id,
104
107
  totalSteps: flowSteps.length,
105
108
  hasOnGenerationStart: !!onGenerationStart,
109
+ dataKeys: Object.keys(mergedData),
106
110
  });
107
111
  }
108
112
  if (nextStepDef?.type === StepType.GENERATING && onGenerationStart) {
109
- onGenerationStart(customData, nextStep);
113
+ onGenerationStart(mergedData, nextStep, handleGenerationError);
110
114
  return;
111
115
  }
112
116
  nextStep();
113
- }, [currentStepIndex, flowSteps, customData, onGenerationStart, nextStep]);
117
+ }, [currentStepIndex, flowSteps, customData, onGenerationStart, nextStep, handleGenerationError]);
114
118
 
115
119
  const handlePhotoContinue = useCallback(
116
120
  (stepId: string, image: UploadedImage) => {
@@ -118,7 +122,8 @@ export function useWizardFlowHandlers(props: UseWizardFlowHandlersProps) {
118
122
  console.log("[handlePhotoContinue] Called", { stepId, hasImage: !!image, currentStepIndex });
119
123
  }
120
124
  setCustomData(stepId, image);
121
- handleNextStep();
125
+ // Pass the just-set data to avoid stale closure issue
126
+ handleNextStep({ [stepId]: image });
122
127
  },
123
128
  [setCustomData, handleNextStep, currentStepIndex],
124
129
  );
@@ -89,7 +89,23 @@ export const GenericPhotoUploadScreen: React.FC<PhotoUploadScreenProps> = ({
89
89
  });
90
90
 
91
91
  const handleContinuePress = () => {
92
- if (!canContinue || !image) return;
92
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
93
+ console.log("[GenericPhotoUploadScreen] handleContinuePress called", {
94
+ canContinue,
95
+ hasImage: !!image,
96
+ imageUri: image?.uri?.substring(0, 50),
97
+ stepId,
98
+ });
99
+ }
100
+ if (!canContinue || !image) {
101
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
102
+ console.log("[GenericPhotoUploadScreen] BLOCKED - canContinue:", canContinue, "image:", !!image);
103
+ }
104
+ return;
105
+ }
106
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
107
+ console.log("[GenericPhotoUploadScreen] Calling onContinue with image");
108
+ }
93
109
  onContinue(image);
94
110
  };
95
111