增加查看原图功能;增加检查铁粉进度功能

This commit is contained in:
yezian 2024-12-20 20:40:46 +08:00
parent e44b611998
commit f5487d23b5
7 changed files with 163 additions and 102 deletions

View File

@ -19,8 +19,10 @@ import MyModal from "../MyModal";
import { Image } from "expo-image"; import { Image } from "expo-image";
import { Button } from "@rneui/themed"; import { Button } from "@rneui/themed";
import { LinearGradient } from "expo-linear-gradient"; import { LinearGradient } from "expo-linear-gradient";
import { generateSignature } from "../../utils/crypto";
import baseRequest from "../../utils/baseRequest";
//imageUrls [{ url: string }] //imageUrls [{ url: string , id: int }] id
//index int //index int
//lockedStartIndex int //lockedStartIndex int
//onPressUnlockBtn () => void //onPressUnlockBtn () => void
@ -33,6 +35,7 @@ export function ImageViewer({
index, index,
lockedStartIndex, lockedStartIndex,
onPressUnlockBtn, onPressUnlockBtn,
setImageViewerProps,
}) { }) {
const tailwind = useTailwind(); const tailwind = useTailwind();
const insets = useSafeAreaInsets(); const insets = useSafeAreaInsets();
@ -57,76 +60,6 @@ export function ImageViewer({
return false; return false;
}, []); }, []);
const MenusComponent = useCallback(
({ cancel, saveToLocal }) => (
<Modal
visible={true}
transparent={true}
statusBarTranslucent
animationType="fade"
>
<TouchableOpacity
onPress={cancel}
activeOpacity={1}
style={tailwind("flex flex-1 bg-[#00000080]")}
>
<TouchableOpacity
activeOpacity={1}
style={{
paddingBottom: insets.bottom,
paddingLeft: insets.left,
paddingRight: insets.right,
...tailwind(
"absolute bottom-0 left-0 h-32 w-full bg-[#13121F] rounded-t-2xl"
),
}}
>
<View style={tailwind("flex flex-1 flex-row items-center px-4")}>
<TouchableOpacity
onPress={async () => {
const isVip = await checkRole();
if (isVip) {
saveToLocal();
return;
}
closeImageViewer();
navigation.navigate("WebWithoutHeader", {
uri: process.env.EXPO_PUBLIC_WEB_URL + "/vip",
});
}}
style={tailwind("flex flex-col items-center px-4")}
>
<Icon type="ionicon" name="image" size={30} color="white" />
<Text
style={tailwind("text-sm text-[#FFFFFF80] font-medium mt-1")}
>
保存(会员特权)
</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={cancel}
style={tailwind("flex flex-col items-center px-4")}
>
<Icon
type="ionicon"
name="close-circle"
size={30}
color="white"
/>
<Text
style={tailwind("text-sm text-[#FFFFFF80] font-medium mt-1")}
>
取消
</Text>
</TouchableOpacity>
</View>
</TouchableOpacity>
</TouchableOpacity>
</Modal>
),
[]
);
const [isVipModalVisible, setIsVipModalVisible] = useState(false); const [isVipModalVisible, setIsVipModalVisible] = useState(false);
const [isSaving, setIsSaving] = useState(false); const [isSaving, setIsSaving] = useState(false);
const hanldSaveImage = async (index) => { const hanldSaveImage = async (index) => {
@ -141,6 +74,58 @@ export function ImageViewer({
setIsSaving(false); 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 ( return (
<Modal visible={isVisible} statusBarTranslucent transparent={true}> <Modal visible={isVisible} statusBarTranslucent transparent={true}>
<OriginImageViewer <OriginImageViewer
@ -189,32 +174,62 @@ export function ImageViewer({
return <Image {...props} />; return <Image {...props} />;
}} }}
renderFooter={(index) => ( renderFooter={(index) => (
<TouchableOpacity <View style={tailwind("flex flex-row items-center")}>
onPress={() => hanldSaveImage(index)} <TouchableOpacity
style={{ onPress={() => hanldSaveImage(index)}
marginLeft: 20, style={{
marginBottom: insets.bottom, marginLeft: 20,
...tailwind( marginBottom: insets.bottom,
"flex justify-center items-center w-12 h-12 bg-[#FFFFFF1A] rounded-full" ...tailwind(
), "flex justify-center items-center w-14 h-14 bg-[#FFFFFF1A] rounded-full"
}} ),
> }}
{isSaving && <ActivityIndicator size="small" />} >
{!isSaving && ( {isSaving && <ActivityIndicator size="small" />}
<Icon {!isSaving && (
type="ionicon" <Icon
name="save-outline" type="ionicon"
size={20} name="save-outline"
color="white" 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>
)} )}
</TouchableOpacity> </View>
)} )}
onSave={(url) => { onSave={(url) => {
saveImage(url); saveImage(url);
}} }}
saveToLocalByLongPress saveToLocalByLongPress={false}
menus={MenusComponent}
loadingRender={() => <ActivityIndicator size="large" />} loadingRender={() => <ActivityIndicator size="large" />}
/> />
<Toast /> <Toast />
@ -222,7 +237,7 @@ export function ImageViewer({
visible={isVipModalVisible} visible={isVipModalVisible}
setVisible={setIsVipModalVisible} setVisible={setIsVipModalVisible}
title="是否开通会员?" title="是否开通会员?"
content="会员可无限制保存图片/视频,一次开通永久有效。" content="会员可无限制保存图片、查看原图,一次开通永久有效。"
cancel={() => { cancel={() => {
setIsVipModalVisible(false); setIsVipModalVisible(false);
}} }}

View File

@ -257,9 +257,8 @@ export default function Post({ data }) {
// //
function ImageDisplay({ media }) { function ImageDisplay({ media }) {
const navigation = useNavigation();
const tailwind = useTailwind(); const tailwind = useTailwind();
const images = media.map((item) => ({ url: item.urls[0] })); const images = media.map((item) => ({ url: item.urls[0], id: item.id }));
const { showImageViewer } = useImageViewer(); const { showImageViewer } = useImageViewer();

View File

@ -608,7 +608,7 @@ function ImageDisplay({
const { showImageViewer } = useImageViewer(); const { showImageViewer } = useImageViewer();
const images = displayMedia.map((item) => { const images = displayMedia.map((item) => {
return { url: item?.urls[0] }; return { url: item?.urls[0], id: item?.id };
}); });
const [isCollapsed, setIsCollapsed] = useState(true); const [isCollapsed, setIsCollapsed] = useState(true);

View File

@ -28,6 +28,7 @@ export const ImageViewerProvider = ({ children }) => {
{...imageViewerProps} {...imageViewerProps}
onClose={closeImageViewer} onClose={closeImageViewer}
onChange={changeImageViewerIndex} onChange={changeImageViewerIndex}
setImageViewerProps={setImageViewerProps}
/> />
)} )}
</ImageViewerContext.Provider> </ImageViewerContext.Provider>

View File

@ -87,9 +87,8 @@ export default function SpaceIntroduce({ navigation, route }) {
const images = data?.streamer_ext?.album?.images const images = data?.streamer_ext?.album?.images
?.slice(0, 5) ?.slice(0, 5)
?.map((image) => { ?.map((image) => {
return image?.urls[0]; return { url: image?.urls[0], id: image?.id };
}); });
const imagesForImageViewer = images?.map((url) => ({ url }));
//0 //0
const handleJoinFreeSpace = async () => { const handleJoinFreeSpace = async () => {
@ -288,7 +287,7 @@ export default function SpaceIntroduce({ navigation, route }) {
activeOpacity={1} activeOpacity={1}
onPress={() => { onPress={() => {
showImageViewer({ showImageViewer({
imageUrls: imagesForImageViewer, imageUrls: images,
index: index, index: index,
}); });
}} }}

View File

@ -245,8 +245,10 @@ export default function StreamerProfile({ navigation, route }) {
const { showImageViewer } = useImageViewer(); const { showImageViewer } = useImageViewer();
const images = data?.album?.images?.map((image) => image?.urls[0]); const images = data?.album?.images?.map((image) => ({
const imagesForImageViewer = images?.map((url) => ({ url })); url: image?.urls[0],
id: image?.id,
}));
return ( return (
<> <>
<Swiper <Swiper
@ -297,7 +299,7 @@ export default function StreamerProfile({ navigation, route }) {
<TouchableWithoutFeedback <TouchableWithoutFeedback
onPress={() => { onPress={() => {
showImageViewer({ showImageViewer({
imageUrls: imagesForImageViewer, imageUrls: images,
index: index - 1, index: index - 1,
}); });
}} }}

View File

@ -215,6 +215,42 @@ export default function StreamerSpace({ navigation, route }) {
//bottom sheet //bottom sheet
const snapPoints = useMemo(() => ["73%", "100%"], []); const snapPoints = useMemo(() => ["73%", "100%"], []);
//100
const handleFansIdentityRefresh = async () => {
const apiUrl = process.env.EXPO_PUBLIC_API_URL;
try {
const base = await baseRequest();
const body = {
zid: data?.id,
...base,
};
const signature = await generateSignature(body);
const _response = await fetch(
`${apiUrl}/api/zone_moment/fans_identity_refresh?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;
}
await getData();
setIsIronFanModalVisible(false);
} catch (error) {
console.error(error);
}
};
//Modal //Modal
const [isIronFanModalVisible, setIsIronFanModalVisible] = useState(false); const [isIronFanModalVisible, setIsIronFanModalVisible] = useState(false);
const ironFanProgress = useMemo( const ironFanProgress = useMemo(
@ -283,6 +319,15 @@ export default function StreamerSpace({ navigation, route }) {
> >
查看铁粉专享内容 查看铁粉专享内容
</Button> </Button>
<Text
onPress={handleFansIdentityRefresh}
style={{
textDecorationLine: "underline",
...tailwind("text-sm font-medium text-[#FF669E] mt-2"),
}}
>
进度已满但还未成为铁粉
</Text>
</TouchableOpacity> </TouchableOpacity>
</TouchableOpacity> </TouchableOpacity>
</Modal> </Modal>