xref: /MusicFree/src/components/musicBar/index.tsx (revision 6613e77203923e5b1742a49281bfa5de03fc1440)
1import React, {memo, useEffect, useState} from 'react';
2import {Keyboard, StyleSheet, View} from 'react-native';
3import rpx from '@/utils/rpx';
4import {CircularProgressBase} from 'react-native-circular-progress-indicator';
5
6import {useSafeAreaInsets} from 'react-native-safe-area-context';
7import {showPanel} from '../panels/usePanel';
8import useColors from '@/hooks/useColors';
9import IconButton from '../base/iconButton';
10import TrackPlayer from '@/core/trackPlayer';
11import {musicIsPaused} from '@/utils/trackUtils';
12import MusicInfo from './musicInfo';
13import Icon from '@/components/base/icon.tsx';
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                hitSlop={{
41                    top: 10,
42                    left: 10,
43                    right: 10,
44                    bottom: 10,
45                }}
46                color={colors.musicBarText}
47                onPress={async () => {
48                    if (isPaused) {
49                        await TrackPlayer.play();
50                    } else {
51                        await TrackPlayer.pause();
52                    }
53                }}
54            />
55        </CircularProgressBase>
56    );
57}
58function MusicBar() {
59    const musicItem = TrackPlayer.useCurrentMusic();
60
61    const [showKeyboard, setKeyboardStatus] = useState(false);
62
63    const colors = useColors();
64    const safeAreaInsets = useSafeAreaInsets();
65
66    useEffect(() => {
67        const showSubscription = Keyboard.addListener('keyboardDidShow', () => {
68            setKeyboardStatus(true);
69        });
70        const hideSubscription = Keyboard.addListener('keyboardDidHide', () => {
71            setKeyboardStatus(false);
72        });
73
74        return () => {
75            showSubscription.remove();
76            hideSubscription.remove();
77        };
78    }, []);
79
80    return (
81        <>
82            {musicItem && !showKeyboard && (
83                <View
84                    style={[
85                        style.wrapper,
86                        {
87                            backgroundColor: colors.musicBar,
88                            paddingRight: safeAreaInsets.right + rpx(24),
89                        },
90                    ]}
91                    accessible
92                    accessibilityLabel={`歌曲: ${musicItem.title} 歌手: ${musicItem.artist}`}
93                    // onPress={() => {
94                    //     navigate(ROUTE_PATH.MUSIC_DETAIL);
95                    // }}
96                >
97                    <MusicInfo musicItem={musicItem} />
98                    <View style={style.actionGroup}>
99                        <CircularPlayBtn />
100                        <Icon
101                            accessible
102                            accessibilityLabel="播放列表"
103                            name="playlist"
104                            size={rpx(56)}
105                            onPress={() => {
106                                showPanel('PlayList');
107                            }}
108                            color={colors.musicBarText}
109                            style={[style.actionIcon]}
110                        />
111                    </View>
112                </View>
113            )}
114        </>
115    );
116}
117
118export default memo(MusicBar, () => true);
119
120const style = StyleSheet.create({
121    wrapper: {
122        width: '100%',
123        height: rpx(132),
124        flexDirection: 'row',
125        alignItems: 'center',
126        paddingRight: rpx(24),
127    },
128    actionGroup: {
129        width: rpx(200),
130        justifyContent: 'flex-end',
131        flexDirection: 'row',
132        alignItems: 'center',
133    },
134    actionIcon: {
135        marginLeft: rpx(36),
136    },
137});
138