xref: /MusicFree/src/components/base/listItem.tsx (revision 6704747af84cebd842b258efac7143542722fac5)
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 Image from './image';
8import IconButton from './iconButton';
9import FastImage from './fastImage';
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></Component>
39    ) : (
40      <View style={[leftStyle.artworkWrapper, {width}]}>
41        {index !== undefined ? (
42          <ThemeText fontColor="secondary" style={{fontStyle: 'italic'}}>
43            {index}
44          </ThemeText>
45        ) : icon !== undefined ? (
46          <IconButton {...icon}></IconButton>
47        ) : (
48          <FastImage
49            style={leftStyle.artwork}
50            uri={artwork?.startsWith('//') ? `https:${artwork}` : artwork}
51            emptySrc={fallback}></FastImage>
52        )}
53      </View>
54    )
55  ) : (
56    <></>
57  );
58}
59
60const leftStyle = StyleSheet.create({
61  artworkWrapper: {
62    justifyContent: 'center',
63    alignItems: 'center',
64  },
65  artwork: {
66    width: rpx(76),
67    height: rpx(76),
68    borderRadius: rpx(16),
69  },
70});
71
72/** 歌单item */
73interface IListItemProps {
74  /** 标题 */
75  title: string | number;
76  /** 描述 */
77  desc?: string | JSX.Element;
78  /** 标签 */
79  tag?: string;
80  left?: ILeftProps;
81  /** 右侧按钮 */
82  right?: () => JSX.Element;
83  itemPaddingHorizontal?: number;
84  itemHeight?: number;
85  onPress?: () => void;
86}
87
88export default function ListItem(props: IListItemProps) {
89  const {
90    title,
91    desc,
92    tag,
93    right,
94    itemHeight,
95    onPress,
96    left,
97    itemPaddingHorizontal = rpx(24),
98  } = props;
99  return (
100    <List.Item
101      left={() => <Left {...(left ?? {})}></Left>}
102      style={[
103        style.wrapper,
104        {
105          paddingHorizontal: itemPaddingHorizontal,
106          height: itemHeight ?? rpx(120),
107          paddingVertical: 0,
108        },
109      ]}
110      title={() => (
111        <View
112          style={{
113            alignItems: 'stretch',
114            justifyContent: 'center',
115            height: itemHeight ?? rpx(120),
116            marginRight: right ? rpx(18) : 0,
117          }}>
118          <View style={style.titleWrapper}>
119            <ThemeText numberOfLines={1} style={style.textWidth}>
120              {title}
121            </ThemeText>
122            {tag ? <Tag tagName={tag}></Tag> : <></>}
123          </View>
124          {desc ? (
125            <ThemeText
126              fontColor="secondary"
127              fontSize="description"
128              numberOfLines={1}
129              style={[style.textWidth, {marginTop: rpx(18)}]}>
130              {desc}
131            </ThemeText>
132          ) : (
133            <></>
134          )}
135        </View>
136      )}
137      titleStyle={{
138        paddingVertical: 0,
139        marginLeft: 0,
140        marginVertical: 0,
141      }}
142      right={right ? right : () => <></>}
143      onPress={onPress}></List.Item>
144  );
145}
146const style = StyleSheet.create({
147  wrapper: {
148    justifyContent: 'center',
149  },
150  titleWrapper: {
151    flexDirection: 'row',
152    alignItems: 'center',
153    justifyContent: 'space-between',
154  },
155  textWidth: {
156    maxWidth: rpx(460),
157  },
158  artworkWrapper: {
159    width: rpx(76),
160    justifyContent: 'center',
161    alignItems: 'center',
162    marginRight: rpx(12),
163  },
164  artwork: {
165    width: rpx(76),
166    height: rpx(76),
167    borderRadius: rpx(16),
168  },
169});
170