feat: ask优化
This commit is contained in:
parent
1941790a05
commit
69735168f7
@ -18,7 +18,7 @@ import ContextMenu from "../gusture/contextMenu";
|
||||
import { ThemedText } from "../ThemedText";
|
||||
import SelectModel from "./selectModel";
|
||||
import SingleContentModel from "./singleContentModel";
|
||||
import TypewriterText from "./typewriterText";
|
||||
import Loading from './threeCircle';
|
||||
import { mergeArrays, saveMediaToGallery } from "./utils";
|
||||
|
||||
interface RenderMessageProps {
|
||||
@ -43,18 +43,20 @@ const MessageItem = ({ setCancel, cancel = true, t, insets, item, sessionId, set
|
||||
<View className={`flex-row items-start gap-2 w-full ${isUser ? 'justify-end' : 'justify-start'}`}>
|
||||
{!isUser && <ChatSvg width={36} height={36} />}
|
||||
<View className="max-w-[90%] mb-[1rem] flex flex-col gap-2 ">
|
||||
<View style={{ width: "100%", flexDirection: "row", alignItems: "flex-end" }}>
|
||||
<View
|
||||
className={`${isUser ? '!bg-bgPrimary ml-10 rounded-full' : '!bg-aiBubble rounded-2xl'} border-0 ${!isUser && (item.content.video_material_infos && item.content.video_material_infos.length > 0 || item.content.image_material_infos && item.content.image_material_infos.length > 0) ? '!rounded-t-3xl !rounded-b-2xl' : '!rounded-3xl'}`}
|
||||
style={[
|
||||
styles.messageBubble,
|
||||
isUser ? styles.userBubble : styles.aiBubble
|
||||
isUser ? styles.userBubble : styles.aiBubble,
|
||||
{ marginRight: item.content.text == "正在寻找,请稍等..." ? 0 : isUser ? 0 : 10 }
|
||||
]}
|
||||
className={`${isUser ? '!bg-bgPrimary ml-10 rounded-full' : '!bg-aiBubble mr-10 rounded-2xl'} border-0 ${!isUser && (item.content.video_material_infos && item.content.video_material_infos.length > 0 || item.content.image_material_infos && item.content.image_material_infos.length > 0) ? '!rounded-t-3xl !rounded-b-2xl' : '!rounded-3xl'}`}
|
||||
>
|
||||
<View className={`${isUser ? 'bg-bgPrimary' : 'bg-aiBubble'}`}>
|
||||
<Text style={isUser ? styles.userText : styles.aiText}>
|
||||
{!isUser
|
||||
?
|
||||
sessionId ? item.content.text : <TypewriterText text={item.content.text} speed={100} loop={item.content.text == "正在寻找,请稍等..."} />
|
||||
sessionId ? item.content.text : item.content.text == "正在寻找,请稍等..." ? <Loading /> : item.content.text
|
||||
: item.content.text
|
||||
}
|
||||
</Text>
|
||||
@ -139,6 +141,14 @@ const MessageItem = ({ setCancel, cancel = true, t, insets, item, sessionId, set
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
{
|
||||
item.content.text == "正在寻找,请稍等..."
|
||||
&&
|
||||
<Text style={{ color: "d9d9d9" }}>
|
||||
{t("ask:ask.think")}
|
||||
</Text>
|
||||
}
|
||||
</View>
|
||||
{/* {item.askAgain && item.askAgain.length > 0 && (
|
||||
<View className={`mr-10`}>
|
||||
{item.askAgain.map((suggestion, index, array) => (
|
||||
@ -247,10 +257,12 @@ const styles = StyleSheet.create({
|
||||
userText: {
|
||||
color: '#4C320C',
|
||||
fontSize: 16,
|
||||
lineHeight: 24,
|
||||
},
|
||||
aiText: {
|
||||
color: '#000',
|
||||
fontSize: 16,
|
||||
lineHeight: 24,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@ -170,11 +170,11 @@ export default function SendMessage(props: Props) {
|
||||
returnKeyType="send"
|
||||
/>
|
||||
<TouchableOpacity
|
||||
style={styles.voiceButton}
|
||||
style={[styles.voiceButton, { bottom: -10 }]}
|
||||
onPress={handleSubmit}
|
||||
className={`absolute right-0 bottom-0`} // 使用绝对定位将按钮放在输入框内右侧
|
||||
className="absolute right-2"
|
||||
>
|
||||
<View style={{ transform: [{ rotate: '330deg' }] }}>
|
||||
<View>
|
||||
<SendSvg color={'white'} width={24} height={24} />
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
@ -204,18 +204,18 @@ const styles = StyleSheet.create({
|
||||
borderWidth: 1,
|
||||
borderRadius: 25,
|
||||
paddingHorizontal: 20,
|
||||
paddingVertical: 12,
|
||||
paddingVertical: 13,
|
||||
fontSize: 16,
|
||||
width: '100%', // 确保输入框宽度撑满
|
||||
paddingRight: 50
|
||||
},
|
||||
voiceButton: {
|
||||
width: 40,
|
||||
height: 40,
|
||||
padding: 8,
|
||||
borderRadius: 20,
|
||||
backgroundColor: '#FF9500',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
marginRight: 8, // 添加一点
|
||||
position: 'absolute',
|
||||
transform: [{ translateY: -12 }],
|
||||
},
|
||||
});
|
||||
114
components/ask/threeCircle.tsx
Normal file
114
components/ask/threeCircle.tsx
Normal file
@ -0,0 +1,114 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { Animated, StyleSheet, View } from 'react-native';
|
||||
|
||||
const Loading = () => {
|
||||
// 创建三个动画值,控制每个点的大小变化
|
||||
const anim1 = useRef(new Animated.Value(0)).current;
|
||||
const anim2 = useRef(new Animated.Value(0)).current;
|
||||
const anim3 = useRef(new Animated.Value(0)).current;
|
||||
|
||||
// 定义动画序列
|
||||
const startAnimation = () => {
|
||||
// 重置动画值
|
||||
anim1.setValue(0);
|
||||
anim2.setValue(0);
|
||||
anim3.setValue(0);
|
||||
|
||||
// 创建动画序列
|
||||
Animated.loop(
|
||||
Animated.stagger(200, [
|
||||
// 第一个点动画
|
||||
Animated.sequence([
|
||||
Animated.timing(anim1, {
|
||||
toValue: 1,
|
||||
duration: 400,
|
||||
useNativeDriver: true,
|
||||
}),
|
||||
Animated.timing(anim1, {
|
||||
toValue: 0,
|
||||
duration: 400,
|
||||
useNativeDriver: true,
|
||||
}),
|
||||
]),
|
||||
// 第二个点动画
|
||||
Animated.sequence([
|
||||
Animated.timing(anim2, {
|
||||
toValue: 1,
|
||||
duration: 400,
|
||||
useNativeDriver: true,
|
||||
}),
|
||||
Animated.timing(anim2, {
|
||||
toValue: 0,
|
||||
duration: 400,
|
||||
useNativeDriver: true,
|
||||
}),
|
||||
]),
|
||||
// 第三个点动画
|
||||
Animated.sequence([
|
||||
Animated.timing(anim3, {
|
||||
toValue: 1,
|
||||
duration: 400,
|
||||
useNativeDriver: true,
|
||||
}),
|
||||
Animated.timing(anim3, {
|
||||
toValue: 0,
|
||||
duration: 400,
|
||||
useNativeDriver: true,
|
||||
}),
|
||||
]),
|
||||
])
|
||||
).start();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
startAnimation();
|
||||
return () => {
|
||||
// 清理动画
|
||||
anim1.stopAnimation();
|
||||
anim2.stopAnimation();
|
||||
anim3.stopAnimation();
|
||||
};
|
||||
}, []);
|
||||
|
||||
// 颜色插值
|
||||
const color1 = anim1.interpolate({
|
||||
inputRange: [0, 0.5, 1],
|
||||
outputRange: ['#999999', '#4C320C', '#999999'],
|
||||
});
|
||||
|
||||
const color2 = anim2.interpolate({
|
||||
inputRange: [0, 0.5, 1],
|
||||
outputRange: ['#999999', '#4C320C', '#999999'],
|
||||
});
|
||||
|
||||
const color3 = anim3.interpolate({
|
||||
inputRange: [0, 0.5, 1],
|
||||
outputRange: ['#999999', '#4C320C', '#999999'],
|
||||
});
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Animated.View style={[styles.dot, { backgroundColor: color1 }]} />
|
||||
<Animated.View style={[styles.dot, { backgroundColor: color2 }]} />
|
||||
<Animated.View style={[styles.dot, { backgroundColor: color3 }]} />
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
padding: 8,
|
||||
},
|
||||
dot: {
|
||||
width: 8,
|
||||
height: 8,
|
||||
borderRadius: 4,
|
||||
marginHorizontal: 4,
|
||||
backgroundColor: '#999999',
|
||||
},
|
||||
});
|
||||
|
||||
export default Loading;
|
||||
@ -30,6 +30,7 @@
|
||||
"introduction2": "Looking for the perfect image? Try these search tips for better results:\n\n• Be specific: Try 'autumn forest', 'minimalist desk', or 'vintage poster design'\n\n• Add details: For specific styles, try 'watercolor cat' or 'cyberpunk city nightscape'; for specific uses, try 'royalty-free landscape' or 'commercial use icons'\n\n• Describe the scene: Try 'sunlight through leaves' or 'rainy day coffee shop window'\n\nEnter these keywords, and you might just find the perfect shot!",
|
||||
"introduction3": "Want to make your videos more engaging and story-driven? Start with an image search!\n\nFirst, decide on your video's theme—whether it's healing natural landscapes, retro cityscapes, or vibrant life moments. Then search for related images. For example, if your theme is 'Spring Limited,' search for 'cherry blossoms falling,' 'picnic in the grass,' or 'first buds of spring.'\n\nThese images can help you visualize your video's flow and even spark new ideas—like how an old photo of a vintage object might inspire a story about time, or how a series of starry sky images could connect into a narrative about dreams and distant places. String these images together with the right music and captions, and you've got yourself a heartwarming video. Give it a try!",
|
||||
"search": "Search Assets",
|
||||
"video": "Create Video"
|
||||
"video": "Create Video",
|
||||
"think": "Thinking..."
|
||||
}
|
||||
}
|
||||
@ -30,6 +30,7 @@
|
||||
"introduction2": "想找合适的图片?试试这样搜更精准:\n\n• 明确主题:比如'秋日森林'、'极简风书桌'、'复古海报设计'\n\n• 加上细节:想找特定风格?试试'水彩风猫咪'、'赛博朋克城市夜景';需要特定用途?比如'无版权风景图'、'可商用图标'\n\n• 描述场景:比如'阳光透过树叶的光斑'、'雨天咖啡馆窗外'\n\n输入这些关键词,说不定就能找到你想要的画面啦~",
|
||||
"introduction3": "想让你的视频内容更吸睛、更有故事感吗?不妨试试从搜索图片入手吧!\n\n你可以先确定视频的主题——是治愈系的自然风景,还是复古风的城市街景,或是充满活力的生活瞬间?然后根据主题去搜索相关的图片,比如想做'春日限定'主题,就搜'樱花飘落''草地野餐''嫩芽初绽'之类的画面。\n\n这些图片能帮你快速理清视频的画面脉络,甚至能激发新的创意——比如一张老照片里的复古物件,或许能延伸出一段关于时光的故事;一组星空图片,说不定能串联成关于梦想与远方的叙事。把这些图片按你的想法串联起来,配上合适的音乐和文案,一段有温度的视频就诞生啦,试试看吧~",
|
||||
"search": "检索素材",
|
||||
"video": "创作视频"
|
||||
"video": "创作视频",
|
||||
"think": "思考中..."
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user