212 lines
6.7 KiB
JavaScript
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>
|
|
);
|
|
}
|
|
}
|