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