1import React from 'react'; 2import {StyleSheet, View} from 'react-native'; 3import rpx from '@/utils/rpx'; 4import {List} from 'react-native-paper'; 5import Tag from './tag'; 6import ThemeText from './themeText'; 7import IconButton from './iconButton'; 8import FastImage from './fastImage'; 9 10export interface ILeftProps { 11 /** 序号 */ 12 index?: number | string; 13 /** 封面图 */ 14 artwork?: string; 15 /** 封面图的兜底 */ 16 fallback?: any; 17 /** icon */ 18 icon?: Parameters<typeof IconButton>[0]; 19 /** 宽度 */ 20 width?: number; 21 /** 组件 */ 22 component?: () => JSX.Element; 23} 24 25function Left(props?: ILeftProps) { 26 const { 27 index, 28 artwork, 29 fallback, 30 icon, 31 width = rpx(100), 32 component: Component, 33 } = props ?? {}; 34 35 return props && Object.keys(props).length ? ( 36 Component ? ( 37 <Component /> 38 ) : ( 39 <View style={[leftStyle.artworkWrapper, {width}]}> 40 {index !== undefined ? ( 41 <ThemeText 42 fontColor="secondary" 43 style={{fontStyle: 'italic'}}> 44 {index} 45 </ThemeText> 46 ) : icon !== undefined ? ( 47 <IconButton {...icon} /> 48 ) : ( 49 <FastImage 50 style={leftStyle.artwork} 51 uri={ 52 artwork?.startsWith('//') 53 ? `https:${artwork}` 54 : artwork 55 } 56 emptySrc={fallback} 57 /> 58 )} 59 </View> 60 ) 61 ) : ( 62 <></> 63 ); 64} 65 66const leftStyle = StyleSheet.create({ 67 artworkWrapper: { 68 justifyContent: 'center', 69 alignItems: 'center', 70 }, 71 artwork: { 72 width: rpx(76), 73 height: rpx(76), 74 borderRadius: rpx(16), 75 }, 76}); 77 78/** 歌单item */ 79interface IListItemProps { 80 /** 标题 */ 81 title: string | number; 82 /** 描述 */ 83 desc?: string | JSX.Element; 84 /** 标签 */ 85 tag?: string; 86 left?: ILeftProps; 87 /** 右侧按钮 */ 88 right?: () => JSX.Element; 89 itemPaddingHorizontal?: number; 90 itemHeight?: number; 91 itemBackgroundColor?: string; 92 onPress?: () => void; 93 onLongPress?: () => void; 94} 95 96export default function ListItem(props: IListItemProps) { 97 const { 98 title, 99 desc, 100 tag, 101 right, 102 itemHeight, 103 onPress, 104 onLongPress, 105 left, 106 itemBackgroundColor, 107 itemPaddingHorizontal = rpx(24), 108 } = props; 109 return ( 110 <List.Item 111 onLongPress={onLongPress} 112 left={() => <Left {...(left ?? {})} />} 113 style={[ 114 style.wrapper, 115 { 116 paddingHorizontal: itemPaddingHorizontal, 117 height: itemHeight ?? rpx(120), 118 paddingVertical: 0, 119 backgroundColor: itemBackgroundColor, 120 }, 121 ]} 122 title={() => ( 123 <View 124 style={{ 125 alignItems: 'stretch', 126 justifyContent: 'center', 127 height: itemHeight ?? rpx(120), 128 marginRight: right ? rpx(18) : 0, 129 }}> 130 <View style={style.titleWrapper}> 131 <ThemeText numberOfLines={1} style={style.textWidth}> 132 {title} 133 </ThemeText> 134 {tag ? <Tag tagName={tag} /> : <></>} 135 </View> 136 {desc ? ( 137 <ThemeText 138 fontColor="secondary" 139 fontSize="description" 140 numberOfLines={1} 141 style={[style.textWidth, {marginTop: rpx(18)}]}> 142 {desc} 143 </ThemeText> 144 ) : ( 145 <></> 146 )} 147 </View> 148 )} 149 titleStyle={{ 150 paddingVertical: 0, 151 marginLeft: 0, 152 marginVertical: 0, 153 }} 154 right={right ? right : () => <></>} 155 onPress={onPress} 156 /> 157 ); 158} 159const style = StyleSheet.create({ 160 wrapper: { 161 justifyContent: 'center', 162 }, 163 titleWrapper: { 164 flexDirection: 'row', 165 alignItems: 'center', 166 justifyContent: 'space-between', 167 }, 168 textWidth: { 169 maxWidth: rpx(460), 170 }, 171 artworkWrapper: { 172 width: rpx(76), 173 justifyContent: 'center', 174 alignItems: 'center', 175 marginRight: rpx(12), 176 }, 177 artwork: { 178 width: rpx(76), 179 height: rpx(76), 180 borderRadius: rpx(16), 181 }, 182}); 183