'use client'; import SendSvg from '@/assets/icons/svg/send.svg'; import SunSvg from '@/assets/icons/svg/sun.svg'; import VideoSvg from '@/assets/icons/svg/video.svg'; import React, { Dispatch, SetStateAction, useCallback, useEffect, useRef, useState } from 'react'; import { EventSubscription, Keyboard, ScrollView, StyleSheet, TextInput, TouchableOpacity, View } from 'react-native'; import { Message } from '@/types/ask'; import { ThemedText } from '../ThemedText'; import { createNewConversation, getConversation } from './utils'; interface Props { setIsHello: Dispatch>, conversationId: string | null, setUserMessages: Dispatch>; setConversationId: (conversationId: string) => void, selectedImages: string[]; setSelectedImages: Dispatch>; } export default function SendMessage(props: Props) { const { setIsHello, conversationId, setUserMessages, setConversationId, selectedImages, setSelectedImages } = props; // 用户询问 const [inputValue, setInputValue] = useState(''); // 添加一个ref来跟踪键盘状态 const keyboardDidShowListener = useRef(null); const keyboardDidHideListener = useRef(null); const isKeyboardVisible = useRef(false); useEffect(() => { // 使用keyboardWillShow而不是keyboardDidShow,这样可以在键盘完全显示前更新UI const showSubscription = Keyboard.addListener('keyboardWillShow', () => { isKeyboardVisible.current = true; if (!conversationId) { // 确保在下一个事件循环中更新状态,避免可能的渲染问题 requestAnimationFrame(() => { setIsHello(false); setUserMessages([ { content: { text: '想打开记忆盲盒吗?描述你的回忆,我来帮你找回照片、生成影片或解锁隐藏彩蛋✨' }, role: 'Assistant', timestamp: new Date().toISOString() } ]) }); } }); const hideSubscription = Keyboard.addListener('keyboardWillHide', () => { isKeyboardVisible.current = false; }); return () => { showSubscription.remove(); hideSubscription.remove(); }; }, [conversationId]); // 发送询问 const handleSubmit = useCallback(async () => { const text = inputValue.trim(); // 用户输入信息之后进行后续操作 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) { const data = await createNewConversation(text); setConversationId(data); const response = await getConversation({ session_id: data, user_text: text, material_ids: [] }); setSelectedImages([]); setUserMessages((prev: Message[]) => { const newMessages = [...(prev || [])]; if (response) { newMessages.push(response); } return newMessages.filter((item: Message) => item?.content?.text !== '正在寻找,请稍等...' ); }); } else { const response = await getConversation({ session_id: conversationId, user_text: text, material_ids: selectedImages }); setSelectedImages([]); setUserMessages((prev: Message[]) => { const newMessages = [...(prev || [])]; if (response) { newMessages.push(response); } return newMessages.filter((item: Message) => item?.content?.text !== '正在寻找,请稍等...' ); }); } // 将输入框清空 setInputValue(''); // 只有在键盘可见时才关闭键盘 if (isKeyboardVisible.current) { Keyboard.dismiss(); } } }, [inputValue, conversationId, selectedImages, createNewConversation, getConversation]); const handleQuitly = (type: string) => { setIsHello(false) setUserMessages(pre => ([ ...pre, { content: { text: type === "search" ? '想找合适的图片?试试这样搜更精准:\n\n• 明确主题:比如"秋日森林""极简风书桌""复古海报设计"\n\n• 加上细节:想找特定风格?试试"水彩风猫咪""赛博朋克城市夜景";需要特定用途?比如"无版权风景图""可商用图标"\n\n• 描述场景:比如"阳光透过树叶的光斑""雨天咖啡馆窗外"\n\n输入这些关键词,说不定就能找到你想要的画面啦~' : '想让你的视频内容更吸睛、更有故事感吗?不妨试试从搜索图片入手吧!\n\n你可以先确定视频的主题——是治愈系的自然风景,还是复古风的城市街景,或是充满活力的生活瞬间?然后根据主题去搜索相关的图片,比如想做"春日限定"主题,就搜"樱花飘落""草地野餐""嫩芽初绽"之类的画面。\n\n这些图片能帮你快速理清视频的画面脉络,甚至能激发新的创意——比如一张老照片里的复古物件,或许能延伸出一段关于时光的故事;一组星空图片,说不定能串联成关于梦想与远方的叙事。把这些图片按你的想法串联起来,配上合适的音乐和文案,一段有温度的视频就诞生啦,试试看吧~' }, role: 'Assistant', timestamp: new Date().toISOString() } ])) }; return ( handleQuitly('search')}> 检索素材 handleQuitly('video')}> 创作视频 { setInputValue(text); }} onSubmitEditing={handleSubmit} // 调起的键盘类型 returnKeyType="send" /> ); } const styles = StyleSheet.create({ button: { paddingHorizontal: 8, paddingVertical: 4, margin: 5, borderRadius: 25, alignItems: 'center', borderWidth: 2, display: 'flex', flexDirection: 'row', gap: 5 }, 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, // 添加一点 }, });