xref: /MusicFree/src/pages/artistDetail/components/header.tsx (revision 2aa881935ca35b8fb1abc4206e0dc35149231456)
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 {Avatar} from 'react-native-paper';
12import ThemeText from '@/components/base/themeText';
13import Tag from '@/components/base/tag';
14import {useParams} from '@/entry/router';
15
16const headerHeight = rpx(350);
17export default function Header() {
18    const {artistItem} = useParams<'artist-detail'>();
19
20    const heightValue = useSharedValue(headerHeight);
21    const opacityValue = useSharedValue(1);
22    const scrollToTopState = useAtomValue(scrollToTopAtom);
23
24    const heightStyle = useAnimatedStyle(() => {
25        return {
26            height: heightValue.value,
27            opacity: opacityValue.value,
28        };
29    });
30
31    const avatar = artistItem.avatar?.startsWith('//')
32        ? `https:${artistItem.avatar}`
33        : artistItem.avatar;
34
35    /** 折叠 */
36    useEffect(() => {
37        if (scrollToTopState) {
38            heightValue.value = withTiming(headerHeight);
39            opacityValue.value = withTiming(1);
40        } else {
41            heightValue.value = withTiming(0);
42            opacityValue.value = withTiming(0);
43        }
44    }, [scrollToTopState]);
45
46    return (
47        <Animated.View style={[style.wrapper, heightStyle]}>
48            <View style={style.headerWrapper}>
49                <Avatar.Image size={rpx(144)} source={{uri: avatar}} />
50                <View style={style.info}>
51                    <View style={style.title}>
52                        <ThemeText
53                            fontSize="title"
54                            style={style.titleText}
55                            numberOfLines={1}
56                            ellipsizeMode="tail">
57                            {artistItem?.name ?? ''}
58                        </ThemeText>
59                        {artistItem.platform ? (
60                            <Tag tagName={artistItem.platform} />
61                        ) : null}
62                    </View>
63
64                    {artistItem.fans ? (
65                        <ThemeText fontSize="subTitle" fontColor="secondary">
66                            粉丝数: {artistItem.fans}
67                        </ThemeText>
68                    ) : null}
69                </View>
70            </View>
71
72            <ThemeText
73                style={style.description}
74                numberOfLines={2}
75                ellipsizeMode="tail"
76                fontColor="secondary"
77                fontSize="description">
78                {artistItem?.description ?? ''}
79            </ThemeText>
80        </Animated.View>
81    );
82}
83
84const style = StyleSheet.create({
85    wrapper: {
86        width: rpx(750),
87        height: headerHeight,
88        backgroundColor: 'rgba(28, 28, 28, 0.1)',
89        zIndex: 1,
90    },
91    headerWrapper: {
92        width: rpx(750),
93        paddingTop: rpx(24),
94        paddingHorizontal: rpx(24),
95        height: rpx(240),
96        flexDirection: 'row',
97        alignItems: 'center',
98    },
99    info: {
100        marginLeft: rpx(24),
101        justifyContent: 'space-around',
102        height: rpx(144),
103    },
104    title: {
105        flexDirection: 'row',
106        alignItems: 'center',
107    },
108    titleText: {
109        marginRight: rpx(18),
110        maxWidth: rpx(400),
111    },
112    description: {
113        marginTop: rpx(24),
114        width: rpx(750),
115        paddingHorizontal: rpx(24),
116    },
117});
118