mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-09 10:34:17 +00:00
support for live mode
This commit is contained in:
parent
05428959ff
commit
37b920b5ab
@ -7,193 +7,210 @@ import useHideOnMouseStop from "@hooks/useHideOnMouseStop"
|
||||
|
||||
import { Icons } from "@components/Icons"
|
||||
import Controls from "@components/Player/Controls"
|
||||
import LiveInfo from "@components/Player/LiveInfo"
|
||||
|
||||
import { usePlayerStateContext } from "@contexts/WithPlayerContext"
|
||||
|
||||
function isOverflown(element) {
|
||||
if (!element) {
|
||||
return false
|
||||
}
|
||||
if (!element) {
|
||||
return false
|
||||
}
|
||||
|
||||
return element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth;
|
||||
return (
|
||||
element.scrollHeight > element.clientHeight ||
|
||||
element.scrollWidth > element.clientWidth
|
||||
)
|
||||
}
|
||||
|
||||
const PlayerController = React.forwardRef((props, ref) => {
|
||||
const [playerState] = usePlayerStateContext()
|
||||
const [playerState] = usePlayerStateContext()
|
||||
|
||||
const titleRef = React.useRef()
|
||||
const titleRef = React.useRef()
|
||||
|
||||
const [hide, onMouseEnter, onMouseLeave] = useHideOnMouseStop({ delay: 3000, hideCursor: true })
|
||||
const [titleIsOverflown, setTitleIsOverflown] = React.useState(false)
|
||||
const [hide, onMouseEnter, onMouseLeave] = useHideOnMouseStop({
|
||||
delay: 3000,
|
||||
hideCursor: true,
|
||||
})
|
||||
const [titleIsOverflown, setTitleIsOverflown] = React.useState(false)
|
||||
|
||||
const [currentTime, setCurrentTime] = React.useState(0)
|
||||
const [trackDuration, setTrackDuration] = React.useState(0)
|
||||
const [draggingTime, setDraggingTime] = React.useState(false)
|
||||
const [currentDragWidth, setCurrentDragWidth] = React.useState(0)
|
||||
const [syncInterval, setSyncInterval] = React.useState(null)
|
||||
const [currentTime, setCurrentTime] = React.useState(0)
|
||||
const [trackDuration, setTrackDuration] = React.useState(0)
|
||||
const [draggingTime, setDraggingTime] = React.useState(false)
|
||||
const [currentDragWidth, setCurrentDragWidth] = React.useState(0)
|
||||
const [syncInterval, setSyncInterval] = React.useState(null)
|
||||
|
||||
async function onDragEnd(seekTime) {
|
||||
setDraggingTime(false)
|
||||
async function onDragEnd(seekTime) {
|
||||
setDraggingTime(false)
|
||||
|
||||
app.cores.player.controls.seek(seekTime)
|
||||
app.cores.player.controls.seek(seekTime)
|
||||
|
||||
syncPlayback()
|
||||
}
|
||||
syncPlayback()
|
||||
}
|
||||
|
||||
async function syncPlayback() {
|
||||
if (!playerState.track_manifest) {
|
||||
return false
|
||||
}
|
||||
async function syncPlayback() {
|
||||
if (!playerState.track_manifest) {
|
||||
return false
|
||||
}
|
||||
|
||||
const currentTrackTime = app.cores.player.controls.seek()
|
||||
const currentTrackTime = app.cores.player.controls.seek()
|
||||
|
||||
setCurrentTime(currentTrackTime)
|
||||
}
|
||||
setCurrentTime(currentTrackTime)
|
||||
}
|
||||
|
||||
//* Handle when playback status change
|
||||
React.useEffect(() => {
|
||||
if (playerState.playback_status === "playing") {
|
||||
setSyncInterval(setInterval(syncPlayback, 1000))
|
||||
} else {
|
||||
if (syncInterval) {
|
||||
clearInterval(syncInterval)
|
||||
}
|
||||
}
|
||||
}, [playerState.playback_status])
|
||||
//* Handle when playback status change
|
||||
React.useEffect(() => {
|
||||
if (playerState.playback_status === "playing") {
|
||||
setSyncInterval(setInterval(syncPlayback, 1000))
|
||||
} else {
|
||||
if (syncInterval) {
|
||||
clearInterval(syncInterval)
|
||||
}
|
||||
}
|
||||
}, [playerState.playback_status])
|
||||
|
||||
React.useEffect(() => {
|
||||
setTitleIsOverflown(isOverflown(titleRef.current))
|
||||
setTrackDuration(app.cores.player.controls.duration())
|
||||
}, [playerState.track_manifest])
|
||||
React.useEffect(() => {
|
||||
setTitleIsOverflown(isOverflown(titleRef.current))
|
||||
setTrackDuration(app.cores.player.controls.duration())
|
||||
}, [playerState.track_manifest])
|
||||
|
||||
React.useEffect(() => {
|
||||
syncPlayback()
|
||||
}, [])
|
||||
React.useEffect(() => {
|
||||
syncPlayback()
|
||||
}, [])
|
||||
|
||||
const isStopped = playerState.playback_status === "stopped"
|
||||
const isStopped = playerState.playback_status === "stopped"
|
||||
|
||||
return <div
|
||||
className={classnames(
|
||||
"lyrics-player-controller-wrapper",
|
||||
{
|
||||
["hidden"]: props.lyrics?.video_source && hide,
|
||||
}
|
||||
)}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
>
|
||||
<div className="lyrics-player-controller">
|
||||
<div className="lyrics-player-controller-info">
|
||||
<div className="lyrics-player-controller-info-title">
|
||||
{
|
||||
<h4
|
||||
ref={titleRef}
|
||||
className={classnames(
|
||||
"lyrics-player-controller-info-title-text",
|
||||
{
|
||||
["overflown"]: titleIsOverflown,
|
||||
}
|
||||
)}
|
||||
>
|
||||
{
|
||||
playerState.playback_status === "stopped" ? "Nothing is playing" : <>
|
||||
{playerState.track_manifest?.title ?? "Nothing is playing"}
|
||||
</>
|
||||
}
|
||||
</h4>
|
||||
}
|
||||
return (
|
||||
<div
|
||||
className={classnames("lyrics-player-controller-wrapper", {
|
||||
["hidden"]: props.lyrics?.video_source && hide,
|
||||
})}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
>
|
||||
<div className="lyrics-player-controller">
|
||||
<div className="lyrics-player-controller-info">
|
||||
<div className="lyrics-player-controller-info-title">
|
||||
{
|
||||
<h4
|
||||
ref={titleRef}
|
||||
className={classnames(
|
||||
"lyrics-player-controller-info-title-text",
|
||||
{
|
||||
["overflown"]: titleIsOverflown,
|
||||
},
|
||||
)}
|
||||
>
|
||||
{playerState.playback_status === "stopped" ||
|
||||
(!playerState.track_manifest?.title &&
|
||||
"Nothing is playing")}
|
||||
|
||||
{
|
||||
titleIsOverflown && <Marquee
|
||||
//gradient
|
||||
//gradientColor={bgColor}
|
||||
//gradientWidth={20}
|
||||
play={!isStopped}
|
||||
>
|
||||
<h4>
|
||||
{
|
||||
isStopped ?
|
||||
"Nothing is playing" :
|
||||
<>
|
||||
{playerState.track_manifest?.title ?? "Untitled"}
|
||||
</>
|
||||
}
|
||||
</h4>
|
||||
</Marquee>
|
||||
}
|
||||
</div>
|
||||
{playerState.playback_status !== "stopped" &&
|
||||
playerState.track_manifest?.title}
|
||||
</h4>
|
||||
}
|
||||
|
||||
<div className="lyrics-player-controller-info-details">
|
||||
<span>{playerState.track_manifest?.artistStr}</span>
|
||||
</div>
|
||||
</div>
|
||||
{titleIsOverflown && (
|
||||
<Marquee
|
||||
//gradient
|
||||
//gradientColor={bgColor}
|
||||
//gradientWidth={20}
|
||||
play={!isStopped}
|
||||
>
|
||||
<h4>
|
||||
{isStopped ? (
|
||||
"Nothing is playing"
|
||||
) : (
|
||||
<>
|
||||
{playerState.track_manifest
|
||||
?.title ?? "Untitled"}
|
||||
</>
|
||||
)}
|
||||
</h4>
|
||||
</Marquee>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<Controls />
|
||||
<div className="lyrics-player-controller-info-details">
|
||||
<span>{playerState.track_manifest?.artistStr}</span>
|
||||
</div>
|
||||
|
||||
<div className="lyrics-player-controller-progress-wrapper">
|
||||
<div
|
||||
className="lyrics-player-controller-progress"
|
||||
onMouseDown={(e) => {
|
||||
setDraggingTime(true)
|
||||
}}
|
||||
onMouseUp={(e) => {
|
||||
const rect = e.currentTarget.getBoundingClientRect()
|
||||
const seekTime = trackDuration * (e.clientX - rect.left) / rect.width
|
||||
{playerState.live && (
|
||||
<LiveInfo radioId={playerState.radioId} />
|
||||
)}
|
||||
</div>
|
||||
|
||||
onDragEnd(seekTime)
|
||||
}}
|
||||
onMouseMove={(e) => {
|
||||
const rect = e.currentTarget.getBoundingClientRect()
|
||||
const atWidth = (e.clientX - rect.left) / rect.width * 100
|
||||
<Controls streamMode={playerState.live} />
|
||||
|
||||
setCurrentDragWidth(atWidth)
|
||||
}}
|
||||
>
|
||||
<div className="lyrics-player-controller-progress-bar"
|
||||
style={{
|
||||
width: `${draggingTime ? currentDragWidth : ((currentTime / trackDuration) * 100)}%`
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{!playerState.live && (
|
||||
<div className="lyrics-player-controller-progress-wrapper">
|
||||
<div
|
||||
className="lyrics-player-controller-progress"
|
||||
onMouseDown={(e) => {
|
||||
setDraggingTime(true)
|
||||
}}
|
||||
onMouseUp={(e) => {
|
||||
const rect =
|
||||
e.currentTarget.getBoundingClientRect()
|
||||
const seekTime =
|
||||
(trackDuration * (e.clientX - rect.left)) /
|
||||
rect.width
|
||||
|
||||
<div className="lyrics-player-controller-tags">
|
||||
{
|
||||
playerState.track_manifest?.metadata.lossless && <Tag
|
||||
icon={<Icons.Lossless
|
||||
style={{
|
||||
margin:0,
|
||||
}}
|
||||
/>}
|
||||
bordered={false}
|
||||
/>
|
||||
}
|
||||
{
|
||||
playerState.track_manifest?.explicit && <Tag
|
||||
bordered={false}
|
||||
>
|
||||
Explicit
|
||||
</Tag>
|
||||
}
|
||||
{
|
||||
props.lyrics?.sync_audio_at && <Tag
|
||||
bordered={false}
|
||||
icon={<Icons.TbMovie />}
|
||||
>
|
||||
Video
|
||||
</Tag>
|
||||
}
|
||||
{
|
||||
props.lyrics?.available_langs?.length > 1 && <Button
|
||||
icon={<Icons.MdTranslate />}
|
||||
type={props.translationEnabled ? "primary" : "default"}
|
||||
onClick={() => props.toggleTranslationEnabled()}
|
||||
size="small"
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
onDragEnd(seekTime)
|
||||
}}
|
||||
onMouseMove={(e) => {
|
||||
const rect =
|
||||
e.currentTarget.getBoundingClientRect()
|
||||
const atWidth =
|
||||
((e.clientX - rect.left) / rect.width) * 100
|
||||
|
||||
setCurrentDragWidth(atWidth)
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="lyrics-player-controller-progress-bar"
|
||||
style={{
|
||||
width: `${draggingTime ? currentDragWidth : (currentTime / trackDuration) * 100}%`,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="lyrics-player-controller-tags">
|
||||
{playerState.track_manifest?.metadata.lossless && (
|
||||
<Tag
|
||||
icon={
|
||||
<Icons.Lossless
|
||||
style={{
|
||||
margin: 0,
|
||||
}}
|
||||
/>
|
||||
}
|
||||
bordered={false}
|
||||
/>
|
||||
)}
|
||||
{playerState.track_manifest?.explicit && (
|
||||
<Tag bordered={false}>Explicit</Tag>
|
||||
)}
|
||||
{props.lyrics?.sync_audio_at && (
|
||||
<Tag bordered={false} icon={<Icons.TbMovie />}>
|
||||
Video
|
||||
</Tag>
|
||||
)}
|
||||
{props.lyrics?.available_langs?.length > 1 && (
|
||||
<Button
|
||||
icon={<Icons.MdTranslate />}
|
||||
type={
|
||||
props.translationEnabled ? "primary" : "default"
|
||||
}
|
||||
onClick={() => props.toggleTranslationEnabled()}
|
||||
size="small"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
export default PlayerController
|
||||
export default PlayerController
|
||||
|
Loading…
x
Reference in New Issue
Block a user