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