tiefen_space_app/components/Post/index.jsx

212 lines
6.7 KiB
JavaScript

import {
View,
Text,
TouchableOpacity,
Dimensions,
Modal,
TouchableWithoutFeedback,
ActivityIndicator,
} from "react-native";
import React, { useState } from "react";
import { useTailwind } from "tailwind-rn";
import { Icon } from "@rneui/themed";
import { Image } from "expo-image";
import ImageViewer from "react-native-image-zoom-viewer";
import VideoModal from "../VideoModal";
import { useNavigation } from "@react-navigation/native";
//todo:给头像加上在线状态
const blurhash = "LcKUTa%gOYWBYRt6xuoJo~s8V@fk";
const screenWidth = Dimensions.get("window").width;
export default function Post({ data }) {
const tailwind = useTailwind();
const navigation = useNavigation();
const [like, setLike] = useState(data.like === 1);
const [showVideo, setShowVideo] = useState(false);
return (
<View style={tailwind("flex p-4 mb-2 bg-white")}>
<View style={tailwind("flex flex-row")}>
<TouchableWithoutFeedback
onPress={() =>
navigation.navigate("StreamerProfile", { mid: data.mid })
}
>
<Image
style={tailwind("w-10 h-10 rounded-full")}
source={data.head}
placeholder={blurhash}
contentFit="cover"
transition={1000}
cachePolicy="disk"
/>
</TouchableWithoutFeedback>
<View style={tailwind("flex flex-col flex-1 justify-around ml-2")}>
<Text style={tailwind("text-base font-semibold")}>{data.name}</Text>
<Text style={tailwind("text-sm text-gray-400")}>{data.time}</Text>
</View>
<TouchableOpacity
style={tailwind("flex flex-row items-center")}
onPress={() => setLike(!like)}
>
<Icon
type="ionicon"
name={like ? "heart" : "heart-outline"}
size={30}
color="#ef4444"
/>
<Text style={tailwind("text-base text-red-500")}>
{like ? data.like_num + 1 : data.like_num}
</Text>
</TouchableOpacity>
</View>
<Text style={tailwind("text-base my-2")}>{data.content}</Text>
{/* 媒体展示 */}
{data.media.type === "image" ? (
<ImageDisplay media={data.media} />
) : (
<View style={tailwind("flex flex-row")}>
<TouchableOpacity
activeOpacity={1}
onPress={() => {
setShowVideo(true);
}}
>
<View>
<PosterDisplay media={data.media} />
<VideoModal
visible={showVideo}
setVisible={setShowVideo}
url={data.media.url[0]}
height={data.media.height}
width={data.media.width}
/>
</View>
</TouchableOpacity>
<View style={tailwind("flex-1")}></View>
</View>
)}
</View>
);
}
//媒体为图片时展示内容的组件
function ImageDisplay({ media }) {
const tailwind = useTailwind();
const [isModalVisible, setIsModalVisible] = useState(false);
const [imageIndex, setImageIndex] = useState();
const images = media.url.map((url) => ({ url }));
if (media.url) {
return (
<View style={tailwind("flex flex-row flex-wrap")}>
{media.url.length > 1 ? (
media.url.map((item, index) => (
<View key={index} style={tailwind("p-0.5 w-1/3")}>
<TouchableWithoutFeedback
onPress={() => {
setIsModalVisible(true);
setImageIndex(index);
}}
>
<Image
style={{
height: screenWidth / 3.6,
...tailwind("w-full rounded-lg"),
}}
source={item}
placeholder={blurhash}
contentFit="cover"
transition={1000}
cachePolicy="disk"
/>
</TouchableWithoutFeedback>
</View>
))
) : (
<Image
style={{
width:
media.width < media.height
? (media.width / media.height) * 200
: 250,
height:
media.width < media.height
? 200
: (media.height / media.width) * 250,
...tailwind("rounded-lg"),
}}
source={media.url[0]}
placeholder={blurhash}
contentFit="cover"
transition={1000}
cachePolicy="disk"
/>
)}
<Modal visible={isModalVisible} statusBarTranslucent transparent={true}>
<TouchableWithoutFeedback onPress={() => setIsModalVisible(false)}>
<ImageViewer
imageUrls={images}
enableSwipeDown
onSwipeDown={() => setIsModalVisible(false)}
index={imageIndex}
loadingRender={() => <ActivityIndicator size="large" />}
/>
</TouchableWithoutFeedback>
</Modal>
</View>
);
}
}
//媒体为视频时展示封面的组件
function PosterDisplay({ media }) {
const tailwind = useTailwind();
if (media.poster) {
return (
<View style={tailwind("flex")}>
<View style={tailwind("flex flex-row flex-wrap")}>
<Image
style={{
width:
media.poster.width < media.poster.height
? (media.poster.width / media.poster.height) * 200
: 250,
height:
media.poster.width < media.poster.height
? 200
: (media.poster.height / media.poster.width) * 250,
...tailwind("rounded-lg"),
}}
source={media.poster.url}
placeholder={blurhash}
contentFit="cover"
transition={1000}
cachePolicy="disk"
/>
<View
style={{
width:
media.poster.width < media.poster.height
? (media.poster.width / media.poster.height) * 200
: 250,
height:
media.poster.width < media.poster.height
? 200
: (media.poster.height / media.poster.width) * 250,
...tailwind(
"flex absolute rounded-full left-0 top-0 z-10 justify-center items-center"
),
}}
>
<View
style={tailwind("rounded-full bg-white w-4 h-4 absolute")}
></View>
<Icon type="ionicon" name="play-circle" size={40} color="#030712" />
</View>
</View>
</View>
);
}
}