2025-08-06 18:57:18 +08:00

135 lines
3.8 KiB
TypeScript

import CancelSvg from "@/assets/icons/svg/cancel.svg";
import DownloadSvg from "@/assets/icons/svg/download.svg";
import { ContentPart } from "@/types/ask";
import { TFunction } from 'i18next';
import React from 'react';
import { Image, Pressable, StyleSheet, Text as ThemedText, View } from 'react-native';
import { saveMediaToGallery } from "../../ask/utils";
import ContextMenu from "../../gusture/contextMenu";
interface MediaGridProps {
mediaItems: ContentPart[];
setModalVisible: React.Dispatch<React.SetStateAction<{ visible: boolean, data: ContentPart }>>;
setCancel: React.Dispatch<React.SetStateAction<boolean>>;
cancel: boolean;
t: TFunction;
}
const MediaGrid = ({ mediaItems, setModalVisible, setCancel, cancel, t }: MediaGridProps) => {
// Only show up to 6 images (2 rows of 3)
const displayItems = mediaItems.slice(0, 6);
const itemCount = displayItems.length;
// Calculate item width based on number of items
const getItemWidth = () => {
if (itemCount === 1) return '100%';
if (itemCount === 2) return '49%';
return '32%'; // For 3+ items
};
// Calculate container style based on number of items
const getContainerStyle = () => {
if (itemCount === 1) return styles.singleItemContainer;
return styles.multiItemContainer;
};
return (
<View style={[styles.container, getContainerStyle()]}>
{displayItems.map((media, index) => (
<Pressable
key={media.id}
onPress={() => {
setModalVisible({ visible: true, data: media });
}}
style={[styles.imageContainer, { width: getItemWidth() }]}
>
<ContextMenu
items={[
{
svg: <DownloadSvg width={20} height={20} />,
label: t("ask:ask.save"),
onPress: () => {
if (media?.url) {
saveMediaToGallery(media?.url, t);
}
},
textStyle: { color: '#4C320C' }
},
{
svg: <CancelSvg width={20} height={20} color='red' />,
label: t("ask:ask.cancel"),
onPress: () => {
setCancel(true);
},
textStyle: { color: 'red' }
}
]}
cancel={cancel}
menuStyle={styles.contextMenu}
>
<Image
source={{ uri: media?.url }}
style={styles.image}
resizeMode="cover"
loadingIndicatorSource={require('@/assets/images/png/placeholder.png')}
/>
{itemCount > 3 && index === 5 && mediaItems.length > 6 && (
<View style={styles.overlay}>
<ThemedText style={styles.overlayText}>+{mediaItems.length - 5}</ThemedText>
</View>
)}
</ContextMenu>
</Pressable>
))}
</View>
);
};
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'space-between',
},
singleItemContainer: {
width: '100%',
},
multiItemContainer: {
width: '100%',
},
imageContainer: {
marginBottom: 8,
aspectRatio: 1,
},
image: {
width: '100%',
height: '100%',
borderRadius: 8,
},
contextMenu: {
backgroundColor: 'white',
borderRadius: 8,
padding: 8,
minWidth: 150,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.25,
shadowRadius: 4,
elevation: 5,
},
overlay: {
...StyleSheet.absoluteFillObject,
backgroundColor: 'rgba(0,0,0,0.5)',
borderRadius: 8,
justifyContent: 'center',
alignItems: 'center',
},
overlayText: {
color: 'white',
fontSize: 24,
fontWeight: 'bold',
},
});
export default MediaGrid;