@umituz/react-native-ai-generation-content 1.19.8 → 1.19.9

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.19.8",
3
+ "version": "1.19.9",
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",
@@ -14,8 +14,6 @@ export type {
14
14
  CoupleFeatureSelection,
15
15
  } from "./domain/types";
16
16
  export { COUPLE_FUTURE_DEFAULTS } from "./domain/types";
17
- export { useCoupleFutureGeneration } from "./presentation/hooks/useCoupleFutureGeneration";
18
- export type { CoupleFutureConfig as UseCoupleFutureGenerationConfig } from "./presentation/hooks/useCoupleFutureGeneration";
19
17
  export { useCoupleFutureFlow } from "./presentation/hooks/useCoupleFutureFlow";
20
18
  export type {
21
19
  CoupleFutureFlowConfig,
@@ -1,105 +1,146 @@
1
1
  /**
2
2
  * useCoupleFutureFlow Hook
3
- * Handles couple future wizard flow logic
3
+ * Optimized: Merged flow + generation logic
4
+ * Uses centralized orchestrator directly
4
5
  */
5
6
 
6
- import { useCallback, useEffect, useRef } from "react";
7
+ import { useCallback, useEffect, useRef, useMemo } from "react";
7
8
  import { InteractionManager } from "react-native";
8
- import { useCoupleFutureGeneration } from "./useCoupleFutureGeneration";
9
+ import {
10
+ useGenerationOrchestrator,
11
+ type GenerationStrategy,
12
+ type AlertMessages,
13
+ } from "../../../../presentation/hooks/generation";
14
+ import { executeCoupleFuture } from "../../infrastructure/executor";
9
15
  import { buildGenerationInputFromConfig } from "../../infrastructure/generationUtils";
16
+ import { createCreationsRepository } from "../../../../domains/creations/infrastructure/adapters";
10
17
  import type { UploadedImage } from "../../../partner-upload/domain/types";
11
- import type {
12
- CoupleFutureFlowConfig,
13
- CoupleFutureFlowState,
14
- CoupleFutureFlowActions,
15
- CoupleFutureFlowProps,
16
- } from "./coupleFutureFlow.types";
18
+ import type { CoupleFutureInput } from "../../domain/types";
19
+ import type { Creation } from "../../../../domains/creations/domain/entities/Creation";
17
20
 
18
21
  declare const __DEV__: boolean;
19
22
 
20
- export type {
21
- CoupleFutureFlowConfig,
22
- CoupleFutureFlowState,
23
- CoupleFutureFlowActions,
24
- CoupleFutureFlowProps,
25
- };
23
+ export interface CoupleFutureFlowConfig<TStep, TScenarioId> {
24
+ steps: {
25
+ SCENARIO: TStep;
26
+ SCENARIO_PREVIEW: TStep;
27
+ COUPLE_FEATURE_SELECTOR: TStep;
28
+ TEXT_INPUT: TStep;
29
+ PARTNER_A: TStep;
30
+ PARTNER_B: TStep;
31
+ GENERATING: TStep;
32
+ };
33
+ customScenarioId: TScenarioId;
34
+ }
35
+
36
+ export interface CoupleFutureFlowState<TStep, TScenarioId> {
37
+ step: TStep;
38
+ selectedScenarioId: TScenarioId | null;
39
+ selectedFeature: string | null;
40
+ partnerA: unknown;
41
+ partnerB: unknown;
42
+ partnerAName: string;
43
+ partnerBName: string;
44
+ customPrompt: string | null;
45
+ visualStyle: string | null;
46
+ selection: unknown;
47
+ isProcessing: boolean;
48
+ scenarioConfig: unknown;
49
+ selectedScenarioData: { requiresPhoto?: boolean } | null;
50
+ }
51
+
52
+ export interface CoupleFutureFlowActions<TStep, TScenarioId, TResult> {
53
+ setStep: (step: TStep) => void;
54
+ selectScenario: (id: TScenarioId) => void;
55
+ setPartnerA: (image: unknown) => void;
56
+ setPartnerAName: (name: string) => void;
57
+ setPartnerB: (image: unknown) => void;
58
+ setPartnerBName: (name: string) => void;
59
+ setCustomPrompt: (prompt: string) => void;
60
+ setVisualStyle: (style: string) => void;
61
+ startGeneration: () => void;
62
+ generationSuccess: (result: TResult) => void;
63
+ generationError: (error: string) => void;
64
+ requireFeature: (callback: () => void) => void;
65
+ onNavigateToHistory: () => void;
66
+ }
67
+
68
+ export interface CoupleFutureFlowProps<TStep, TScenarioId, TResult> {
69
+ userId?: string;
70
+ config: CoupleFutureFlowConfig<TStep, TScenarioId>;
71
+ state: CoupleFutureFlowState<TStep, TScenarioId>;
72
+ actions: CoupleFutureFlowActions<TStep, TScenarioId, TResult>;
73
+ generationConfig: {
74
+ visualStyleModifiers: Record<string, string>;
75
+ defaultPartnerAName: string;
76
+ defaultPartnerBName: string;
77
+ };
78
+ alertMessages: AlertMessages;
79
+ processResult: (imageUrl: string, input: CoupleFutureInput) => TResult;
80
+ buildCreation: (result: TResult, input: CoupleFutureInput) => Creation | null;
81
+ onCreditsExhausted: () => void;
82
+ }
26
83
 
27
84
  export const useCoupleFutureFlow = <TStep, TScenarioId, TResult>(
28
85
  props: CoupleFutureFlowProps<TStep, TScenarioId, TResult>,
29
86
  ) => {
30
- const { config, state, actions, generationConfig, alertMessages } = props;
31
- const { processResult, buildCreation, onCreditsExhausted, userId } = props;
87
+ const { config, state, actions, generationConfig, alertMessages, userId } = props;
88
+ const { processResult, buildCreation, onCreditsExhausted } = props;
32
89
  const hasStarted = useRef(false);
90
+ const lastInputRef = useRef<CoupleFutureInput | null>(null);
91
+ const repository = useMemo(() => createCreationsRepository("creations"), []);
33
92
 
34
- if (typeof __DEV__ !== "undefined" && __DEV__) {
35
- console.log("[CoupleFutureFlow] Hook initialized:", { userId, step: state.step });
36
- }
93
+ // Strategy for orchestrator - directly uses executor
94
+ const strategy: GenerationStrategy<CoupleFutureInput, TResult> = useMemo(
95
+ () => ({
96
+ execute: async (input, onProgress) => {
97
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
98
+ console.log("[CoupleFutureFlow] 🎯 Executing generation...");
99
+ }
100
+ lastInputRef.current = input;
101
+ const result = await executeCoupleFuture(
102
+ { partnerABase64: input.partnerABase64, partnerBBase64: input.partnerBBase64, prompt: input.prompt },
103
+ { onProgress },
104
+ );
105
+ if (!result.success || !result.imageUrl) throw new Error(result.error || "Generation failed");
106
+ return processResult(result.imageUrl, input);
107
+ },
108
+ getCreditCost: () => 1,
109
+ save: async (result, uid) => {
110
+ const input = lastInputRef.current;
111
+ if (!input) return;
112
+ const creation = buildCreation(result, input);
113
+ if (creation) await repository.create(uid, creation);
114
+ },
115
+ }),
116
+ [processResult, buildCreation, repository],
117
+ );
37
118
 
38
- const { generate, isGenerating, progress } = useCoupleFutureGeneration<TResult>({
119
+ // Use orchestrator directly
120
+ const { generate, isGenerating, progress } = useGenerationOrchestrator(strategy, {
39
121
  userId,
122
+ alertMessages,
40
123
  onCreditsExhausted,
41
124
  onSuccess: (result) => {
42
- if (typeof __DEV__ !== "undefined" && __DEV__) {
43
- console.log("[CoupleFutureFlow] 🎉 onSuccess callback triggered");
44
- }
45
- actions.generationSuccess(result);
46
- InteractionManager.runAfterInteractions(() => {
47
- if (typeof __DEV__ !== "undefined" && __DEV__) {
48
- console.log("[CoupleFutureFlow] 🔄 Navigating to History in 300ms...");
49
- }
50
- setTimeout(() => actions.onNavigateToHistory(), 300);
51
- });
125
+ if (typeof __DEV__ !== "undefined" && __DEV__) console.log("[CoupleFutureFlow] 🎉 Success");
126
+ actions.generationSuccess(result as TResult);
127
+ InteractionManager.runAfterInteractions(() => setTimeout(() => actions.onNavigateToHistory(), 300));
52
128
  },
53
- onError: (error) => {
54
- if (typeof __DEV__ !== "undefined" && __DEV__) {
55
- console.log("[CoupleFutureFlow] ❌ onError callback:", error);
56
- }
57
- actions.generationError(error);
129
+ onError: (err) => {
130
+ if (typeof __DEV__ !== "undefined" && __DEV__) console.log("[CoupleFutureFlow] ❌ Error:", err.message);
131
+ actions.generationError(err.message);
58
132
  },
59
- processResult: processResult as never,
60
- buildCreation: buildCreation as never,
61
- alertMessages,
62
133
  });
63
134
 
64
- const { step, isProcessing, selectedFeature, selectedScenarioId, selectedScenarioData } = state;
65
-
135
+ // Trigger generation when step changes to GENERATING
66
136
  useEffect(() => {
67
- if (typeof __DEV__ !== "undefined" && __DEV__) {
68
- console.log("[CoupleFutureFlow] useEffect triggered:", {
69
- step,
70
- isProcessing,
71
- hasStarted: hasStarted.current,
72
- targetStep: config.steps.GENERATING,
73
- });
74
- }
75
-
76
- if (step !== config.steps.GENERATING) {
137
+ if (state.step !== config.steps.GENERATING) {
77
138
  hasStarted.current = false;
78
139
  return;
79
140
  }
80
- if (!isProcessing || hasStarted.current) {
81
- if (typeof __DEV__ !== "undefined" && __DEV__) {
82
- console.log("[CoupleFutureFlow] ⚠️ Skipping generation:", {
83
- reason: !isProcessing ? "isProcessing=false" : "already started",
84
- });
85
- }
86
- return;
87
- }
141
+ if (!state.isProcessing || hasStarted.current) return;
88
142
  hasStarted.current = true;
89
143
 
90
- if (typeof __DEV__ !== "undefined" && __DEV__) {
91
- console.log("[CoupleFutureFlow] 🚀 Building generation input...");
92
- console.log("[CoupleFutureFlow] State:", {
93
- hasPartnerA: !!state.partnerA,
94
- hasPartnerB: !!state.partnerB,
95
- partnerAName: state.partnerAName,
96
- partnerBName: state.partnerBName,
97
- hasScenarioConfig: !!state.scenarioConfig,
98
- customPrompt: state.customPrompt?.slice(0, 100),
99
- visualStyle: state.visualStyle,
100
- });
101
- }
102
-
103
144
  const input = buildGenerationInputFromConfig({
104
145
  partnerA: state.partnerA as never,
105
146
  partnerB: state.partnerB as never,
@@ -114,56 +155,29 @@ export const useCoupleFutureFlow = <TStep, TScenarioId, TResult>(
114
155
  visualStyles: generationConfig.visualStyleModifiers,
115
156
  customScenarioId: config.customScenarioId as string,
116
157
  });
158
+ if (input) generate(input);
159
+ }, [state, config, generationConfig, generate]);
117
160
 
118
- if (typeof __DEV__ !== "undefined" && __DEV__) {
119
- console.log("[CoupleFutureFlow] 📦 Generation input built:", {
120
- hasInput: !!input,
121
- prompt: input?.prompt?.slice(0, 200),
122
- });
123
- }
124
-
125
- if (input) {
126
- if (typeof __DEV__ !== "undefined" && __DEV__) {
127
- console.log("[CoupleFutureFlow] 🚀 Calling generate()...");
128
- }
129
- generate(input);
130
- }
131
- }, [step, isProcessing, state, config, generationConfig, generate]);
132
-
161
+ // Handlers
133
162
  const handleScenarioSelect = useCallback(
134
163
  (id: string) => {
135
- if (typeof __DEV__ !== "undefined" && __DEV__) {
136
- console.log("[CoupleFutureFlow] handleScenarioSelect:", id);
137
- }
138
164
  actions.selectScenario(id as TScenarioId);
139
165
  actions.setStep(config.steps.SCENARIO_PREVIEW);
140
166
  },
141
167
  [actions, config.steps.SCENARIO_PREVIEW],
142
168
  );
143
169
 
144
- const handleScenarioPreviewBack = useCallback(
145
- () => actions.setStep(config.steps.SCENARIO),
146
- [actions, config.steps.SCENARIO],
147
- );
170
+ const handleScenarioPreviewBack = useCallback(() => actions.setStep(config.steps.SCENARIO), [actions, config.steps.SCENARIO]);
148
171
 
149
172
  const handleScenarioPreviewContinue = useCallback(() => {
150
- if (selectedFeature) {
151
- actions.setStep(config.steps.COUPLE_FEATURE_SELECTOR);
152
- } else if (
153
- selectedScenarioId === config.customScenarioId ||
154
- selectedScenarioData?.requiresPhoto === false
155
- ) {
173
+ if (state.selectedFeature) actions.setStep(config.steps.COUPLE_FEATURE_SELECTOR);
174
+ else if (state.selectedScenarioId === config.customScenarioId || state.selectedScenarioData?.requiresPhoto === false)
156
175
  actions.setStep(config.steps.TEXT_INPUT);
157
- } else {
158
- actions.setStep(config.steps.PARTNER_A);
159
- }
160
- }, [actions, config, selectedFeature, selectedScenarioId, selectedScenarioData]);
176
+ else actions.setStep(config.steps.PARTNER_A);
177
+ }, [actions, config, state.selectedFeature, state.selectedScenarioId, state.selectedScenarioData]);
161
178
 
162
179
  const handlePartnerAContinue = useCallback(
163
180
  (image: UploadedImage, name: string) => {
164
- if (typeof __DEV__ !== "undefined" && __DEV__) {
165
- console.log("[CoupleFutureFlow] handlePartnerAContinue:", { hasImage: !!image, name });
166
- }
167
181
  actions.setPartnerA(image);
168
182
  actions.setPartnerAName(name);
169
183
  actions.setStep(config.steps.PARTNER_B);
@@ -172,23 +186,12 @@ export const useCoupleFutureFlow = <TStep, TScenarioId, TResult>(
172
186
  );
173
187
 
174
188
  const handlePartnerABack = useCallback(() => {
175
- const targetStep =
176
- selectedScenarioId === config.customScenarioId
177
- ? config.steps.TEXT_INPUT
178
- : config.steps.SCENARIO_PREVIEW;
179
- actions.setStep(targetStep);
180
- }, [actions, config, selectedScenarioId]);
189
+ actions.setStep(state.selectedScenarioId === config.customScenarioId ? config.steps.TEXT_INPUT : config.steps.SCENARIO_PREVIEW);
190
+ }, [actions, config, state.selectedScenarioId]);
181
191
 
182
192
  const handlePartnerBContinue = useCallback(
183
193
  (image: UploadedImage, name: string) => {
184
- if (typeof __DEV__ !== "undefined" && __DEV__) {
185
- console.log("[CoupleFutureFlow] handlePartnerBContinue:", { hasImage: !!image, name });
186
- console.log("[CoupleFutureFlow] Calling requireFeature()...");
187
- }
188
194
  actions.requireFeature(() => {
189
- if (typeof __DEV__ !== "undefined" && __DEV__) {
190
- console.log("[CoupleFutureFlow] 🔓 Feature gate passed, starting generation");
191
- }
192
195
  actions.setPartnerB(image);
193
196
  actions.setPartnerBName(name);
194
197
  actions.startGeneration();
@@ -197,34 +200,19 @@ export const useCoupleFutureFlow = <TStep, TScenarioId, TResult>(
197
200
  [actions],
198
201
  );
199
202
 
200
- const handlePartnerBBack = useCallback(
201
- () => actions.setStep(config.steps.PARTNER_A),
202
- [actions, config.steps.PARTNER_A],
203
- );
203
+ const handlePartnerBBack = useCallback(() => actions.setStep(config.steps.PARTNER_A), [actions, config.steps.PARTNER_A]);
204
204
 
205
205
  const handleMagicPromptContinue = useCallback(
206
206
  (prompt: string, style: string) => {
207
- if (typeof __DEV__ !== "undefined" && __DEV__) {
208
- console.log("[CoupleFutureFlow] handleMagicPromptContinue:", {
209
- promptLength: prompt.length,
210
- style,
211
- });
212
- }
213
207
  actions.setCustomPrompt(prompt);
214
208
  actions.setVisualStyle(style);
215
- if (selectedScenarioId === config.customScenarioId) {
216
- actions.setStep(config.steps.PARTNER_A);
217
- } else {
218
- actions.startGeneration();
219
- }
209
+ if (state.selectedScenarioId === config.customScenarioId) actions.setStep(config.steps.PARTNER_A);
210
+ else actions.startGeneration();
220
211
  },
221
- [actions, config, selectedScenarioId],
212
+ [actions, config, state.selectedScenarioId],
222
213
  );
223
214
 
224
- const handleMagicPromptBack = useCallback(
225
- () => actions.setStep(config.steps.SCENARIO_PREVIEW),
226
- [actions, config.steps.SCENARIO_PREVIEW],
227
- );
215
+ const handleMagicPromptBack = useCallback(() => actions.setStep(config.steps.SCENARIO_PREVIEW), [actions, config.steps.SCENARIO_PREVIEW]);
228
216
 
229
217
  return {
230
218
  isGenerating,
@@ -1,71 +0,0 @@
1
- /**
2
- * Couple Future Flow Types
3
- * Type definitions for couple future wizard flow
4
- */
5
-
6
- export interface CoupleFutureFlowConfig<TStep, TScenarioId> {
7
- steps: {
8
- SCENARIO: TStep;
9
- SCENARIO_PREVIEW: TStep;
10
- COUPLE_FEATURE_SELECTOR: TStep;
11
- TEXT_INPUT: TStep;
12
- PARTNER_A: TStep;
13
- PARTNER_B: TStep;
14
- GENERATING: TStep;
15
- };
16
- customScenarioId: TScenarioId;
17
- }
18
-
19
- export interface CoupleFutureFlowState<TStep, TScenarioId> {
20
- step: TStep;
21
- selectedScenarioId: TScenarioId | null;
22
- selectedFeature: string | null;
23
- partnerA: unknown;
24
- partnerB: unknown;
25
- partnerAName: string;
26
- partnerBName: string;
27
- customPrompt: string | null;
28
- visualStyle: string | null;
29
- selection: unknown;
30
- isProcessing: boolean;
31
- scenarioConfig: unknown;
32
- selectedScenarioData: { requiresPhoto?: boolean } | null;
33
- }
34
-
35
- export interface CoupleFutureFlowActions<TStep, TScenarioId, TResult> {
36
- setStep: (step: TStep) => void;
37
- selectScenario: (id: TScenarioId) => void;
38
- setPartnerA: (image: unknown) => void;
39
- setPartnerAName: (name: string) => void;
40
- setPartnerB: (image: unknown) => void;
41
- setPartnerBName: (name: string) => void;
42
- setCustomPrompt: (prompt: string) => void;
43
- setVisualStyle: (style: string) => void;
44
- startGeneration: () => void;
45
- generationSuccess: (result: TResult) => void;
46
- generationError: (error: string) => void;
47
- requireFeature: (callback: () => void) => void;
48
- onNavigateToHistory: () => void;
49
- }
50
-
51
- export interface CoupleFutureFlowProps<TStep, TScenarioId, TResult> {
52
- userId?: string;
53
- config: CoupleFutureFlowConfig<TStep, TScenarioId>;
54
- state: CoupleFutureFlowState<TStep, TScenarioId>;
55
- actions: CoupleFutureFlowActions<TStep, TScenarioId, TResult>;
56
- generationConfig: {
57
- visualStyleModifiers: Record<string, string>;
58
- defaultPartnerAName: string;
59
- defaultPartnerBName: string;
60
- };
61
- alertMessages: {
62
- networkError: string;
63
- policyViolation: string;
64
- saveFailed: string;
65
- creditFailed: string;
66
- unknown: string;
67
- };
68
- processResult: (imageUrl: string, input: unknown) => TResult;
69
- buildCreation: (result: TResult, input: unknown) => unknown;
70
- onCreditsExhausted: () => void;
71
- }
@@ -1,141 +0,0 @@
1
- /**
2
- * useCoupleFutureGeneration Hook
3
- * Couple future generation using centralized orchestrator
4
- */
5
-
6
- import { useMemo, useCallback, useRef } from "react";
7
- import {
8
- useGenerationOrchestrator,
9
- type GenerationStrategy,
10
- type AlertMessages,
11
- } from "../../../../presentation/hooks/generation";
12
- import { executeCoupleFuture } from "../../infrastructure/executor";
13
- import type { CoupleFutureInput } from "../../domain/types";
14
- import { createCreationsRepository } from "../../../../domains/creations/infrastructure/adapters";
15
- import type { Creation } from "../../../../domains/creations/domain/entities/Creation";
16
-
17
- declare const __DEV__: boolean;
18
-
19
- export interface CoupleFutureConfig<TResult> {
20
- userId: string | undefined;
21
- processResult: (imageUrl: string, input: CoupleFutureInput) => TResult;
22
- buildCreation?: (result: TResult, input: CoupleFutureInput) => Creation | null;
23
- onCreditsExhausted?: () => void;
24
- onSuccess?: (result: TResult) => void;
25
- onError?: (error: string) => void;
26
- alertMessages: AlertMessages;
27
- }
28
-
29
- export const useCoupleFutureGeneration = <TResult>(config: CoupleFutureConfig<TResult>) => {
30
- const { userId, processResult, buildCreation, onCreditsExhausted, onSuccess, onError, alertMessages } = config;
31
-
32
- if (typeof __DEV__ !== "undefined" && __DEV__) {
33
- console.log("[CoupleFutureGeneration] Hook initialized:", {
34
- userId,
35
- hasBuildCreation: !!buildCreation,
36
- hasOnSuccess: !!onSuccess,
37
- });
38
- }
39
-
40
- const repository = useMemo(() => createCreationsRepository("creations"), []);
41
- const lastInputRef = useRef<CoupleFutureInput | null>(null);
42
-
43
- const strategy: GenerationStrategy<CoupleFutureInput, TResult> = useMemo(
44
- () => ({
45
- execute: async (input, onProgress) => {
46
- if (typeof __DEV__ !== "undefined" && __DEV__) {
47
- console.log("[CoupleFutureGeneration] 🎯 strategy.execute() START");
48
- console.log("[CoupleFutureGeneration] Input prompt:", input.prompt?.slice(0, 200));
49
- console.log("[CoupleFutureGeneration] Has partnerA:", !!input.partnerABase64);
50
- console.log("[CoupleFutureGeneration] Has partnerB:", !!input.partnerBBase64);
51
- }
52
-
53
- lastInputRef.current = input;
54
-
55
- if (typeof __DEV__ !== "undefined" && __DEV__) {
56
- console.log("[CoupleFutureGeneration] 📡 Calling executeCoupleFuture()...");
57
- }
58
-
59
- const result = await executeCoupleFuture(
60
- {
61
- partnerABase64: input.partnerABase64,
62
- partnerBBase64: input.partnerBBase64,
63
- prompt: input.prompt,
64
- },
65
- { onProgress },
66
- );
67
-
68
- if (typeof __DEV__ !== "undefined" && __DEV__) {
69
- console.log("[CoupleFutureGeneration] 📡 executeCoupleFuture() returned:", {
70
- success: result.success,
71
- hasImageUrl: !!result.imageUrl,
72
- error: result.error,
73
- });
74
- }
75
-
76
- if (!result.success || !result.imageUrl) {
77
- if (typeof __DEV__ !== "undefined" && __DEV__) {
78
- console.log("[CoupleFutureGeneration] ❌ Generation failed:", result.error);
79
- }
80
- throw new Error(result.error || "Generation failed");
81
- }
82
-
83
- if (typeof __DEV__ !== "undefined" && __DEV__) {
84
- console.log("[CoupleFutureGeneration] ✅ Processing result with processResult()");
85
- }
86
-
87
- return processResult(result.imageUrl, input);
88
- },
89
- getCreditCost: () => 1,
90
- save: buildCreation
91
- ? async (result, uid) => {
92
- if (typeof __DEV__ !== "undefined" && __DEV__) {
93
- console.log("[CoupleFutureGeneration] 💾 strategy.save() START");
94
- }
95
- const input = lastInputRef.current;
96
- if (input) {
97
- const creation = buildCreation(result, input);
98
- if (creation) {
99
- if (typeof __DEV__ !== "undefined" && __DEV__) {
100
- console.log("[CoupleFutureGeneration] 💾 Saving creation to repository...");
101
- }
102
- await repository.create(uid, creation);
103
- if (typeof __DEV__ !== "undefined" && __DEV__) {
104
- console.log("[CoupleFutureGeneration] ✅ Creation saved");
105
- }
106
- }
107
- }
108
- }
109
- : undefined,
110
- }),
111
- [processResult, buildCreation, repository],
112
- );
113
-
114
- const handleError = useCallback(
115
- (error: { message: string }) => {
116
- if (typeof __DEV__ !== "undefined" && __DEV__) {
117
- console.log("[CoupleFutureGeneration] ❌ handleError:", error.message);
118
- }
119
- onError?.(error.message);
120
- },
121
- [onError],
122
- );
123
-
124
- const handleSuccess = useCallback(
125
- (result: unknown) => {
126
- if (typeof __DEV__ !== "undefined" && __DEV__) {
127
- console.log("[CoupleFutureGeneration] 🎉 handleSuccess called");
128
- }
129
- onSuccess?.(result as TResult);
130
- },
131
- [onSuccess],
132
- );
133
-
134
- return useGenerationOrchestrator(strategy, {
135
- userId,
136
- alertMessages,
137
- onCreditsExhausted,
138
- onSuccess: handleSuccess,
139
- onError: handleError,
140
- });
141
- };