tiefen_space_app/components/VideoModal/index.jsx

170 lines
5.1 KiB
JavaScript

import {
View,
Dimensions,
Modal,
TouchableWithoutFeedback,
TouchableOpacity,
Text,
ActivityIndicator,
Platform,
} from "react-native";
import React, { useState, useRef, useCallback } from "react";
import { useTailwind } from "tailwind-rn";
import { Icon } from "@rneui/themed";
import { Video, ResizeMode } from "expo-av";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { get } from "../../utils/storeInfo";
import MyModal from "../MyModal";
import Toast from "react-native-toast-message";
import { useNavigation } from "@react-navigation/native";
import saveVideo from "../../utils/saveVideo";
const screenWidth = Dimensions.get("window").width;
export default function VideoModal({ visible, setVisible, url }) {
const tailwind = useTailwind();
const insets = useSafeAreaInsets();
const navigation = useNavigation();
const [isReady, setIsReady] = useState(false);
const videoRef = useRef(null);
const [videoSize, setVideoSize] = useState({ width: 720, height: 1280 });
const checkRole = useCallback(async () => {
const account = await get("account");
const role = account.role;
const isVip = account.is_a_member;
if (role !== 0 || isVip === 1) return true;
return false;
}, []);
const [isVipModalVisible, setIsVipModalVisible] = useState(false);
const [isSaving, setIsSaving] = useState(false);
const [progress, setProgress] = useState(0);
const hanldSaveVideo = async () => {
const isVip = await checkRole();
if (!isVip) {
setIsVipModalVisible(true);
return;
}
if (isSaving) return;
setIsSaving(true);
const callback = (downloadProgress) => {
const _progress =
downloadProgress.totalBytesWritten /
downloadProgress.totalBytesExpectedToWrite;
setProgress((_progress * 100).toFixed());
};
await saveVideo(url, callback);
setIsSaving(false);
};
return (
<Modal
visible={visible}
transparent={true}
statusBarTranslucent
style={tailwind("flex flex-1")}
>
<TouchableWithoutFeedback onPress={() => setVisible(false)}>
<View
style={{
backgroundColor: "rgba(0,0,0,0.8)",
...tailwind("flex-1 justify-center items-center"),
}}
>
<View
style={{
top: insets.top,
right: 20,
...tailwind(
"absolute z-10 flex justify-center items-center w-12 h-12 bg-[#FFFFFF1A] rounded-full"
),
}}
>
<Icon type="ionicon" name="close" size={24} color="#f9fafb" />
</View>
<TouchableOpacity
style={tailwind("flex justify-center items-center")}
activeOpacity={1}
>
{!isReady && (
<View
style={tailwind(
"flex flex-1 absolute z-10 justify-center items-center"
)}
>
<ActivityIndicator size="large" />
</View>
)}
<Video
ref={videoRef}
style={{
width: screenWidth - 40,
height:
(videoSize.height / videoSize.width) * (screenWidth - 40),
...tailwind("z-0 rounded-lg relative"),
}}
isLooping
shouldPlay
useNativeControls
source={{
uri: url,
}}
resizeMode={ResizeMode.COVER}
onReadyForDisplay={({ naturalSize }) => {
setVideoSize({
width: naturalSize.width,
height: naturalSize.height,
});
setIsReady(true);
}}
/>
</TouchableOpacity>
{Platform.OS === "android" && (
<TouchableOpacity
onPress={hanldSaveVideo}
style={{
left: 20,
bottom: insets.bottom,
...tailwind(
"flex absolute justify-center items-center w-12 h-12 bg-[#FFFFFF1A] rounded-full"
),
}}
>
{isSaving && (
<Text style={tailwind("text-white")}>{progress}%</Text>
)}
{!isSaving && (
<Icon
type="ionicon"
name="save-outline"
size={20}
color="white"
/>
)}
</TouchableOpacity>
)}
</View>
</TouchableWithoutFeedback>
<Toast />
<MyModal
visible={isVipModalVisible}
setVisible={setIsVipModalVisible}
title="是否开通会员?"
content="会员可无限制保存图片/视频,一次开通永久有效。"
cancel={() => {
setIsVipModalVisible(false);
}}
confirm={() => {
setIsVipModalVisible(false);
setVisible(false);
navigation.navigate("WebWithoutHeader", {
uri: process.env.EXPO_PUBLIC_WEB_URL + "/vip",
});
}}
/>
</Modal>
);
}