@umituz/react-native-ai-generation-content 1.17.7 → 1.17.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/ai-hug/index.ts +4 -0
- package/src/features/ai-hug/presentation/components/AIHugFeature.tsx +209 -0
- package/src/features/ai-hug/presentation/components/index.ts +2 -0
- package/src/features/ai-hug/presentation/index.ts +1 -0
- package/src/features/ai-kiss/index.ts +4 -0
- package/src/features/ai-kiss/presentation/components/AIKissFeature.tsx +202 -0
- package/src/features/ai-kiss/presentation/components/index.ts +2 -0
- package/src/features/ai-kiss/presentation/index.ts +1 -0
- package/src/features/anime-selfie/index.ts +4 -0
- package/src/features/anime-selfie/presentation/components/AnimeSelfieFeature.tsx +199 -0
- package/src/features/anime-selfie/presentation/components/index.ts +2 -0
- package/src/features/anime-selfie/presentation/index.ts +1 -0
- package/src/features/face-swap/index.ts +4 -0
- package/src/features/face-swap/presentation/components/FaceSwapFeature.tsx +202 -0
- package/src/features/face-swap/presentation/components/index.ts +2 -0
- package/src/features/face-swap/presentation/index.ts +1 -0
- package/src/features/photo-restoration/presentation/components/PhotoRestoreFeature.tsx +47 -35
- package/src/features/remove-background/index.ts +4 -0
- package/src/features/remove-background/presentation/components/RemoveBackgroundFeature.tsx +199 -0
- package/src/features/remove-background/presentation/components/index.ts +2 -0
- package/src/features/remove-background/presentation/index.ts +1 -0
- package/src/features/remove-object/index.ts +4 -0
- package/src/features/remove-object/presentation/components/RemoveObjectFeature.tsx +249 -0
- package/src/features/remove-object/presentation/components/index.ts +2 -0
- package/src/features/remove-object/presentation/index.ts +1 -0
- package/src/features/upscaling/presentation/components/UpscaleFeature.tsx +47 -35
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RemoveObjectFeature Component
|
|
3
|
+
* Self-contained remove object feature UI component
|
|
4
|
+
* Uses hook internally, only requires config and translations
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React, { useCallback, useMemo } from "react";
|
|
8
|
+
import { View, ScrollView, StyleSheet, Image, Dimensions, TextInput } from "react-native";
|
|
9
|
+
import {
|
|
10
|
+
useAppDesignTokens,
|
|
11
|
+
AtomicText,
|
|
12
|
+
AtomicButton,
|
|
13
|
+
} from "@umituz/react-native-design-system";
|
|
14
|
+
import { PhotoUploadCard } from "../../../../presentation/components/PhotoUploadCard";
|
|
15
|
+
import { ErrorDisplay } from "../../../../presentation/components/display/ErrorDisplay";
|
|
16
|
+
import { useRemoveObjectFeature } from "../hooks";
|
|
17
|
+
import type {
|
|
18
|
+
RemoveObjectTranslations,
|
|
19
|
+
RemoveObjectFeatureConfig,
|
|
20
|
+
} from "../../domain/types";
|
|
21
|
+
|
|
22
|
+
export interface RemoveObjectFeatureProps {
|
|
23
|
+
config: RemoveObjectFeatureConfig;
|
|
24
|
+
userId: string;
|
|
25
|
+
translations: RemoveObjectTranslations;
|
|
26
|
+
onSelectImage: () => Promise<string | null>;
|
|
27
|
+
onSaveImage: (imageUrl: string) => Promise<void>;
|
|
28
|
+
renderProcessingModal?: (props: {
|
|
29
|
+
visible: boolean;
|
|
30
|
+
progress: number;
|
|
31
|
+
}) => React.ReactNode;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const RemoveObjectFeature: React.FC<RemoveObjectFeatureProps> = ({
|
|
35
|
+
config,
|
|
36
|
+
userId,
|
|
37
|
+
translations,
|
|
38
|
+
onSelectImage,
|
|
39
|
+
onSaveImage,
|
|
40
|
+
renderProcessingModal,
|
|
41
|
+
}) => {
|
|
42
|
+
const tokens = useAppDesignTokens();
|
|
43
|
+
const feature = useRemoveObjectFeature({
|
|
44
|
+
config,
|
|
45
|
+
userId,
|
|
46
|
+
onSelectImage,
|
|
47
|
+
onSaveImage,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const photoTranslations = useMemo(
|
|
51
|
+
() => ({
|
|
52
|
+
tapToUpload: translations.uploadTitle,
|
|
53
|
+
selectPhoto: translations.uploadSubtitle,
|
|
54
|
+
change: translations.uploadChange,
|
|
55
|
+
analyzing: translations.uploadAnalyzing,
|
|
56
|
+
}),
|
|
57
|
+
[translations],
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
const handleProcess = useCallback(() => {
|
|
61
|
+
void feature.process();
|
|
62
|
+
}, [feature]);
|
|
63
|
+
|
|
64
|
+
const handleSave = useCallback(() => {
|
|
65
|
+
void feature.save();
|
|
66
|
+
}, [feature]);
|
|
67
|
+
|
|
68
|
+
const handleSelectImage = useCallback(() => {
|
|
69
|
+
void feature.selectImage();
|
|
70
|
+
}, [feature]);
|
|
71
|
+
|
|
72
|
+
if (feature.processedUrl) {
|
|
73
|
+
const screenWidth = Dimensions.get("window").width;
|
|
74
|
+
const imageSize = screenWidth - 48;
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<ScrollView
|
|
78
|
+
style={[styles.container, { backgroundColor: tokens.colors.backgroundPrimary }]}
|
|
79
|
+
contentContainerStyle={styles.content}
|
|
80
|
+
showsVerticalScrollIndicator={false}
|
|
81
|
+
>
|
|
82
|
+
<AtomicText
|
|
83
|
+
type="headlineMedium"
|
|
84
|
+
style={[styles.successText, { color: tokens.colors.success }]}
|
|
85
|
+
>
|
|
86
|
+
{translations.successText}
|
|
87
|
+
</AtomicText>
|
|
88
|
+
|
|
89
|
+
<View style={styles.resultImageContainer}>
|
|
90
|
+
<Image
|
|
91
|
+
source={{ uri: feature.processedUrl }}
|
|
92
|
+
style={[styles.resultImage, { width: imageSize, height: imageSize }]}
|
|
93
|
+
resizeMode="contain"
|
|
94
|
+
/>
|
|
95
|
+
</View>
|
|
96
|
+
|
|
97
|
+
<View style={styles.resultActions}>
|
|
98
|
+
<AtomicButton
|
|
99
|
+
title={translations.saveButtonText}
|
|
100
|
+
onPress={handleSave}
|
|
101
|
+
variant="primary"
|
|
102
|
+
size="lg"
|
|
103
|
+
/>
|
|
104
|
+
<AtomicButton
|
|
105
|
+
title={translations.tryAnotherText}
|
|
106
|
+
onPress={feature.reset}
|
|
107
|
+
variant="secondary"
|
|
108
|
+
size="lg"
|
|
109
|
+
/>
|
|
110
|
+
</View>
|
|
111
|
+
</ScrollView>
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return (
|
|
116
|
+
<>
|
|
117
|
+
<ScrollView
|
|
118
|
+
style={[styles.container, { backgroundColor: tokens.colors.backgroundPrimary }]}
|
|
119
|
+
contentContainerStyle={styles.content}
|
|
120
|
+
showsVerticalScrollIndicator={false}
|
|
121
|
+
>
|
|
122
|
+
<AtomicText
|
|
123
|
+
type="bodyLarge"
|
|
124
|
+
style={[styles.description, { color: tokens.colors.textSecondary }]}
|
|
125
|
+
>
|
|
126
|
+
{translations.description}
|
|
127
|
+
</AtomicText>
|
|
128
|
+
|
|
129
|
+
<PhotoUploadCard
|
|
130
|
+
imageUri={feature.imageUri}
|
|
131
|
+
onPress={handleSelectImage}
|
|
132
|
+
isValidating={feature.isProcessing}
|
|
133
|
+
disabled={feature.isProcessing}
|
|
134
|
+
translations={photoTranslations}
|
|
135
|
+
config={{
|
|
136
|
+
aspectRatio: 1,
|
|
137
|
+
borderRadius: 24,
|
|
138
|
+
showValidationStatus: false,
|
|
139
|
+
allowChange: true,
|
|
140
|
+
}}
|
|
141
|
+
/>
|
|
142
|
+
|
|
143
|
+
<View style={styles.promptContainer}>
|
|
144
|
+
<AtomicText
|
|
145
|
+
type="labelMedium"
|
|
146
|
+
style={[styles.promptLabel, { color: tokens.colors.textPrimary }]}
|
|
147
|
+
>
|
|
148
|
+
{translations.maskTitle}
|
|
149
|
+
</AtomicText>
|
|
150
|
+
<TextInput
|
|
151
|
+
style={[
|
|
152
|
+
styles.promptInput,
|
|
153
|
+
{
|
|
154
|
+
backgroundColor: tokens.colors.backgroundSecondary,
|
|
155
|
+
color: tokens.colors.textPrimary,
|
|
156
|
+
borderColor: tokens.colors.border,
|
|
157
|
+
},
|
|
158
|
+
]}
|
|
159
|
+
value={feature.prompt}
|
|
160
|
+
onChangeText={feature.setPrompt}
|
|
161
|
+
placeholder={translations.promptPlaceholder}
|
|
162
|
+
placeholderTextColor={tokens.colors.textTertiary}
|
|
163
|
+
multiline
|
|
164
|
+
numberOfLines={3}
|
|
165
|
+
editable={!feature.isProcessing}
|
|
166
|
+
/>
|
|
167
|
+
<AtomicText
|
|
168
|
+
type="bodySmall"
|
|
169
|
+
style={[styles.promptHint, { color: tokens.colors.textTertiary }]}
|
|
170
|
+
>
|
|
171
|
+
{translations.maskSubtitle}
|
|
172
|
+
</AtomicText>
|
|
173
|
+
</View>
|
|
174
|
+
|
|
175
|
+
<ErrorDisplay error={feature.error} />
|
|
176
|
+
|
|
177
|
+
<View style={styles.buttonContainer}>
|
|
178
|
+
<AtomicButton
|
|
179
|
+
title={
|
|
180
|
+
feature.isProcessing
|
|
181
|
+
? translations.processingText
|
|
182
|
+
: translations.processButtonText
|
|
183
|
+
}
|
|
184
|
+
onPress={handleProcess}
|
|
185
|
+
disabled={!feature.imageUri || feature.isProcessing}
|
|
186
|
+
variant="primary"
|
|
187
|
+
size="lg"
|
|
188
|
+
/>
|
|
189
|
+
</View>
|
|
190
|
+
</ScrollView>
|
|
191
|
+
|
|
192
|
+
{renderProcessingModal?.({ visible: feature.isProcessing, progress: feature.progress })}
|
|
193
|
+
</>
|
|
194
|
+
);
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
const styles = StyleSheet.create({
|
|
198
|
+
container: {
|
|
199
|
+
flex: 1,
|
|
200
|
+
},
|
|
201
|
+
content: {
|
|
202
|
+
paddingVertical: 16,
|
|
203
|
+
},
|
|
204
|
+
description: {
|
|
205
|
+
textAlign: "center",
|
|
206
|
+
marginHorizontal: 24,
|
|
207
|
+
marginBottom: 24,
|
|
208
|
+
lineHeight: 24,
|
|
209
|
+
},
|
|
210
|
+
promptContainer: {
|
|
211
|
+
marginHorizontal: 24,
|
|
212
|
+
marginTop: 16,
|
|
213
|
+
marginBottom: 8,
|
|
214
|
+
},
|
|
215
|
+
promptLabel: {
|
|
216
|
+
marginBottom: 8,
|
|
217
|
+
},
|
|
218
|
+
promptInput: {
|
|
219
|
+
borderWidth: 1,
|
|
220
|
+
borderRadius: 12,
|
|
221
|
+
padding: 12,
|
|
222
|
+
minHeight: 80,
|
|
223
|
+
textAlignVertical: "top",
|
|
224
|
+
fontSize: 16,
|
|
225
|
+
},
|
|
226
|
+
promptHint: {
|
|
227
|
+
marginTop: 8,
|
|
228
|
+
},
|
|
229
|
+
successText: {
|
|
230
|
+
textAlign: "center",
|
|
231
|
+
marginBottom: 24,
|
|
232
|
+
},
|
|
233
|
+
resultImageContainer: {
|
|
234
|
+
alignItems: "center",
|
|
235
|
+
marginHorizontal: 24,
|
|
236
|
+
marginBottom: 24,
|
|
237
|
+
},
|
|
238
|
+
resultImage: {
|
|
239
|
+
borderRadius: 16,
|
|
240
|
+
},
|
|
241
|
+
resultActions: {
|
|
242
|
+
marginHorizontal: 24,
|
|
243
|
+
gap: 12,
|
|
244
|
+
},
|
|
245
|
+
buttonContainer: {
|
|
246
|
+
marginHorizontal: 24,
|
|
247
|
+
marginTop: 8,
|
|
248
|
+
},
|
|
249
|
+
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* UpscaleFeature Component
|
|
3
|
-
*
|
|
3
|
+
* Self-contained upscale feature UI component
|
|
4
|
+
* Uses hook internally, only requires config and translations
|
|
4
5
|
*/
|
|
5
6
|
|
|
6
7
|
import React, { useCallback, useMemo } from "react";
|
|
@@ -12,23 +13,24 @@ import {
|
|
|
12
13
|
} from "@umituz/react-native-design-system";
|
|
13
14
|
import { PhotoUploadCard } from "../../../../presentation/components/PhotoUploadCard";
|
|
14
15
|
import { UpscaleResultView } from "./UpscaleResultView";
|
|
16
|
+
import { useUpscaleFeature } from "../hooks";
|
|
15
17
|
import type {
|
|
16
18
|
UpscaleTranslations,
|
|
17
19
|
UpscaleFeatureConfig,
|
|
18
20
|
} from "../../domain/types";
|
|
19
21
|
|
|
20
22
|
export interface UpscaleFeatureProps {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
/** Feature configuration with provider-specific settings */
|
|
24
|
+
config: UpscaleFeatureConfig;
|
|
25
|
+
/** User ID for the generation request */
|
|
26
|
+
userId: string;
|
|
27
|
+
/** Translations for all UI text */
|
|
26
28
|
translations: UpscaleTranslations;
|
|
27
|
-
|
|
28
|
-
onSelectImage: () =>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
/** Image picker callback */
|
|
30
|
+
onSelectImage: () => Promise<string | null>;
|
|
31
|
+
/** Save image callback */
|
|
32
|
+
onSaveImage: (imageUrl: string) => Promise<void>;
|
|
33
|
+
/** Optional custom processing modal renderer */
|
|
32
34
|
renderProcessingModal?: (props: {
|
|
33
35
|
visible: boolean;
|
|
34
36
|
progress: number;
|
|
@@ -36,20 +38,22 @@ export interface UpscaleFeatureProps {
|
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
export const UpscaleFeature: React.FC<UpscaleFeatureProps> = ({
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
isProcessing,
|
|
42
|
-
progress,
|
|
43
|
-
error,
|
|
41
|
+
config,
|
|
42
|
+
userId,
|
|
44
43
|
translations,
|
|
45
44
|
onSelectImage,
|
|
46
|
-
|
|
47
|
-
onSave,
|
|
48
|
-
onReset,
|
|
45
|
+
onSaveImage,
|
|
49
46
|
renderProcessingModal,
|
|
50
47
|
}) => {
|
|
51
48
|
const tokens = useAppDesignTokens();
|
|
52
49
|
|
|
50
|
+
const feature = useUpscaleFeature({
|
|
51
|
+
config,
|
|
52
|
+
userId,
|
|
53
|
+
onSelectImage,
|
|
54
|
+
onSaveImage,
|
|
55
|
+
});
|
|
56
|
+
|
|
53
57
|
const photoTranslations = useMemo(
|
|
54
58
|
() => ({
|
|
55
59
|
tapToUpload: translations.uploadTitle,
|
|
@@ -61,10 +65,18 @@ export const UpscaleFeature: React.FC<UpscaleFeatureProps> = ({
|
|
|
61
65
|
);
|
|
62
66
|
|
|
63
67
|
const handleProcess = useCallback(() => {
|
|
64
|
-
|
|
65
|
-
}, [
|
|
68
|
+
void feature.process();
|
|
69
|
+
}, [feature]);
|
|
70
|
+
|
|
71
|
+
const handleSave = useCallback(() => {
|
|
72
|
+
void feature.save();
|
|
73
|
+
}, [feature]);
|
|
74
|
+
|
|
75
|
+
const handleSelectImage = useCallback(() => {
|
|
76
|
+
void feature.selectImage();
|
|
77
|
+
}, [feature]);
|
|
66
78
|
|
|
67
|
-
if (processedUrl && imageUri) {
|
|
79
|
+
if (feature.processedUrl && feature.imageUri) {
|
|
68
80
|
return (
|
|
69
81
|
<ScrollView
|
|
70
82
|
style={[styles.container, { backgroundColor: tokens.colors.backgroundPrimary }]}
|
|
@@ -72,8 +84,8 @@ export const UpscaleFeature: React.FC<UpscaleFeatureProps> = ({
|
|
|
72
84
|
showsVerticalScrollIndicator={false}
|
|
73
85
|
>
|
|
74
86
|
<UpscaleResultView
|
|
75
|
-
originalUri={imageUri}
|
|
76
|
-
processedUri={processedUrl}
|
|
87
|
+
originalUri={feature.imageUri}
|
|
88
|
+
processedUri={feature.processedUrl}
|
|
77
89
|
translations={{
|
|
78
90
|
successText: translations.successText,
|
|
79
91
|
saveButtonText: translations.saveButtonText,
|
|
@@ -81,8 +93,8 @@ export const UpscaleFeature: React.FC<UpscaleFeatureProps> = ({
|
|
|
81
93
|
beforeLabel: translations.beforeLabel,
|
|
82
94
|
afterLabel: translations.afterLabel,
|
|
83
95
|
}}
|
|
84
|
-
onSave={
|
|
85
|
-
onReset={
|
|
96
|
+
onSave={handleSave}
|
|
97
|
+
onReset={feature.reset}
|
|
86
98
|
/>
|
|
87
99
|
</ScrollView>
|
|
88
100
|
);
|
|
@@ -103,10 +115,10 @@ export const UpscaleFeature: React.FC<UpscaleFeatureProps> = ({
|
|
|
103
115
|
</AtomicText>
|
|
104
116
|
|
|
105
117
|
<PhotoUploadCard
|
|
106
|
-
imageUri={imageUri}
|
|
107
|
-
onPress={
|
|
108
|
-
isValidating={isProcessing}
|
|
109
|
-
disabled={isProcessing}
|
|
118
|
+
imageUri={feature.imageUri}
|
|
119
|
+
onPress={handleSelectImage}
|
|
120
|
+
isValidating={feature.isProcessing}
|
|
121
|
+
disabled={feature.isProcessing}
|
|
110
122
|
translations={photoTranslations}
|
|
111
123
|
config={{
|
|
112
124
|
aspectRatio: 1,
|
|
@@ -116,7 +128,7 @@ export const UpscaleFeature: React.FC<UpscaleFeatureProps> = ({
|
|
|
116
128
|
}}
|
|
117
129
|
/>
|
|
118
130
|
|
|
119
|
-
{error && (
|
|
131
|
+
{feature.error && (
|
|
120
132
|
<View
|
|
121
133
|
style={[
|
|
122
134
|
styles.errorContainer,
|
|
@@ -124,7 +136,7 @@ export const UpscaleFeature: React.FC<UpscaleFeatureProps> = ({
|
|
|
124
136
|
]}
|
|
125
137
|
>
|
|
126
138
|
<AtomicText type="bodyMedium" style={{ color: tokens.colors.error }}>
|
|
127
|
-
{error}
|
|
139
|
+
{feature.error}
|
|
128
140
|
</AtomicText>
|
|
129
141
|
</View>
|
|
130
142
|
)}
|
|
@@ -132,19 +144,19 @@ export const UpscaleFeature: React.FC<UpscaleFeatureProps> = ({
|
|
|
132
144
|
<View style={styles.buttonContainer}>
|
|
133
145
|
<AtomicButton
|
|
134
146
|
title={
|
|
135
|
-
isProcessing
|
|
147
|
+
feature.isProcessing
|
|
136
148
|
? translations.processingText
|
|
137
149
|
: translations.processButtonText
|
|
138
150
|
}
|
|
139
151
|
onPress={handleProcess}
|
|
140
|
-
disabled={!imageUri || isProcessing}
|
|
152
|
+
disabled={!feature.imageUri || feature.isProcessing}
|
|
141
153
|
variant="primary"
|
|
142
154
|
size="lg"
|
|
143
155
|
/>
|
|
144
156
|
</View>
|
|
145
157
|
</ScrollView>
|
|
146
158
|
|
|
147
|
-
{renderProcessingModal?.({ visible: isProcessing, progress })}
|
|
159
|
+
{renderProcessingModal?.({ visible: feature.isProcessing, progress: feature.progress })}
|
|
148
160
|
</>
|
|
149
161
|
);
|
|
150
162
|
};
|