164 lines
5.3 KiB
TypeScript
164 lines
5.3 KiB
TypeScript
'use client';
|
||
import SendSvg from '@/assets/icons/svg/send.svg';
|
||
import React, { Dispatch, SetStateAction, useCallback, useEffect, useState } from 'react';
|
||
import {
|
||
Keyboard,
|
||
StyleSheet,
|
||
TextInput,
|
||
TouchableOpacity,
|
||
View
|
||
} from 'react-native';
|
||
|
||
import { fetchApi } from '@/lib/server-api-util';
|
||
import { Message } from '@/types/ask';
|
||
|
||
interface Props {
|
||
setIsHello: Dispatch<SetStateAction<boolean>>,
|
||
conversationId: string | null,
|
||
setUserMessages: Dispatch<SetStateAction<Message[]>>;
|
||
setConversationId: (conversationId: string) => void,
|
||
selectedImages: string[];
|
||
setSelectedImages: Dispatch<SetStateAction<string[]>>;
|
||
}
|
||
export default function SendMessage(props: Props) {
|
||
const { setIsHello, conversationId, setUserMessages, setConversationId, selectedImages, setSelectedImages } = props;
|
||
|
||
// 用户询问
|
||
const [inputValue, setInputValue] = useState('');
|
||
|
||
// 创建新对话并获取消息
|
||
const createNewConversation = useCallback(async (user_text: string) => {
|
||
const data = await fetchApi<string>("/chat/new", {
|
||
method: "POST",
|
||
});
|
||
setConversationId(data);
|
||
await getConversation({ session_id: data, user_text, material_ids: [] });
|
||
}, []);
|
||
|
||
// 获取对话信息
|
||
const getConversation = useCallback(async ({ session_id, user_text, material_ids }: { session_id: string, user_text: string, material_ids: string[] }) => {
|
||
// 获取对话信息必须要有对话id
|
||
if (!session_id) return;
|
||
|
||
const response = await fetchApi<Message>(`/chat`, {
|
||
method: "POST",
|
||
body: JSON.stringify({
|
||
session_id,
|
||
user_text,
|
||
material_ids
|
||
})
|
||
});
|
||
setSelectedImages([]);
|
||
setUserMessages((prev: Message[]) => [...prev, response]?.filter((item: Message) => item.content.text !== '正在寻找,请稍等...'));
|
||
}, []);
|
||
|
||
// 发送询问
|
||
const handleSubmit = () => {
|
||
const text = inputValue;
|
||
// 用户输入信息之后进行后续操作
|
||
if (text) {
|
||
// 将用户输入信息添加到消息列表中
|
||
setUserMessages(pre => ([...pre, {
|
||
content: {
|
||
text: text
|
||
},
|
||
role: 'User',
|
||
timestamp: new Date().toISOString()
|
||
},
|
||
{
|
||
content: {
|
||
text: "正在寻找,请稍等..."
|
||
},
|
||
role: 'Assistant',
|
||
timestamp: new Date().toISOString()
|
||
}
|
||
]));
|
||
// 如果没有对话ID,创建新对话并获取消息,否则直接获取消息
|
||
if (!conversationId) {
|
||
createNewConversation(text);
|
||
} else {
|
||
getConversation({
|
||
session_id: conversationId,
|
||
user_text: text,
|
||
material_ids: selectedImages
|
||
});
|
||
}
|
||
// 将输入框清空
|
||
setInputValue('');
|
||
}
|
||
}
|
||
useEffect(() => {
|
||
const keyboardWillShowListener = Keyboard.addListener(
|
||
'keyboardWillShow',
|
||
() => {
|
||
console.log('Keyboard will show');
|
||
setIsHello(false);
|
||
setUserMessages([{
|
||
content: {
|
||
text: "快来寻找你的记忆吧。。。"
|
||
},
|
||
role: 'Assistant',
|
||
timestamp: new Date().toISOString()
|
||
}])
|
||
}
|
||
);
|
||
|
||
return () => {
|
||
keyboardWillShowListener.remove();
|
||
};
|
||
}, []);
|
||
|
||
return (
|
||
<View style={styles.container}>
|
||
<View className="relative w-full">
|
||
<TextInput
|
||
style={styles.input}
|
||
placeholder="Ask MeMo Anything..."
|
||
placeholderTextColor="#999"
|
||
value={inputValue}
|
||
onChangeText={(text: string) => {
|
||
setInputValue(text);
|
||
}}
|
||
onSubmitEditing={handleSubmit}
|
||
// 调起的键盘类型
|
||
returnKeyType="send"
|
||
/>
|
||
<TouchableOpacity
|
||
style={styles.voiceButton}
|
||
onPress={handleSubmit}
|
||
className={`absolute right-0 top-1/2 -translate-y-1/2 `} // 使用绝对定位将按钮放在输入框内右侧
|
||
>
|
||
<View style={{ transform: [{ rotate: '330deg' }] }}>
|
||
<SendSvg color={'white'} width={24} height={24} />
|
||
</View>
|
||
</TouchableOpacity>
|
||
</View>
|
||
</View>
|
||
);
|
||
}
|
||
|
||
const styles = StyleSheet.create({
|
||
container: {
|
||
justifyContent: 'center',
|
||
backgroundColor: '#transparent',
|
||
},
|
||
input: {
|
||
borderColor: '#FF9500',
|
||
borderWidth: 1,
|
||
borderRadius: 25,
|
||
paddingHorizontal: 20,
|
||
paddingVertical: 12,
|
||
fontSize: 16,
|
||
width: '100%', // 确保输入框宽度撑满
|
||
paddingRight: 50
|
||
},
|
||
voiceButton: {
|
||
width: 40,
|
||
height: 40,
|
||
borderRadius: 20,
|
||
backgroundColor: '#FF9500',
|
||
justifyContent: 'center',
|
||
alignItems: 'center',
|
||
marginRight: 8, // 添加一点
|
||
},
|
||
}); |