tiefen_space_app/components/ImageViewer/index.jsx

255 lines
7.5 KiB
React
Raw Normal View History

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";
2024-04-24 16:33:47 +08:00
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
2024-04-24 16:33:47 +08:00
//lockedStartIndex int
//onPressUnlockBtn () => void
export function ImageViewer({
isShow,
onClose,
2024-04-24 16:33:47 +08:00
onChange,
imageUrls,
index,
lockedStartIndex,
2024-04-24 16:33:47 +08:00
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);
2024-04-24 16:33:47 +08:00
await saveImage(imageUrls[index].url);
setIsSaving(false);
};
//查看原图
const handleCheckOriginalImage = async (index) => {
const isVip = await checkRole();
if (!isVip) {
setIsVipModalVisible(true);
return;
}
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);
}
};
return (
<Modal visible={isVisible} statusBarTranslucent transparent={true}>
<OriginImageViewer
imageUrls={imageUrls}
index={index}
onClick={closeImageViewer}
onSwipeDown={closeImageViewer}
2024-04-24 16:33:47 +08:00
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();
2024-04-24 16:33:47 +08:00
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")}
2024-04-24 16:33:47 +08:00
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"
),
}}
>
<Icon
type="ionicon"
name="image-outline"
size={20}
color="white"
/>
<Text
style={tailwind("text-xs text-[#FFFFFF80] font-medium mt-1")}
>
原图
</Text>
</TouchableOpacity>
)}
</View>
)}
2024-04-24 16:33:47 +08:00
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>
);
}