增加查看原图功能;增加检查铁粉进度功能
This commit is contained in:
parent
e44b611998
commit
f5487d23b5
|
@ -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,13 +174,14 @@ export function ImageViewer({
|
||||||
return <Image {...props} />;
|
return <Image {...props} />;
|
||||||
}}
|
}}
|
||||||
renderFooter={(index) => (
|
renderFooter={(index) => (
|
||||||
|
<View style={tailwind("flex flex-row items-center")}>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
onPress={() => hanldSaveImage(index)}
|
onPress={() => hanldSaveImage(index)}
|
||||||
style={{
|
style={{
|
||||||
marginLeft: 20,
|
marginLeft: 20,
|
||||||
marginBottom: insets.bottom,
|
marginBottom: insets.bottom,
|
||||||
...tailwind(
|
...tailwind(
|
||||||
"flex justify-center items-center w-12 h-12 bg-[#FFFFFF1A] rounded-full"
|
"flex justify-center items-center w-14 h-14 bg-[#FFFFFF1A] rounded-full"
|
||||||
),
|
),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -208,13 +194,42 @@ export function ImageViewer({
|
||||||
color="white"
|
color="white"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
<Text
|
||||||
|
style={tailwind("text-xs text-[#FFFFFF80] font-medium mt-1")}
|
||||||
|
>
|
||||||
|
保存
|
||||||
|
</Text>
|
||||||
</TouchableOpacity>
|
</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>
|
||||||
)}
|
)}
|
||||||
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);
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -28,6 +28,7 @@ export const ImageViewerProvider = ({ children }) => {
|
||||||
{...imageViewerProps}
|
{...imageViewerProps}
|
||||||
onClose={closeImageViewer}
|
onClose={closeImageViewer}
|
||||||
onChange={changeImageViewerIndex}
|
onChange={changeImageViewerIndex}
|
||||||
|
setImageViewerProps={setImageViewerProps}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</ImageViewerContext.Provider>
|
</ImageViewerContext.Provider>
|
||||||
|
|
|
@ -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,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -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,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in New Issue