xref: /MusicFree/src/components/base/listItem.tsx (revision 17c7a0a6c88f237337df25e2f48d3610e0b8d9bd)
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