@umituz/react-native-ai-generation-content 1.20.23 → 1.20.24
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.20.
|
|
3
|
+
"version": "1.20.24",
|
|
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",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import React
|
|
2
|
+
import React from "react";
|
|
3
3
|
import { View, ScrollView, Platform, TouchableOpacity, Image } from "react-native";
|
|
4
4
|
import {
|
|
5
5
|
useAppDesignTokens,
|
|
@@ -14,55 +14,9 @@ import { PartnerStepScreen } from "../../../features/partner-upload/presentation
|
|
|
14
14
|
import { AIGenerationConfig } from "../AIGenerationConfig";
|
|
15
15
|
import { GenerationProgressContent } from "../GenerationProgressContent";
|
|
16
16
|
import { AIGenerationResult } from "../display/AIGenerationResult";
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
export interface AIGenerateWizardFlowProps {
|
|
21
|
-
readonly featureType: string;
|
|
22
|
-
readonly translations: {
|
|
23
|
-
headerTitle: string;
|
|
24
|
-
uploadSubtitle: string;
|
|
25
|
-
uploadSubtitle2: string;
|
|
26
|
-
continue: string;
|
|
27
|
-
tapToUpload: string;
|
|
28
|
-
selectPhoto: string;
|
|
29
|
-
change: string;
|
|
30
|
-
analyzing: string;
|
|
31
|
-
error: string;
|
|
32
|
-
uploadFailed: string;
|
|
33
|
-
aiDisclosure: string;
|
|
34
|
-
heroTitle: string;
|
|
35
|
-
heroSubtitle: string;
|
|
36
|
-
presetsTitle: string;
|
|
37
|
-
showAdvancedLabel: string;
|
|
38
|
-
hideAdvancedLabel: string;
|
|
39
|
-
promptTitle: string;
|
|
40
|
-
promptPlaceholder: string;
|
|
41
|
-
styleTitle: string;
|
|
42
|
-
durationTitle: string;
|
|
43
|
-
generateButton: string;
|
|
44
|
-
generatingButton: string;
|
|
45
|
-
processingTitle: string;
|
|
46
|
-
processingMessage: string;
|
|
47
|
-
processingHint: string;
|
|
48
|
-
successTitle: string;
|
|
49
|
-
saveButton: string;
|
|
50
|
-
tryAgainButton: string;
|
|
51
|
-
fileTooLarge: string;
|
|
52
|
-
maxFileSize: string;
|
|
53
|
-
};
|
|
54
|
-
readonly styleOptions: any[];
|
|
55
|
-
readonly presets: any[];
|
|
56
|
-
readonly durationOptions: number[];
|
|
57
|
-
readonly onGenerate: (data: {
|
|
58
|
-
prompt: string;
|
|
59
|
-
style: string;
|
|
60
|
-
duration: number;
|
|
61
|
-
images: { uri: string }[];
|
|
62
|
-
}) => Promise<string | null>;
|
|
63
|
-
readonly onBack?: () => void;
|
|
64
|
-
readonly t: (key: string) => string;
|
|
65
|
-
}
|
|
17
|
+
import { AIGenerateStep } from "../../hooks/generation/useAIGenerateState";
|
|
18
|
+
import { useAIGenerateWizardFlow } from "./useAIGenerateWizardFlow";
|
|
19
|
+
import { AIGenerateWizardFlowProps } from "./AIGenerateWizardFlow.types";
|
|
66
20
|
|
|
67
21
|
export const AIGenerateWizardFlow: React.FC<AIGenerateWizardFlowProps> = ({
|
|
68
22
|
featureType,
|
|
@@ -89,85 +43,12 @@ export const AIGenerateWizardFlow: React.FC<AIGenerateWizardFlowProps> = ({
|
|
|
89
43
|
showAdvanced,
|
|
90
44
|
toggleAdvanced,
|
|
91
45
|
isGenerating,
|
|
92
|
-
setIsGenerating,
|
|
93
46
|
progress,
|
|
94
|
-
setProgress,
|
|
95
47
|
result,
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
if (!featureType || !hasAIFeature(featureType)) return 0;
|
|
101
|
-
const config = getAIFeatureConfig(featureType as any);
|
|
102
|
-
if (config.mode === "dual" || config.mode === "dual-video") return 2;
|
|
103
|
-
if (config.mode === "single" || config.mode === "single-with-prompt")
|
|
104
|
-
return 1;
|
|
105
|
-
return 0;
|
|
106
|
-
}, [featureType]);
|
|
107
|
-
|
|
108
|
-
useEffect(() => {
|
|
109
|
-
if (currentStep === AIGenerateStep.INFO) {
|
|
110
|
-
if (imageCountRequired > 0) {
|
|
111
|
-
setCurrentStep(AIGenerateStep.UPLOAD_1);
|
|
112
|
-
} else {
|
|
113
|
-
setCurrentStep(AIGenerateStep.CONFIG);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}, [featureType, imageCountRequired, setCurrentStep, currentStep]);
|
|
117
|
-
|
|
118
|
-
const handleBack = useCallback(() => {
|
|
119
|
-
if (currentStep === AIGenerateStep.UPLOAD_1) {
|
|
120
|
-
onBackProp?.();
|
|
121
|
-
} else if (currentStep === AIGenerateStep.UPLOAD_2) {
|
|
122
|
-
setCurrentStep(AIGenerateStep.UPLOAD_1);
|
|
123
|
-
} else if (currentStep === AIGenerateStep.CONFIG) {
|
|
124
|
-
if (imageCountRequired > 1) {
|
|
125
|
-
setCurrentStep(AIGenerateStep.UPLOAD_2);
|
|
126
|
-
} else if (imageCountRequired > 0) {
|
|
127
|
-
setCurrentStep(AIGenerateStep.UPLOAD_1);
|
|
128
|
-
} else {
|
|
129
|
-
onBackProp?.();
|
|
130
|
-
}
|
|
131
|
-
} else if (currentStep === AIGenerateStep.RESULT) {
|
|
132
|
-
setCurrentStep(AIGenerateStep.CONFIG);
|
|
133
|
-
}
|
|
134
|
-
}, [currentStep, setCurrentStep, imageCountRequired, onBackProp]);
|
|
135
|
-
|
|
136
|
-
const handleNext = useCallback(() => {
|
|
137
|
-
if (currentStep === AIGenerateStep.UPLOAD_1) {
|
|
138
|
-
if (imageCountRequired > 1) {
|
|
139
|
-
setCurrentStep(AIGenerateStep.UPLOAD_2);
|
|
140
|
-
} else {
|
|
141
|
-
setCurrentStep(AIGenerateStep.CONFIG);
|
|
142
|
-
}
|
|
143
|
-
} else if (currentStep === AIGenerateStep.UPLOAD_2) {
|
|
144
|
-
setCurrentStep(AIGenerateStep.CONFIG);
|
|
145
|
-
}
|
|
146
|
-
}, [currentStep, setCurrentStep, imageCountRequired]);
|
|
147
|
-
|
|
148
|
-
const handleGenerate = useCallback(async () => {
|
|
149
|
-
setIsGenerating(true);
|
|
150
|
-
setProgress(10);
|
|
151
|
-
setCurrentStep(AIGenerateStep.GENERATING);
|
|
152
|
-
|
|
153
|
-
try {
|
|
154
|
-
const output = await onGenerate({
|
|
155
|
-
prompt,
|
|
156
|
-
style: selectedStyle,
|
|
157
|
-
duration: selectedDuration,
|
|
158
|
-
images,
|
|
159
|
-
});
|
|
160
|
-
setResult(output);
|
|
161
|
-
setCurrentStep(AIGenerateStep.RESULT);
|
|
162
|
-
} catch (error) {
|
|
163
|
-
// Error handling should be added here
|
|
164
|
-
console.error("Generation failed", error);
|
|
165
|
-
setCurrentStep(AIGenerateStep.CONFIG);
|
|
166
|
-
} finally {
|
|
167
|
-
setIsGenerating(false);
|
|
168
|
-
setProgress(0);
|
|
169
|
-
}
|
|
170
|
-
}, [onGenerate, prompt, selectedStyle, selectedDuration, images, setCurrentStep, setIsGenerating, setProgress, setResult]);
|
|
48
|
+
handleBack,
|
|
49
|
+
handleNext,
|
|
50
|
+
handleGenerate,
|
|
51
|
+
} = useAIGenerateWizardFlow({ featureType, onGenerate, onBack: onBackProp });
|
|
171
52
|
|
|
172
53
|
switch (currentStep) {
|
|
173
54
|
case AIGenerateStep.UPLOAD_1:
|
|
@@ -178,10 +59,7 @@ export const AIGenerateWizardFlow: React.FC<AIGenerateWizardFlowProps> = ({
|
|
|
178
59
|
t={t}
|
|
179
60
|
onBack={handleBack}
|
|
180
61
|
onContinue={(img: any) => {
|
|
181
|
-
setStepImage(isStep2 ? 1 : 0, {
|
|
182
|
-
uri: img.uri,
|
|
183
|
-
previewUrl: img.previewUrl || img.uri,
|
|
184
|
-
});
|
|
62
|
+
setStepImage(isStep2 ? 1 : 0, { uri: img.uri, previewUrl: img.previewUrl || img.uri });
|
|
185
63
|
handleNext();
|
|
186
64
|
}}
|
|
187
65
|
translations={{
|
|
@@ -199,25 +77,14 @@ export const AIGenerateWizardFlow: React.FC<AIGenerateWizardFlowProps> = ({
|
|
|
199
77
|
aiDisclosure: translations.aiDisclosure,
|
|
200
78
|
}}
|
|
201
79
|
initialName=""
|
|
202
|
-
config={{
|
|
203
|
-
showFaceDetection: featureType === "face-swap",
|
|
204
|
-
showNameInput: false,
|
|
205
|
-
showPhotoTips: true,
|
|
206
|
-
}}
|
|
80
|
+
config={{ showFaceDetection: featureType === "face-swap", showNameInput: false, showPhotoTips: true }}
|
|
207
81
|
/>
|
|
208
82
|
);
|
|
209
83
|
}
|
|
210
84
|
|
|
211
85
|
case AIGenerateStep.GENERATING:
|
|
212
86
|
return (
|
|
213
|
-
<ScreenLayout
|
|
214
|
-
header={
|
|
215
|
-
<AIGenScreenHeader
|
|
216
|
-
title={translations.headerTitle}
|
|
217
|
-
onNavigationPress={handleBack}
|
|
218
|
-
/>
|
|
219
|
-
}
|
|
220
|
-
>
|
|
87
|
+
<ScreenLayout header={<AIGenScreenHeader title={translations.headerTitle} onNavigationPress={handleBack} />}>
|
|
221
88
|
<View style={{ flex: 1, padding: tokens.spacing.xl }}>
|
|
222
89
|
<GenerationProgressContent
|
|
223
90
|
progress={progress}
|
|
@@ -231,41 +98,24 @@ export const AIGenerateWizardFlow: React.FC<AIGenerateWizardFlowProps> = ({
|
|
|
231
98
|
|
|
232
99
|
case AIGenerateStep.RESULT:
|
|
233
100
|
return (
|
|
234
|
-
<ScreenLayout
|
|
235
|
-
header={
|
|
236
|
-
<AIGenScreenHeader
|
|
237
|
-
title={translations.headerTitle}
|
|
238
|
-
onNavigationPress={handleBack}
|
|
239
|
-
/>
|
|
240
|
-
}
|
|
241
|
-
>
|
|
101
|
+
<ScreenLayout header={<AIGenScreenHeader title={translations.headerTitle} onNavigationPress={handleBack} />}>
|
|
242
102
|
<AIGenerationResult
|
|
243
103
|
successText={translations.successTitle}
|
|
244
|
-
primaryAction={{
|
|
245
|
-
label: translations.saveButton,
|
|
246
|
-
onPress: () => {},
|
|
247
|
-
icon: "download",
|
|
248
|
-
}}
|
|
104
|
+
primaryAction={{ label: translations.saveButton, onPress: () => {}, icon: "download" }}
|
|
249
105
|
secondaryAction={{
|
|
250
106
|
label: translations.tryAgainButton,
|
|
251
107
|
onPress: () => setCurrentStep(AIGenerateStep.CONFIG),
|
|
252
108
|
icon: "refresh",
|
|
253
109
|
}}
|
|
254
110
|
>
|
|
255
|
-
<Image
|
|
256
|
-
source={{ uri: result || "" }}
|
|
257
|
-
style={{ width: "100%", aspectRatio: 2 / 3, borderRadius: 16 }}
|
|
258
|
-
resizeMode="cover"
|
|
259
|
-
/>
|
|
111
|
+
<Image source={{ uri: result || "" }} style={{ width: "100%", aspectRatio: 2 / 3, borderRadius: 16 }} resizeMode="cover" />
|
|
260
112
|
</AIGenerationResult>
|
|
261
113
|
</ScreenLayout>
|
|
262
114
|
);
|
|
263
115
|
|
|
264
116
|
default:
|
|
265
117
|
return (
|
|
266
|
-
<AtomicKeyboardAvoidingView
|
|
267
|
-
offset={Platform.OS === "ios" ? 94 : 0}
|
|
268
|
-
>
|
|
118
|
+
<AtomicKeyboardAvoidingView offset={Platform.OS === "ios" ? 94 : 0}>
|
|
269
119
|
<ScrollView
|
|
270
120
|
style={{ backgroundColor: tokens.colors.backgroundPrimary }}
|
|
271
121
|
contentContainerStyle={{ paddingBottom: 100 }}
|
|
@@ -328,17 +178,7 @@ export const AIGenerateWizardFlow: React.FC<AIGenerateWizardFlowProps> = ({
|
|
|
328
178
|
onGenerate={handleGenerate}
|
|
329
179
|
images={images}
|
|
330
180
|
hideGenerateButton={true}
|
|
331
|
-
translations={
|
|
332
|
-
presetsTitle: translations.presetsTitle,
|
|
333
|
-
showAdvancedLabel: translations.showAdvancedLabel,
|
|
334
|
-
hideAdvancedLabel: translations.hideAdvancedLabel,
|
|
335
|
-
promptTitle: translations.promptTitle,
|
|
336
|
-
promptPlaceholder: translations.promptPlaceholder,
|
|
337
|
-
styleTitle: translations.styleTitle,
|
|
338
|
-
durationTitle: translations.durationTitle,
|
|
339
|
-
generateButton: translations.generateButton,
|
|
340
|
-
generatingButton: translations.generatingButton,
|
|
341
|
-
}}
|
|
181
|
+
translations={translations}
|
|
342
182
|
/>
|
|
343
183
|
</ScrollView>
|
|
344
184
|
</AtomicKeyboardAvoidingView>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
|
|
2
|
+
export interface AIGenerateWizardTranslations {
|
|
3
|
+
readonly headerTitle: string;
|
|
4
|
+
readonly uploadSubtitle: string;
|
|
5
|
+
readonly uploadSubtitle2: string;
|
|
6
|
+
readonly continue: string;
|
|
7
|
+
readonly tapToUpload: string;
|
|
8
|
+
readonly selectPhoto: string;
|
|
9
|
+
readonly change: string;
|
|
10
|
+
readonly analyzing: string;
|
|
11
|
+
readonly error: string;
|
|
12
|
+
readonly uploadFailed: string;
|
|
13
|
+
readonly aiDisclosure: string;
|
|
14
|
+
readonly heroTitle: string;
|
|
15
|
+
readonly heroSubtitle: string;
|
|
16
|
+
readonly presetsTitle: string;
|
|
17
|
+
readonly showAdvancedLabel: string;
|
|
18
|
+
readonly hideAdvancedLabel: string;
|
|
19
|
+
readonly promptTitle: string;
|
|
20
|
+
readonly promptPlaceholder: string;
|
|
21
|
+
readonly styleTitle: string;
|
|
22
|
+
readonly durationTitle: string;
|
|
23
|
+
readonly generateButton: string;
|
|
24
|
+
readonly generatingButton: string;
|
|
25
|
+
readonly processingTitle: string;
|
|
26
|
+
readonly processingMessage: string;
|
|
27
|
+
readonly processingHint: string;
|
|
28
|
+
readonly successTitle: string;
|
|
29
|
+
readonly saveButton: string;
|
|
30
|
+
readonly tryAgainButton: string;
|
|
31
|
+
readonly fileTooLarge: string;
|
|
32
|
+
readonly maxFileSize: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface AIGenerateWizardFlowProps {
|
|
36
|
+
readonly featureType: string;
|
|
37
|
+
readonly translations: AIGenerateWizardTranslations;
|
|
38
|
+
readonly styleOptions: any[];
|
|
39
|
+
readonly presets: any[];
|
|
40
|
+
readonly durationOptions: number[];
|
|
41
|
+
readonly onGenerate: (data: {
|
|
42
|
+
prompt: string;
|
|
43
|
+
style: string;
|
|
44
|
+
duration: number;
|
|
45
|
+
images: { uri: string }[];
|
|
46
|
+
}) => Promise<string | null>;
|
|
47
|
+
readonly onBack?: () => void;
|
|
48
|
+
readonly t: (key: string) => string;
|
|
49
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
|
|
2
|
+
import { useMemo, useCallback, useEffect } from "react";
|
|
3
|
+
import { useAIGenerateState, AIGenerateStep } from "../../hooks/generation/useAIGenerateState";
|
|
4
|
+
import { getAIFeatureConfig, hasAIFeature } from "../../screens/ai-feature/registry";
|
|
5
|
+
|
|
6
|
+
interface UseAIGenerateWizardFlowProps {
|
|
7
|
+
featureType: string;
|
|
8
|
+
onGenerate: (data: any) => Promise<string | null>;
|
|
9
|
+
onBack?: () => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function useAIGenerateWizardFlow({
|
|
13
|
+
featureType,
|
|
14
|
+
onGenerate,
|
|
15
|
+
onBack: onBackProp,
|
|
16
|
+
}: UseAIGenerateWizardFlowProps) {
|
|
17
|
+
const state = useAIGenerateState();
|
|
18
|
+
const {
|
|
19
|
+
currentStep, setCurrentStep, isGenerating, setIsGenerating,
|
|
20
|
+
setProgress, setResult, images, prompt, selectedStyle,
|
|
21
|
+
selectedDuration, setStepImage
|
|
22
|
+
} = state;
|
|
23
|
+
|
|
24
|
+
const imageCountRequired = useMemo(() => {
|
|
25
|
+
if (!featureType || !hasAIFeature(featureType)) return 0;
|
|
26
|
+
const config = getAIFeatureConfig(featureType as any);
|
|
27
|
+
if (config.mode === "dual" || config.mode === "dual-video") return 2;
|
|
28
|
+
if (config.mode === "single" || config.mode === "single-with-prompt")
|
|
29
|
+
return 1;
|
|
30
|
+
return 0;
|
|
31
|
+
}, [featureType]);
|
|
32
|
+
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (currentStep === AIGenerateStep.INFO) {
|
|
35
|
+
if (imageCountRequired > 0) {
|
|
36
|
+
setCurrentStep(AIGenerateStep.UPLOAD_1);
|
|
37
|
+
} else {
|
|
38
|
+
setCurrentStep(AIGenerateStep.CONFIG);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}, [featureType, imageCountRequired, setCurrentStep, currentStep]);
|
|
42
|
+
|
|
43
|
+
const handleBack = useCallback(() => {
|
|
44
|
+
if (currentStep === AIGenerateStep.UPLOAD_1) {
|
|
45
|
+
onBackProp?.();
|
|
46
|
+
} else if (currentStep === AIGenerateStep.UPLOAD_2) {
|
|
47
|
+
setCurrentStep(AIGenerateStep.UPLOAD_1);
|
|
48
|
+
} else if (currentStep === AIGenerateStep.CONFIG) {
|
|
49
|
+
if (imageCountRequired > 1) {
|
|
50
|
+
setCurrentStep(AIGenerateStep.UPLOAD_2);
|
|
51
|
+
} else if (imageCountRequired > 0) {
|
|
52
|
+
setCurrentStep(AIGenerateStep.UPLOAD_1);
|
|
53
|
+
} else {
|
|
54
|
+
onBackProp?.();
|
|
55
|
+
}
|
|
56
|
+
} else if (currentStep === AIGenerateStep.RESULT) {
|
|
57
|
+
setCurrentStep(AIGenerateStep.CONFIG);
|
|
58
|
+
}
|
|
59
|
+
}, [currentStep, setCurrentStep, imageCountRequired, onBackProp]);
|
|
60
|
+
|
|
61
|
+
const handleNext = useCallback(() => {
|
|
62
|
+
if (currentStep === AIGenerateStep.UPLOAD_1) {
|
|
63
|
+
if (imageCountRequired > 1) {
|
|
64
|
+
setCurrentStep(AIGenerateStep.UPLOAD_2);
|
|
65
|
+
} else {
|
|
66
|
+
setCurrentStep(AIGenerateStep.CONFIG);
|
|
67
|
+
}
|
|
68
|
+
} else if (currentStep === AIGenerateStep.UPLOAD_2) {
|
|
69
|
+
setCurrentStep(AIGenerateStep.CONFIG);
|
|
70
|
+
}
|
|
71
|
+
}, [currentStep, setCurrentStep, imageCountRequired]);
|
|
72
|
+
|
|
73
|
+
const handleGenerate = useCallback(async () => {
|
|
74
|
+
setIsGenerating(true);
|
|
75
|
+
setProgress(10);
|
|
76
|
+
setCurrentStep(AIGenerateStep.GENERATING);
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
const output = await onGenerate({
|
|
80
|
+
prompt,
|
|
81
|
+
style: selectedStyle,
|
|
82
|
+
duration: selectedDuration,
|
|
83
|
+
images,
|
|
84
|
+
});
|
|
85
|
+
setResult(output);
|
|
86
|
+
setCurrentStep(AIGenerateStep.RESULT);
|
|
87
|
+
} catch (error) {
|
|
88
|
+
console.error("Generation failed", error);
|
|
89
|
+
setCurrentStep(AIGenerateStep.CONFIG);
|
|
90
|
+
} finally {
|
|
91
|
+
setIsGenerating(false);
|
|
92
|
+
setProgress(0);
|
|
93
|
+
}
|
|
94
|
+
}, [onGenerate, prompt, selectedStyle, selectedDuration, images, setCurrentStep, setIsGenerating, setProgress, setResult]);
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
...state,
|
|
98
|
+
imageCountRequired,
|
|
99
|
+
handleBack,
|
|
100
|
+
handleNext,
|
|
101
|
+
handleGenerate,
|
|
102
|
+
};
|
|
103
|
+
}
|