xref: /MusicFree/src/components/musicBar/index.tsx (revision 095287552b9baf2f2ceeb9397c563c292a4f7934)
1import React, {memo, useEffect, useState} from 'react';
2import {Keyboard, StyleSheet, View} from 'react-native';
3import rpx from '@/utils/rpx';
4import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
5import {CircularProgressBase} from 'react-native-circular-progress-indicator';
6
7import {useSafeAreaInsets} from 'react-native-safe-area-context';
8import {showPanel} from '../panels/usePanel';
9import useColors from '@/hooks/useColors';
10import IconButton from '../base/iconButton';
11import TrackPlayer from '@/core/trackPlayer';
12import {musicIsPaused} from '@/utils/trackUtils';
13import MusicInfo from './musicInfo';
14
15function CircularPlayBtn() {
16    const progress = TrackPlayer.useProgress();
17    const musicState = TrackPlayer.useMusicState();
18    const colors = useColors();
19
20    const isPaused = musicIsPaused(musicState);
21
22    return (
23        <CircularProgressBase
24            activeStrokeWidth={rpx(4)}
25            inActiveStrokeWidth={rpx(2)}
26            inActiveStrokeOpacity={0.2}
27            value={
28                progress?.duration
29                    ? (100 * progress.position) / progress.duration
30                    : 0
31            }
32            duration={100}
33            radius={rpx(36)}
34            activeStrokeColor={colors.musicBarText}
35            inActiveStrokeColor={colors.textSecondary}>
36            <IconButton
37                accessibilityLabel={'播放或暂停歌曲'}
38                name={isPaused ? 'play' : 'pause'}
39                sizeType={'normal'}
40                color={colors.musicBarText}
41                onPress={async () => {
42                    if (isPaused) {
43                        await TrackPlayer.play();
44                    } else {
45                        await TrackPlayer.pause();
46                    }
47                }}
48            />
49        </CircularProgressBase>
50    );
51}
52function MusicBar() {
53    const musicItem = TrackPlayer.useCurrentMusic();
54
55    const [showKeyboard, setKeyboardStatus] = useState(false);
56
57    const colors = useColors();
58    const safeAreaInsets = useSafeAreaInsets();
59
60    useEffect(() => {
61        const showSubscription = Keyboard.addListener('keyboardDidShow', () => {
62            setKeyboardStatus(true);
63        });
64        const hideSubscription = Keyboard.addListener('keyboardDidHide', () => {
65            setKeyboardStatus(false);
66        });
67
68        return () => {
69            showSubscription.remove();
70            hideSubscription.remove();
71        };
72    }, []);
73
74    return (
75        <>
76            {musicItem && !showKeyboard && (
77                <View
78                    style={[
79                        style.wrapper,
80                        {
81                            backgroundColor: colors.musicBar,
82                            paddingRight: safeAreaInsets.right + rpx(24),
83                        },
84                    ]}
85                    accessible
86                    accessibilityLabel={`歌曲: ${musicItem.title} 歌手: ${musicItem.artist}`}
87                    // onPress={() => {
88                    //     navigate(ROUTE_PATH.MUSIC_DETAIL);
89                    // }}
90                >
91                    <MusicInfo musicItem={musicItem} />
92                    <View style={style.actionGroup}>
93                        <CircularPlayBtn />
94                        <Icon
95                            accessible
96                            accessibilityLabel="播放列表"
97                            name="playlist-music"
98                            size={rpx(56)}
99                            onPress={() => {
100                                showPanel('PlayList');
101                            }}
102                            style={[
103                                style.actionIcon,
104                                {color: colors.musicBarText},
105                            ]}
106                        />
107                    </View>
108                </View>
109            )}
110        </>
111    );
112}
113
114export default memo(MusicBar, () => true);
115
116const style = StyleSheet.create({
117    wrapper: {
118        width: '100%',
119        height: rpx(132),
120        flexDirection: 'row',
121        alignItems: 'center',
122        paddingRight: rpx(24),
123    },
124    actionGroup: {
125        width: rpx(200),
126        justifyContent: 'flex-end',
127        flexDirection: 'row',
128        alignItems: 'center',
129    },
130    actionIcon: {
131        marginLeft: rpx(36),
132    },
133});
134