1import React, {useMemo, useState} from 'react'; 2import {StyleSheet, View} from 'react-native'; 3import rpx from '@/utils/rpx'; 4import ThemeText from '@/components/base/themeText'; 5import useColors from '@/hooks/useColors'; 6import {TouchableWithoutFeedback} from 'react-native-gesture-handler'; 7import MusicSheet from '@/core/musicSheet'; 8import {FlashList} from '@shopify/flash-list'; 9import ListItem from '@/components/base/listItem'; 10import {ROUTE_PATH, useNavigate} from '@/entry/router'; 11import {ImgAsset} from '@/constants/assetsConst'; 12import {showDialog} from '@/components/dialogs/useDialog'; 13import Toast from '@/utils/toast'; 14import Empty from '@/components/base/empty'; 15import IconButton from '@/components/base/iconButton'; 16import {showPanel} from '@/components/panels/usePanel'; 17import {localPluginPlatform} from '@/constants/commonConst'; 18 19export default function Sheets() { 20 const [index, setIndex] = useState(0); 21 const colors = useColors(); 22 const navigate = useNavigate(); 23 24 const allSheets = MusicSheet.useSheets(); 25 const staredSheets = MusicSheet.useStarredMusicSheet(); 26 27 const selectedTabTextStyle = useMemo(() => { 28 return [ 29 styles.selectTabText, 30 { 31 borderBottomColor: colors.primary, 32 }, 33 ]; 34 }, [colors]); 35 36 return ( 37 <> 38 <View style={styles.subTitleContainer}> 39 <TouchableWithoutFeedback 40 style={styles.tabContainer} 41 accessible 42 accessibilityLabel={`我的歌单,共${allSheets.length}个`} 43 onPress={() => { 44 setIndex(0); 45 }}> 46 <ThemeText 47 accessible={false} 48 fontSize="title" 49 style={[ 50 styles.tabText, 51 index === 0 ? selectedTabTextStyle : null, 52 ]}> 53 我的歌单 54 </ThemeText> 55 <ThemeText 56 accessible={false} 57 fontColor="textSecondary" 58 fontSize="subTitle" 59 style={styles.tabText}> 60 {' '} 61 ({allSheets.length}) 62 </ThemeText> 63 </TouchableWithoutFeedback> 64 <TouchableWithoutFeedback 65 style={styles.tabContainer} 66 accessible 67 accessibilityLabel={`收藏歌单,共${staredSheets.length}个`} 68 onPress={() => { 69 setIndex(1); 70 }}> 71 <ThemeText 72 fontSize="title" 73 accessible={false} 74 style={[ 75 styles.tabText, 76 index === 1 ? selectedTabTextStyle : null, 77 ]}> 78 收藏歌单 79 </ThemeText> 80 <ThemeText 81 fontColor="textSecondary" 82 fontSize="subTitle" 83 accessible={false} 84 style={styles.tabText}> 85 {' '} 86 ({staredSheets.length}) 87 </ThemeText> 88 </TouchableWithoutFeedback> 89 <View style={styles.more}> 90 <IconButton 91 name="plus" 92 style={styles.newSheetButton} 93 sizeType="normal" 94 accessibilityLabel="新建歌单" 95 onPress={() => { 96 showPanel('NewMusicSheet'); 97 }} 98 /> 99 <IconButton 100 name="import" 101 sizeType="normal" 102 accessibilityLabel="导入歌单" 103 onPress={() => { 104 showPanel('ImportMusicSheet'); 105 }} 106 /> 107 </View> 108 </View> 109 <FlashList 110 ListEmptyComponent={<Empty />} 111 data={(index === 0 ? allSheets : staredSheets) ?? []} 112 estimatedItemSize={ListItem.Size.big} 113 renderItem={({item: sheet}) => { 114 const isLocalSheet = !( 115 sheet.platform && sheet.platform !== localPluginPlatform 116 ); 117 118 return ( 119 <ListItem 120 key={`${sheet.id}`} 121 heightType="big" 122 withHorizonalPadding 123 onPress={() => { 124 if (isLocalSheet) { 125 navigate(ROUTE_PATH.LOCAL_SHEET_DETAIL, { 126 id: sheet.id, 127 }); 128 } else { 129 navigate(ROUTE_PATH.PLUGIN_SHEET_DETAIL, { 130 sheetInfo: sheet, 131 }); 132 } 133 }}> 134 <ListItem.ListItemImage 135 uri={sheet.coverImg ?? sheet.artwork} 136 fallbackImg={ImgAsset.albumDefault} 137 maskIcon={ 138 sheet.id === MusicSheet.defaultSheet.id 139 ? 'heart' 140 : null 141 } 142 /> 143 <ListItem.Content 144 title={sheet.title} 145 description={ 146 isLocalSheet 147 ? `${sheet.musicList?.length ?? '-'}首` 148 : `${sheet.artist}` 149 } 150 /> 151 {sheet.id !== MusicSheet.defaultSheet.id ? ( 152 <ListItem.ListItemIcon 153 position="right" 154 icon="trash-can-outline" 155 onPress={() => { 156 showDialog('SimpleDialog', { 157 title: '删除歌单', 158 content: `确定删除歌单「${sheet.title}」吗?`, 159 onOk: async () => { 160 if (isLocalSheet) { 161 await MusicSheet.removeSheet( 162 sheet.id, 163 ); 164 Toast.success('已删除'); 165 } else { 166 await MusicSheet.unstarMusicSheet( 167 sheet, 168 ); 169 Toast.success('已取消收藏'); 170 } 171 }, 172 }); 173 }} 174 /> 175 ) : null} 176 </ListItem> 177 ); 178 }} 179 nestedScrollEnabled 180 /> 181 </> 182 ); 183} 184 185const styles = StyleSheet.create({ 186 subTitleContainer: { 187 paddingHorizontal: rpx(24), 188 flexDirection: 'row', 189 alignItems: 'flex-start', 190 marginBottom: rpx(12), 191 }, 192 subTitleLeft: { 193 flexDirection: 'row', 194 }, 195 tabContainer: { 196 flexDirection: 'row', 197 marginRight: rpx(32), 198 }, 199 200 tabText: { 201 lineHeight: rpx(64), 202 }, 203 selectTabText: { 204 borderBottomWidth: rpx(6), 205 fontWeight: 'bold', 206 }, 207 more: { 208 height: rpx(64), 209 marginTop: rpx(3), 210 flexGrow: 1, 211 flexDirection: 'row', 212 justifyContent: 'flex-end', 213 }, 214 newSheetButton: { 215 marginRight: rpx(24), 216 }, 217}); 218