feat: add loading state for sounds

This commit is contained in:
MAZE 2023-11-28 14:23:08 +03:30
parent 85e42f3606
commit aaccbee3d7
3 changed files with 49 additions and 6 deletions

View File

@ -77,6 +77,14 @@
& .icon {
color: #34d399;
& .spinner {
animation-duration: 1s;
animation-iteration-count: infinite;
animation-name: spinner;
animation-timing-function: linear;
line-height: 0;
}
}
}
@ -89,3 +97,13 @@
line-height: 1.6;
}
}
@keyframes spinner {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}

View File

@ -1,4 +1,5 @@
import { useCallback, useEffect } from 'react';
import { ImSpinner9 } from 'react-icons/im/index';
import { Range } from './range';
import { Favorite } from './favorite';
@ -78,7 +79,15 @@ export function Sound({
onKeyDown={toggle}
>
<Favorite id={id} />
<div className={styles.icon}>{icon}</div>
<div className={styles.icon}>
{sound.isLoading ? (
<span className={styles.spinner}>
<ImSpinner9 />
</span>
) : (
icon
)}
</div>
<h3 id={id}>{label}</h3>
<Range id={id} />
</div>

View File

@ -1,4 +1,4 @@
import { useMemo, useEffect, useCallback } from 'react';
import { useMemo, useEffect, useCallback, useState } from 'react';
import { Howl } from 'howler';
import { useSSR } from './use-ssr';
@ -7,12 +7,21 @@ export function useSound(
src: string,
options: { loop?: boolean; volume?: number } = {},
) {
const [hasLoaded, setHasLoaded] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const { isBrowser } = useSSR();
const sound = useMemo<Howl | null>(() => {
let sound: Howl | null = null;
if (isBrowser) {
sound = new Howl({ preload: false, src: src });
sound = new Howl({
onload: () => {
setIsLoading(false);
setHasLoaded(true);
},
preload: false,
src: src,
});
}
return sound;
@ -31,10 +40,14 @@ export function useSound(
const play = useCallback(() => {
if (sound) {
sound.load();
if (!hasLoaded) {
setIsLoading(true);
sound.load();
}
sound.play();
}
}, [sound]);
}, [sound, hasLoaded]);
const stop = useCallback(() => {
if (sound) sound.stop();
@ -44,7 +57,10 @@ export function useSound(
if (sound) sound.pause();
}, [sound]);
const control = useMemo(() => ({ pause, play, stop }), [play, stop, pause]);
const control = useMemo(
() => ({ isLoading, pause, play, stop }),
[play, stop, pause, isLoading],
);
return control;
}