@umituz/react-native-ai-generation-content 1.17.122 → 1.17.124
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/domain/interfaces/ai-provider.interface.ts +2 -0
- package/src/domains/creations/domain/entities/Creation.ts +1 -1
- package/src/features/meme-generator/index.ts +1 -0
- package/src/features/meme-generator/infrastructure/services/MemeGenerationService.ts +82 -0
- package/src/index.ts +2 -0
- package/src/presentation/components/headers/CreditBadge.tsx +58 -0
- package/src/presentation/components/headers/index.ts +1 -0
package/package.json
CHANGED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { providerRegistry } from "../../../../infrastructure/services/provider.registry";
|
|
2
|
+
|
|
3
|
+
export interface MemeGenerationParams {
|
|
4
|
+
prompt: string;
|
|
5
|
+
styleId?: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export class MemeGenerationService {
|
|
9
|
+
/**
|
|
10
|
+
* Enhance a simple user prompt into a rich image generation prompt
|
|
11
|
+
*/
|
|
12
|
+
async enhancePrompt(prompt: string, modelId?: string): Promise<string> {
|
|
13
|
+
try {
|
|
14
|
+
const provider = providerRegistry.getActiveProvider();
|
|
15
|
+
if (!provider) {
|
|
16
|
+
throw new Error("AI provider not available");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const systemPrompt = `You are an AI art director. Take the user's simple meme idea and transform it into a visually rich, detailed, and funny image generation prompt. Your response should be only the new prompt, no explanations. Idea: "${prompt}"`;
|
|
20
|
+
|
|
21
|
+
// Use provided modelId or try to find a default text-to-text model
|
|
22
|
+
const model = modelId || "fal-ai/llama-3-8cl-instruct";
|
|
23
|
+
|
|
24
|
+
const result = await provider.run<{ text?: string, data?: { text: string } }>(
|
|
25
|
+
model,
|
|
26
|
+
{ prompt: systemPrompt }
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
// Handle different provider response formats
|
|
30
|
+
const text = result.text || result.data?.text || prompt;
|
|
31
|
+
return text;
|
|
32
|
+
} catch (error) {
|
|
33
|
+
if (__DEV__) {
|
|
34
|
+
// eslint-disable-next-line no-console
|
|
35
|
+
console.error("[MemeGenerationService] Enhance prompt error:", error);
|
|
36
|
+
}
|
|
37
|
+
return prompt;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Generate a meme image
|
|
43
|
+
*/
|
|
44
|
+
async generateMeme(prompt: string, modelId?: string): Promise<string> {
|
|
45
|
+
try {
|
|
46
|
+
const provider = providerRegistry.getActiveProvider();
|
|
47
|
+
if (!provider) {
|
|
48
|
+
throw new Error("AI provider not available");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const enhancedPrompt = await this.enhancePrompt(prompt, modelId);
|
|
52
|
+
const finalPrompt = `High-quality, funny meme: ${enhancedPrompt}. Cinematic, vibrant, clean subject, NO TEXT in image.`;
|
|
53
|
+
|
|
54
|
+
const model = modelId || "fal-ai/flux/schnell";
|
|
55
|
+
|
|
56
|
+
// For Fal, we usually use subscribe or run
|
|
57
|
+
// provider.run should be enough for quick models like flux/schnell
|
|
58
|
+
const result = await provider.run<{ images: { url: string }[] }>(
|
|
59
|
+
model,
|
|
60
|
+
{
|
|
61
|
+
prompt: finalPrompt,
|
|
62
|
+
image_size: "square",
|
|
63
|
+
num_inference_steps: 4
|
|
64
|
+
}
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
if (result.images && result.images.length > 0) {
|
|
68
|
+
return result.images[0].url;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
throw new Error("No image generated");
|
|
72
|
+
} catch (error) {
|
|
73
|
+
if (__DEV__) {
|
|
74
|
+
// eslint-disable-next-line no-console
|
|
75
|
+
console.error("[MemeGenerationService] Generate meme error:", error);
|
|
76
|
+
}
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export const memeGenerationService = new MemeGenerationService();
|
package/src/index.ts
CHANGED
|
@@ -321,6 +321,7 @@ export {
|
|
|
321
321
|
// Headers
|
|
322
322
|
FeatureHeader,
|
|
323
323
|
AIGenScreenHeader,
|
|
324
|
+
CreditBadge,
|
|
324
325
|
|
|
325
326
|
// Photo Upload
|
|
326
327
|
PhotoUploadCard,
|
|
@@ -380,6 +381,7 @@ export type {
|
|
|
380
381
|
FeatureHeaderProps,
|
|
381
382
|
AIGenScreenHeaderProps,
|
|
382
383
|
NavigationButtonType,
|
|
384
|
+
CreditBadgeProps,
|
|
383
385
|
|
|
384
386
|
// Photo Upload
|
|
385
387
|
PhotoUploadCardProps,
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { View, StyleSheet } from "react-native";
|
|
3
|
+
import {
|
|
4
|
+
AtomicText,
|
|
5
|
+
AtomicIcon,
|
|
6
|
+
useAppDesignTokens,
|
|
7
|
+
} from "@umituz/react-native-design-system";
|
|
8
|
+
|
|
9
|
+
export interface CreditBadgeProps {
|
|
10
|
+
readonly credits: number;
|
|
11
|
+
readonly iconName?: string;
|
|
12
|
+
readonly compact?: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const CreditBadge: React.FC<CreditBadgeProps> = ({
|
|
16
|
+
credits,
|
|
17
|
+
iconName = "flash",
|
|
18
|
+
compact = false,
|
|
19
|
+
}) => {
|
|
20
|
+
const tokens = useAppDesignTokens();
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<View
|
|
24
|
+
style={[
|
|
25
|
+
styles.container,
|
|
26
|
+
compact && styles.compact,
|
|
27
|
+
{ backgroundColor: tokens.colors.surface },
|
|
28
|
+
]}
|
|
29
|
+
>
|
|
30
|
+
<AtomicIcon name={iconName} size="sm" color="warning" />
|
|
31
|
+
<AtomicText
|
|
32
|
+
type={compact ? "labelSmall" : "labelMedium"}
|
|
33
|
+
style={[styles.text, { color: tokens.colors.textPrimary }]}
|
|
34
|
+
>
|
|
35
|
+
{credits}
|
|
36
|
+
</AtomicText>
|
|
37
|
+
</View>
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const styles = StyleSheet.create({
|
|
42
|
+
container: {
|
|
43
|
+
flexDirection: "row",
|
|
44
|
+
alignItems: "center",
|
|
45
|
+
paddingHorizontal: 10,
|
|
46
|
+
paddingVertical: 6,
|
|
47
|
+
borderRadius: 16,
|
|
48
|
+
gap: 4,
|
|
49
|
+
},
|
|
50
|
+
compact: {
|
|
51
|
+
paddingHorizontal: 8,
|
|
52
|
+
paddingVertical: 4,
|
|
53
|
+
borderRadius: 12,
|
|
54
|
+
},
|
|
55
|
+
text: {
|
|
56
|
+
fontWeight: "600",
|
|
57
|
+
},
|
|
58
|
+
});
|