xref: /MusicFree/src/components/musicBar/index.tsx (revision 5589cdf32b2bb0f641e5ac7bf1f6152cd6b9b70e)
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                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"
98                            size={rpx(56)}
99                            onPress={() => {
100                                showPanel('PlayList');
101                            }}
102                            color={colors.musicBarText}
103                            style={[style.actionIcon]}
104                        />
105                    </View>
106                </View>
107            )}
108        </>
109    );
110}
111
112export default memo(MusicBar, () => true);
113
114const style = StyleSheet.create({
115    wrapper: {
116        width: '100%',
117        height: rpx(132),
118        flexDirection: 'row',
119        alignItems: 'center',
120        paddingRight: rpx(24),
121    },
122    actionGroup: {
123        width: rpx(200),
124        justifyContent: 'flex-end',
125        flexDirection: 'row',
126        alignItems: 'center',
127    },
128    actionIcon: {
129        marginLeft: rpx(36),
130    },
131});
132