xref: /MusicFree/src/components/musicBar/index.tsx (revision cd669353b6a483aad2a61863c7df332c267907c6)
1import React, {Fragment, 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}
55
56export default function () {
57    const musicItem = MusicQueue.useCurrentMusicItem();
58
59    const [showKeyboard, setKeyboardStatus] = useState(false);
60    const {showPanel} = usePanel();
61    const navigate = useNavigate();
62    const {colors} = useTheme();
63
64    useEffect(() => {
65        const showSubscription = Keyboard.addListener('keyboardDidShow', () => {
66            setKeyboardStatus(true);
67        });
68        const hideSubscription = Keyboard.addListener('keyboardDidHide', () => {
69            setKeyboardStatus(false);
70        });
71
72        return () => {
73            showSubscription.remove();
74            hideSubscription.remove();
75        };
76    }, []);
77
78    return (
79        <Fragment>
80            {musicItem && !showKeyboard && (
81                <Pressable
82                    style={[
83                        style.wrapper,
84                        {
85                            backgroundColor: Color(colors.primary)
86                                .alpha(0.66)
87                                .toString(),
88                        },
89                    ]}
90                    onPress={() => {
91                        navigate(ROUTE_PATH.MUSIC_DETAIL);
92                    }}>
93                    <View style={style.artworkWrapper}>
94                        <Avatar.Image
95                            size={rpx(96)}
96                            source={
97                                musicItem.artwork
98                                    ? {
99                                          uri: musicItem.artwork,
100                                      }
101                                    : ImgAsset.albumDefault
102                            }
103                        />
104                    </View>
105                    <Text
106                        ellipsizeMode="tail"
107                        style={style.textWrapper}
108                        numberOfLines={1}>
109                        <ThemeText fontSize="content">
110                            {musicItem.title}
111                        </ThemeText>
112                        {musicItem?.artist && (
113                            <ThemeText
114                                fontSize="description"
115                                fontColor="secondary">
116                                {' '}
117                                -{musicItem.artist}
118                            </ThemeText>
119                        )}
120                    </Text>
121                    <View style={style.actionGroup}>
122                        <CircularPlayBtn />
123
124                        <Icon
125                            name="playlist-music"
126                            size={rpx(56)}
127                            onPress={() => {
128                                showPanel('PlayList');
129                            }}
130                            style={[style.actionIcon, {color: colors.text}]}
131                        />
132                    </View>
133                </Pressable>
134            )}
135        </Fragment>
136    );
137}
138
139const style = StyleSheet.create({
140    wrapper: {
141        width: rpx(750),
142        height: rpx(120),
143        flexDirection: 'row',
144        alignItems: 'center',
145        paddingHorizontal: rpx(24),
146    },
147    artworkWrapper: {
148        height: rpx(120),
149        width: rpx(120),
150    },
151    textWrapper: {
152        flexGrow: 1,
153        maxWidth: rpx(382),
154    },
155    actionGroup: {
156        width: rpx(200),
157        justifyContent: 'flex-end',
158        flexDirection: 'row',
159        alignItems: 'center',
160    },
161    actionIcon: {
162        marginLeft: rpx(36),
163    },
164});
165