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.useUserSheets(); 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 /> 121 <ListItem.Content 122 title={sheet.title} 123 description={ 124 isLocalSheet 125 ? `${sheet.musicList?.length ?? '-'}首` 126 : `${sheet.artist}` 127 } 128 /> 129 <ListItem.ListItemIcon 130 position="right" 131 icon="trash-can-outline" 132 onPress={() => { 133 showDialog('SimpleDialog', { 134 title: '删除歌单', 135 content: `确定删除歌单「${sheet.title}」吗?`, 136 onOk: async () => { 137 if (isLocalSheet) { 138 await MusicSheet.removeSheet( 139 sheet.id, 140 ); 141 Toast.success('已删除'); 142 } else { 143 await MusicSheet.unstarMusicSheet( 144 sheet, 145 ); 146 Toast.success('已取消收藏'); 147 } 148 }, 149 }); 150 }} 151 /> 152 </ListItem> 153 ); 154 }} 155 nestedScrollEnabled 156 /> 157 </> 158 ); 159} 160 161const styles = StyleSheet.create({ 162 subTitleContainer: { 163 paddingHorizontal: rpx(24), 164 flexDirection: 'row', 165 alignItems: 'flex-start', 166 marginBottom: rpx(12), 167 }, 168 subTitleLeft: { 169 flexDirection: 'row', 170 }, 171 tabContainer: { 172 flexDirection: 'row', 173 marginRight: rpx(32), 174 }, 175 176 tabText: { 177 lineHeight: rpx(64), 178 }, 179 selectTabText: { 180 borderBottomWidth: rpx(6), 181 fontWeight: 'bold', 182 }, 183 more: { 184 height: rpx(64), 185 marginTop: rpx(3), 186 flexGrow: 1, 187 flexDirection: 'row', 188 justifyContent: 'flex-end', 189 }, 190}); 191