tiefen_space_app/components/MediaPicker/index.jsx

163 lines
4.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { View, TouchableOpacity, Image } from "react-native";
import React, { useState, useEffect } from "react";
import { useTailwind } from "tailwind-rn";
import { Icon } from "@rneui/themed";
import MediaPickerModal from "../MediaPickerModal";
import Toast from "react-native-toast-message";
import { DraggableGrid } from "react-native-draggable-grid";
import { useImageViewer } from "../../context/ImageViewProvider";
import VideoModal from "../VideoModal";
/*
props格式
setDragging 返回正在拖动的状态用于该组件嵌套在ScrollView中的时候禁用ScrollView的滚动
type 选择的媒体类型 "image"|"video"|"mix"
maxCount 最大选择数量
setAssets 向父组件返回媒体
*/
export default function MediaPicker({
setDragging = () => null,
maxCount,
type,
setAssets,
}) {
const tailwind = useTailwind();
const [modalVisible, setModalVisible] = useState(false);
const [newAssets, setNewAssets] = useState([]);
const [_assets, set_Assets] = useState([]);
const { showImageViewer } = useImageViewer();
const [showVideo, setShowVideo] = useState(false);
const [videoUrl, setVideoUrl] = useState("");
//当newAssets改变的时候添加新数据到assets
useEffect(() => {
const temAssets = newAssets.map((item) => ({
...item,
key: Date.now().toString(36) + Math.random().toString(36),
}));
set_Assets([..._assets, ...temAssets]);
setAssets([..._assets, ...temAssets]);
}, [newAssets]);
//加号选择器
const Picker = () => {
return (
<TouchableOpacity
onPress={() => {
//数量检查
maxCount - _assets.length !== 0
? setModalVisible(!modalVisible)
: Toast.show({
type: "error",
text1: `已达到最大选择数量`,
topOffset: 60,
});
}}
style={{
aspectRatio: 1,
padding: 2,
...tailwind("w-1/4"),
}}
>
<View
style={tailwind(
"border border-dashed border-gray-400 rounded flex-1 justify-center items-center"
)}
>
<Icon type="ionicon" name="add" color="#9ca3af" size={40} />
</View>
</TouchableOpacity>
);
};
const renderItem = (item) => {
const handleDelete = () => {
const updatedAssets = _assets.filter((_item) => _item.key !== item.key);
set_Assets(updatedAssets);
setAssets(updatedAssets);
};
return (
<View
activeOpacity={1}
style={{
aspectRatio: 1,
padding: 2,
...tailwind("w-full"),
}}
key={item.key}
>
<Image src={item.old_uri} style={tailwind("w-full h-full rounded")} />
<View style={tailwind("absolute top-2 right-2")}>
<Icon
type="ionicon"
name="close"
color="white"
size={18}
onPress={handleDelete}
style={tailwind("bg-black rounded-full opacity-70")}
/>
</View>
{item.duration !== 0 && (
<View
style={tailwind(
"absolute flex w-full h-full items-center justify-center"
)}
>
<Icon
type="ionicon"
name="play"
color="white"
size={14}
style={tailwind("bg-black p-2 rounded-full opacity-70")}
/>
</View>
)}
</View>
);
};
return (
<View style={tailwind("flex flex-col w-full")}>
<DraggableGrid
numColumns={4}
renderItem={renderItem}
data={_assets}
onDragStart={() => setDragging(true)}
onDragRelease={(data) => {
set_Assets(data);
setAssets(data);
setDragging(false);
}}
onItemPress={(item) => {
if (item.duration === 0) {
showImageViewer({
imageUrls: [{ url: item.old_uri }],
index: 0,
});
return;
}
setVideoUrl(item.uri);
setShowVideo(true);
}}
/>
<Picker />
<MediaPickerModal
visible={modalVisible}
setVisible={setModalVisible}
type={type}
maxCount={maxCount - _assets.length}
setAssets={setNewAssets}
/>
<VideoModal
visible={showVideo}
setVisible={setShowVideo}
url={videoUrl}
/>
</View>
);
}