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