mirror of
https://github.com/acid-info/logos-press-engine.git
synced 2025-02-23 06:38:27 +00:00
feat: show global audio player when scrolled
This commit is contained in:
parent
1454e5ae97
commit
7d9aedf8e5
@ -8,6 +8,7 @@ import { LogosCircleIcon } from '@/components/Icons/LogosCircleIcon'
|
||||
import { useHookstate } from '@hookstate/core'
|
||||
import { playerState } from '@/components/GlobalAudioPlayer/globalAudioPlayer.state'
|
||||
import EpisodeChannels from './Episode.Channels'
|
||||
import { useEffect, useRef } from 'react'
|
||||
|
||||
export type EpisodeHeaderProps = LPE.Podcast.Document & {
|
||||
url: string
|
||||
@ -26,25 +27,58 @@ const EpisodeHeader = ({
|
||||
const date = new Date(publishedAt)
|
||||
const state = useHookstate(playerState)
|
||||
|
||||
const playerContainerRef = useRef<HTMLDivElement>(null)
|
||||
const playerRef = useRef<ReactPlayer>(null)
|
||||
|
||||
useEffect(() => {
|
||||
const observer = new IntersectionObserver((entries) => {
|
||||
if (entries[0].isIntersecting) {
|
||||
state.set((prev) => ({
|
||||
...prev,
|
||||
isEnabled: false,
|
||||
}))
|
||||
} else {
|
||||
const offset = 0.5 // offset for episode player
|
||||
playerRef.current?.seekTo(state.value.playedSeconds + offset, 'seconds')
|
||||
state.set((prev) => ({
|
||||
...prev,
|
||||
playedSeconds: state.value.playedSeconds + offset,
|
||||
isEnabled: true,
|
||||
}))
|
||||
}
|
||||
})
|
||||
observer.observe(playerContainerRef.current as any)
|
||||
|
||||
return () => {
|
||||
observer.disconnect()
|
||||
state.set((prev) => ({
|
||||
...prev,
|
||||
isEnabled: true,
|
||||
}))
|
||||
}
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<EpisodeHeaderContainer>
|
||||
<PlayerContainer>
|
||||
<PlayerContainer ref={playerContainerRef}>
|
||||
<ReactPlayer
|
||||
ref={playerRef}
|
||||
url={url}
|
||||
controls={true}
|
||||
playing={state.value.playing}
|
||||
volume={state.value.volume}
|
||||
muted={state.value.isEnabled ? true : false}
|
||||
onProgress={(newState: { playedSeconds: number }) => {
|
||||
onProgress={(newState) => {
|
||||
state.set((prev) => ({
|
||||
...prev,
|
||||
playedSeconds: newState.playedSeconds,
|
||||
played: newState.played,
|
||||
loaded: newState.loaded,
|
||||
}))
|
||||
}}
|
||||
onPlay={() =>
|
||||
state.set((prev) => ({
|
||||
...prev,
|
||||
playing: true,
|
||||
isEnabled: true,
|
||||
}))
|
||||
}
|
||||
onPlay={() => {
|
||||
state.set((prev) => ({ ...prev, playing: true }))
|
||||
}}
|
||||
onPause={() => state.set((prev) => ({ ...prev, playing: false }))}
|
||||
onDuration={(duration) =>
|
||||
state.set((prev) => ({ ...prev, duration }))
|
||||
|
@ -25,6 +25,7 @@ export default function GlobalAudioPlayer() {
|
||||
const epState = useHookstate(episodeState)
|
||||
|
||||
const ref = useRef<ReactPlayer>(null)
|
||||
|
||||
const [episode, setEpisode] = useState<EpisodeProps>({
|
||||
title: '',
|
||||
podcast: '',
|
||||
@ -54,7 +55,12 @@ export default function GlobalAudioPlayer() {
|
||||
// }
|
||||
|
||||
const handlePlay = () => {
|
||||
state.set((prev) => ({ ...prev, playing: true }))
|
||||
ref.current?.seekTo(state.value.playedSeconds, 'seconds')
|
||||
state.set((prev) => ({
|
||||
...prev,
|
||||
playing: true,
|
||||
playedSeconds: state.value.playedSeconds,
|
||||
}))
|
||||
}
|
||||
|
||||
const handlePlayPause = () => {
|
||||
@ -85,9 +91,7 @@ export default function GlobalAudioPlayer() {
|
||||
state.set((prev) => ({ ...prev, playing: false }))
|
||||
}
|
||||
|
||||
const handleSeekMouseDown = (
|
||||
e: React.MouseEvent<HTMLInputElement, MouseEvent>,
|
||||
) => {
|
||||
const handleSeekMouseDown = () => {
|
||||
state.set((prev) => ({ ...prev, seeking: true }))
|
||||
}
|
||||
|
||||
@ -113,12 +117,21 @@ export default function GlobalAudioPlayer() {
|
||||
state.set((prev) => ({ ...prev, playbackRate: parseFloat(e.target.value) }))
|
||||
}
|
||||
|
||||
const handleProgress = (newState: { playedSeconds: number }) => {
|
||||
state.set((prev) => ({ ...prev, playedSeconds: newState.playedSeconds }))
|
||||
const handleProgress = (newState: {
|
||||
playedSeconds: number
|
||||
played: number
|
||||
loaded: number
|
||||
}) => {
|
||||
state.set((prev) => ({
|
||||
...prev,
|
||||
playedSeconds: newState.playedSeconds,
|
||||
played: newState.played,
|
||||
loaded: newState.loaded,
|
||||
}))
|
||||
}
|
||||
|
||||
return state.value.isEnabled ? (
|
||||
<Container>
|
||||
return (
|
||||
<Container visible={state.value.isEnabled}>
|
||||
<AudioPlayer>
|
||||
<Buttons>
|
||||
<Row>
|
||||
@ -182,7 +195,7 @@ export default function GlobalAudioPlayer() {
|
||||
loop={state.value.loop}
|
||||
playbackRate={state.value.playbackRate}
|
||||
volume={state.value.volume}
|
||||
muted={state.value.muted}
|
||||
muted={state.value.isEnabled ? false : true}
|
||||
onReady={() => console.log('onReady')}
|
||||
onStart={() => console.log('onStart')}
|
||||
onPlay={handlePlay}
|
||||
@ -208,10 +221,10 @@ export default function GlobalAudioPlayer() {
|
||||
</EpisodeData>
|
||||
</RightMenu>
|
||||
</Container>
|
||||
) : null
|
||||
)
|
||||
}
|
||||
|
||||
const Container = styled.div`
|
||||
const Container = styled.div<{ visible: boolean }>`
|
||||
width: 100vw;
|
||||
height: 80px;
|
||||
padding: 22px 16px;
|
||||
@ -224,6 +237,7 @@ const Container = styled.div`
|
||||
left: 0;
|
||||
border-top: 1px solid rgb(var(--lsd-border-primary));
|
||||
box-sizing: border-box;
|
||||
visibility: ${({ visible }) => (visible ? 'visible' : 'hidden')};
|
||||
`
|
||||
|
||||
const Buttons = styled.div`
|
||||
|
Loading…
x
Reference in New Issue
Block a user