@umituz/react-native-ai-generation-content 1.17.125 → 1.17.127
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.17.
|
|
3
|
+
"version": "1.17.127",
|
|
4
4
|
"description": "Provider-agnostic AI generation orchestration for React Native",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "src/index.ts",
|
|
@@ -44,7 +44,8 @@
|
|
|
44
44
|
"@umituz/react-native-offline": "latest",
|
|
45
45
|
"@umituz/react-native-tanstack": "latest",
|
|
46
46
|
"@umituz/react-native-timezone": "latest",
|
|
47
|
-
"@umituz/react-native-uuid": "latest"
|
|
47
|
+
"@umituz/react-native-uuid": "latest",
|
|
48
|
+
"@umituz/react-native-video-editor": "latest"
|
|
48
49
|
},
|
|
49
50
|
"peerDependencies": {
|
|
50
51
|
"@react-navigation/native": ">=6.0.0",
|
|
@@ -77,6 +78,7 @@
|
|
|
77
78
|
"@umituz/react-native-tanstack": "latest",
|
|
78
79
|
"@umituz/react-native-timezone": "latest",
|
|
79
80
|
"@umituz/react-native-uuid": "latest",
|
|
81
|
+
"@umituz/react-native-video-editor": "latest",
|
|
80
82
|
"eslint": "^9.0.0",
|
|
81
83
|
"expo-application": "^7.0.8",
|
|
82
84
|
"expo-clipboard": "^8.0.8",
|
|
@@ -3,11 +3,9 @@
|
|
|
3
3
|
* Video player with thumbnail and play controls for creation detail view
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import React
|
|
7
|
-
import { View, StyleSheet,
|
|
8
|
-
import {
|
|
9
|
-
import { Image } from "expo-image";
|
|
10
|
-
import { useVideoPlayer, VideoView, type VideoPlayer } from "expo-video";
|
|
6
|
+
import React from "react";
|
|
7
|
+
import { View, StyleSheet, useWindowDimensions } from "react-native";
|
|
8
|
+
import { VideoPlayer } from "@umituz/react-native-video-editor";
|
|
11
9
|
|
|
12
10
|
interface DetailVideoProps {
|
|
13
11
|
readonly videoUrl: string;
|
|
@@ -15,60 +13,24 @@ interface DetailVideoProps {
|
|
|
15
13
|
}
|
|
16
14
|
|
|
17
15
|
const HORIZONTAL_PADDING = 16;
|
|
18
|
-
const ASPECT_RATIO = 16 / 9;
|
|
19
16
|
|
|
20
17
|
export const DetailVideo: React.FC<DetailVideoProps> = ({
|
|
21
18
|
videoUrl,
|
|
22
19
|
thumbnailUrl,
|
|
23
20
|
}) => {
|
|
24
|
-
const tokens = useAppDesignTokens();
|
|
25
21
|
const { width } = useWindowDimensions();
|
|
26
22
|
const videoWidth = width - (HORIZONTAL_PADDING * 2);
|
|
27
|
-
const videoHeight = videoWidth / ASPECT_RATIO;
|
|
28
|
-
const [isPlaying, setIsPlaying] = useState(false);
|
|
29
|
-
|
|
30
|
-
const player = useVideoPlayer(videoUrl, (p: VideoPlayer) => {
|
|
31
|
-
p.loop = true;
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
const handlePlay = useCallback(() => {
|
|
35
|
-
setIsPlaying(true);
|
|
36
|
-
player.play();
|
|
37
|
-
}, [player]);
|
|
38
23
|
|
|
39
24
|
return (
|
|
40
25
|
<View style={styles.container}>
|
|
41
|
-
<
|
|
42
|
-
{
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
) : (
|
|
50
|
-
<TouchableOpacity
|
|
51
|
-
style={styles.thumbnailContainer}
|
|
52
|
-
onPress={handlePlay}
|
|
53
|
-
activeOpacity={0.8}
|
|
54
|
-
>
|
|
55
|
-
{thumbnailUrl ? (
|
|
56
|
-
<Image
|
|
57
|
-
source={{ uri: thumbnailUrl }}
|
|
58
|
-
style={styles.thumbnail}
|
|
59
|
-
contentFit="cover"
|
|
60
|
-
/>
|
|
61
|
-
) : (
|
|
62
|
-
<View style={[styles.placeholder, { backgroundColor: tokens.colors.surfaceSecondary }]} />
|
|
63
|
-
)}
|
|
64
|
-
<View style={styles.playButtonContainer}>
|
|
65
|
-
<View style={[styles.playButton, { backgroundColor: tokens.colors.primary }]}>
|
|
66
|
-
<AtomicIcon name="play" customSize={32} color="onPrimary" />
|
|
67
|
-
</View>
|
|
68
|
-
</View>
|
|
69
|
-
</TouchableOpacity>
|
|
70
|
-
)}
|
|
71
|
-
</View>
|
|
26
|
+
<VideoPlayer
|
|
27
|
+
source={videoUrl}
|
|
28
|
+
thumbnailUrl={thumbnailUrl}
|
|
29
|
+
loop
|
|
30
|
+
nativeControls
|
|
31
|
+
contentFit="cover"
|
|
32
|
+
style={{ width: videoWidth }}
|
|
33
|
+
/>
|
|
72
34
|
</View>
|
|
73
35
|
);
|
|
74
36
|
};
|
|
@@ -78,39 +40,4 @@ const styles = StyleSheet.create({
|
|
|
78
40
|
paddingHorizontal: HORIZONTAL_PADDING,
|
|
79
41
|
marginVertical: 16,
|
|
80
42
|
},
|
|
81
|
-
frame: {
|
|
82
|
-
borderRadius: 16,
|
|
83
|
-
overflow: "hidden",
|
|
84
|
-
},
|
|
85
|
-
video: {
|
|
86
|
-
width: "100%",
|
|
87
|
-
height: "100%",
|
|
88
|
-
},
|
|
89
|
-
thumbnailContainer: {
|
|
90
|
-
width: "100%",
|
|
91
|
-
height: "100%",
|
|
92
|
-
justifyContent: "center",
|
|
93
|
-
alignItems: "center",
|
|
94
|
-
},
|
|
95
|
-
thumbnail: {
|
|
96
|
-
width: "100%",
|
|
97
|
-
height: "100%",
|
|
98
|
-
},
|
|
99
|
-
placeholder: {
|
|
100
|
-
width: "100%",
|
|
101
|
-
height: "100%",
|
|
102
|
-
},
|
|
103
|
-
playButtonContainer: {
|
|
104
|
-
...StyleSheet.absoluteFillObject,
|
|
105
|
-
justifyContent: "center",
|
|
106
|
-
alignItems: "center",
|
|
107
|
-
},
|
|
108
|
-
playButton: {
|
|
109
|
-
width: 64,
|
|
110
|
-
height: 64,
|
|
111
|
-
borderRadius: 32,
|
|
112
|
-
justifyContent: "center",
|
|
113
|
-
alignItems: "center",
|
|
114
|
-
paddingLeft: 4,
|
|
115
|
-
},
|
|
116
43
|
});
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { providerRegistry } from "../../../../infrastructure/services";
|
|
2
2
|
|
|
3
|
-
declare const __DEV__: boolean;
|
|
4
3
|
|
|
5
4
|
export interface MemeGenerationParams {
|
|
6
5
|
prompt: string;
|
|
@@ -21,7 +20,7 @@ export class MemeGenerationService {
|
|
|
21
20
|
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}"`;
|
|
22
21
|
|
|
23
22
|
// Use provided modelId or try to find a default text-to-text model
|
|
24
|
-
const model = modelId || "fal-ai/llama-3-
|
|
23
|
+
const model = modelId || "fal-ai/llama-3-8b-instruct";
|
|
25
24
|
|
|
26
25
|
const result = await provider.run<{ text?: string, data?: { text: string } }>(
|
|
27
26
|
model,
|
|
@@ -42,6 +41,8 @@ export class MemeGenerationService {
|
|
|
42
41
|
|
|
43
42
|
/**
|
|
44
43
|
* Generate a meme image
|
|
44
|
+
* @param prompt The final prompt to use (should already be enhanced if desired)
|
|
45
|
+
* @param modelId Optional Fal model ID
|
|
45
46
|
*/
|
|
46
47
|
async generateMeme(prompt: string, modelId?: string): Promise<string> {
|
|
47
48
|
try {
|
|
@@ -50,13 +51,10 @@ export class MemeGenerationService {
|
|
|
50
51
|
throw new Error("AI provider not available");
|
|
51
52
|
}
|
|
52
53
|
|
|
53
|
-
const
|
|
54
|
-
const finalPrompt = `High-quality, funny meme: ${enhancedPrompt}. Cinematic, vibrant, clean subject, NO TEXT in image.`;
|
|
54
|
+
const finalPrompt = `High-quality, funny meme: ${prompt}. Cinematic, vibrant, clean subject, NO TEXT in image.`;
|
|
55
55
|
|
|
56
56
|
const model = modelId || "fal-ai/flux/schnell";
|
|
57
57
|
|
|
58
|
-
// For Fal, we usually use subscribe or run
|
|
59
|
-
// provider.run should be enough for quick models like flux/schnell
|
|
60
58
|
const result = await provider.run<{ images: { url: string }[] }>(
|
|
61
59
|
model,
|
|
62
60
|
{
|