@umituz/react-native-ai-generation-content 1.17.209 → 1.17.211
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/domains/creations/presentation/components/CreationImagePreview.tsx +7 -1
- package/src/features/ai-hug/index.ts +1 -0
- package/src/features/ai-kiss/index.ts +1 -0
- package/src/features/anime-selfie/index.ts +1 -0
- package/src/features/face-swap/index.ts +1 -0
- package/src/features/hd-touch-up/index.ts +1 -0
- package/src/features/meme-generator/index.ts +1 -0
- package/src/features/meme-generator/presentation/components/MemeGeneratorFeature.tsx +160 -0
- package/src/features/meme-generator/presentation/components/index.ts +2 -0
- package/src/features/photo-restoration/index.ts +1 -0
- package/src/features/remove-background/index.ts +1 -0
- package/src/features/remove-object/index.ts +1 -0
- package/src/features/upscaling/index.ts +1 -0
- package/src/presentation/screens/ai-feature/AIFeatureScreen.tsx +8 -0
- package/src/presentation/screens/ai-feature/translations.ts +1 -0
- package/src/presentation/screens/ai-feature/types.ts +3 -2
package/package.json
CHANGED
|
@@ -4,7 +4,13 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import React, { useMemo, useState } from "react";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
View,
|
|
9
|
+
StyleSheet,
|
|
10
|
+
Image,
|
|
11
|
+
type ImageErrorEventData,
|
|
12
|
+
type NativeSyntheticEvent,
|
|
13
|
+
} from "react-native";
|
|
8
14
|
import {
|
|
9
15
|
useAppDesignTokens,
|
|
10
16
|
AtomicIcon,
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MemeGeneratorFeature Component
|
|
3
|
+
*
|
|
4
|
+
* Unified Text-to-Image feature component for Meme Generation.
|
|
5
|
+
* Integrates PromptInput, StyleSelector, and Generation logic using useTextToImageFeature.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React, { useMemo, useCallback } from "react";
|
|
9
|
+
import { View, ScrollView, StyleSheet, Image, KeyboardAvoidingView, Platform } from "react-native";
|
|
10
|
+
import { useAppDesignTokens, AtomicIcon, AtomicCard, AtomicText, AtomicSpinner } from "@umituz/react-native-design-system";
|
|
11
|
+
import { getAuthService } from "../../../../infrastructure/config";
|
|
12
|
+
import { useTextToImageFeature } from "../../../text-to-image/presentation/hooks/useTextToImageFeature";
|
|
13
|
+
import { PromptInput } from "../../../../presentation/components/PromptInput";
|
|
14
|
+
import { StyleSelector } from "../../../../presentation/components/selectors/StyleSelector";
|
|
15
|
+
import { GenerateButton } from "../../../../presentation/components/buttons/GenerateButton";
|
|
16
|
+
import { GridSelector } from "../../../../presentation/components/selectors/GridSelector";
|
|
17
|
+
import { ResultDisplay } from "../../../../presentation/components/result/ResultDisplay";
|
|
18
|
+
|
|
19
|
+
// Constants (Using default provided styles if config doesn't override)
|
|
20
|
+
import { DEFAULT_IMAGE_STYLES } from "../../../text-to-image/domain/constants/processing-modes.constants";
|
|
21
|
+
|
|
22
|
+
export interface MemeGeneratorFeatureProps {
|
|
23
|
+
config: any; // AIFeatureConfig merged with extraConfig
|
|
24
|
+
translations: any;
|
|
25
|
+
onSaveImage: (url: string) => Promise<void>;
|
|
26
|
+
onBeforeProcess?: () => Promise<boolean>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const MemeGeneratorFeature: React.FC<MemeGeneratorFeatureProps> = ({
|
|
30
|
+
config,
|
|
31
|
+
translations,
|
|
32
|
+
onSaveImage,
|
|
33
|
+
onBeforeProcess,
|
|
34
|
+
}) => {
|
|
35
|
+
const tokens = useAppDesignTokens();
|
|
36
|
+
const authService = getAuthService();
|
|
37
|
+
const userId = authService.getUserId() || "anonymous";
|
|
38
|
+
|
|
39
|
+
// Config can override styles, or use defaults
|
|
40
|
+
const stylesList = config.styles || DEFAULT_IMAGE_STYLES || [];
|
|
41
|
+
|
|
42
|
+
// Transform styles for GridSelector
|
|
43
|
+
const styleOptions = useMemo(() => stylesList.map((s: any) => ({
|
|
44
|
+
value: s.id,
|
|
45
|
+
label: s.name,
|
|
46
|
+
emoji: s.emoji || s.icon, // Handle different formats
|
|
47
|
+
description: s.description
|
|
48
|
+
})), [stylesList]);
|
|
49
|
+
|
|
50
|
+
const { state, setPrompt, generate, reset, isReady } = useTextToImageFeature({
|
|
51
|
+
config: {
|
|
52
|
+
model: config.model || "fal-ai/nano-banana-edit",
|
|
53
|
+
buildInput: config.buildInput,
|
|
54
|
+
extractResult: config.extractResult,
|
|
55
|
+
...config
|
|
56
|
+
},
|
|
57
|
+
userId,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const [selectedStyle, setSelectedStyle] = React.useState<string | null>(null);
|
|
61
|
+
|
|
62
|
+
const handleGenerate = useCallback(async () => {
|
|
63
|
+
if (onBeforeProcess) {
|
|
64
|
+
const canProceed = await onBeforeProcess();
|
|
65
|
+
if (!canProceed) return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Append style logic handled via buildInput or here
|
|
69
|
+
// For now simple pass
|
|
70
|
+
await generate();
|
|
71
|
+
}, [generate, onBeforeProcess]);
|
|
72
|
+
|
|
73
|
+
const handleSave = useCallback(() => {
|
|
74
|
+
if (state.imageUrl) {
|
|
75
|
+
onSaveImage(state.imageUrl);
|
|
76
|
+
}
|
|
77
|
+
}, [state.imageUrl, onSaveImage]);
|
|
78
|
+
|
|
79
|
+
const styles = StyleSheet.create({
|
|
80
|
+
container: {
|
|
81
|
+
flex: 1,
|
|
82
|
+
},
|
|
83
|
+
content: {
|
|
84
|
+
padding: tokens.spacing.lg,
|
|
85
|
+
gap: tokens.spacing.xl,
|
|
86
|
+
paddingBottom: 100,
|
|
87
|
+
},
|
|
88
|
+
section: {
|
|
89
|
+
gap: tokens.spacing.md,
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
if (state.imageUrl) {
|
|
94
|
+
return (
|
|
95
|
+
<ResultDisplay
|
|
96
|
+
imageUrl={state.imageUrl}
|
|
97
|
+
onSave={handleSave}
|
|
98
|
+
onTryAgain={reset}
|
|
99
|
+
translations={{
|
|
100
|
+
save: translations.saveButtonText || "Save",
|
|
101
|
+
tryAgain: translations.tryAnotherText || "Try Another",
|
|
102
|
+
success: translations.successText || "Meme Generated!"
|
|
103
|
+
}}
|
|
104
|
+
/>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return (
|
|
109
|
+
<KeyboardAvoidingView
|
|
110
|
+
behavior={Platform.OS === "ios" ? "padding" : "height"}
|
|
111
|
+
style={styles.container}
|
|
112
|
+
>
|
|
113
|
+
<ScrollView contentContainerStyle={styles.content} keyboardShouldPersistTaps="handled">
|
|
114
|
+
|
|
115
|
+
{/* Prompt Input */}
|
|
116
|
+
<View style={styles.section}>
|
|
117
|
+
<AtomicText type="labelLarge" style={{color: tokens.colors.textPrimary}}>
|
|
118
|
+
{translations.promptLabel || "Your Meme Idea"}
|
|
119
|
+
</AtomicText>
|
|
120
|
+
<PromptInput
|
|
121
|
+
value={state.prompt}
|
|
122
|
+
onChangeText={setPrompt}
|
|
123
|
+
placeholder={translations.promptPlaceholder || "Enter your funny idea..."}
|
|
124
|
+
isDisabled={state.isProcessing}
|
|
125
|
+
minHeight={100}
|
|
126
|
+
/>
|
|
127
|
+
</View>
|
|
128
|
+
|
|
129
|
+
{/* Style Selector */}
|
|
130
|
+
{styleOptions.length > 0 && (
|
|
131
|
+
<GridSelector
|
|
132
|
+
title={translations.styleLabel || "Choose a Style"}
|
|
133
|
+
options={styleOptions}
|
|
134
|
+
selectedValue={selectedStyle}
|
|
135
|
+
onSelect={setSelectedStyle}
|
|
136
|
+
disabled={state.isProcessing}
|
|
137
|
+
columns={3}
|
|
138
|
+
/>
|
|
139
|
+
)}
|
|
140
|
+
|
|
141
|
+
{/* Generate Button */}
|
|
142
|
+
<GenerateButton
|
|
143
|
+
onPress={handleGenerate}
|
|
144
|
+
isLoading={state.isProcessing}
|
|
145
|
+
isDisabled={!isReady}
|
|
146
|
+
title={translations.processButtonText || "Generate Meme"}
|
|
147
|
+
/>
|
|
148
|
+
|
|
149
|
+
{/* Error Display */}
|
|
150
|
+
{state.error && (
|
|
151
|
+
<AtomicCard style={{backgroundColor: tokens.colors.errorContainer}}>
|
|
152
|
+
<AtomicText style={{color: tokens.colors.error}}>
|
|
153
|
+
{state.error}
|
|
154
|
+
</AtomicText>
|
|
155
|
+
</AtomicCard>
|
|
156
|
+
)}
|
|
157
|
+
</ScrollView>
|
|
158
|
+
</KeyboardAvoidingView>
|
|
159
|
+
);
|
|
160
|
+
};
|
|
@@ -25,6 +25,7 @@ import { ReplaceBackgroundFeature } from "../../../features/replace-background/p
|
|
|
25
25
|
import { FaceSwapFeature } from "../../../features/face-swap/presentation/components/FaceSwapFeature";
|
|
26
26
|
import { AIHugFeature } from "../../../features/ai-hug/presentation/components/AIHugFeature";
|
|
27
27
|
import { AIKissFeature } from "../../../features/ai-kiss/presentation/components/AIKissFeature";
|
|
28
|
+
import { MemeGeneratorFeature } from "../../../features/meme-generator/presentation/components/MemeGeneratorFeature";
|
|
28
29
|
|
|
29
30
|
import { createFeatureTranslations } from "./translations";
|
|
30
31
|
import type { AIFeatureScreenProps, AIFeatureId } from "./types";
|
|
@@ -45,6 +46,7 @@ const FEATURE_COMPONENTS: Record<AIFeatureId, React.ComponentType<any>> = {
|
|
|
45
46
|
"face-swap": FaceSwapFeature,
|
|
46
47
|
"ai-hug": AIHugFeature,
|
|
47
48
|
"ai-kiss": AIKissFeature,
|
|
49
|
+
"meme-generator": MemeGeneratorFeature,
|
|
48
50
|
};
|
|
49
51
|
|
|
50
52
|
/**
|
|
@@ -115,6 +117,12 @@ export const AIFeatureScreen: React.FC<AIFeatureScreenProps> = ({
|
|
|
115
117
|
onSelectImage,
|
|
116
118
|
onSaveImage: onSaveMedia,
|
|
117
119
|
};
|
|
120
|
+
case "text-input":
|
|
121
|
+
return {
|
|
122
|
+
...baseProps,
|
|
123
|
+
onSaveImage: onSaveMedia,
|
|
124
|
+
// Text input doesn't need image selection
|
|
125
|
+
};
|
|
118
126
|
case "dual":
|
|
119
127
|
return {
|
|
120
128
|
...baseProps,
|
|
@@ -84,6 +84,7 @@ export function createFeatureTranslations(config: AIFeatureConfig, t: TranslateF
|
|
|
84
84
|
? createComparisonTranslations(translationPrefix, t)
|
|
85
85
|
: createSingleImageTranslations(translationPrefix, t);
|
|
86
86
|
case "single-with-prompt":
|
|
87
|
+
case "text-input":
|
|
87
88
|
return createPromptTranslations(translationPrefix, t);
|
|
88
89
|
case "dual":
|
|
89
90
|
case "dual-video":
|
|
@@ -18,12 +18,13 @@ export type AIFeatureId =
|
|
|
18
18
|
| "replace-background"
|
|
19
19
|
| "face-swap"
|
|
20
20
|
| "ai-hug"
|
|
21
|
-
| "ai-kiss"
|
|
21
|
+
| "ai-kiss"
|
|
22
|
+
| "meme-generator";
|
|
22
23
|
|
|
23
24
|
/**
|
|
24
25
|
* Image mode for the feature
|
|
25
26
|
*/
|
|
26
|
-
export type AIFeatureMode = "single" | "single-with-prompt" | "dual" | "dual-video";
|
|
27
|
+
export type AIFeatureMode = "single" | "single-with-prompt" | "dual" | "dual-video" | "text-input";
|
|
27
28
|
|
|
28
29
|
/**
|
|
29
30
|
* Output type of the feature
|