xref: /MusicFree/src/components/base/listItem.tsx (revision 7aed04d4f1a71bc87732a88b0583e6ae702976b2)
11119c2eaS猫头猫import React, {ReactNode} from 'react';
21119c2eaS猫头猫import {
31119c2eaS猫头猫    StyleProp,
41119c2eaS猫头猫    StyleSheet,
51119c2eaS猫头猫    TextProps,
61119c2eaS猫头猫    TextStyle,
71119c2eaS猫头猫    TouchableHighlight,
81119c2eaS猫头猫    TouchableOpacity,
91119c2eaS猫头猫    View,
101119c2eaS猫头猫    ViewStyle,
111119c2eaS猫头猫} from 'react-native';
1219dc08ecS猫头猫import rpx from '@/utils/rpx';
131119c2eaS猫头猫import useColors from '@/hooks/useColors';
141119c2eaS猫头猫import ThemeText from './themeText';
151119c2eaS猫头猫import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
161119c2eaS猫头猫import {
171119c2eaS猫头猫    fontSizeConst,
181119c2eaS猫头猫    fontWeightConst,
191119c2eaS猫头猫    iconSizeConst,
201119c2eaS猫头猫} from '@/constants/uiConst';
211119c2eaS猫头猫import FastImage from './fastImage';
221119c2eaS猫头猫import {ImageStyle} from 'react-native-fast-image';
2319dc08ecS猫头猫
241119c2eaS猫头猫interface IListItemProps {
251119c2eaS猫头猫    // 是否有左右边距
261119c2eaS猫头猫    withHorizonalPadding?: boolean;
271119c2eaS猫头猫    // 左边距
281119c2eaS猫头猫    leftPadding?: number;
291119c2eaS猫头猫    // 右边距
301119c2eaS猫头猫    rightPadding?: number;
311119c2eaS猫头猫    // height:
321119c2eaS猫头猫    style?: StyleProp<ViewStyle>;
331119c2eaS猫头猫    // 高度类型
34e01046d9S猫头猫    heightType?: 'big' | 'small' | 'smallest' | 'normal' | 'none';
351119c2eaS猫头猫    children?: ReactNode;
361119c2eaS猫头猫    onPress?: () => void;
371119c2eaS猫头猫    onLongPress?: () => void;
381119c2eaS猫头猫}
391119c2eaS猫头猫
401119c2eaS猫头猫const defaultPadding = rpx(24);
411119c2eaS猫头猫const defaultActionWidth = rpx(80);
421119c2eaS猫头猫
431119c2eaS猫头猫const Size = {
441119c2eaS猫头猫    big: rpx(120),
451119c2eaS猫头猫    normal: rpx(108),
461119c2eaS猫头猫    small: rpx(96),
47e01046d9S猫头猫    smallest: rpx(72),
481119c2eaS猫头猫    none: undefined,
491119c2eaS猫头猫};
501119c2eaS猫头猫
511119c2eaS猫头猫function ListItem(props: IListItemProps) {
521119c2eaS猫头猫    const {
531119c2eaS猫头猫        withHorizonalPadding,
541119c2eaS猫头猫        leftPadding = defaultPadding,
551119c2eaS猫头猫        rightPadding = defaultPadding,
561119c2eaS猫头猫        style,
571119c2eaS猫头猫        heightType = 'normal',
581119c2eaS猫头猫        children,
591119c2eaS猫头猫        onPress,
601119c2eaS猫头猫        onLongPress,
611119c2eaS猫头猫    } = props;
621119c2eaS猫头猫
631119c2eaS猫头猫    const defaultStyle: StyleProp<ViewStyle> = {
641119c2eaS猫头猫        paddingLeft: withHorizonalPadding ? leftPadding : 0,
651119c2eaS猫头猫        paddingRight: withHorizonalPadding ? rightPadding : 0,
661119c2eaS猫头猫        height: Size[heightType],
671119c2eaS猫头猫    };
681119c2eaS猫头猫
691119c2eaS猫头猫    const colors = useColors();
701119c2eaS猫头猫
711119c2eaS猫头猫    return (
721119c2eaS猫头猫        <TouchableHighlight
731119c2eaS猫头猫            style={styles.container}
741119c2eaS猫头猫            underlayColor={colors.listActive}
751119c2eaS猫头猫            onPress={onPress}
761119c2eaS猫头猫            onLongPress={onLongPress}>
771119c2eaS猫头猫            <View style={[styles.container, defaultStyle, style]}>
781119c2eaS猫头猫                {children}
791119c2eaS猫头猫            </View>
801119c2eaS猫头猫        </TouchableHighlight>
811119c2eaS猫头猫    );
821119c2eaS猫头猫}
831119c2eaS猫头猫
841119c2eaS猫头猫interface IListItemTextProps {
851119c2eaS猫头猫    children?: number | string;
861119c2eaS猫头猫    fontSize?: keyof typeof fontSizeConst;
871119c2eaS猫头猫    fontWeight?: keyof typeof fontWeightConst;
881119c2eaS猫头猫    width?: number;
891119c2eaS猫头猫    position?: 'left' | 'right' | 'none';
901119c2eaS猫头猫    fixedWidth?: boolean;
911119c2eaS猫头猫    containerStyle?: StyleProp<ViewStyle>;
921119c2eaS猫头猫    contentStyle?: StyleProp<TextStyle>;
931119c2eaS猫头猫    contentProps?: TextProps;
941119c2eaS猫头猫}
951119c2eaS猫头猫
961119c2eaS猫头猫function ListItemText(props: IListItemTextProps) {
971119c2eaS猫头猫    const {
981119c2eaS猫头猫        children,
991119c2eaS猫头猫        fontSize,
1001119c2eaS猫头猫        fontWeight,
1011119c2eaS猫头猫        position = 'left',
1021119c2eaS猫头猫        fixedWidth,
1031119c2eaS猫头猫        width,
1041119c2eaS猫头猫        containerStyle,
1051119c2eaS猫头猫        contentStyle,
1061119c2eaS猫头猫        contentProps = {},
1071119c2eaS猫头猫    } = props;
1081119c2eaS猫头猫
1091119c2eaS猫头猫    const defaultStyle: StyleProp<ViewStyle> = {
1101119c2eaS猫头猫        marginRight: position === 'left' ? defaultPadding : 0,
1111119c2eaS猫头猫        marginLeft: position === 'right' ? defaultPadding : 0,
1121119c2eaS猫头猫        width: fixedWidth ? width ?? defaultActionWidth : undefined,
1131119c2eaS猫头猫        flexBasis: fixedWidth ? width ?? defaultActionWidth : undefined,
1141119c2eaS猫头猫    };
1151119c2eaS猫头猫
1161119c2eaS猫头猫    return (
1171119c2eaS猫头猫        <View style={[styles.actionBase, defaultStyle, containerStyle]}>
1181119c2eaS猫头猫            <ThemeText
1191119c2eaS猫头猫                fontSize={fontSize}
1201119c2eaS猫头猫                style={contentStyle}
1211119c2eaS猫头猫                fontWeight={fontWeight}
1221119c2eaS猫头猫                {...contentProps}>
1231119c2eaS猫头猫                {children}
1241119c2eaS猫头猫            </ThemeText>
1251119c2eaS猫头猫        </View>
1261119c2eaS猫头猫    );
1271119c2eaS猫头猫}
1281119c2eaS猫头猫
1291119c2eaS猫头猫interface IListItemIconProps {
1301119c2eaS猫头猫    icon: string;
1311119c2eaS猫头猫    iconSize?: number;
1321119c2eaS猫头猫    width?: number;
1331119c2eaS猫头猫    position?: 'left' | 'right' | 'none';
1341119c2eaS猫头猫    fixedWidth?: boolean;
1351119c2eaS猫头猫    containerStyle?: StyleProp<ViewStyle>;
1361119c2eaS猫头猫    contentStyle?: StyleProp<TextStyle>;
1371119c2eaS猫头猫    onPress?: () => void;
1381119c2eaS猫头猫}
1391119c2eaS猫头猫
1401119c2eaS猫头猫function ListItemIcon(props: IListItemIconProps) {
1411119c2eaS猫头猫    const {
1421119c2eaS猫头猫        icon,
1431119c2eaS猫头猫        iconSize = iconSizeConst.normal,
1441119c2eaS猫头猫        position = 'left',
1451119c2eaS猫头猫        fixedWidth,
1461119c2eaS猫头猫        width,
1471119c2eaS猫头猫        containerStyle,
1481119c2eaS猫头猫        contentStyle,
1491119c2eaS猫头猫        onPress,
1501119c2eaS猫头猫    } = props;
1511119c2eaS猫头猫
1526cfecf1cS猫头猫    const colors = useColors();
1536cfecf1cS猫头猫
1541119c2eaS猫头猫    const defaultStyle: StyleProp<ViewStyle> = {
1551119c2eaS猫头猫        marginRight: position === 'left' ? defaultPadding : 0,
1561119c2eaS猫头猫        marginLeft: position === 'right' ? defaultPadding : 0,
1571119c2eaS猫头猫        width: fixedWidth ? width ?? defaultActionWidth : undefined,
1581119c2eaS猫头猫        flexBasis: fixedWidth ? width ?? defaultActionWidth : undefined,
1591119c2eaS猫头猫    };
1601119c2eaS猫头猫
1611119c2eaS猫头猫    const innerContent = (
1621119c2eaS猫头猫        <View style={[styles.actionBase, defaultStyle, containerStyle]}>
1636cfecf1cS猫头猫            <Icon
1646cfecf1cS猫头猫                name={icon}
1656cfecf1cS猫头猫                size={iconSize}
1666cfecf1cS猫头猫                style={contentStyle}
1676cfecf1cS猫头猫                color={colors.text}
1686cfecf1cS猫头猫            />
1691119c2eaS猫头猫        </View>
1701119c2eaS猫头猫    );
1711119c2eaS猫头猫
1721119c2eaS猫头猫    return onPress ? (
1731119c2eaS猫头猫        <TouchableOpacity onPress={onPress}>{innerContent}</TouchableOpacity>
1741119c2eaS猫头猫    ) : (
1751119c2eaS猫头猫        innerContent
1761119c2eaS猫头猫    );
1771119c2eaS猫头猫}
1781119c2eaS猫头猫
1791119c2eaS猫头猫interface IListItemImageProps {
1801119c2eaS猫头猫    uri?: string;
1811119c2eaS猫头猫    fallbackImg?: number;
1821119c2eaS猫头猫    imageSize?: number;
1831119c2eaS猫头猫    width?: number;
1841119c2eaS猫头猫    position?: 'left' | 'right';
1851119c2eaS猫头猫    fixedWidth?: boolean;
1861119c2eaS猫头猫    containerStyle?: StyleProp<ViewStyle>;
1871119c2eaS猫头猫    contentStyle?: StyleProp<ImageStyle>;
188*7aed04d4S猫头猫    maskIcon?: string | null;
1891119c2eaS猫头猫}
1901119c2eaS猫头猫
1911119c2eaS猫头猫function ListItemImage(props: IListItemImageProps) {
1921119c2eaS猫头猫    const {
1931119c2eaS猫头猫        uri,
1941119c2eaS猫头猫        fallbackImg,
1951119c2eaS猫头猫        position = 'left',
1961119c2eaS猫头猫        fixedWidth,
1971119c2eaS猫头猫        width,
1981119c2eaS猫头猫        containerStyle,
1991119c2eaS猫头猫        contentStyle,
200*7aed04d4S猫头猫        maskIcon,
2011119c2eaS猫头猫    } = props;
2021119c2eaS猫头猫
2031119c2eaS猫头猫    const defaultStyle: StyleProp<ViewStyle> = {
2041119c2eaS猫头猫        marginRight: position === 'left' ? defaultPadding : 0,
2051119c2eaS猫头猫        marginLeft: position === 'right' ? defaultPadding : 0,
2061119c2eaS猫头猫        width: fixedWidth ? width ?? defaultActionWidth : undefined,
2071119c2eaS猫头猫        flexBasis: fixedWidth ? width ?? defaultActionWidth : undefined,
2081119c2eaS猫头猫    };
2091119c2eaS猫头猫
2101119c2eaS猫头猫    return (
2111119c2eaS猫头猫        <View style={[styles.actionBase, defaultStyle, containerStyle]}>
2121119c2eaS猫头猫            <FastImage
2131119c2eaS猫头猫                style={[styles.leftImage, contentStyle]}
2141119c2eaS猫头猫                uri={uri}
2151119c2eaS猫头猫                emptySrc={fallbackImg}
2161119c2eaS猫头猫            />
217*7aed04d4S猫头猫            {maskIcon ? (
218*7aed04d4S猫头猫                <View style={[styles.leftImage, styles.imageMask]}>
219*7aed04d4S猫头猫                    <Icon
220*7aed04d4S猫头猫                        name={maskIcon}
221*7aed04d4S猫头猫                        size={iconSizeConst.normal}
222*7aed04d4S猫头猫                        color="red"
223*7aed04d4S猫头猫                    />
224*7aed04d4S猫头猫                </View>
225*7aed04d4S猫头猫            ) : null}
2261119c2eaS猫头猫        </View>
2271119c2eaS猫头猫    );
2281119c2eaS猫头猫}
2291119c2eaS猫头猫
2301119c2eaS猫头猫interface IContentProps {
2311119c2eaS猫头猫    title?: ReactNode;
2326cfecf1cS猫头猫    children?: ReactNode;
2331119c2eaS猫头猫    description?: ReactNode;
2341119c2eaS猫头猫    containerStyle?: StyleProp<ViewStyle>;
2351119c2eaS猫头猫}
2361119c2eaS猫头猫
2371119c2eaS猫头猫function Content(props: IContentProps) {
2386cfecf1cS猫头猫    const {
2396cfecf1cS猫头猫        children,
2406cfecf1cS猫头猫        title = children,
2416cfecf1cS猫头猫        description = null,
2426cfecf1cS猫头猫        containerStyle,
2436cfecf1cS猫头猫    } = props;
2441119c2eaS猫头猫
2451119c2eaS猫头猫    let realTitle;
2461119c2eaS猫头猫    let realDescription;
2471119c2eaS猫头猫
2481119c2eaS猫头猫    if (typeof title === 'string' || typeof title === 'number') {
2491119c2eaS猫头猫        realTitle = <ThemeText numberOfLines={1}>{title}</ThemeText>;
2501119c2eaS猫头猫    } else {
2511119c2eaS猫头猫        realTitle = title;
2521119c2eaS猫头猫    }
2531119c2eaS猫头猫
2541119c2eaS猫头猫    if (typeof description === 'string' || typeof description === 'number') {
2551119c2eaS猫头猫        realDescription = (
2561119c2eaS猫头猫            <ThemeText
2571119c2eaS猫头猫                numberOfLines={1}
2581119c2eaS猫头猫                fontSize="description"
259277c5280S猫头猫                fontColor="textSecondary"
2601119c2eaS猫头猫                style={styles.contentDesc}>
2611119c2eaS猫头猫                {description}
2621119c2eaS猫头猫            </ThemeText>
2631119c2eaS猫头猫        );
2641119c2eaS猫头猫    } else {
2651119c2eaS猫头猫        realDescription = description;
2661119c2eaS猫头猫    }
2671119c2eaS猫头猫
2681119c2eaS猫头猫    return (
2691119c2eaS猫头猫        <View style={[styles.itemContentContainer, containerStyle]}>
2701119c2eaS猫头猫            {realTitle}
2711119c2eaS猫头猫            {realDescription}
2721119c2eaS猫头猫        </View>
2731119c2eaS猫头猫    );
27419dc08ecS猫头猫}
275e650bfb3S猫头猫
276e01046d9S猫头猫export function ListItemHeader(props: {children?: ReactNode}) {
277e01046d9S猫头猫    const {children} = props;
278e01046d9S猫头猫    return (
279e01046d9S猫头猫        <ListItem
280e01046d9S猫头猫            withHorizonalPadding
281e01046d9S猫头猫            heightType="smallest"
282e01046d9S猫头猫            style={styles.listItemHeader}>
283e01046d9S猫头猫            {typeof children === 'string' ? (
284e01046d9S猫头猫                <ThemeText
285e01046d9S猫头猫                    fontSize="subTitle"
286e01046d9S猫头猫                    fontColor="textSecondary"
287e01046d9S猫头猫                    fontWeight="bold">
288e01046d9S猫头猫                    {children}
289e01046d9S猫头猫                </ThemeText>
290e01046d9S猫头猫            ) : (
291e01046d9S猫头猫                children
292e01046d9S猫头猫            )}
293e01046d9S猫头猫        </ListItem>
294e01046d9S猫头猫    );
295e01046d9S猫头猫}
296e01046d9S猫头猫
297e650bfb3S猫头猫const styles = StyleSheet.create({
2981119c2eaS猫头猫    /** listitem */
2991119c2eaS猫头猫    container: {
3001119c2eaS猫头猫        width: '100%',
3011119c2eaS猫头猫        flexDirection: 'row',
3021119c2eaS猫头猫        alignItems: 'center',
3031119c2eaS猫头猫    },
3041119c2eaS猫头猫    /** left */
3051119c2eaS猫头猫    actionBase: {
3061119c2eaS猫头猫        height: '100%',
3071119c2eaS猫头猫        flexShrink: 0,
3081119c2eaS猫头猫        flexGrow: 0,
3091119c2eaS猫头猫        flexBasis: 0,
3101119c2eaS猫头猫        flexDirection: 'row',
3111119c2eaS猫头猫        justifyContent: 'center',
3121119c2eaS猫头猫        alignItems: 'center',
3131119c2eaS猫头猫    },
3141119c2eaS猫头猫
3151119c2eaS猫头猫    leftImage: {
3161119c2eaS猫头猫        width: rpx(80),
3171119c2eaS猫头猫        height: rpx(80),
3181119c2eaS猫头猫        borderRadius: rpx(16),
3191119c2eaS猫头猫    },
320*7aed04d4S猫头猫    imageMask: {
321*7aed04d4S猫头猫        position: 'absolute',
322*7aed04d4S猫头猫        alignItems: 'center',
323*7aed04d4S猫头猫        justifyContent: 'center',
324*7aed04d4S猫头猫        backgroundColor: '#00000022',
325*7aed04d4S猫头猫    },
3261119c2eaS猫头猫    itemContentContainer: {
3271119c2eaS猫头猫        flex: 1,
3281119c2eaS猫头猫        height: '100%',
3291119c2eaS猫头猫        justifyContent: 'center',
3301119c2eaS猫头猫    },
3311119c2eaS猫头猫    contentDesc: {
3321119c2eaS猫头猫        marginTop: rpx(16),
33319dc08ecS猫头猫    },
334e01046d9S猫头猫
335e01046d9S猫头猫    listItemHeader: {
336e01046d9S猫头猫        marginTop: rpx(20),
337e01046d9S猫头猫    },
33819dc08ecS猫头猫});
3391119c2eaS猫头猫
3401119c2eaS猫头猫ListItem.Size = Size;
3411119c2eaS猫头猫ListItem.ListItemIcon = ListItemIcon;
3421119c2eaS猫头猫ListItem.ListItemImage = ListItemImage;
3431119c2eaS猫头猫ListItem.ListItemText = ListItemText;
3441119c2eaS猫头猫ListItem.Content = Content;
3451119c2eaS猫头猫
3461119c2eaS猫头猫export default ListItem;
347