@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 +1 -1
- package/src/features/couple-future/index.ts +0 -2
- package/src/features/couple-future/presentation/hooks/useCoupleFutureFlow.ts +128 -140
- package/src/features/couple-future/presentation/hooks/coupleFutureFlow.types.ts +0 -71
- package/src/features/couple-future/presentation/hooks/useCoupleFutureGeneration.ts +0 -141
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-ai-generation-content",
|
|
3
|
-
"version": "1.19.
|
|
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
|
-
*
|
|
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 {
|
|
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
|
-
|
|
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
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
|
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
|
-
|
|
35
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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: (
|
|
54
|
-
if (typeof __DEV__ !== "undefined" && __DEV__)
|
|
55
|
-
|
|
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
|
-
|
|
65
|
-
|
|
135
|
+
// Trigger generation when step changes to GENERATING
|
|
66
136
|
useEffect(() => {
|
|
67
|
-
if (
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
158
|
-
|
|
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
|
-
|
|
176
|
-
|
|
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
|
-
|
|
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
|
-
};
|