xref: /MusicFree/src/components/base/listItem.tsx (revision 277c528005b29b919b3eda695ee03717976a5a83)
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猫头猫    // 高度类型
341119c2eaS猫头猫    heightType?: 'big' | 'small' | '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),
471119c2eaS猫头猫    none: undefined,
481119c2eaS猫头猫};
491119c2eaS猫头猫
501119c2eaS猫头猫function ListItem(props: IListItemProps) {
511119c2eaS猫头猫    const {
521119c2eaS猫头猫        withHorizonalPadding,
531119c2eaS猫头猫        leftPadding = defaultPadding,
541119c2eaS猫头猫        rightPadding = defaultPadding,
551119c2eaS猫头猫        style,
561119c2eaS猫头猫        heightType = 'normal',
571119c2eaS猫头猫        children,
581119c2eaS猫头猫        onPress,
591119c2eaS猫头猫        onLongPress,
601119c2eaS猫头猫    } = props;
611119c2eaS猫头猫
621119c2eaS猫头猫    const defaultStyle: StyleProp<ViewStyle> = {
631119c2eaS猫头猫        paddingLeft: withHorizonalPadding ? leftPadding : 0,
641119c2eaS猫头猫        paddingRight: withHorizonalPadding ? rightPadding : 0,
651119c2eaS猫头猫        height: Size[heightType],
661119c2eaS猫头猫    };
671119c2eaS猫头猫
681119c2eaS猫头猫    const colors = useColors();
691119c2eaS猫头猫
701119c2eaS猫头猫    return (
711119c2eaS猫头猫        <TouchableHighlight
721119c2eaS猫头猫            style={styles.container}
731119c2eaS猫头猫            underlayColor={colors.listActive}
741119c2eaS猫头猫            onPress={onPress}
751119c2eaS猫头猫            onLongPress={onLongPress}>
761119c2eaS猫头猫            <View style={[styles.container, defaultStyle, style]}>
771119c2eaS猫头猫                {children}
781119c2eaS猫头猫            </View>
791119c2eaS猫头猫        </TouchableHighlight>
801119c2eaS猫头猫    );
811119c2eaS猫头猫}
821119c2eaS猫头猫
831119c2eaS猫头猫interface IListItemTextProps {
841119c2eaS猫头猫    children?: number | string;
851119c2eaS猫头猫    fontSize?: keyof typeof fontSizeConst;
861119c2eaS猫头猫    fontWeight?: keyof typeof fontWeightConst;
871119c2eaS猫头猫    width?: number;
881119c2eaS猫头猫    position?: 'left' | 'right' | 'none';
891119c2eaS猫头猫    fixedWidth?: boolean;
901119c2eaS猫头猫    containerStyle?: StyleProp<ViewStyle>;
911119c2eaS猫头猫    contentStyle?: StyleProp<TextStyle>;
921119c2eaS猫头猫    contentProps?: TextProps;
931119c2eaS猫头猫}
941119c2eaS猫头猫
951119c2eaS猫头猫function ListItemText(props: IListItemTextProps) {
961119c2eaS猫头猫    const {
971119c2eaS猫头猫        children,
981119c2eaS猫头猫        fontSize,
991119c2eaS猫头猫        fontWeight,
1001119c2eaS猫头猫        position = 'left',
1011119c2eaS猫头猫        fixedWidth,
1021119c2eaS猫头猫        width,
1031119c2eaS猫头猫        containerStyle,
1041119c2eaS猫头猫        contentStyle,
1051119c2eaS猫头猫        contentProps = {},
1061119c2eaS猫头猫    } = props;
1071119c2eaS猫头猫
1081119c2eaS猫头猫    const defaultStyle: StyleProp<ViewStyle> = {
1091119c2eaS猫头猫        marginRight: position === 'left' ? defaultPadding : 0,
1101119c2eaS猫头猫        marginLeft: position === 'right' ? defaultPadding : 0,
1111119c2eaS猫头猫        width: fixedWidth ? width ?? defaultActionWidth : undefined,
1121119c2eaS猫头猫        flexBasis: fixedWidth ? width ?? defaultActionWidth : undefined,
1131119c2eaS猫头猫    };
1141119c2eaS猫头猫
1151119c2eaS猫头猫    return (
1161119c2eaS猫头猫        <View style={[styles.actionBase, defaultStyle, containerStyle]}>
1171119c2eaS猫头猫            <ThemeText
1181119c2eaS猫头猫                fontSize={fontSize}
1191119c2eaS猫头猫                style={contentStyle}
1201119c2eaS猫头猫                fontWeight={fontWeight}
1211119c2eaS猫头猫                {...contentProps}>
1221119c2eaS猫头猫                {children}
1231119c2eaS猫头猫            </ThemeText>
1241119c2eaS猫头猫        </View>
1251119c2eaS猫头猫    );
1261119c2eaS猫头猫}
1271119c2eaS猫头猫
1281119c2eaS猫头猫interface IListItemIconProps {
1291119c2eaS猫头猫    icon: string;
1301119c2eaS猫头猫    iconSize?: number;
1311119c2eaS猫头猫    width?: number;
1321119c2eaS猫头猫    position?: 'left' | 'right' | 'none';
1331119c2eaS猫头猫    fixedWidth?: boolean;
1341119c2eaS猫头猫    containerStyle?: StyleProp<ViewStyle>;
1351119c2eaS猫头猫    contentStyle?: StyleProp<TextStyle>;
1361119c2eaS猫头猫    onPress?: () => void;
1371119c2eaS猫头猫}
1381119c2eaS猫头猫
1391119c2eaS猫头猫function ListItemIcon(props: IListItemIconProps) {
1401119c2eaS猫头猫    const {
1411119c2eaS猫头猫        icon,
1421119c2eaS猫头猫        iconSize = iconSizeConst.normal,
1431119c2eaS猫头猫        position = 'left',
1441119c2eaS猫头猫        fixedWidth,
1451119c2eaS猫头猫        width,
1461119c2eaS猫头猫        containerStyle,
1471119c2eaS猫头猫        contentStyle,
1481119c2eaS猫头猫        onPress,
1491119c2eaS猫头猫    } = props;
1501119c2eaS猫头猫
1516cfecf1cS猫头猫    const colors = useColors();
1526cfecf1cS猫头猫
1531119c2eaS猫头猫    const defaultStyle: StyleProp<ViewStyle> = {
1541119c2eaS猫头猫        marginRight: position === 'left' ? defaultPadding : 0,
1551119c2eaS猫头猫        marginLeft: position === 'right' ? defaultPadding : 0,
1561119c2eaS猫头猫        width: fixedWidth ? width ?? defaultActionWidth : undefined,
1571119c2eaS猫头猫        flexBasis: fixedWidth ? width ?? defaultActionWidth : undefined,
1581119c2eaS猫头猫    };
1591119c2eaS猫头猫
1601119c2eaS猫头猫    const innerContent = (
1611119c2eaS猫头猫        <View style={[styles.actionBase, defaultStyle, containerStyle]}>
1626cfecf1cS猫头猫            <Icon
1636cfecf1cS猫头猫                name={icon}
1646cfecf1cS猫头猫                size={iconSize}
1656cfecf1cS猫头猫                style={contentStyle}
1666cfecf1cS猫头猫                color={colors.text}
1676cfecf1cS猫头猫            />
1681119c2eaS猫头猫        </View>
1691119c2eaS猫头猫    );
1701119c2eaS猫头猫
1711119c2eaS猫头猫    return onPress ? (
1721119c2eaS猫头猫        <TouchableOpacity onPress={onPress}>{innerContent}</TouchableOpacity>
1731119c2eaS猫头猫    ) : (
1741119c2eaS猫头猫        innerContent
1751119c2eaS猫头猫    );
1761119c2eaS猫头猫}
1771119c2eaS猫头猫
1781119c2eaS猫头猫interface IListItemImageProps {
1791119c2eaS猫头猫    uri?: string;
1801119c2eaS猫头猫    fallbackImg?: number;
1811119c2eaS猫头猫    imageSize?: number;
1821119c2eaS猫头猫    width?: number;
1831119c2eaS猫头猫    position?: 'left' | 'right';
1841119c2eaS猫头猫    fixedWidth?: boolean;
1851119c2eaS猫头猫    containerStyle?: StyleProp<ViewStyle>;
1861119c2eaS猫头猫    contentStyle?: StyleProp<ImageStyle>;
1871119c2eaS猫头猫}
1881119c2eaS猫头猫
1891119c2eaS猫头猫function ListItemImage(props: IListItemImageProps) {
1901119c2eaS猫头猫    const {
1911119c2eaS猫头猫        uri,
1921119c2eaS猫头猫        fallbackImg,
1931119c2eaS猫头猫        position = 'left',
1941119c2eaS猫头猫        fixedWidth,
1951119c2eaS猫头猫        width,
1961119c2eaS猫头猫        containerStyle,
1971119c2eaS猫头猫        contentStyle,
1981119c2eaS猫头猫    } = props;
1991119c2eaS猫头猫
2001119c2eaS猫头猫    const defaultStyle: StyleProp<ViewStyle> = {
2011119c2eaS猫头猫        marginRight: position === 'left' ? defaultPadding : 0,
2021119c2eaS猫头猫        marginLeft: position === 'right' ? defaultPadding : 0,
2031119c2eaS猫头猫        width: fixedWidth ? width ?? defaultActionWidth : undefined,
2041119c2eaS猫头猫        flexBasis: fixedWidth ? width ?? defaultActionWidth : undefined,
2051119c2eaS猫头猫    };
2061119c2eaS猫头猫
2071119c2eaS猫头猫    return (
2081119c2eaS猫头猫        <View style={[styles.actionBase, defaultStyle, containerStyle]}>
2091119c2eaS猫头猫            <FastImage
2101119c2eaS猫头猫                style={[styles.leftImage, contentStyle]}
2111119c2eaS猫头猫                uri={uri}
2121119c2eaS猫头猫                emptySrc={fallbackImg}
2131119c2eaS猫头猫            />
2141119c2eaS猫头猫        </View>
2151119c2eaS猫头猫    );
2161119c2eaS猫头猫}
2171119c2eaS猫头猫
2181119c2eaS猫头猫interface IContentProps {
2191119c2eaS猫头猫    title?: ReactNode;
2206cfecf1cS猫头猫    children?: ReactNode;
2211119c2eaS猫头猫    description?: ReactNode;
2221119c2eaS猫头猫    containerStyle?: StyleProp<ViewStyle>;
2231119c2eaS猫头猫}
2241119c2eaS猫头猫
2251119c2eaS猫头猫function Content(props: IContentProps) {
2266cfecf1cS猫头猫    const {
2276cfecf1cS猫头猫        children,
2286cfecf1cS猫头猫        title = children,
2296cfecf1cS猫头猫        description = null,
2306cfecf1cS猫头猫        containerStyle,
2316cfecf1cS猫头猫    } = props;
2321119c2eaS猫头猫
2331119c2eaS猫头猫    let realTitle;
2341119c2eaS猫头猫    let realDescription;
2351119c2eaS猫头猫
2361119c2eaS猫头猫    if (typeof title === 'string' || typeof title === 'number') {
2371119c2eaS猫头猫        realTitle = <ThemeText numberOfLines={1}>{title}</ThemeText>;
2381119c2eaS猫头猫    } else {
2391119c2eaS猫头猫        realTitle = title;
2401119c2eaS猫头猫    }
2411119c2eaS猫头猫
2421119c2eaS猫头猫    if (typeof description === 'string' || typeof description === 'number') {
2431119c2eaS猫头猫        realDescription = (
2441119c2eaS猫头猫            <ThemeText
2451119c2eaS猫头猫                numberOfLines={1}
2461119c2eaS猫头猫                fontSize="description"
247*277c5280S猫头猫                fontColor="textSecondary"
2481119c2eaS猫头猫                style={styles.contentDesc}>
2491119c2eaS猫头猫                {description}
2501119c2eaS猫头猫            </ThemeText>
2511119c2eaS猫头猫        );
2521119c2eaS猫头猫    } else {
2531119c2eaS猫头猫        realDescription = description;
2541119c2eaS猫头猫    }
2551119c2eaS猫头猫
2561119c2eaS猫头猫    return (
2571119c2eaS猫头猫        <View style={[styles.itemContentContainer, containerStyle]}>
2581119c2eaS猫头猫            {realTitle}
2591119c2eaS猫头猫            {realDescription}
2601119c2eaS猫头猫        </View>
2611119c2eaS猫头猫    );
26219dc08ecS猫头猫}
263e650bfb3S猫头猫
264e650bfb3S猫头猫const styles = StyleSheet.create({
2651119c2eaS猫头猫    /** listitem */
2661119c2eaS猫头猫    container: {
2671119c2eaS猫头猫        width: '100%',
2681119c2eaS猫头猫        flexDirection: 'row',
2691119c2eaS猫头猫        alignItems: 'center',
2701119c2eaS猫头猫    },
2711119c2eaS猫头猫    /** left */
2721119c2eaS猫头猫    actionBase: {
2731119c2eaS猫头猫        height: '100%',
2741119c2eaS猫头猫        flexShrink: 0,
2751119c2eaS猫头猫        flexGrow: 0,
2761119c2eaS猫头猫        flexBasis: 0,
2771119c2eaS猫头猫        flexDirection: 'row',
2781119c2eaS猫头猫        justifyContent: 'center',
2791119c2eaS猫头猫        alignItems: 'center',
2801119c2eaS猫头猫    },
2811119c2eaS猫头猫
2821119c2eaS猫头猫    leftImage: {
2831119c2eaS猫头猫        width: rpx(80),
2841119c2eaS猫头猫        height: rpx(80),
2851119c2eaS猫头猫        borderRadius: rpx(16),
2861119c2eaS猫头猫    },
2871119c2eaS猫头猫    itemContentContainer: {
2881119c2eaS猫头猫        flex: 1,
2891119c2eaS猫头猫        height: '100%',
2901119c2eaS猫头猫        justifyContent: 'center',
2911119c2eaS猫头猫    },
2921119c2eaS猫头猫    contentDesc: {
2931119c2eaS猫头猫        marginTop: rpx(16),
29419dc08ecS猫头猫    },
29519dc08ecS猫头猫});
2961119c2eaS猫头猫
2971119c2eaS猫头猫ListItem.Size = Size;
2981119c2eaS猫头猫ListItem.ListItemIcon = ListItemIcon;
2991119c2eaS猫头猫ListItem.ListItemImage = ListItemImage;
3001119c2eaS猫头猫ListItem.ListItemText = ListItemText;
3011119c2eaS猫头猫ListItem.Content = Content;
3021119c2eaS猫头猫
3031119c2eaS猫头猫export default ListItem;
304