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