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 onPress={() => { 42 setIndex(0); 43 }}> 44 <ThemeText 45 fontSize="title" 46 style={[ 47 styles.tabText, 48 index === 0 ? selectedTabTextStyle : null, 49 ]}> 50 我的歌单 51 </ThemeText> 52 <ThemeText 53 fontColor="textSecondary" 54 fontSize="subTitle" 55 style={styles.tabText}> 56 {' '} 57 ({allSheets.length}) 58 </ThemeText> 59 </TouchableWithoutFeedback> 60 <TouchableWithoutFeedback 61 style={styles.tabContainer} 62 onPress={() => { 63 setIndex(1); 64 }}> 65 <ThemeText 66 fontSize="title" 67 style={[ 68 styles.tabText, 69 index === 1 ? selectedTabTextStyle : null, 70 ]}> 71 收藏歌单 72 </ThemeText> 73 <ThemeText 74 fontColor="textSecondary" 75 fontSize="subTitle" 76 style={styles.tabText}> 77 {' '} 78 ({staredSheets.length}) 79 </ThemeText> 80 </TouchableWithoutFeedback> 81 <View style={styles.more}> 82 <IconButton 83 name="plus" 84 sizeType="normal" 85 accessibilityLabel="新建歌单" 86 onPress={() => { 87 showPanel('NewMusicSheet'); 88 }} 89 /> 90 </View> 91 </View> 92 <FlashList 93 ListEmptyComponent={<Empty />} 94 data={(index === 0 ? allSheets : staredSheets) ?? []} 95 estimatedItemSize={ListItem.Size.big} 96 renderItem={({item: sheet}) => { 97 const isLocalSheet = !( 98 sheet.platform && sheet.platform !== localPluginPlatform 99 ); 100 101 return ( 102 <ListItem 103 key={`${sheet.id}`} 104 heightType="big" 105 withHorizonalPadding 106 onPress={() => { 107 if (isLocalSheet) { 108 navigate(ROUTE_PATH.LOCAL_SHEET_DETAIL, { 109 id: sheet.id, 110 }); 111 } else { 112 navigate(ROUTE_PATH.PLUGIN_SHEET_DETAIL, { 113 sheetInfo: sheet, 114 }); 115 } 116 }}> 117 <ListItem.ListItemImage 118 uri={sheet.coverImg ?? sheet.artwork} 119 fallbackImg={ImgAsset.albumDefault} 120 maskIcon={ 121 sheet.id === MusicSheet.defaultSheet.id 122 ? 'heart' 123 : null 124 } 125 /> 126 <ListItem.Content 127 title={sheet.title} 128 description={ 129 isLocalSheet 130 ? `${sheet.musicList?.length ?? '-'}首` 131 : `${sheet.artist}` 132 } 133 /> 134 <ListItem.ListItemIcon 135 position="right" 136 icon="trash-can-outline" 137 onPress={() => { 138 showDialog('SimpleDialog', { 139 title: '删除歌单', 140 content: `确定删除歌单「${sheet.title}」吗?`, 141 onOk: async () => { 142 if (isLocalSheet) { 143 await MusicSheet.removeSheet( 144 sheet.id, 145 ); 146 Toast.success('已删除'); 147 } else { 148 await MusicSheet.unstarMusicSheet( 149 sheet, 150 ); 151 Toast.success('已取消收藏'); 152 } 153 }, 154 }); 155 }} 156 /> 157 </ListItem> 158 ); 159 }} 160 nestedScrollEnabled 161 /> 162 </> 163 ); 164} 165 166const styles = StyleSheet.create({ 167 subTitleContainer: { 168 paddingHorizontal: rpx(24), 169 flexDirection: 'row', 170 alignItems: 'flex-start', 171 marginBottom: rpx(12), 172 }, 173 subTitleLeft: { 174 flexDirection: 'row', 175 }, 176 tabContainer: { 177 flexDirection: 'row', 178 marginRight: rpx(32), 179 }, 180 181 tabText: { 182 lineHeight: rpx(64), 183 }, 184 selectTabText: { 185 borderBottomWidth: rpx(6), 186 fontWeight: 'bold', 187 }, 188 more: { 189 height: rpx(64), 190 marginTop: rpx(3), 191 flexGrow: 1, 192 flexDirection: 'row', 193 justifyContent: 'flex-end', 194 }, 195}); 196