Skip to content

Commit

Permalink
feat: add basic audio player
Browse files Browse the repository at this point in the history
  • Loading branch information
remvze committed Oct 6, 2023
1 parent c9e8bd4 commit 5a7a58e
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 6 deletions.
22 changes: 17 additions & 5 deletions src/components/sound/sound.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,41 @@
import { useState, useEffect } from 'react';

import { useSound } from '@/hooks/use-sound';
import { cn } from '@/helpers/styles';

import styles from './sound.module.css';

interface SoundProps {
sound: { label: string; src: string };
label: string;
src: string;
}

export function Sound({ sound }: SoundProps) {
export function Sound({ label, src }: SoundProps) {
const [isSelected, setIsSelected] = useState(false);
const [volume, setVolume] = useState(0.5);

const sound = useSound(src, { loop: true, volume });

useEffect(() => {
if (!isSelected) setVolume(0.5);
}, [isSelected]);
if (!isSelected) {
sound?.pause();
setVolume(0.5);
}

if (isSelected) {
sound?.play();
}
}, [isSelected, sound]);

return (
<div
className={cn(styles.sound, isSelected && styles.selected)}
onClick={() => setIsSelected(prev => !prev)}
onKeyDown={() => setIsSelected(prev => !prev)}
>
<h3>{sound.label}</h3>
<h3>{label}</h3>
<input
autoComplete="off"
disabled={!isSelected}
max={100}
min={0}
Expand Down
2 changes: 1 addition & 1 deletion src/components/sounds/sounds.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export function Sounds({ sounds }: SoundsProps) {
return (
<div className={styles.sounds}>
{sounds.map(sound => (
<Sound key={sound.label} sound={sound} />
<Sound key={sound.label} {...sound} />
))}
</div>
);
Expand Down
32 changes: 32 additions & 0 deletions src/hooks/use-sound.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { useMemo, useEffect } from 'react';

import { useSSR } from './use-ssr';

export function useSound(
src: string,
options: { volume?: number; loop?: boolean } = {},
): HTMLAudioElement | null {
const { isBrowser } = useSSR();
const sound = useMemo<HTMLAudioElement | null>(() => {
let sound: HTMLAudioElement | null = null;

if (isBrowser) {
sound = new Audio(src);
sound.preload = 'none';
}

return sound;
}, [src, isBrowser]);

useEffect(() => {
if (sound)
sound.loop = typeof options.loop === 'boolean' ? options.loop : false;
}, [sound, options.loop]);

useEffect(() => {
if (sound)
sound.volume = typeof options.volume === 'number' ? options.volume : 0.5;
}, [sound, options.volume]);

return sound;
}
11 changes: 11 additions & 0 deletions src/hooks/use-ssr.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export function useSSR() {
const isDOM =
typeof window !== 'undefined' &&
window.document &&
window.document.documentElement;

return {
isBrowser: isDOM,
isServer: !isDOM,
};
}

0 comments on commit 5a7a58e

Please sign in to comment.