xref: /MusicFree/src/components/musicBar/index.tsx (revision 2aa881935ca35b8fb1abc4206e0dc35149231456)
1import React, {Fragment, memo, useEffect, useState} from 'react';
2import {Keyboard, Pressable, StyleSheet, Text, View} from 'react-native';
3import rpx from '@/utils/rpx';
4import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
5import MusicQueue from '@/core/musicQueue';
6import {Avatar, IconButton, useTheme} from 'react-native-paper';
7import {CircularProgressBase} from 'react-native-circular-progress-indicator';
8import {ROUTE_PATH, useNavigate} from '@/entry/router';
9
10import musicIsPaused from '@/utils/musicIsPaused';
11import usePanel from '../panels/usePanel';
12import Color from 'color';
13import ThemeText from '../base/themeText';
14import {ImgAsset} from '@/constants/assetsConst';
15
16function CircularPlayBtn() {
17    const progress = MusicQueue.useProgress();
18    const musicState = MusicQueue.usePlaybackState();
19    const {colors} = useTheme();
20
21    return (
22        <CircularProgressBase
23            activeStrokeWidth={rpx(4)}
24            inActiveStrokeWidth={rpx(2)}
25            inActiveStrokeOpacity={0.2}
26            value={
27                progress?.duration
28                    ? (100 * progress.position) / progress.duration
29                    : 0
30            }
31            duration={100}
32            radius={rpx(36)}
33            activeStrokeColor={colors.text}
34            inActiveStrokeColor={Color(colors.text).alpha(0.5).toString()}>
35            {musicIsPaused(musicState) ? (
36                <IconButton
37                    icon="play"
38                    size={rpx(48)}
39                    onPress={async () => {
40                        await MusicQueue.play();
41                    }}
42                />
43            ) : (
44                <IconButton
45                    icon="pause"
46                    size={rpx(48)}
47                    onPress={async () => {
48                        await MusicQueue.pause();
49                    }}
50                />
51            )}
52        </CircularProgressBase>
53    );
54}
55function MusicBar() {
56    const musicItem = MusicQueue.useCurrentMusicItem();
57
58    const [showKeyboard, setKeyboardStatus] = useState(false);
59    const {showPanel} = usePanel();
60    const navigate = useNavigate();
61    const {colors} = useTheme();
62
63    useEffect(() => {
64        const showSubscription = Keyboard.addListener('keyboardDidShow', () => {
65            setKeyboardStatus(true);
66        });
67        const hideSubscription = Keyboard.addListener('keyboardDidHide', () => {
68            setKeyboardStatus(false);
69        });
70
71        return () => {
72            showSubscription.remove();
73            hideSubscription.remove();
74        };
75    }, []);
76
77    return (
78        <Fragment>
79            {musicItem && !showKeyboard && (
80                <Pressable
81                    style={[
82                        style.wrapper,
83                        {
84                            backgroundColor: Color(colors.primary)
85                                .alpha(0.66)
86                                .toString(),
87                        },
88                    ]}
89                    onPress={() => {
90                        navigate(ROUTE_PATH.MUSIC_DETAIL);
91                    }}>
92                    <View style={style.artworkWrapper}>
93                        <Avatar.Image
94                            size={rpx(96)}
95                            source={
96                                musicItem?.artwork
97                                    ? {
98                                          uri: musicItem.artwork,
99                                      }
100                                    : ImgAsset.albumDefault
101                            }
102                        />
103                    </View>
104                    <Text
105                        ellipsizeMode="tail"
106                        style={style.textWrapper}
107                        numberOfLines={1}>
108                        <ThemeText fontSize="content">
109                            {musicItem?.title}
110                        </ThemeText>
111                        {musicItem?.artist && (
112                            <ThemeText
113                                fontSize="description"
114                                fontColor="secondary">
115                                {' '}
116                                -{musicItem.artist}
117                            </ThemeText>
118                        )}
119                    </Text>
120                    <View style={style.actionGroup}>
121                        <CircularPlayBtn />
122
123                        <Icon
124                            name="playlist-music"
125                            size={rpx(56)}
126                            onPress={() => {
127                                showPanel('PlayList');
128                            }}
129                            style={[style.actionIcon, {color: colors.text}]}
130                        />
131                    </View>
132                </Pressable>
133            )}
134        </Fragment>
135    );
136}
137
138export default memo(MusicBar, () => true);
139
140const style = StyleSheet.create({
141    wrapper: {
142        width: rpx(750),
143        height: rpx(120),
144        flexDirection: 'row',
145        alignItems: 'center',
146        paddingHorizontal: rpx(24),
147    },
148    artworkWrapper: {
149        height: rpx(120),
150        width: rpx(120),
151    },
152    textWrapper: {
153        flexGrow: 1,
154        maxWidth: rpx(382),
155    },
156    actionGroup: {
157        width: rpx(200),
158        justifyContent: 'flex-end',
159        flexDirection: 'row',
160        alignItems: 'center',
161    },
162    actionIcon: {
163        marginLeft: rpx(36),
164    },
165});
166