1import React, {useState} from 'react'; 2import {Pressable, StyleSheet, View} from 'react-native'; 3import rpx from '@/utils/rpx'; 4import LinearGradient from 'react-native-linear-gradient'; 5import {Divider, IconButton, useTheme} from 'react-native-paper'; 6import MusicQueue from '@/core/musicQueue'; 7import Icon from 'react-native-vector-icons/MaterialCommunityIcons'; 8import usePanel from '@/components/panels/usePanel'; 9import {iconSizeConst} from '@/constants/uiConst'; 10import Color from 'color'; 11import ThemeText from '@/components/base/themeText'; 12import {ImgAsset} from '@/constants/assetsConst'; 13import FastImage from '@/components/base/fastImage'; 14import {ROUTE_PATH, useNavigate} from '@/entry/router'; 15 16interface IHeaderProps { 17 topListDetail: IMusic.IMusicTopListItem | null; 18 19 musicList: IMusic.IMusicItem[] | null; 20} 21export default function Header(props: IHeaderProps) { 22 const {topListDetail, musicList} = props; 23 const {showPanel} = usePanel(); 24 const {colors} = useTheme(); 25 26 const [maxLines, setMaxLines] = useState<number | undefined>(6); 27 28 const toggleShowMore = () => { 29 if (maxLines) { 30 setMaxLines(undefined); 31 } else { 32 setMaxLines(6); 33 } 34 }; 35 36 const navigate = useNavigate(); 37 38 return ( 39 <> 40 <LinearGradient 41 colors={[ 42 Color(colors.primary).alpha(0.8).toString(), 43 Color(colors.primary).alpha(0.15).toString(), 44 ]} 45 style={style.wrapper}> 46 <View style={style.content}> 47 <FastImage 48 style={style.coverImg} 49 uri={topListDetail?.artwork ?? topListDetail?.coverImg} 50 emptySrc={ImgAsset.albumDefault} 51 /> 52 <View style={style.details}> 53 <ThemeText>{topListDetail?.title}</ThemeText> 54 <ThemeText fontColor="secondary" fontSize="description"> 55 共{musicList ? musicList.length ?? 0 : '-'}首{' '} 56 </ThemeText> 57 </View> 58 </View> 59 <Divider style={style.divider} /> 60 {topListDetail?.description ? ( 61 <Pressable onPress={toggleShowMore}> 62 <View 63 style={style.albumDesc} 64 onLayout={evt => { 65 console.log(evt.nativeEvent.layout); 66 }}> 67 <ThemeText 68 fontColor="secondary" 69 fontSize="description" 70 numberOfLines={maxLines}> 71 {topListDetail.description} 72 </ThemeText> 73 </View> 74 </Pressable> 75 ) : null} 76 </LinearGradient> 77 <View 78 style={[ 79 style.topWrapper, 80 { 81 backgroundColor: Color(colors.primary) 82 .alpha(0.15) 83 .toString(), 84 }, 85 ]}> 86 <Pressable 87 style={style.playAll} 88 onPress={() => { 89 if (musicList) { 90 MusicQueue.playWithReplaceQueue( 91 musicList[0], 92 musicList, 93 ); 94 } 95 }}> 96 <Icon 97 name="play-circle-outline" 98 style={style.playAllIcon} 99 size={iconSizeConst.normal} 100 color={colors.text} 101 /> 102 <ThemeText fontWeight="bold">播放全部</ThemeText> 103 </Pressable> 104 <IconButton 105 icon={'plus-box-multiple-outline'} 106 size={rpx(48)} 107 onPress={async () => { 108 showPanel('AddToMusicSheet', { 109 musicItem: musicList ?? [], 110 }); 111 }} 112 /> 113 <IconButton 114 icon="playlist-edit" 115 size={rpx(48)} 116 onPress={async () => { 117 navigate(ROUTE_PATH.MUSIC_LIST_EDITOR, { 118 musicList: musicList, 119 musicSheet: { 120 title: topListDetail?.title, 121 }, 122 }); 123 }} 124 /> 125 </View> 126 </> 127 ); 128} 129 130const style = StyleSheet.create({ 131 wrapper: { 132 width: rpx(750), 133 paddingVertical: rpx(24), 134 justifyContent: 'center', 135 alignItems: 'center', 136 }, 137 content: { 138 width: rpx(702), 139 flexDirection: 'row', 140 justifyContent: 'space-between', 141 alignItems: 'center', 142 }, 143 coverImg: { 144 width: rpx(210), 145 height: rpx(210), 146 borderRadius: rpx(24), 147 }, 148 details: { 149 width: rpx(456), 150 height: rpx(140), 151 justifyContent: 'space-between', 152 }, 153 divider: { 154 marginVertical: rpx(18), 155 }, 156 157 albumDesc: { 158 width: rpx(702), 159 }, 160 /** playall */ 161 topWrapper: { 162 height: rpx(72), 163 paddingHorizontal: rpx(24), 164 flexDirection: 'row', 165 alignItems: 'center', 166 }, 167 playAll: { 168 flex: 1, 169 flexDirection: 'row', 170 alignItems: 'center', 171 }, 172 playAllIcon: { 173 marginRight: rpx(12), 174 }, 175}); 176