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