@umituz/react-native-ai-generation-content 1.17.87 → 1.17.89
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/text-to-image/index.ts +9 -1
- package/src/features/text-to-image/presentation/hooks/index.ts +8 -0
- package/src/features/text-to-image/presentation/hooks/useGeneration.ts +22 -2
- package/src/features/text-to-image/presentation/hooks/useTextToImageCallbacksBuilder.ts +200 -0
package/package.json
CHANGED
|
@@ -65,7 +65,12 @@ export type { ExecuteTextToImageOptions } from "./infrastructure";
|
|
|
65
65
|
// PRESENTATION LAYER - Hooks
|
|
66
66
|
// =============================================================================
|
|
67
67
|
|
|
68
|
-
export {
|
|
68
|
+
export {
|
|
69
|
+
useFormState,
|
|
70
|
+
useGeneration,
|
|
71
|
+
useTextToImageForm,
|
|
72
|
+
useTextToImageCallbacksBuilder,
|
|
73
|
+
} from "./presentation";
|
|
69
74
|
export type {
|
|
70
75
|
UseFormStateOptions,
|
|
71
76
|
UseFormStateReturn,
|
|
@@ -74,6 +79,9 @@ export type {
|
|
|
74
79
|
UseGenerationReturn,
|
|
75
80
|
UseTextToImageFormOptions,
|
|
76
81
|
UseTextToImageFormReturn,
|
|
82
|
+
TextToImageCallbacksBuilderConfig,
|
|
83
|
+
UseTextToImageCallbacksBuilderOptions,
|
|
84
|
+
UseTextToImageCallbacksBuilderReturn,
|
|
77
85
|
} from "./presentation";
|
|
78
86
|
|
|
79
87
|
// Provider-based Feature Hook
|
|
@@ -28,3 +28,11 @@ export type {
|
|
|
28
28
|
UseTextToImageFeatureProps,
|
|
29
29
|
UseTextToImageFeatureReturn,
|
|
30
30
|
} from "./useTextToImageFeature";
|
|
31
|
+
|
|
32
|
+
// Callbacks Builder Hook
|
|
33
|
+
export { useTextToImageCallbacksBuilder } from "./useTextToImageCallbacksBuilder";
|
|
34
|
+
export type {
|
|
35
|
+
TextToImageCallbacksBuilderConfig,
|
|
36
|
+
UseTextToImageCallbacksBuilderOptions,
|
|
37
|
+
UseTextToImageCallbacksBuilderReturn,
|
|
38
|
+
} from "./useTextToImageCallbacksBuilder";
|
|
@@ -35,6 +35,8 @@ const initialState: GenerationState = {
|
|
|
35
35
|
error: null,
|
|
36
36
|
};
|
|
37
37
|
|
|
38
|
+
declare const __DEV__: boolean;
|
|
39
|
+
|
|
38
40
|
export function useGeneration(options: UseGenerationOptions): UseGenerationReturn {
|
|
39
41
|
const { formState, callbacks, onPromptCleared } = options;
|
|
40
42
|
const [generationState, setGenerationState] = useState<GenerationState>(initialState);
|
|
@@ -42,23 +44,35 @@ export function useGeneration(options: UseGenerationOptions): UseGenerationRetur
|
|
|
42
44
|
const totalCost = callbacks.calculateCost(formState.numImages, formState.selectedModel);
|
|
43
45
|
|
|
44
46
|
const handleGenerate = useCallback(async (): Promise<TextToImageGenerationResult | null> => {
|
|
47
|
+
if (__DEV__) console.log("[TextToImage] handleGenerate called");
|
|
48
|
+
|
|
45
49
|
const trimmedPrompt = formState.prompt.trim();
|
|
46
50
|
|
|
47
51
|
if (!trimmedPrompt) {
|
|
52
|
+
if (__DEV__) console.log("[TextToImage] No prompt provided");
|
|
48
53
|
setGenerationState((prev) => ({ ...prev, error: "Prompt is required" }));
|
|
49
54
|
return null;
|
|
50
55
|
}
|
|
51
56
|
|
|
52
|
-
|
|
57
|
+
const isAuth = callbacks.isAuthenticated();
|
|
58
|
+
if (__DEV__) console.log("[TextToImage] isAuthenticated:", isAuth);
|
|
59
|
+
|
|
60
|
+
if (!isAuth) {
|
|
61
|
+
if (__DEV__) console.log("[TextToImage] Auth required - calling onAuthRequired");
|
|
53
62
|
callbacks.onAuthRequired?.();
|
|
54
63
|
return null;
|
|
55
64
|
}
|
|
56
65
|
|
|
57
|
-
|
|
66
|
+
const affordable = callbacks.canAfford(totalCost);
|
|
67
|
+
if (__DEV__) console.log("[TextToImage] canAfford:", affordable, "totalCost:", totalCost);
|
|
68
|
+
|
|
69
|
+
if (!affordable) {
|
|
70
|
+
if (__DEV__) console.log("[TextToImage] Credits required - calling onCreditsRequired");
|
|
58
71
|
callbacks.onCreditsRequired?.(totalCost);
|
|
59
72
|
return null;
|
|
60
73
|
}
|
|
61
74
|
|
|
75
|
+
if (__DEV__) console.log("[TextToImage] Starting generation...");
|
|
62
76
|
setGenerationState({ isGenerating: true, progress: 0, error: null });
|
|
63
77
|
|
|
64
78
|
const request: TextToImageGenerationRequest = {
|
|
@@ -73,14 +87,19 @@ export function useGeneration(options: UseGenerationOptions): UseGenerationRetur
|
|
|
73
87
|
outputFormat: formState.outputFormat,
|
|
74
88
|
};
|
|
75
89
|
|
|
90
|
+
if (__DEV__) console.log("[TextToImage] Request:", JSON.stringify(request, null, 2));
|
|
91
|
+
|
|
76
92
|
try {
|
|
77
93
|
const result = await callbacks.executeGeneration(request);
|
|
94
|
+
if (__DEV__) console.log("[TextToImage] Result:", JSON.stringify(result, null, 2));
|
|
78
95
|
|
|
79
96
|
if (result.success === true) {
|
|
97
|
+
if (__DEV__) console.log("[TextToImage] Success! Image URLs:", result.imageUrls);
|
|
80
98
|
callbacks.onSuccess?.(result.imageUrls);
|
|
81
99
|
onPromptCleared?.();
|
|
82
100
|
setGenerationState({ isGenerating: false, progress: 100, error: null });
|
|
83
101
|
} else {
|
|
102
|
+
if (__DEV__) console.log("[TextToImage] Generation failed:", result.error);
|
|
84
103
|
setGenerationState({ isGenerating: false, progress: 0, error: result.error });
|
|
85
104
|
callbacks.onError?.(result.error);
|
|
86
105
|
}
|
|
@@ -88,6 +107,7 @@ export function useGeneration(options: UseGenerationOptions): UseGenerationRetur
|
|
|
88
107
|
return result;
|
|
89
108
|
} catch (error) {
|
|
90
109
|
const message = error instanceof Error ? error.message : String(error);
|
|
110
|
+
if (__DEV__) console.error("[TextToImage] Exception:", message);
|
|
91
111
|
setGenerationState({ isGenerating: false, progress: 0, error: message });
|
|
92
112
|
callbacks.onError?.(message);
|
|
93
113
|
return null;
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text-to-Image Callbacks Builder Hook
|
|
3
|
+
* Creates callbacks with integrated credit, auth, and creations systems
|
|
4
|
+
* Main app only provides config, package handles everything
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { useCallback, useMemo, useRef } from "react";
|
|
8
|
+
import { useQueryClient } from "@tanstack/react-query";
|
|
9
|
+
import type {
|
|
10
|
+
TextToImageCallbacks,
|
|
11
|
+
TextToImageGenerationRequest,
|
|
12
|
+
TextToImageGenerationResult,
|
|
13
|
+
NumImages,
|
|
14
|
+
TextToImageInputBuilder,
|
|
15
|
+
} from "../../domain/types";
|
|
16
|
+
import { executeTextToImage } from "../../infrastructure";
|
|
17
|
+
|
|
18
|
+
export interface TextToImageCallbacksBuilderConfig {
|
|
19
|
+
userId: string | null;
|
|
20
|
+
isAuthenticated: boolean;
|
|
21
|
+
isPremium: boolean;
|
|
22
|
+
imageCredits: number;
|
|
23
|
+
creditCostPerImage: number;
|
|
24
|
+
model: string;
|
|
25
|
+
buildInput: TextToImageInputBuilder;
|
|
26
|
+
deductCredit: (type: "image" | "text") => Promise<void>;
|
|
27
|
+
openPaywall: () => void;
|
|
28
|
+
onNavigateToCreations?: () => void;
|
|
29
|
+
saveCreation?: (imageUrl: string, prompt: string) => Promise<void>;
|
|
30
|
+
invalidateCreationsQuery?: () => void;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface UseTextToImageCallbacksBuilderOptions {
|
|
34
|
+
config: TextToImageCallbacksBuilderConfig;
|
|
35
|
+
onSuccess?: (imageUrls: string[]) => void;
|
|
36
|
+
onError?: (error: string) => void;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface UseTextToImageCallbacksBuilderReturn {
|
|
40
|
+
callbacks: TextToImageCallbacks;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
declare const __DEV__: boolean;
|
|
44
|
+
|
|
45
|
+
export function useTextToImageCallbacksBuilder(
|
|
46
|
+
options: UseTextToImageCallbacksBuilderOptions,
|
|
47
|
+
): UseTextToImageCallbacksBuilderReturn {
|
|
48
|
+
const { config, onSuccess, onError } = options;
|
|
49
|
+
const queryClient = useQueryClient();
|
|
50
|
+
const isGeneratingRef = useRef(false);
|
|
51
|
+
|
|
52
|
+
const executeGeneration = useCallback(
|
|
53
|
+
async (
|
|
54
|
+
request: TextToImageGenerationRequest,
|
|
55
|
+
): Promise<TextToImageGenerationResult> => {
|
|
56
|
+
if (!config.userId) {
|
|
57
|
+
return { success: false, error: "User ID not found" };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (isGeneratingRef.current) {
|
|
61
|
+
return { success: false, error: "Generation already in progress" };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
isGeneratingRef.current = true;
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
const result = await executeTextToImage(
|
|
68
|
+
{
|
|
69
|
+
prompt: request.prompt,
|
|
70
|
+
userId: config.userId,
|
|
71
|
+
negativePrompt: request.negativePrompt,
|
|
72
|
+
options: {
|
|
73
|
+
aspectRatio: request.aspectRatio,
|
|
74
|
+
size: request.size,
|
|
75
|
+
numImages: request.numImages,
|
|
76
|
+
guidanceScale: request.guidanceScale,
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
model: request.model || config.model,
|
|
81
|
+
buildInput: config.buildInput,
|
|
82
|
+
},
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
if (!result.success) {
|
|
86
|
+
return { success: false, error: result.error || "Generation failed" };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const imageUrls =
|
|
90
|
+
result.imageUrls || (result.imageUrl ? [result.imageUrl] : []);
|
|
91
|
+
|
|
92
|
+
if (imageUrls.length === 0) {
|
|
93
|
+
return { success: false, error: "No images generated" };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
await config.deductCredit("image");
|
|
97
|
+
|
|
98
|
+
return { success: true, imageUrls };
|
|
99
|
+
} catch (error) {
|
|
100
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
101
|
+
return { success: false, error: message };
|
|
102
|
+
} finally {
|
|
103
|
+
isGeneratingRef.current = false;
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
[config],
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
const calculateCost = useCallback(
|
|
110
|
+
(numImages: NumImages, _model?: string | null): number => {
|
|
111
|
+
return config.creditCostPerImage * numImages;
|
|
112
|
+
},
|
|
113
|
+
[config.creditCostPerImage],
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
const checkCanAfford = useCallback(
|
|
117
|
+
(cost: number): boolean => {
|
|
118
|
+
if (config.isPremium) return true;
|
|
119
|
+
return config.imageCredits >= cost;
|
|
120
|
+
},
|
|
121
|
+
[config.isPremium, config.imageCredits],
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
const checkIsAuthenticated = useCallback(
|
|
125
|
+
(): boolean => config.isAuthenticated,
|
|
126
|
+
[config.isAuthenticated],
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
const handleAuthRequired = useCallback(() => {
|
|
130
|
+
config.openPaywall();
|
|
131
|
+
}, [config]);
|
|
132
|
+
|
|
133
|
+
const handleCreditsRequired = useCallback(
|
|
134
|
+
(_cost: number) => config.openPaywall(),
|
|
135
|
+
[config],
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
const handleSuccess = useCallback(
|
|
139
|
+
async (imageUrls: string[]) => {
|
|
140
|
+
if (!config.userId || imageUrls.length === 0) return;
|
|
141
|
+
|
|
142
|
+
try {
|
|
143
|
+
if (config.saveCreation) {
|
|
144
|
+
for (const imageUrl of imageUrls) {
|
|
145
|
+
await config.saveCreation(imageUrl, "");
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (config.invalidateCreationsQuery) {
|
|
150
|
+
config.invalidateCreationsQuery();
|
|
151
|
+
} else {
|
|
152
|
+
queryClient.invalidateQueries({ queryKey: ["creations"] });
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
onSuccess?.(imageUrls);
|
|
156
|
+
config.onNavigateToCreations?.();
|
|
157
|
+
} catch (error) {
|
|
158
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
159
|
+
console.error("[TextToImage] Failed to save creation:", error);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
[config, queryClient, onSuccess],
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
const handleError = useCallback(
|
|
167
|
+
(error: string) => {
|
|
168
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
169
|
+
console.error("[TextToImage] Generation error:", error);
|
|
170
|
+
}
|
|
171
|
+
onError?.(error);
|
|
172
|
+
},
|
|
173
|
+
[onError],
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
const callbacks = useMemo<TextToImageCallbacks>(
|
|
177
|
+
() => ({
|
|
178
|
+
executeGeneration,
|
|
179
|
+
calculateCost,
|
|
180
|
+
canAfford: checkCanAfford,
|
|
181
|
+
isAuthenticated: checkIsAuthenticated,
|
|
182
|
+
onAuthRequired: handleAuthRequired,
|
|
183
|
+
onCreditsRequired: handleCreditsRequired,
|
|
184
|
+
onSuccess: handleSuccess,
|
|
185
|
+
onError: handleError,
|
|
186
|
+
}),
|
|
187
|
+
[
|
|
188
|
+
executeGeneration,
|
|
189
|
+
calculateCost,
|
|
190
|
+
checkCanAfford,
|
|
191
|
+
checkIsAuthenticated,
|
|
192
|
+
handleAuthRequired,
|
|
193
|
+
handleCreditsRequired,
|
|
194
|
+
handleSuccess,
|
|
195
|
+
handleError,
|
|
196
|
+
],
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
return { callbacks };
|
|
200
|
+
}
|