tiefen_space_app/components/ImageViewer/index.jsx

262 lines
7.7 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,
Text,
Modal,
TouchableOpacity,
ActivityIndicator,
Platform,
} from "react-native";
import React, { useState, useCallback, useEffect } from "react";
import { ImageViewer as OriginImageViewer } from "react-native-image-zoom-viewer";
import { Icon } from "@rneui/themed";
import { useTailwind } from "tailwind-rn";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import saveImage from "../../utils/saveImage";
import Toast from "react-native-toast-message";
import { get } from "../../utils/storeInfo";
import { useNavigation } from "@react-navigation/native";
import MyModal from "../MyModal";
import { Image } from "expo-image";
import { Button } from "@rneui/themed";
import { LinearGradient } from "expo-linear-gradient";
import { generateSignature } from "../../utils/crypto";
import baseRequest from "../../utils/baseRequest";
//imageUrls [{ url: string , id: int }] 网络图片需要查看原图时才传id其他情况不用
//index int
//lockedStartIndex int
//onPressUnlockBtn () => void
export function ImageViewer({
isShow,
onClose,
onChange,
imageUrls,
index,
lockedStartIndex,
onPressUnlockBtn,
setImageViewerProps,
}) {
const tailwind = useTailwind();
const insets = useSafeAreaInsets();
const navigation = useNavigation();
const [isVisible, setIsVisible] = useState(false);
useEffect(() => {
setIsVisible(isShow);
}, [isShow]);
const closeImageViewer = () => {
setIsVisible(false);
onClose && onClose();
};
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 hanldSaveImage = async (index) => {
const isVip = await checkRole();
if (!isVip) {
setIsVipModalVisible(true);
return;
}
if (isSaving) return;
setIsSaving(true);
await saveImage(imageUrls[index].url);
setIsSaving(false);
};
//查看原图
const [isLoading, setIsLoading] = useState(false);
const handleCheckOriginalImage = async (index) => {
const isVip = await checkRole();
if (!isVip) {
setIsVipModalVisible(true);
return;
}
setIsLoading(true);
const apiUrl = process.env.EXPO_PUBLIC_API_URL;
try {
const base = await baseRequest();
const body = {
image_id: imageUrls[index].id,
...base,
};
const signature = await generateSignature(body);
const _response = await fetch(
`${apiUrl}/api/previews/original_image?signature=${signature}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(body),
}
);
const _data = await _response.json();
if (_data.ret === -1) {
Toast.show({
type: "error",
text1: _data.msg,
topOffset: 60,
});
return;
}
setImageViewerProps((prev) => {
let newImageViewerProps = prev;
newImageViewerProps.imageUrls[index] = {
id: imageUrls[index].id,
url: _data?.data?.urls[0],
};
return { ...newImageViewerProps };
});
Toast.show({
type: "success",
text1: "已切换至原图",
topOffset: 60,
});
} catch (error) {
console.error(error);
} finally {
setIsLoading(false);
}
};
return (
<Modal visible={isVisible} statusBarTranslucent transparent={true}>
<OriginImageViewer
imageUrls={imageUrls}
index={index}
onClick={closeImageViewer}
onSwipeDown={closeImageViewer}
onChange={onChange ? (index) => onChange(index) : () => null}
enableSwipeDown
backgroundColor="#07050A"
renderImage={(props) => {
if (index >= lockedStartIndex) {
return (
<View>
<Image
{...props}
blurRadius={Platform.OS === "ios" ? 100 : 10}
/>
<View
style={tailwind(
"absolute flex justify-center items-center top-0 left-0 bg-[#00000080] w-full h-full"
)}
>
<Button
onPress={() => {
closeImageViewer();
onPressUnlockBtn();
}}
ViewComponent={LinearGradient}
radius="999"
size="md"
linearGradientProps={{
colors: ["#FF668B", "#FF66F0"],
start: { x: 0, y: 0.5 },
end: { x: 1, y: 0.5 },
}}
titleStyle={tailwind("text-base font-medium")}
containerStyle={tailwind("w-3/4 px-4")}
>
立即解锁
</Button>
</View>
</View>
);
}
return <Image {...props} />;
}}
renderFooter={(index) => (
<View style={tailwind("flex flex-row items-center")}>
<TouchableOpacity
onPress={() => hanldSaveImage(index)}
style={{
marginLeft: 20,
marginBottom: insets.bottom,
...tailwind(
"flex justify-center items-center w-14 h-14 bg-[#FFFFFF1A] rounded-full"
),
}}
>
{isSaving && <ActivityIndicator size="small" />}
{!isSaving && (
<Icon
type="ionicon"
name="save-outline"
size={20}
color="white"
/>
)}
<Text
style={tailwind("text-xs text-[#FFFFFF80] font-medium mt-1")}
>
保存
</Text>
</TouchableOpacity>
{imageUrls[index]?.id && (
<TouchableOpacity
onPress={() => handleCheckOriginalImage(index)}
style={{
marginLeft: 20,
marginBottom: insets.bottom,
...tailwind(
"flex justify-center items-center w-14 h-14 bg-[#FFFFFF1A] rounded-full"
),
}}
>
{isLoading && <ActivityIndicator size="small" />}
{!isLoading && (
<Icon
type="ionicon"
name="image-outline"
size={20}
color="white"
/>
)}
<Text
style={tailwind("text-xs text-[#FFFFFF80] font-medium mt-1")}
>
原图
</Text>
</TouchableOpacity>
)}
</View>
)}
onSave={(url) => {
saveImage(url);
}}
saveToLocalByLongPress={false}
loadingRender={() => <ActivityIndicator size="large" />}
/>
<Toast />
<MyModal
visible={isVipModalVisible}
setVisible={setIsVipModalVisible}
title="是否开通会员?"
content="会员可无限制保存图片、查看原图,一次开通永久有效。"
cancel={() => {
setIsVipModalVisible(false);
}}
confirm={() => {
setIsVipModalVisible(false);
closeImageViewer();
navigation.navigate("WebWithoutHeader", {
uri: process.env.EXPO_PUBLIC_WEB_URL + "/vip",
});
}}
/>
</Modal>
);
}