175 lines
5.3 KiB
JavaScript
175 lines
5.3 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;
|
|
const screenHeight = Dimensions.get("window").height;
|
|
|
|
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:
|
|
(videoSize.width / videoSize.height) * (screenHeight - 160),
|
|
maxWidth: screenWidth - 40,
|
|
// height: 200,
|
|
height:
|
|
(videoSize.height / videoSize.width) * (screenWidth - 40),
|
|
...tailwind("z-0 rounded-lg relative"),
|
|
maxHeight: screenHeight - 160,
|
|
}}
|
|
isLooping
|
|
shouldPlay
|
|
useNativeControls
|
|
source={{
|
|
uri: url,
|
|
}}
|
|
resizeMode={ResizeMode.CONTAIN}
|
|
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>
|
|
);
|
|
}
|