2023-07-01 13:05:59 +00:00
|
|
|
import { clsx } from 'clsx'
|
2024-02-04 11:25:21 +00:00
|
|
|
import { Show, createSignal } from 'solid-js'
|
2023-07-01 13:05:59 +00:00
|
|
|
|
2023-11-14 15:10:00 +00:00
|
|
|
import { MediaItem } from '../../../pages/types'
|
2023-07-01 13:05:59 +00:00
|
|
|
import { useOutsideClickHandler } from '../../../utils/useOutsideClickHandler'
|
|
|
|
import { Icon } from '../../_shared/Icon'
|
2023-11-14 15:10:00 +00:00
|
|
|
|
2023-07-01 13:05:59 +00:00
|
|
|
import styles from './AudioPlayer.module.scss'
|
|
|
|
|
2023-07-18 11:26:32 +00:00
|
|
|
type Props = {
|
|
|
|
onPlayMedia: () => void
|
|
|
|
playPrevTrack: () => void
|
|
|
|
playNextTrack: () => void
|
|
|
|
onVolumeChange: (volume: number) => void
|
|
|
|
isPlaying: boolean
|
|
|
|
currentTrack: MediaItem
|
|
|
|
}
|
|
|
|
|
|
|
|
export const PlayerHeader = (props: Props) => {
|
2023-07-01 13:05:59 +00:00
|
|
|
const volumeContainerRef: { current: HTMLDivElement } = {
|
2023-11-14 15:10:00 +00:00
|
|
|
current: null,
|
2023-07-01 13:05:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const [isVolumeBarOpened, setIsVolumeBarOpened] = createSignal(false)
|
|
|
|
|
|
|
|
const toggleVolumeBar = () => {
|
|
|
|
setIsVolumeBarOpened(!isVolumeBarOpened())
|
|
|
|
}
|
|
|
|
|
|
|
|
useOutsideClickHandler({
|
|
|
|
containerRef: volumeContainerRef,
|
|
|
|
predicate: () => isVolumeBarOpened(),
|
2023-11-14 15:10:00 +00:00
|
|
|
handler: () => toggleVolumeBar(),
|
2023-07-01 13:05:59 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div class={styles.playerHeader}>
|
2023-07-18 11:26:32 +00:00
|
|
|
<div class={styles.playerTitle}>{props.currentTrack.title}</div>
|
2023-07-01 13:05:59 +00:00
|
|
|
<div class={styles.playerControls}>
|
|
|
|
<button
|
2023-07-14 13:06:21 +00:00
|
|
|
type="button"
|
2023-07-18 11:26:32 +00:00
|
|
|
onClick={props.onPlayMedia}
|
2023-07-01 13:05:59 +00:00
|
|
|
class={clsx(
|
|
|
|
styles.playButton,
|
2023-11-14 15:10:00 +00:00
|
|
|
props.isPlaying ? styles.playButtonInvertPause : styles.playButtonInvertPlay,
|
2023-07-01 13:05:59 +00:00
|
|
|
)}
|
|
|
|
aria-label="Play"
|
|
|
|
data-playing="false"
|
|
|
|
>
|
2023-07-18 11:26:32 +00:00
|
|
|
<Icon name={props.isPlaying ? 'pause' : 'play'} />
|
2023-07-01 13:05:59 +00:00
|
|
|
</button>
|
|
|
|
<button
|
2023-07-14 13:06:21 +00:00
|
|
|
type="button"
|
2023-07-18 11:26:32 +00:00
|
|
|
onClick={props.playPrevTrack}
|
2023-07-01 13:05:59 +00:00
|
|
|
class={clsx(styles.controlsButton)}
|
|
|
|
aria-label="Previous"
|
|
|
|
>
|
|
|
|
<Icon name="player-arrow" />
|
|
|
|
</button>
|
|
|
|
<button
|
2023-07-14 13:06:21 +00:00
|
|
|
type="button"
|
2023-07-18 11:26:32 +00:00
|
|
|
onClick={props.playNextTrack}
|
2023-07-01 13:05:59 +00:00
|
|
|
class={clsx(styles.controlsButton, styles.controlsButtonNext)}
|
|
|
|
aria-label="Next"
|
|
|
|
>
|
|
|
|
<Icon name="player-arrow" />
|
|
|
|
</button>
|
|
|
|
<div ref={(el) => (volumeContainerRef.current = el)} class={styles.volumeContainer}>
|
|
|
|
<Show when={isVolumeBarOpened()}>
|
|
|
|
<input
|
|
|
|
type="range"
|
|
|
|
id="volume"
|
|
|
|
min="0"
|
|
|
|
max="1"
|
|
|
|
value="1"
|
|
|
|
step="0.01"
|
|
|
|
class={styles.volume}
|
2023-07-18 11:26:32 +00:00
|
|
|
onChange={({ target }) => props.onVolumeChange(Number(target.value))}
|
2023-07-01 13:05:59 +00:00
|
|
|
/>
|
|
|
|
</Show>
|
|
|
|
<button onClick={toggleVolumeBar} class={styles.volumeButton} role="button" aria-label="Volume">
|
|
|
|
<Icon name="volume" />
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|