2025-07-16 19:51:30 +08:00

61 lines
2.3 KiB
TypeScript

import { Message, Video } from '@/types/ask';
import { MaterialItem } from '@/types/personal-info';
import React, { Dispatch, memo, SetStateAction, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import {
FlatList,
SafeAreaView
} from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import renderMessage from "./aiChat";
interface ChatProps {
userMessages: Message[];
sessionId: string;
setSelectedImages: Dispatch<SetStateAction<string[]>>;
selectedImages: string[];
}
function ChatComponent({ userMessages, sessionId, setSelectedImages, selectedImages }: ChatProps) {
const flatListRef = useRef<FlatList>(null);
const insets = useSafeAreaInsets();
const [modalVisible, setModalVisible] = React.useState({ visible: false, data: {} as Video | MaterialItem });
// 使用 useCallback 缓存 keyExtractor 函数
const keyExtractor = useCallback((item: Message) => `${item.role}-${item.timestamp}`, []);
// 使用 useMemo 缓存样式对象
const contentContainerStyle = useMemo(() => ({ padding: 16 }), []);
// 详情弹窗
const [modalDetailsVisible, setModalDetailsVisible] = useState<boolean>(false);
// 自动滚动到底部
useEffect(() => {
if (userMessages.length > 0) {
setTimeout(() => {
flatListRef.current?.scrollToEnd({ animated: true });
}, 100);
}
}, [userMessages]);
return (
<SafeAreaView className='flex-1'>
<FlatList
ref={flatListRef}
data={userMessages}
keyExtractor={keyExtractor}
contentContainerStyle={contentContainerStyle}
keyboardDismissMode="interactive"
removeClippedSubviews={true}
maxToRenderPerBatch={10}
updateCellsBatchingPeriod={50}
initialNumToRender={10}
windowSize={11}
renderItem={({ item }) => renderMessage({ setSelectedImages, selectedImages, insets, item, sessionId, modalVisible, setModalVisible, setModalDetailsVisible, modalDetailsVisible })}
/>
</SafeAreaView>
);
}
// 使用 React.memo 包装组件,避免不必要的重渲染
export default memo(ChatComponent);