161 lines
5.0 KiB
TypeScript

import MoreSvg from "@/assets/icons/svg/more.svg";
import { ContentPart, getMessageText, isMessageContainMedia } from "@/types/ask";
import { TFunction } from 'i18next';
import React from 'react';
import { Platform, StyleSheet, TouchableOpacity, View } from 'react-native';
import Markdown from "react-native-markdown-display";
import Loading from '../../ask/threeCircle';
import { ThemedText } from "../../ThemedText";
import MediaGrid from './MediaGrid';
interface MessageContentProps {
item: any;
isUser: boolean;
setModalVisible: React.Dispatch<React.SetStateAction<{ visible: boolean, data: ContentPart }>>;
setCancel: React.Dispatch<React.SetStateAction<boolean>>;
cancel: boolean;
t: TFunction;
setSelectedImages: React.Dispatch<React.SetStateAction<string[]>>;
setModalDetailsVisible: React.Dispatch<React.SetStateAction<{ visible: boolean, content: any }>>;
}
const chineseMarkdownStyle = StyleSheet.create({
// General body text
body: {
fontSize: 14,
lineHeight: 24.5, // 1.75 * fontSize for better readability
color: '#333',
},
// Headings
heading1: {
fontSize: 24,
fontWeight: 'bold',
marginTop: 10,
marginBottom: 10,
lineHeight: 36,
borderBottomWidth: 1,
borderColor: '#eee',
paddingBottom: 5,
},
heading2: {
fontSize: 22,
fontWeight: 'bold',
marginTop: 8,
marginBottom: 8,
lineHeight: 33,
},
heading3: {
fontSize: 20,
fontWeight: 'bold',
marginTop: 6,
marginBottom: 6,
lineHeight: 30,
},
// Paragraph: Add vertical margin for better separation
paragraph: {
marginTop: 10,
marginBottom: 10,
},
// Lists
bullet_list_icon: {
fontSize: 16,
lineHeight: 28,
marginRight: 8,
},
list_item: {
flexDirection: 'row',
alignItems: 'flex-start',
marginBottom: 8,
},
// Code blocks
code_block: {
fontFamily: Platform.OS === 'ios' ? 'Courier New' : 'monospace',
backgroundColor: '#f5f5f5',
padding: 15,
borderRadius: 4,
marginVertical: 10,
fontSize: 14,
lineHeight: 21,
},
// Blockquote
blockquote: {
backgroundColor: '#f0f0f0',
borderLeftColor: '#ccc',
borderLeftWidth: 4,
paddingHorizontal: 15,
paddingVertical: 10,
marginVertical: 10,
},
// Link
link: {
color: '#007aff', // Standard blue link color
textDecorationLine: 'underline',
},
// Horizontal Rule
hr: {
backgroundColor: '#e0e0e0',
height: 1,
marginVertical: 15,
},
});
const MessageContent = ({
item,
isUser,
setModalVisible,
setCancel,
cancel,
t,
setSelectedImages,
setModalDetailsVisible
}: MessageContentProps) => {
return (
<View className={`${isUser ? 'bg-bgPrimary' : 'bg-aiBubble'} rounded-2xl`}>
{getMessageText(item) == "keepSearchIng" && !isUser ? (
<Loading />
) : (
<View className="px-2">
<Markdown style={chineseMarkdownStyle}>
{getMessageText(item)}
</Markdown>
</View>
)}
{isMessageContainMedia(item) && (
<View className="relative">
{item.content instanceof Array && (() => {
const mediaItems = item.content.filter((media: ContentPart) => media.type !== 'text');
return (
<View className="mt-2">
<MediaGrid
mediaItems={mediaItems}
setModalVisible={setModalVisible}
setCancel={setCancel}
cancel={cancel}
t={t}
/>
</View>
);
})()}
{
(item.content instanceof Array && item.content.length > 3)
&& <TouchableOpacity className="absolute top-1/2 -translate-y-1/2 -right-4 translate-x-1/2 bg-bgPrimary flex flex-row items-center gap-2 p-1 pl-2 rounded-full" onPress={() => {
setSelectedImages([])
setModalDetailsVisible({ visible: true, content: item.content });
}}>
<ThemedText className="!text-white font-semibold">{item.content.length}</ThemedText>
<View className="bg-white rounded-full p-2">
<MoreSvg />
</View>
</TouchableOpacity>
}
</View>
)}
</View>
);
};
export default React.memo(MessageContent);