xref: /MusicFree/src/components/base/listItem.tsx (revision b882a19d884fffa32f7c8cef31652b909dceaa0f)
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    onPress?: () => void;
92}
93
94export default function ListItem(props: IListItemProps) {
95    const {
96        title,
97        desc,
98        tag,
99        right,
100        itemHeight,
101        onPress,
102        left,
103        itemPaddingHorizontal = rpx(24),
104    } = props;
105    return (
106        <List.Item
107            left={() => <Left {...(left ?? {})} />}
108            style={[
109                style.wrapper,
110                {
111                    paddingHorizontal: itemPaddingHorizontal,
112                    height: itemHeight ?? rpx(120),
113                    paddingVertical: 0,
114                },
115            ]}
116            title={() => (
117                <View
118                    style={{
119                        alignItems: 'stretch',
120                        justifyContent: 'center',
121                        height: itemHeight ?? rpx(120),
122                        marginRight: right ? rpx(18) : 0,
123                    }}>
124                    <View style={style.titleWrapper}>
125                        <ThemeText numberOfLines={1} style={style.textWidth}>
126                            {title}
127                        </ThemeText>
128                        {tag ? <Tag tagName={tag} /> : <></>}
129                    </View>
130                    {desc ? (
131                        <ThemeText
132                            fontColor="secondary"
133                            fontSize="description"
134                            numberOfLines={1}
135                            style={[style.textWidth, {marginTop: rpx(18)}]}>
136                            {desc}
137                        </ThemeText>
138                    ) : (
139                        <></>
140                    )}
141                </View>
142            )}
143            titleStyle={{
144                paddingVertical: 0,
145                marginLeft: 0,
146                marginVertical: 0,
147            }}
148            right={right ? right : () => <></>}
149            onPress={onPress}
150        />
151    );
152}
153const style = StyleSheet.create({
154    wrapper: {
155        justifyContent: 'center',
156    },
157    titleWrapper: {
158        flexDirection: 'row',
159        alignItems: 'center',
160        justifyContent: 'space-between',
161    },
162    textWidth: {
163        maxWidth: rpx(460),
164    },
165    artworkWrapper: {
166        width: rpx(76),
167        justifyContent: 'center',
168        alignItems: 'center',
169        marginRight: rpx(12),
170    },
171    artwork: {
172        width: rpx(76),
173        height: rpx(76),
174        borderRadius: rpx(16),
175    },
176});
177