1import React, { useState } from "react"; 2import { StyleSheet, TouchableOpacity, View } from "react-native"; 3import rpx from "@/utils/rpx"; 4import PanelFullscreen from "@/components/panels/base/panelFullscreen.tsx"; 5import { hidePanel } from "@/components/panels/usePanel.ts"; 6import ThemeText from "@/components/base/themeText.tsx"; 7import Toast from "@/utils/toast.ts"; 8import useColors from "@/hooks/useColors.ts"; 9import MusicSheet from "@/core/musicSheet"; 10import Input from "@/components/base/input.tsx"; 11import { fontSizeConst } from "@/constants/uiConst.ts"; 12import AppBar from "@/components/base/appBar.tsx"; 13import globalStyle from "@/constants/globalStyle.ts"; 14import VerticalSafeAreaView from "@/components/base/verticalSafeAreaView.tsx"; 15import Image from "@/components/base/image.tsx"; 16import { ImgAsset } from "@/constants/assetsConst.ts"; 17import { launchImageLibrary } from "react-native-image-picker"; 18import { addFileScheme, addRandomHash } from "@/utils/fileUtils.ts"; 19import pathConst from "@/constants/pathConst.ts"; 20import { readAsStringAsync } from "expo-file-system"; 21import { exists, unlink, writeFile } from "react-native-fs"; 22 23interface IEditSheetDetailProps { 24 musicSheet: IMusic.IMusicSheetItem; 25} 26 27export default function EditMusicSheetInfo(props: IEditSheetDetailProps) { 28 const { musicSheet } = props; 29 const colors = useColors(); 30 31 const [coverImg, setCoverImg] = useState(musicSheet?.coverImg); 32 const [title, setTitle] = useState(musicSheet?.title); 33 34 const onChangeCoverPress = async () => { 35 try { 36 const result = await launchImageLibrary({ 37 mediaType: 'photo', 38 }); 39 const uri = result.assets?.[0].uri; 40 if (!uri) { 41 return; 42 } 43 console.log(uri); 44 setCoverImg(uri); 45 } catch (e) { 46 console.log(e); 47 } 48 }; 49 50 function onTitleChange(_: string) { 51 setTitle(_); 52 } 53 54 async function onConfirm() { 55 // 判断是否相同 56 if ( 57 coverImg === musicSheet?.coverImg && 58 title === musicSheet?.title 59 ) { 60 hidePanel(); 61 return; 62 } 63 64 let newCoverImg = coverImg; 65 if (coverImg && coverImg !== musicSheet?.coverImg) { 66 newCoverImg = addFileScheme( 67 `${pathConst.dataPath}sheet${musicSheet.id}${coverImg.substring( 68 coverImg.lastIndexOf('.'), 69 )}`, 70 ); 71 try { 72 if ((await exists(newCoverImg))) { 73 await unlink(newCoverImg); 74 } 75 76 // Copy 77 const rawImage = await readAsStringAsync(coverImg, { 78 encoding: 'base64' 79 }); 80 await writeFile(newCoverImg, rawImage, 'base64'); 81 } catch (e) { 82 console.log(e); 83 } 84 } 85 let _title = title; 86 if (!_title?.length) { 87 _title = musicSheet.title; 88 } 89 // 更新歌单信息 90 MusicSheet.updateMusicSheetBase(musicSheet.id, { 91 coverImg: newCoverImg ? addRandomHash(newCoverImg) : undefined, 92 title: _title 93 }).then(() => { 94 Toast.success("更新歌单信息成功~"); 95 }); 96 hidePanel(); 97 } 98 99 return ( 100 <PanelFullscreen> 101 <VerticalSafeAreaView style={globalStyle.fwflex1}> 102 <AppBar onBackPress={hidePanel} withStatusBar> 103 编辑歌单信息 104 </AppBar> 105 <View style={style.row}> 106 <ThemeText>封面</ThemeText> 107 <TouchableOpacity 108 onPress={onChangeCoverPress} 109 onLongPress={() => { 110 setCoverImg(undefined); 111 }}> 112 <Image 113 style={style.coverImg} 114 uri={coverImg} 115 emptySrc={ImgAsset.albumDefault} 116 /> 117 </TouchableOpacity> 118 </View> 119 <View style={style.row}> 120 <ThemeText>歌单名</ThemeText> 121 <Input 122 numberOfLines={1} 123 textAlign="right" 124 value={title} 125 hasHorizontalPadding={false} 126 onChangeText={onTitleChange} 127 style={{ 128 height: fontSizeConst.content * 2.5, 129 width: "50%", 130 borderBottomWidth: 1, 131 includeFontPadding: false, 132 borderBottomColor: colors.text 133 }} 134 /> 135 </View> 136 <TouchableOpacity 137 activeOpacity={0.6} 138 onPress={onConfirm} 139 style={[ 140 { 141 backgroundColor: colors.primary 142 }, 143 style.button 144 ]}> 145 <ThemeText color={"white"}>确认</ThemeText> 146 </TouchableOpacity> 147 </VerticalSafeAreaView> 148 </PanelFullscreen> 149 ); 150} 151 152const style = StyleSheet.create({ 153 row: { 154 marginTop: rpx(28), 155 height: rpx(120), 156 flexDirection: "row", 157 justifyContent: "space-between", 158 alignItems: "center", 159 paddingBottom: rpx(12), 160 paddingHorizontal: rpx(24) 161 }, 162 coverImg: { 163 width: rpx(100), 164 height: rpx(100), 165 borderRadius: rpx(28) 166 }, 167 button: { 168 marginHorizontal: rpx(24), 169 borderRadius: rpx(8), 170 height: rpx(72), 171 marginTop: rpx(24), 172 justifyContent: "center", 173 alignItems: "center" 174 } 175}); 176