tiefen_space_app/screeens/EditStreamerMedia/index.jsx

394 lines
13 KiB
React
Raw Normal View History

2024-04-18 22:58:59 +08:00
import {
View,
Text,
ScrollView,
TouchableOpacity,
KeyboardAvoidingView,
Platform,
ActivityIndicator,
} from "react-native";
2024-09-27 16:04:56 +08:00
import React, { useState, useEffect, useCallback } from "react";
2024-04-18 22:58:59 +08:00
import { useTailwind } from "tailwind-rn";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { Divider, Icon, Button } from "@rneui/themed";
import { Image } from "expo-image";
import { Formik } from "formik";
import MediaPicker from "../../components/MediaPicker";
import Toast from "react-native-toast-message";
import { get } from "../../utils/storeInfo";
import { multiUpload } from "../../utils/upload";
import baseRequest from "../../utils/baseRequest";
import { generateSignature } from "../../utils/crypto";
import MediaGrid from "../../components/MediaGrid";
2024-09-27 16:04:56 +08:00
import * as ImagePicker from "expo-image-picker";
import * as VideoThumbnails from "expo-video-thumbnails";
2024-04-18 22:58:59 +08:00
const blurhash = "LcKUTa%gOYWBYRt6xuoJo~s8V@fk";
export default function EditStreamerMedia({ navigation, route }) {
const tailwind = useTailwind();
const insets = useSafeAreaInsets();
2024-09-27 16:04:56 +08:00
//保存封面图
2024-04-18 22:58:59 +08:00
const [displayImage, setDisplayImage] = useState([]);
2024-09-27 16:04:56 +08:00
//选择封面图
const pickDisPlayImage = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
quality: 1,
});
if (!result.canceled) {
setDisplayImage(result.assets);
}
};
//保存展示视频
2024-04-18 22:58:59 +08:00
const [displayVideo, setDisplayVideo] = useState([]);
2024-09-27 16:04:56 +08:00
//为视频生成封面
const generateThumbnail = useCallback(async (uri) => {
try {
const videoCover = await VideoThumbnails.getThumbnailAsync(uri);
return videoCover;
} catch (e) {
console.warn(e);
}
}, []);
//选择视频
const pickDisPlayVideo = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Videos,
quality: 1,
});
if (!result.canceled) {
for (let i = 0; i < result.assets.length; i++) {
if (result.assets[i].duration > 0) {
const videoCover = await generateThumbnail(result.assets[i].uri);
result.assets[i].cover = videoCover.uri;
}
}
setDisplayVideo(result.assets);
}
};
2024-04-18 22:58:59 +08:00
//保存新添加的相册图片
const [photos, setPhotos] = useState([]);
//展示旧相册图片组件
const [oldPhotos, setOldPhotos] = useState([]);
//正在加载数据
const [isLoading, setIsloading] = useState(true);
useEffect(() => {
const getData = async () => {
const account = await get("account");
const apiUrl = process.env.EXPO_PUBLIC_API_URL;
const base = await baseRequest();
const signature = await generateSignature({
mid: account?.mid,
...base,
});
try {
//获取主播数据
const streamerResponse = await fetch(
`${apiUrl}/api/streamer/list_by_mid?signature=${signature}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
mid: account?.mid,
...base,
}),
}
);
const streamerData = await streamerResponse.json();
if (streamerData.ret === -1) {
Toast.show({
type: "error",
text1: streamerData.msg,
topOffset: 60,
});
return;
}
setDisplayImage([
{
notChanged: true,
id: { image_ids: streamerData.data.streamer.cover.image_ids },
uri: streamerData.data.streamer.cover.images[0].urls[0],
},
]);
setDisplayVideo([
{
notChanged: true,
id: { video_ids: streamerData.data.streamer.shorts.video_ids },
2024-09-27 16:04:56 +08:00
cover:
2024-04-18 22:58:59 +08:00
streamerData?.data?.streamer?.shorts?.videos[0]?.cover_urls[0],
},
]);
setOldPhotos(streamerData.data.streamer.album.images);
setIsloading(false);
} catch (error) {
console.error(error);
}
};
getData();
}, []);
//正在提交状态
const [isSubmitting, setIsSubmitting] = useState(false);
//是否正在拖动图片用于禁用ScrollView的滚动
const [dragging, setDragging] = useState(false);
2024-04-18 22:58:59 +08:00
//loading时展示加载中
if (isLoading) {
return (
<ActivityIndicator style={tailwind("mt-32")} size="large" color="white" />
);
}
return (
<KeyboardAvoidingView
behavior={Platform.OS == "ios" ? "padding" : "height"}
keyboardVerticalOffset={insets.bottom + 60}
style={{
paddingLeft: insets.left,
paddingRight: insets.right,
...tailwind("flex-1"),
}}
>
<ScrollView scrollEnabled={!dragging} style={tailwind("px-4 py-4")}>
2024-04-18 22:58:59 +08:00
<Formik
initialValues={{}}
enableReinitialize
onSubmit={async () => {
//相册不得低于2张
if (oldPhotos.length + photos.length < 2) {
Toast.show({
type: "error",
text1: "相册至少需要上传2张照片哦",
topOffset: 60,
});
return;
}
//相册不得超过9张
if (oldPhotos.length + photos.length > 9) {
Toast.show({
type: "error",
text1: "相册最多只能上传9张照片哦",
topOffset: 60,
});
return;
}
setIsSubmitting(true);
const account = await get("account");
const cover = displayImage[0].notChanged
? displayImage[0].id
: await multiUpload(displayImage);
const shorts = displayVideo[0].notChanged
? displayVideo[0].id
: await multiUpload(displayVideo);
const newPhotosIds = await multiUpload(photos);
const oldPhotosIds = oldPhotos.map((item) => item.id);
const album = {
image_ids: [...oldPhotosIds, ...newPhotosIds?.image_ids],
};
if (
!cover.image_ids.length ||
!shorts.video_ids.length ||
!album.image_ids.length
) {
Toast.show({
type: "error",
text1: "上传失败,请联系客服进行上传",
topOffset: 60,
});
setIsSubmitting(false);
return;
}
//获取环境变量
const apiUrl = process.env.EXPO_PUBLIC_API_URL;
//上传表单
const base = await baseRequest();
const signature = await generateSignature({
mid: account?.mid,
cover: cover,
shorts: shorts,
album: album,
...base,
});
try {
const response = await fetch(
`${apiUrl}/api/streamer/update?signature=${signature}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
mid: account?.mid,
cover: cover,
shorts: shorts,
album: album,
...base,
}),
}
);
const streamerData = await response.json();
if (streamerData.ret === -1) {
Toast.show({
type: "error",
text1: streamerData.msg,
topOffset: 60,
});
return;
}
//提交成功后弹窗提示并返回上级
Toast.show({
type: "info",
text1: "提交成功,等耐心等待审核",
2024-04-18 22:58:59 +08:00
topOffset: 60,
});
navigation.goBack();
} catch (error) {
console.error(error);
} finally {
setIsSubmitting(false);
}
}}
>
{({ handleSubmit }) => (
<>
<Text style={tailwind("text-sm text-[#F53030] font-medium")}>
将展示在推荐主页空间请认真完善
</Text>
<View style={tailwind("my-2 bg-[#FFFFFF1A] p-2 rounded-2xl")}>
<View style={tailwind("flex-row justify-between items-center")}>
<Text style={tailwind("text-base text-white font-medium")}>
<Text style={tailwind("text-[#F53030]")}>*</Text>
封面图
</Text>
<TouchableOpacity
2024-09-27 16:04:56 +08:00
onPress={() => pickDisPlayImage()}
2024-04-18 22:58:59 +08:00
style={tailwind("flex-row items-center")}
>
{displayImage.length !== 0 ? (
<Image
style={tailwind("w-12 h-12 rounded-lg")}
source={displayImage[0].uri}
placeholder={blurhash}
contentFit="cover"
transition={1000}
cachePolicy="disk"
/>
) : (
<Text
style={tailwind("text-xs text-[#FFFFFF80] font-medium")}
>
请尽量选择横屏照片
</Text>
)}
<Icon
name="chevron-forward-outline"
type="ionicon"
color="white"
/>
</TouchableOpacity>
</View>
<Divider style={tailwind("my-2")} />
<View style={tailwind("flex-row justify-between items-center")}>
<Text style={tailwind("text-base text-white font-medium")}>
<Text style={tailwind("text-[#F53030]")}>*</Text>
展示视频
</Text>
<TouchableOpacity
2024-09-27 16:04:56 +08:00
onPress={() => pickDisPlayVideo()}
2024-04-18 22:58:59 +08:00
style={tailwind("flex-row items-center")}
>
{displayVideo.length !== 0 ? (
<Image
style={tailwind("w-12 h-16 rounded-lg")}
2024-09-27 16:04:56 +08:00
source={displayVideo[0].cover}
2024-04-18 22:58:59 +08:00
placeholder={blurhash}
contentFit="cover"
transition={1000}
cachePolicy="disk"
/>
) : (
<Text
style={tailwind("text-xs text-[#FFFFFF80] font-medium")}
>
请选择60秒内短视频
</Text>
)}
<Icon
name="chevron-forward-outline"
type="ionicon"
color="white"
/>
</TouchableOpacity>
</View>
<Divider style={tailwind("my-2")} />
<View>
<View
style={tailwind("flex-row justify-between items-center")}
>
<Text style={tailwind("text-base text-white font-medium")}>
<Text style={tailwind("text-[#F53030]")}>*</Text>
相册
</Text>
<Text
style={tailwind("text-xs text-[#FFFFFF80] font-medium")}
>
请上传29张照片
</Text>
</View>
<MediaGrid
setDragging={setDragging}
assets={oldPhotos}
setAssets={setOldPhotos}
/>
2024-04-18 22:58:59 +08:00
<MediaPicker
setDragging={setDragging}
2024-04-18 22:58:59 +08:00
maxCount={9}
type="image"
setAssets={setPhotos}
/>
</View>
</View>
<Button
color="#FF669E"
radius="999"
size="md"
disabled={isSubmitting}
disabledStyle={tailwind("bg-[#FFFFFF80]")}
disabledTitleStyle={tailwind("text-white")}
onPress={(e) => {
handleSubmit(e);
}}
titleStyle={tailwind("text-base")}
containerStyle={{
marginBottom: insets.bottom + 60,
...tailwind("mt-4"),
}}
>
{isSubmitting && (
<ActivityIndicator size="small" color="white" />
)}
{isSubmitting ? "正在提交..." : "确认修改"}
</Button>
</>
)}
</Formik>
</ScrollView>
</KeyboardAvoidingView>
);
}