76 lines
2.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 { useTranslation } from 'react-i18next';
import {
FlatList,
SafeAreaView
} from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import MessageItem 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 });
const { t } = useTranslation();
// 使用 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) {
// 延迟滚动以确保渲染完成
const timer = setTimeout(() => {
flatListRef.current?.scrollToEnd({ animated: true });
}, 150);
return () => clearTimeout(timer);
}
}, [userMessages]);
// 优化 FlatList 性能 - 提供 getItemLayout 方法
const getItemLayout = useCallback((data: Message[] | null | undefined, index: number) => {
// 假设每个消息项的高度大约为 100可根据实际情况调整
const averageItemHeight = 100;
return {
length: averageItemHeight,
offset: averageItemHeight * index,
index,
};
}, []);
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}
getItemLayout={getItemLayout}
renderItem={({ item }) => MessageItem({ t, setSelectedImages, selectedImages, insets, item, sessionId, modalVisible, setModalVisible, setModalDetailsVisible, modalDetailsVisible })}
/>
</SafeAreaView>
);
}
// 使用 React.memo 包装组件,避免不必要的重渲染
export default memo(ChatComponent);