|
@ -1,132 +1,229 @@ |
|
|
import React, { useContext, useEffect, useRef } from 'react'; |
|
|
import React, { useEffect, useState, useRef } from 'react'; |
|
|
import ReactAudioPlayer from 'react-audio-player'; |
|
|
import { FlexboxGrid, Icon, Slider, Button } from 'rsuite'; |
|
|
import { Button } from 'rsuite'; |
|
|
import format from 'format-duration'; |
|
|
import { useAppDispatch, useAppSelector } from '../../redux/hooks'; |
|
|
import styled from 'styled-components'; |
|
|
import { |
|
|
import { |
|
|
incrementCurrentIndex, |
|
|
incrementCurrentIndex, |
|
|
incrementPlayerIndex, |
|
|
decrementCurrentIndex, |
|
|
|
|
|
setVolume, |
|
|
|
|
|
setPlayerVolume, |
|
|
|
|
|
setStatus, |
|
|
} from '../../redux/playQueueSlice'; |
|
|
} from '../../redux/playQueueSlice'; |
|
|
import { PlayerContext } from './Player'; |
|
|
import { useAppDispatch, useAppSelector } from '../../redux/hooks'; |
|
|
|
|
|
import Player from './Player'; |
|
|
|
|
|
import 'react-rangeslider/lib/index.css'; |
|
|
|
|
|
|
|
|
const PlayerBar = () => { |
|
|
const PlayerContainer = styled.div` |
|
|
const player1Ref = useRef<any>(); |
|
|
background: #000000; |
|
|
const player2Ref = useRef<any>(); |
|
|
height: 100%; |
|
|
const { |
|
|
border-top: 1px solid #48545c; |
|
|
player1Volume, |
|
|
`;
|
|
|
player2Volume, |
|
|
|
|
|
setPlayer1Volume, |
|
|
|
|
|
setPlayer2Volume, |
|
|
|
|
|
incremented, |
|
|
|
|
|
setIncremented, |
|
|
|
|
|
globalVolume, |
|
|
|
|
|
currentPlayer, |
|
|
|
|
|
setCurrentPlayer, |
|
|
|
|
|
} = useContext(PlayerContext); |
|
|
|
|
|
|
|
|
|
|
|
const dispatch = useAppDispatch(); |
|
|
const PlayerColumn = styled.div<{ |
|
|
const playQueue = useAppSelector((state) => state.playQueue); |
|
|
left?: boolean; |
|
|
|
|
|
center?: boolean; |
|
|
|
|
|
right?: boolean; |
|
|
|
|
|
height: string; |
|
|
|
|
|
}>` |
|
|
|
|
|
height: ${(props) => props.height}; |
|
|
|
|
|
display: flex; |
|
|
|
|
|
align-items: center; |
|
|
|
|
|
justify-content: ${(props) => |
|
|
|
|
|
props.left |
|
|
|
|
|
? 'flex-start' |
|
|
|
|
|
: props.center |
|
|
|
|
|
? 'center' |
|
|
|
|
|
: props.right |
|
|
|
|
|
? 'flex-end' |
|
|
|
|
|
: 'center'}; |
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
const handleListen = () => { |
|
|
const PlayerControlIcon = styled(Icon)` |
|
|
const fadeDuration = 10; |
|
|
color: #b3b3b3; |
|
|
const currentTime = player1Ref.current?.audioEl.current?.currentTime || 0; |
|
|
padding: 0 15px 0 15px; |
|
|
const duration = player1Ref.current?.audioEl.current?.duration; |
|
|
&:hover { |
|
|
const fadeAtTime = duration - fadeDuration; |
|
|
color: #fff; |
|
|
|
|
|
|
|
|
if (currentTime >= fadeAtTime) { |
|
|
|
|
|
if (player2Ref.current.audioEl.current) { |
|
|
|
|
|
// Once fading starts, start playing player 2 and set current to 2
|
|
|
|
|
|
setPlayer1Volume( |
|
|
|
|
|
player1Volume - globalVolume / (fadeDuration * 2) <= 0 |
|
|
|
|
|
? 0 |
|
|
|
|
|
: player1Volume - globalVolume / (fadeDuration * 2) |
|
|
|
|
|
); |
|
|
|
|
|
setPlayer2Volume( |
|
|
|
|
|
player2Volume + globalVolume / (fadeDuration * 1.5) >= globalVolume |
|
|
|
|
|
? globalVolume |
|
|
|
|
|
: player2Volume + globalVolume / (fadeDuration * 1.5) |
|
|
|
|
|
); |
|
|
|
|
|
player2Ref.current.audioEl.current.play(); |
|
|
|
|
|
if (!incremented) { |
|
|
|
|
|
dispatch(incrementCurrentIndex('none')); |
|
|
|
|
|
setIncremented(true); |
|
|
|
|
|
} |
|
|
} |
|
|
setCurrentPlayer(2); |
|
|
`;
|
|
|
|
|
|
|
|
|
|
|
|
const PlayerBar = () => { |
|
|
|
|
|
const playQueue = useAppSelector((state) => state.playQueue); |
|
|
|
|
|
const dispatch = useAppDispatch(); |
|
|
|
|
|
const [seek, setSeek] = useState(0); |
|
|
|
|
|
const [isDragging, setIsDragging] = useState(false); |
|
|
|
|
|
const [manualSeek, setManualSeek] = useState(0); |
|
|
|
|
|
const [isLoading, setIsLoading] = useState(false); |
|
|
|
|
|
const playersRef = useRef<any>(); |
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
|
|
setSeek(playQueue.currentSeek); |
|
|
|
|
|
}, [playQueue.currentSeek]); |
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
|
|
if (isDragging) { |
|
|
|
|
|
if (playQueue.currentPlayer === 1) { |
|
|
|
|
|
playersRef.current.player1.audioEl.current.currentTime = manualSeek; |
|
|
|
|
|
} else { |
|
|
|
|
|
playersRef.current.player2.audioEl.current.currentTime = manualSeek; |
|
|
} |
|
|
} |
|
|
console.log('fading player1...'); |
|
|
|
|
|
|
|
|
// Wait for the seek to catch up, otherwise the bar will bounce back and forth
|
|
|
|
|
|
setTimeout(() => { |
|
|
|
|
|
setIsDragging(false); |
|
|
|
|
|
}, 1500); |
|
|
} |
|
|
} |
|
|
console.log(`player1: ${currentTime} / ${fadeAtTime}`); |
|
|
}, [isDragging, manualSeek, playQueue.currentPlayer]); |
|
|
|
|
|
|
|
|
|
|
|
/* const handleOnLoadStart = () => { |
|
|
|
|
|
dispatch(setIsLoading()); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
const handleListen2 = () => { |
|
|
const handleOnLoadedData = () => { |
|
|
const fadeDuration = 10; |
|
|
dispatch(setIsLoaded()); |
|
|
const currentTime = player2Ref.current?.audioEl.current?.currentTime || 0; |
|
|
}; */ |
|
|
const duration = player2Ref.current?.audioEl.current?.duration; |
|
|
|
|
|
const fadeAtTime = duration - fadeDuration; |
|
|
const handleClickNext = () => { |
|
|
|
|
|
dispatch(incrementCurrentIndex('usingHotkey')); |
|
|
if (currentTime >= fadeAtTime) { |
|
|
}; |
|
|
if (player1Ref.current.audioEl.current) { |
|
|
|
|
|
// Once fading starts, start playing player 1 and set current to 1
|
|
|
const handleClickPrevious = () => { |
|
|
setPlayer1Volume( |
|
|
dispatch(decrementCurrentIndex('usingHotkey')); |
|
|
player1Volume + globalVolume / (fadeDuration * 1.5) >= globalVolume |
|
|
}; |
|
|
? globalVolume |
|
|
|
|
|
: player1Volume + globalVolume / (fadeDuration * 1.5) |
|
|
const handleClickPlayPause = () => { |
|
|
); |
|
|
dispatch(setStatus(playQueue.status === 'PLAYING' ? 'PAUSED' : 'PLAYING')); |
|
|
setPlayer2Volume( |
|
|
}; |
|
|
player2Volume - globalVolume / (fadeDuration * 2) <= 0 |
|
|
|
|
|
? 0 |
|
|
const handleVolumeSlider = (e: number) => { |
|
|
: player2Volume - globalVolume / (fadeDuration * 2) |
|
|
const vol = Number((e / 100).toFixed(2)); |
|
|
); |
|
|
dispatch(setVolume(vol)); |
|
|
player1Ref.current.audioEl.current.play(); |
|
|
dispatch(setPlayerVolume({ player: playQueue.currentPlayer, volume: vol })); |
|
|
if (!incremented) { |
|
|
|
|
|
dispatch(incrementCurrentIndex('none')); |
|
|
|
|
|
setIncremented(true); |
|
|
|
|
|
} |
|
|
|
|
|
setCurrentPlayer(1); |
|
|
|
|
|
} |
|
|
|
|
|
console.log('fading player2...'); |
|
|
|
|
|
} |
|
|
|
|
|
console.log(`player2: ${currentTime} / ${fadeAtTime}`); |
|
|
|
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
const handleOnEnded1 = () => { |
|
|
const handleSeekSlider = (e: number) => { |
|
|
dispatch(incrementPlayerIndex(1)); |
|
|
setIsDragging(true); |
|
|
setPlayer1Volume(0); |
|
|
setManualSeek(e); |
|
|
setPlayer2Volume(globalVolume); |
|
|
console.log(e); |
|
|
setIncremented(false); |
|
|
|
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
const handleOnEnded2 = () => { |
|
|
const handleOnWaiting = () => { |
|
|
dispatch(incrementPlayerIndex(2)); |
|
|
/* console.log( |
|
|
setPlayer1Volume(globalVolume); |
|
|
(playersRef.current?.player1.audioEl.current.onwaiting = () => { |
|
|
setPlayer2Volume(0); |
|
|
console.log('Waiting'); |
|
|
setIncremented(false); |
|
|
}) |
|
|
|
|
|
); */ |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
return ( |
|
|
return ( |
|
|
<> |
|
|
<PlayerContainer> |
|
|
<ReactAudioPlayer |
|
|
<Player ref={playersRef} isDragging={isDragging} /> |
|
|
ref={player1Ref} |
|
|
<Button onClick={handleOnWaiting} /> |
|
|
src={playQueue.entry[playQueue.player1Index]?.streamUrl} |
|
|
|
|
|
listenInterval={500} |
|
|
<FlexboxGrid align="middle" style={{ height: '100%' }}> |
|
|
preload="auto" |
|
|
<FlexboxGrid.Item |
|
|
onListen={handleListen} |
|
|
colspan={6} |
|
|
onEnded={handleOnEnded1} |
|
|
style={{ textAlign: 'left', paddingLeft: '25px' }} |
|
|
controls |
|
|
> |
|
|
volume={player1Volume} |
|
|
<PlayerColumn left height="50px"> |
|
|
autoPlay={playQueue.player1Index === playQueue.currentIndex} |
|
|
<div>Is seeking: {isDragging ? 'true' : 'false'}</div> |
|
|
|
|
|
</PlayerColumn> |
|
|
|
|
|
</FlexboxGrid.Item> |
|
|
|
|
|
<FlexboxGrid.Item |
|
|
|
|
|
colspan={12} |
|
|
|
|
|
style={{ textAlign: 'center', verticalAlign: 'middle' }} |
|
|
|
|
|
> |
|
|
|
|
|
<PlayerColumn center height="45px"> |
|
|
|
|
|
<PlayerControlIcon icon="random" size="lg" /> |
|
|
|
|
|
<PlayerControlIcon |
|
|
|
|
|
icon="step-backward" |
|
|
|
|
|
size="lg" |
|
|
|
|
|
onClick={handleClickPrevious} |
|
|
|
|
|
/> |
|
|
|
|
|
<PlayerControlIcon |
|
|
|
|
|
icon={ |
|
|
|
|
|
playQueue.status === 'PLAYING' ? 'pause-circle' : 'play-circle' |
|
|
|
|
|
} |
|
|
|
|
|
size="3x" |
|
|
|
|
|
onClick={handleClickPlayPause} |
|
|
|
|
|
/> |
|
|
|
|
|
<PlayerControlIcon |
|
|
|
|
|
icon="step-forward" |
|
|
|
|
|
size="lg" |
|
|
|
|
|
onClick={handleClickNext} |
|
|
|
|
|
/> |
|
|
|
|
|
<PlayerControlIcon |
|
|
|
|
|
icon="repeat" |
|
|
|
|
|
size="lg" |
|
|
|
|
|
onClick={() => console.log('h')} |
|
|
|
|
|
/> |
|
|
|
|
|
</PlayerColumn> |
|
|
|
|
|
<PlayerColumn center height="35px"> |
|
|
|
|
|
<FlexboxGrid |
|
|
|
|
|
justify="center" |
|
|
|
|
|
style={{ |
|
|
|
|
|
width: '100%', |
|
|
|
|
|
display: 'flex', |
|
|
|
|
|
alignItems: 'center', |
|
|
|
|
|
height: '35px', |
|
|
|
|
|
}} |
|
|
|
|
|
> |
|
|
|
|
|
<FlexboxGrid.Item |
|
|
|
|
|
colspan={4} |
|
|
|
|
|
style={{ textAlign: 'right', paddingRight: '10px' }} |
|
|
|
|
|
> |
|
|
|
|
|
{format((isDragging ? manualSeek : seek) * 1000)} |
|
|
|
|
|
</FlexboxGrid.Item> |
|
|
|
|
|
<FlexboxGrid.Item colspan={16}> |
|
|
|
|
|
<Slider |
|
|
|
|
|
progress |
|
|
|
|
|
defaultValue={0} |
|
|
|
|
|
value={isDragging ? manualSeek : seek} |
|
|
|
|
|
tooltip={false} |
|
|
|
|
|
max={ |
|
|
|
|
|
playQueue.entry[playQueue.currentIndex]?.duration - |
|
|
|
|
|
10 * 1.3 || 0 |
|
|
|
|
|
} |
|
|
|
|
|
onChange={handleSeekSlider} |
|
|
|
|
|
style={{ width: '100%' }} |
|
|
|
|
|
/> |
|
|
|
|
|
</FlexboxGrid.Item> |
|
|
|
|
|
<FlexboxGrid.Item |
|
|
|
|
|
colspan={4} |
|
|
|
|
|
style={{ textAlign: 'left', paddingLeft: '10px' }} |
|
|
|
|
|
> |
|
|
|
|
|
{format( |
|
|
|
|
|
playQueue.entry[playQueue.currentIndex]?.duration * 1000 || 0 |
|
|
|
|
|
)} |
|
|
|
|
|
</FlexboxGrid.Item> |
|
|
|
|
|
</FlexboxGrid> |
|
|
|
|
|
</PlayerColumn> |
|
|
|
|
|
</FlexboxGrid.Item> |
|
|
|
|
|
<FlexboxGrid.Item |
|
|
|
|
|
colspan={6} |
|
|
|
|
|
style={{ textAlign: 'right', paddingRight: '25px' }} |
|
|
|
|
|
> |
|
|
|
|
|
<PlayerColumn right height="45px"> |
|
|
|
|
|
<Icon |
|
|
|
|
|
icon={ |
|
|
|
|
|
playQueue.volume > 0.7 |
|
|
|
|
|
? 'volume-up' |
|
|
|
|
|
: playQueue.volume < 0.3 |
|
|
|
|
|
? 'volume-off' |
|
|
|
|
|
: 'volume-down' |
|
|
|
|
|
} |
|
|
|
|
|
size="lg" |
|
|
|
|
|
style={{ marginRight: '15px' }} |
|
|
/> |
|
|
/> |
|
|
<ReactAudioPlayer |
|
|
<Slider |
|
|
ref={player2Ref} |
|
|
progress |
|
|
src={playQueue.entry[playQueue.player2Index]?.streamUrl} |
|
|
value={Math.floor(playQueue.volume * 100)} |
|
|
listenInterval={500} |
|
|
style={{ width: '80px' }} |
|
|
preload="auto" |
|
|
onChange={handleVolumeSlider} |
|
|
onListen={handleListen2} |
|
|
|
|
|
onEnded={handleOnEnded2} |
|
|
|
|
|
controls |
|
|
|
|
|
volume={player2Volume} |
|
|
|
|
|
autoPlay={playQueue.player2Index === playQueue.currentIndex} |
|
|
|
|
|
/> |
|
|
/> |
|
|
<Button onClick={() => console.log(playQueue.entry)}>Length</Button> |
|
|
</PlayerColumn> |
|
|
|
|
|
</FlexboxGrid.Item> |
|
|
|
|
|
</FlexboxGrid> |
|
|
|
|
|
{/* <Button onClick={() => console.log(playQueue.entry)}>Length</Button> |
|
|
<div> |
|
|
<div> |
|
|
{`Current index: ${playQueue.currentIndex} | `} |
|
|
{`Current index: ${playQueue.currentIndex} | `} |
|
|
{`Player1 index: ${playQueue.player1Index} - ${ |
|
|
{`Player1 index: ${playQueue.player1Index} - ${ |
|
@ -136,8 +233,8 @@ const PlayerBar = () => { |
|
|
playQueue.entry[playQueue.player2Index]?.title |
|
|
playQueue.entry[playQueue.player2Index]?.title |
|
|
} | `}
|
|
|
} | `}
|
|
|
{`CurrentPlayer: ${playQueue.currentPlayer}`} |
|
|
{`CurrentPlayer: ${playQueue.currentPlayer}`} |
|
|
</div> |
|
|
</div> */} |
|
|
</> |
|
|
</PlayerContainer> |
|
|
); |
|
|
); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|