76 lines
2.9 KiB
TypeScript
76 lines
2.9 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 { 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); |