|
@ -1,4 +1,5 @@ |
|
|
import React, { useEffect, useState, useRef } from 'react'; |
|
|
import React, { useEffect, useState, useRef } from 'react'; |
|
|
|
|
|
import settings from 'electron-settings'; |
|
|
import { FlexboxGrid, Icon, Grid, Row, Col } from 'rsuite'; |
|
|
import { FlexboxGrid, Icon, Grid, Row, Col } from 'rsuite'; |
|
|
import { useHistory } from 'react-router-dom'; |
|
|
import { useHistory } from 'react-router-dom'; |
|
|
import { LazyLoadImage } from 'react-lazy-load-image-component'; |
|
|
import { LazyLoadImage } from 'react-lazy-load-image-component'; |
|
@ -30,6 +31,12 @@ const PlayerBar = () => { |
|
|
const [seek, setSeek] = useState(0); |
|
|
const [seek, setSeek] = useState(0); |
|
|
const [isDragging, setIsDragging] = useState(false); |
|
|
const [isDragging, setIsDragging] = useState(false); |
|
|
const [manualSeek, setManualSeek] = useState(0); |
|
|
const [manualSeek, setManualSeek] = useState(0); |
|
|
|
|
|
const [seekForwardInterval] = useState<number>( |
|
|
|
|
|
Number(settings.getSync('seekForwardInterval')) || 5 |
|
|
|
|
|
); |
|
|
|
|
|
const [seekBackwardInterval] = useState<number>( |
|
|
|
|
|
Number(settings.getSync('seekBackwardInterval')) || 5 |
|
|
|
|
|
); |
|
|
const playersRef = useRef<any>(); |
|
|
const playersRef = useRef<any>(); |
|
|
const history = useHistory(); |
|
|
const history = useHistory(); |
|
|
|
|
|
|
|
@ -71,6 +78,98 @@ const PlayerBar = () => { |
|
|
dispatch(setPlayerVolume({ player: playQueue.currentPlayer, volume: vol })); |
|
|
dispatch(setPlayerVolume({ player: playQueue.currentPlayer, volume: vol })); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const handleVolumeKey = (e: any) => { |
|
|
|
|
|
if (e.keyCode === 38) { |
|
|
|
|
|
const vol = Number( |
|
|
|
|
|
(playQueue.volume + 0.05 > 1 ? 1 : playQueue.volume + 0.05).toFixed(2) |
|
|
|
|
|
); |
|
|
|
|
|
dispatch(setVolume(vol)); |
|
|
|
|
|
dispatch( |
|
|
|
|
|
setPlayerVolume({ |
|
|
|
|
|
player: playQueue.currentPlayer, |
|
|
|
|
|
volume: vol, |
|
|
|
|
|
}) |
|
|
|
|
|
); |
|
|
|
|
|
} else if (e.keyCode === 40) { |
|
|
|
|
|
const vol = Number( |
|
|
|
|
|
(playQueue.volume - 0.05 < 0 ? 0 : playQueue.volume - 0.05).toFixed(2) |
|
|
|
|
|
); |
|
|
|
|
|
dispatch(setVolume(vol)); |
|
|
|
|
|
dispatch( |
|
|
|
|
|
setPlayerVolume({ |
|
|
|
|
|
player: playQueue.currentPlayer, |
|
|
|
|
|
volume: vol, |
|
|
|
|
|
}) |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const handleClickForward = () => { |
|
|
|
|
|
setIsDragging(true); |
|
|
|
|
|
|
|
|
|
|
|
if (playQueue.isFading) { |
|
|
|
|
|
if (playQueue.currentPlayer === 1) { |
|
|
|
|
|
playersRef.current.player2.audioEl.current.pause(); |
|
|
|
|
|
playersRef.current.player2.audioEl.current.currentTime = 0; |
|
|
|
|
|
dispatch(setPlayerVolume({ player: 1, volume: playQueue.volume })); |
|
|
|
|
|
dispatch(setPlayerVolume({ player: 2, volume: 0 })); |
|
|
|
|
|
} else { |
|
|
|
|
|
playersRef.current.player1.audioEl.current.pause(); |
|
|
|
|
|
playersRef.current.player1.audioEl.current.currentTime = 0; |
|
|
|
|
|
dispatch(setPlayerVolume({ player: 1, volume: 0 })); |
|
|
|
|
|
dispatch(setPlayerVolume({ player: 2, volume: playQueue.volume })); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (playQueue.currentPlayer === 1) { |
|
|
|
|
|
const calculatedTime = |
|
|
|
|
|
playersRef.current.player1.audioEl.current.currentTime + |
|
|
|
|
|
seekForwardInterval; |
|
|
|
|
|
const songDuration = playersRef.current.player1.audioEl.current.duration; |
|
|
|
|
|
setManualSeek( |
|
|
|
|
|
calculatedTime > songDuration ? songDuration - 1 : calculatedTime |
|
|
|
|
|
); |
|
|
|
|
|
} else { |
|
|
|
|
|
const calculatedTime = |
|
|
|
|
|
playersRef.current.player2.audioEl.current.currentTime + |
|
|
|
|
|
seekForwardInterval; |
|
|
|
|
|
const songDuration = playersRef.current.player2.audioEl.current.duration; |
|
|
|
|
|
setManualSeek( |
|
|
|
|
|
calculatedTime > songDuration ? songDuration - 1 : calculatedTime |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const handleClickBackward = () => { |
|
|
|
|
|
setIsDragging(true); |
|
|
|
|
|
|
|
|
|
|
|
if (playQueue.isFading) { |
|
|
|
|
|
if (playQueue.currentPlayer === 1) { |
|
|
|
|
|
playersRef.current.player2.audioEl.current.pause(); |
|
|
|
|
|
playersRef.current.player2.audioEl.current.currentTime = 0; |
|
|
|
|
|
dispatch(setPlayerVolume({ player: 1, volume: playQueue.volume })); |
|
|
|
|
|
dispatch(setPlayerVolume({ player: 2, volume: 0 })); |
|
|
|
|
|
} else { |
|
|
|
|
|
playersRef.current.player1.audioEl.current.pause(); |
|
|
|
|
|
playersRef.current.player1.audioEl.current.currentTime = 0; |
|
|
|
|
|
dispatch(setPlayerVolume({ player: 1, volume: 0 })); |
|
|
|
|
|
dispatch(setPlayerVolume({ player: 2, volume: playQueue.volume })); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (playQueue.currentPlayer === 1) { |
|
|
|
|
|
const calculatedTime = |
|
|
|
|
|
playersRef.current.player1.audioEl.current.currentTime - |
|
|
|
|
|
seekBackwardInterval; |
|
|
|
|
|
setManualSeek(calculatedTime < 0 ? 0 : calculatedTime); |
|
|
|
|
|
} else { |
|
|
|
|
|
const calculatedTime = |
|
|
|
|
|
playersRef.current.player2.audioEl.current.currentTime - |
|
|
|
|
|
seekBackwardInterval; |
|
|
|
|
|
setManualSeek(calculatedTime < 0 ? 0 : calculatedTime); |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
const handleSeekSlider = (e: number) => { |
|
|
const handleSeekSlider = (e: number) => { |
|
|
setIsDragging(true); |
|
|
setIsDragging(true); |
|
|
|
|
|
|
|
@ -118,19 +217,22 @@ const PlayerBar = () => { |
|
|
alignItems: 'center', |
|
|
alignItems: 'center', |
|
|
}} |
|
|
}} |
|
|
> |
|
|
> |
|
|
<Col |
|
|
<Col xs={2} style={{ height: '100%', width: '80px' }}> |
|
|
xs={2} |
|
|
|
|
|
onClick={() => history.push(`/nowplaying`)} |
|
|
|
|
|
style={{ height: '100%', width: '80px' }} |
|
|
|
|
|
> |
|
|
|
|
|
{playQueue.entry.length >= 1 && ( |
|
|
{playQueue.entry.length >= 1 && ( |
|
|
<LazyLoadImage |
|
|
<LazyLoadImage |
|
|
|
|
|
tabIndex={0} |
|
|
src={playQueue.entry[playQueue.currentIndex].image} |
|
|
src={playQueue.entry[playQueue.currentIndex].image} |
|
|
alt="trackImg" |
|
|
alt="trackImg" |
|
|
effect="opacity" |
|
|
effect="opacity" |
|
|
width="65" |
|
|
width="65" |
|
|
height="65" |
|
|
height="65" |
|
|
style={{ borderRadius: '10px', cursor: 'pointer' }} |
|
|
style={{ borderRadius: '10px', cursor: 'pointer' }} |
|
|
|
|
|
onClick={() => history.push(`/nowplaying`)} |
|
|
|
|
|
onKeyDown={(e: any) => { |
|
|
|
|
|
if (e.keyCode === 32) { |
|
|
|
|
|
history.push(`/nowplaying`); |
|
|
|
|
|
} |
|
|
|
|
|
}} |
|
|
/> |
|
|
/> |
|
|
)} |
|
|
)} |
|
|
</Col> |
|
|
</Col> |
|
@ -144,7 +246,7 @@ const PlayerBar = () => { |
|
|
}} |
|
|
}} |
|
|
> |
|
|
> |
|
|
{playQueue.entry.length >= 1 && ( |
|
|
{playQueue.entry.length >= 1 && ( |
|
|
<LinkButton> |
|
|
<LinkButton tabIndex={0}> |
|
|
{playQueue.entry[playQueue.currentIndex]?.title || |
|
|
{playQueue.entry[playQueue.currentIndex]?.title || |
|
|
'Unknown title'} |
|
|
'Unknown title'} |
|
|
</LinkButton> |
|
|
</LinkButton> |
|
@ -153,7 +255,7 @@ const PlayerBar = () => { |
|
|
|
|
|
|
|
|
<Row style={{ height: '35px', width: '100%' }}> |
|
|
<Row style={{ height: '35px', width: '100%' }}> |
|
|
{playQueue.entry.length >= 1 && ( |
|
|
{playQueue.entry.length >= 1 && ( |
|
|
<LinkButton subtitle="true"> |
|
|
<LinkButton tabIndex={0} subtitle="true"> |
|
|
{playQueue.entry[playQueue.currentIndex]?.artist || |
|
|
{playQueue.entry[playQueue.currentIndex]?.artist || |
|
|
'Unknown artist'} |
|
|
'Unknown artist'} |
|
|
</LinkButton> |
|
|
</LinkButton> |
|
@ -169,14 +271,35 @@ const PlayerBar = () => { |
|
|
style={{ textAlign: 'center', verticalAlign: 'middle' }} |
|
|
style={{ textAlign: 'center', verticalAlign: 'middle' }} |
|
|
> |
|
|
> |
|
|
<PlayerColumn center height="45px"> |
|
|
<PlayerColumn center height="45px"> |
|
|
<PlayerControlIcon icon="backward" size="lg" fixedWidth /> |
|
|
{/* Seek Backward Button */} |
|
|
|
|
|
<PlayerControlIcon |
|
|
|
|
|
tabIndex={0} |
|
|
|
|
|
icon="backward" |
|
|
|
|
|
size="lg" |
|
|
|
|
|
fixedWidth |
|
|
|
|
|
onClick={handleClickBackward} |
|
|
|
|
|
onKeyDown={(e: any) => { |
|
|
|
|
|
if (e.keyCode === 32) { |
|
|
|
|
|
handleClickBackward(); |
|
|
|
|
|
} |
|
|
|
|
|
}} |
|
|
|
|
|
/> |
|
|
|
|
|
{/* Previous Song Button */} |
|
|
<PlayerControlIcon |
|
|
<PlayerControlIcon |
|
|
|
|
|
tabIndex={0} |
|
|
icon="step-backward" |
|
|
icon="step-backward" |
|
|
size="lg" |
|
|
size="lg" |
|
|
fixedWidth |
|
|
fixedWidth |
|
|
onClick={handleClickPrevious} |
|
|
onClick={handleClickPrevious} |
|
|
|
|
|
onKeyDown={(e: any) => { |
|
|
|
|
|
if (e.keyCode === 32) { |
|
|
|
|
|
handleClickPrevious(); |
|
|
|
|
|
} |
|
|
|
|
|
}} |
|
|
/> |
|
|
/> |
|
|
|
|
|
{/* Play/Pause Button */} |
|
|
<PlayerControlIcon |
|
|
<PlayerControlIcon |
|
|
|
|
|
tabIndex={0} |
|
|
icon={ |
|
|
icon={ |
|
|
playQueue.status === 'PLAYING' |
|
|
playQueue.status === 'PLAYING' |
|
|
? 'pause-circle' |
|
|
? 'pause-circle' |
|
@ -188,14 +311,38 @@ const PlayerBar = () => { |
|
|
} |
|
|
} |
|
|
size="3x" |
|
|
size="3x" |
|
|
onClick={handleClickPlayPause} |
|
|
onClick={handleClickPlayPause} |
|
|
|
|
|
onKeyDown={(e: any) => { |
|
|
|
|
|
if (e.keyCode === 32) { |
|
|
|
|
|
handleClickPlayPause(); |
|
|
|
|
|
} |
|
|
|
|
|
}} |
|
|
/> |
|
|
/> |
|
|
|
|
|
{/* Next Song Button */} |
|
|
<PlayerControlIcon |
|
|
<PlayerControlIcon |
|
|
|
|
|
tabIndex={0} |
|
|
icon="step-forward" |
|
|
icon="step-forward" |
|
|
size="lg" |
|
|
size="lg" |
|
|
fixedWidth |
|
|
fixedWidth |
|
|
onClick={handleClickNext} |
|
|
onClick={handleClickNext} |
|
|
|
|
|
onKeyDown={(e: any) => { |
|
|
|
|
|
if (e.keyCode === 32) { |
|
|
|
|
|
handleClickNext(); |
|
|
|
|
|
} |
|
|
|
|
|
}} |
|
|
|
|
|
/> |
|
|
|
|
|
{/* Seek Forward Button */} |
|
|
|
|
|
<PlayerControlIcon |
|
|
|
|
|
tabIndex={0} |
|
|
|
|
|
icon="forward" |
|
|
|
|
|
size="lg" |
|
|
|
|
|
fixedWidth |
|
|
|
|
|
onClick={handleClickForward} |
|
|
|
|
|
onKeyDown={(e: any) => { |
|
|
|
|
|
if (e.keyCode === 32) { |
|
|
|
|
|
handleClickForward(); |
|
|
|
|
|
} |
|
|
|
|
|
}} |
|
|
/> |
|
|
/> |
|
|
<PlayerControlIcon icon="forward" size="lg" fixedWidth /> |
|
|
|
|
|
</PlayerColumn> |
|
|
</PlayerColumn> |
|
|
<PlayerColumn center height="35px"> |
|
|
<PlayerColumn center height="35px"> |
|
|
<FlexboxGrid |
|
|
<FlexboxGrid |
|
@ -214,6 +361,7 @@ const PlayerBar = () => { |
|
|
{format((isDragging ? manualSeek : seek) * 1000)} |
|
|
{format((isDragging ? manualSeek : seek) * 1000)} |
|
|
</FlexboxGrid.Item> |
|
|
</FlexboxGrid.Item> |
|
|
<FlexboxGrid.Item colspan={16}> |
|
|
<FlexboxGrid.Item colspan={16}> |
|
|
|
|
|
{/* Seek Slider */} |
|
|
<CustomSlider |
|
|
<CustomSlider |
|
|
progress |
|
|
progress |
|
|
defaultValue={0} |
|
|
defaultValue={0} |
|
@ -252,8 +400,10 @@ const PlayerBar = () => { |
|
|
> |
|
|
> |
|
|
{playQueue.entry.length >= 1 && ( |
|
|
{playQueue.entry.length >= 1 && ( |
|
|
<> |
|
|
<> |
|
|
|
|
|
{/* Star Button */} |
|
|
<CustomTooltip text="Star" delay={1000}> |
|
|
<CustomTooltip text="Star" delay={1000}> |
|
|
<PlayerControlIcon |
|
|
<PlayerControlIcon |
|
|
|
|
|
tabIndex={0} |
|
|
icon={ |
|
|
icon={ |
|
|
playQueue.entry[playQueue.currentIndex].starred |
|
|
playQueue.entry[playQueue.currentIndex].starred |
|
|
? 'star' |
|
|
? 'star' |
|
@ -268,22 +418,37 @@ const PlayerBar = () => { |
|
|
}} |
|
|
}} |
|
|
/> |
|
|
/> |
|
|
</CustomTooltip> |
|
|
</CustomTooltip> |
|
|
|
|
|
|
|
|
|
|
|
{/* Shuffle Button */} |
|
|
<CustomTooltip text="Shuffle" delay={1000}> |
|
|
<CustomTooltip text="Shuffle" delay={1000}> |
|
|
<PlayerControlIcon |
|
|
<PlayerControlIcon |
|
|
|
|
|
tabIndex={0} |
|
|
icon="random" |
|
|
icon="random" |
|
|
size="lg" |
|
|
size="lg" |
|
|
onClick={handleShuffle} |
|
|
onClick={handleShuffle} |
|
|
|
|
|
onKeyDown={(e: any) => { |
|
|
|
|
|
if (e.keyCode === 32) { |
|
|
|
|
|
handleShuffle(); |
|
|
|
|
|
} |
|
|
|
|
|
}} |
|
|
style={{ |
|
|
style={{ |
|
|
color: playQueue.shuffle ? '#1179ac' : undefined, |
|
|
color: playQueue.shuffle ? '#1179ac' : undefined, |
|
|
}} |
|
|
}} |
|
|
/> |
|
|
/> |
|
|
</CustomTooltip> |
|
|
</CustomTooltip> |
|
|
|
|
|
|
|
|
|
|
|
{/* Repeat Button */} |
|
|
<CustomTooltip text="Repeat" delay={1000}> |
|
|
<CustomTooltip text="Repeat" delay={1000}> |
|
|
<PlayerControlIcon |
|
|
<PlayerControlIcon |
|
|
|
|
|
tabIndex={0} |
|
|
icon="repeat" |
|
|
icon="repeat" |
|
|
size="lg" |
|
|
size="lg" |
|
|
onClick={handleRepeat} |
|
|
onClick={handleRepeat} |
|
|
inverse={playQueue.repeat === 'all'} |
|
|
onKeyDown={(e: any) => { |
|
|
|
|
|
if (e.keyCode === 32) { |
|
|
|
|
|
handleRepeat(); |
|
|
|
|
|
} |
|
|
|
|
|
}} |
|
|
style={{ |
|
|
style={{ |
|
|
color: |
|
|
color: |
|
|
playQueue.repeat === 'all' |
|
|
playQueue.repeat === 'all' |
|
@ -303,6 +468,7 @@ const PlayerBar = () => { |
|
|
justifyContent: 'flex-end', |
|
|
justifyContent: 'flex-end', |
|
|
}} |
|
|
}} |
|
|
> |
|
|
> |
|
|
|
|
|
{/* Volume Slider */} |
|
|
<Icon |
|
|
<Icon |
|
|
icon={ |
|
|
icon={ |
|
|
playQueue.volume > 0.7 |
|
|
playQueue.volume > 0.7 |
|
@ -315,11 +481,13 @@ const PlayerBar = () => { |
|
|
style={{ marginRight: '15px', padding: '0' }} |
|
|
style={{ marginRight: '15px', padding: '0' }} |
|
|
/> |
|
|
/> |
|
|
<CustomSlider |
|
|
<CustomSlider |
|
|
|
|
|
tabIndex={0} |
|
|
progress |
|
|
progress |
|
|
value={Math.floor(playQueue.volume * 100)} |
|
|
value={Math.floor(playQueue.volume * 100)} |
|
|
tooltip={false} |
|
|
tooltip={false} |
|
|
style={{ width: '100px', marginRight: '10px' }} |
|
|
style={{ width: '100px', marginRight: '10px' }} |
|
|
onChange={handleVolumeSlider} |
|
|
onChange={handleVolumeSlider} |
|
|
|
|
|
onKeyDown={handleVolumeKey} |
|
|
/> |
|
|
/> |
|
|
</Row> |
|
|
</Row> |
|
|
</Grid> |
|
|
</Grid> |
|
|