tiefen_space_app/screeens/EditStreamerMedia/index.jsx

394 lines
13 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,
ScrollView,
TouchableOpacity,
KeyboardAvoidingView,
Platform,
ActivityIndicator,
} from "react-native";
import React, { useState, useEffect, useCallback } from "react";
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";
import * as ImagePicker from "expo-image-picker";
import * as VideoThumbnails from "expo-video-thumbnails";
const blurhash = "LcKUTa%gOYWBYRt6xuoJo~s8V@fk";
export default function EditStreamerMedia({ navigation, route }) {
const tailwind = useTailwind();
const insets = useSafeAreaInsets();
//保存封面图
const [displayImage, setDisplayImage] = useState([]);
//选择封面图
const pickDisPlayImage = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
quality: 1,
});
if (!result.canceled) {
setDisplayImage(result.assets);
}
};
//保存展示视频
const [displayVideo, setDisplayVideo] = useState([]);
//为视频生成封面
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);
}
};
//保存新添加的相册图片
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 },
cover:
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);
//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")}>
<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: "提交成功,等耐心等待审核",
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
onPress={() => pickDisPlayImage()}
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
onPress={() => pickDisPlayVideo()}
style={tailwind("flex-row items-center")}
>
{displayVideo.length !== 0 ? (
<Image
style={tailwind("w-12 h-16 rounded-lg")}
source={displayVideo[0].cover}
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}
/>
<MediaPicker
setDragging={setDragging}
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>
);
}