135 lines
3.8 KiB
TypeScript
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;
|