1import React, { useMemo } from "react"; 2import { Image, Pressable, StyleSheet, View } from "react-native"; 3import rpx from "@/utils/rpx"; 4 5import Download from "@/core/download"; 6import LocalMusicSheet from "@/core/localMusicSheet"; 7import { ROUTE_PATH } from "@/core/router"; 8import { ImgAsset } from "@/constants/assetsConst"; 9import Toast from "@/utils/toast"; 10import toast from "@/utils/toast"; 11import useOrientation from "@/hooks/useOrientation"; 12import { showPanel } from "@/components/panels/usePanel"; 13import TrackPlayer from "@/core/trackPlayer"; 14import { iconSizeConst } from "@/constants/uiConst"; 15import PersistStatus from "@/core/persistStatus.ts"; 16import HeartIcon from "../heartIcon"; 17import Icon from "@/components/base/icon.tsx"; 18import PluginManager from "@/core/pluginManager.ts"; 19 20export default function Operations() { 21 //briefcase-download-outline briefcase-check-outline checkbox-marked-circle-outline 22 const musicItem = TrackPlayer.useCurrentMusic(); 23 const currentQuality = TrackPlayer.useCurrentQuality(); 24 const isDownloaded = LocalMusicSheet.useIsLocal(musicItem); 25 26 const rate = PersistStatus.useValue('music.rate', 100); 27 const orientation = useOrientation(); 28 29 const supportComment = useMemo(() => { 30 return !musicItem 31 ? false 32 : !!PluginManager.getByMedia(musicItem)?.instance?.getMusicComments; 33 }, [musicItem]); 34 35 return ( 36 <View 37 style={[ 38 styles.wrapper, 39 orientation === 'horizontal' ? styles.horizontalWrapper : null, 40 ]}> 41 <HeartIcon /> 42 <Pressable 43 onPress={() => { 44 if (!musicItem) { 45 return; 46 } 47 showPanel('MusicQuality', { 48 musicItem, 49 async onQualityPress(quality) { 50 const changeResult = 51 await TrackPlayer.changeQuality(quality); 52 if (!changeResult) { 53 Toast.warn('当前暂无此音质音乐'); 54 } 55 }, 56 }); 57 }}> 58 <Image 59 source={ImgAsset.quality[currentQuality]} 60 style={styles.quality} 61 /> 62 </Pressable> 63 <Icon 64 name={isDownloaded ? 'check-circle-outline' : 'arrow-down-tray'} 65 size={iconSizeConst.normal} 66 color="white" 67 onPress={() => { 68 if (musicItem && !isDownloaded) { 69 showPanel('MusicQuality', { 70 type: 'download', 71 musicItem, 72 async onQualityPress(quality) { 73 Download.downloadMusic(musicItem, quality); 74 }, 75 }); 76 } 77 }} 78 /> 79 <Pressable 80 onPress={() => { 81 if (!musicItem) { 82 return; 83 } 84 showPanel('PlayRate', { 85 async onRatePress(newRate) { 86 if (rate !== newRate) { 87 try { 88 await TrackPlayer.setRate(newRate / 100); 89 PersistStatus.set('music.rate', newRate); 90 } catch {} 91 } 92 }, 93 }); 94 }}> 95 <Image source={ImgAsset.rate[rate!]} style={styles.quality} /> 96 </Pressable> 97 <Icon 98 name="chat-bubble-oval-left-ellipsis" 99 size={iconSizeConst.normal} 100 color="white" 101 opacity={supportComment ? 1 : 0.2} 102 onPress={() => { 103 if (!supportComment) { 104 toast.warn('当前歌曲暂无评论'); 105 return; 106 } 107 if (musicItem) { 108 showPanel('MusicComment', { 109 musicItem, 110 }); 111 } 112 }} 113 /> 114 <Icon 115 name="ellipsis-vertical" 116 size={iconSizeConst.normal} 117 color="white" 118 onPress={() => { 119 if (musicItem) { 120 showPanel('MusicItemOptions', { 121 musicItem: musicItem, 122 from: ROUTE_PATH.MUSIC_DETAIL, 123 }); 124 } 125 }} 126 /> 127 </View> 128 ); 129} 130 131const styles = StyleSheet.create({ 132 wrapper: { 133 width: '100%', 134 height: rpx(80), 135 marginBottom: rpx(24), 136 flexDirection: 'row', 137 alignItems: 'center', 138 justifyContent: 'space-around', 139 }, 140 horizontalWrapper: { 141 marginBottom: 0, 142 }, 143 quality: { 144 width: rpx(52), 145 height: rpx(52), 146 }, 147}); 148