xref: /MusicFree/src/pages/artistDetail/components/header.tsx (revision 410a159129b1f6a7a1f44fde7bfad9a46f91e161)
1import React, {useEffect} from 'react';
2import {StyleSheet, View} from 'react-native';
3import rpx from '@/utils/rpx';
4import Animated, {
5    useAnimatedStyle,
6    useSharedValue,
7    withTiming,
8} from 'react-native-reanimated';
9import {useAtomValue} from 'jotai';
10import {scrollToTopAtom} from '../store/atoms';
11import ThemeText from '@/components/base/themeText';
12import Tag from '@/components/base/tag';
13import {useParams} from '@/entry/router';
14import Image from '@/components/base/image';
15import {ImgAsset} from '@/constants/assetsConst';
16
17const headerHeight = rpx(350);
18
19interface IHeaderProps {
20    neverFold?: boolean;
21}
22
23export default function Header(props: IHeaderProps) {
24    const {neverFold} = props;
25
26    const {artistItem} = useParams<'artist-detail'>();
27
28    const heightValue = useSharedValue(headerHeight);
29    const opacityValue = useSharedValue(1);
30    const scrollToTopState = useAtomValue(scrollToTopAtom);
31
32    const heightStyle = useAnimatedStyle(() => {
33        return {
34            height: heightValue.value,
35            opacity: opacityValue.value,
36        };
37    });
38
39    const avatar = artistItem.avatar?.startsWith('//')
40        ? `https:${artistItem.avatar}`
41        : artistItem.avatar;
42
43    /** 折叠 */
44    useEffect(() => {
45        if (neverFold) {
46            heightValue.value = withTiming(headerHeight);
47            opacityValue.value = withTiming(1);
48            return;
49        }
50        if (scrollToTopState) {
51            heightValue.value = withTiming(headerHeight);
52            opacityValue.value = withTiming(1);
53        } else {
54            heightValue.value = withTiming(0);
55            opacityValue.value = withTiming(0);
56        }
57    }, [scrollToTopState, neverFold]);
58
59    return (
60        <Animated.View style={[styles.wrapper, heightStyle]}>
61            <View style={styles.headerWrapper}>
62                <Image
63                    emptySrc={ImgAsset.albumDefault}
64                    uri={avatar}
65                    style={styles.artist}
66                />
67                <View style={styles.info}>
68                    <View style={styles.title}>
69                        <ThemeText
70                            fontSize="title"
71                            style={styles.titleText}
72                            numberOfLines={1}
73                            ellipsizeMode="tail">
74                            {artistItem?.name ?? ''}
75                        </ThemeText>
76                        {artistItem.platform ? (
77                            <Tag tagName={artistItem.platform} />
78                        ) : null}
79                    </View>
80
81                    {artistItem.fans ? (
82                        <ThemeText
83                            fontSize="subTitle"
84                            fontColor="textSecondary">
85                            粉丝数: {artistItem.fans}
86                        </ThemeText>
87                    ) : null}
88                </View>
89            </View>
90
91            <ThemeText
92                style={styles.description}
93                numberOfLines={2}
94                ellipsizeMode="tail"
95                fontColor="textSecondary"
96                fontSize="description">
97                {artistItem?.description ?? ''}
98            </ThemeText>
99        </Animated.View>
100    );
101}
102
103const styles = StyleSheet.create({
104    wrapper: {
105        width: rpx(750),
106        height: headerHeight,
107        backgroundColor: 'rgba(28, 28, 28, 0.1)',
108        zIndex: 1,
109    },
110    artist: {
111        width: rpx(144),
112        height: rpx(144),
113        borderRadius: rpx(16),
114    },
115    headerWrapper: {
116        width: rpx(750),
117        paddingTop: rpx(24),
118        paddingHorizontal: rpx(24),
119        height: rpx(240),
120        flexDirection: 'row',
121        alignItems: 'center',
122    },
123    info: {
124        marginLeft: rpx(24),
125        justifyContent: 'space-around',
126        height: rpx(144),
127    },
128    title: {
129        flexDirection: 'row',
130        alignItems: 'center',
131    },
132    titleText: {
133        marginRight: rpx(18),
134        maxWidth: rpx(400),
135    },
136    description: {
137        marginTop: rpx(24),
138        width: rpx(750),
139        paddingHorizontal: rpx(24),
140    },
141});
142