feat: 选择图片弹窗

This commit is contained in:
jinyaqiu 2025-08-04 15:49:26 +08:00
parent 84e1263981
commit 240601b97b

View File

@ -3,12 +3,14 @@ import DownloadSvg from '@/assets/icons/svg/download.svg';
import FolderSvg from "@/assets/icons/svg/folder.svg"; import FolderSvg from "@/assets/icons/svg/folder.svg";
import ReturnArrow from "@/assets/icons/svg/returnArrow.svg"; import ReturnArrow from "@/assets/icons/svg/returnArrow.svg";
import YesSvg from "@/assets/icons/svg/yes.svg"; import YesSvg from "@/assets/icons/svg/yes.svg";
import { ContentPart } from '@/types/ask';
import { TFunction } from "i18next"; import { TFunction } from "i18next";
import React from "react"; import React from "react";
import { FlatList, Image, Modal, StyleSheet, TouchableOpacity, View } from "react-native"; import { FlatList, Image, Modal, StyleSheet, TouchableOpacity, View } from "react-native";
import ContextMenu from "../gusture/contextMenu"; import ContextMenu from "../gusture/contextMenu";
import { ThemedText } from "../ThemedText"; import { ThemedText } from "../ThemedText";
import { mergeArrays, saveMediaToGallery } from "./utils"; import { mergeArrays, saveMediaToGallery } from "./utils";
import VideoPlayer from './VideoPlayer';
interface SelectModelProps { interface SelectModelProps {
modalDetailsVisible: { visible: boolean, content: any }; modalDetailsVisible: { visible: boolean, content: any };
@ -21,6 +23,7 @@ interface SelectModelProps {
setCancel: React.Dispatch<React.SetStateAction<boolean>>; setCancel: React.Dispatch<React.SetStateAction<boolean>>;
} }
const SelectModel = ({ modalDetailsVisible, setModalDetailsVisible, insets, setSelectedImages, selectedImages, t, cancel, setCancel }: SelectModelProps) => { const SelectModel = ({ modalDetailsVisible, setModalDetailsVisible, insets, setSelectedImages, selectedImages, t, cancel, setCancel }: SelectModelProps) => {
const items = modalDetailsVisible?.content?.filter((media: ContentPart) => media.type !== 'text');
return ( return (
<Modal <Modal
@ -42,7 +45,7 @@ const SelectModel = ({ modalDetailsVisible, setModalDetailsVisible, insets, setS
</View> </View>
<View style={{ flex: 1 }}> <View style={{ flex: 1 }}>
<FlatList <FlatList
data={mergeArrays(modalDetailsVisible?.content?.image_material_infos || [], modalDetailsVisible?.content?.video_material_infos || [])} data={items}
numColumns={3} numColumns={3}
keyExtractor={(item) => item.id} keyExtractor={(item) => item.id}
showsVerticalScrollIndicator={false} showsVerticalScrollIndicator={false}
@ -56,14 +59,6 @@ const SelectModel = ({ modalDetailsVisible, setModalDetailsVisible, insets, setS
const itemId = item?.id || item?.video?.id; const itemId = item?.id || item?.video?.id;
const isSelected = selectedImages.includes(itemId); const isSelected = selectedImages.includes(itemId);
const toggleSelection = () => {
setSelectedImages(prev =>
isSelected
? prev.filter(id => id !== itemId)
: [...prev, itemId]
);
};
return ( return (
<View style={detailsStyles.gridItemContainer} key={itemId}> <View style={detailsStyles.gridItemContainer} key={itemId}>
@ -79,7 +74,7 @@ const SelectModel = ({ modalDetailsVisible, setModalDetailsVisible, insets, setS
svg: <DownloadSvg width={20} height={20} />, svg: <DownloadSvg width={20} height={20} />,
label: t("ask:ask.save"), label: t("ask:ask.save"),
onPress: () => { onPress: () => {
const imageUrl = item?.file_info?.url || item.video?.file_info?.url; const imageUrl = item?.url;
if (imageUrl) { if (imageUrl) {
saveMediaToGallery(imageUrl, t); saveMediaToGallery(imageUrl, t);
} }
@ -106,13 +101,25 @@ const SelectModel = ({ modalDetailsVisible, setModalDetailsVisible, insets, setS
elevation: 5, elevation: 5,
}} }}
> >
<Image {item?.type === 'image' ? (
source={{ uri: item?.preview_file_info?.url || item.video?.preview_file_info?.url }} <Image
style={detailsStyles.image} source={{ uri: item?.url }}
onError={(error) => console.log('Image load error:', error.nativeEvent.error)} style={detailsStyles.image}
onLoad={() => console.log('Image loaded successfully')} onError={(error) => console.log('Image load error:', error.nativeEvent.error)}
loadingIndicatorSource={require('@/assets/images/png/placeholder.png')} onLoad={() => console.log('Image loaded successfully')}
/> loadingIndicatorSource={require('@/assets/images/png/placeholder.png')}
/>
) : (
<VideoPlayer
videoUrl={item?.url || ""}
style={{
width: '100%',
height: '100%',
alignSelf: 'center',
justifyContent: 'center',
}}
/>
)}
</ContextMenu> </ContextMenu>
<TouchableOpacity <TouchableOpacity