feat: add loader for favorites

This commit is contained in:
MAZE 2024-01-09 16:09:07 +03:30
parent a33ae450cf
commit f682a910da
4 changed files with 26 additions and 7 deletions

View file

@ -5,7 +5,7 @@ import { Range } from './range';
import { Favorite } from './favorite';
import { useSound } from '@/hooks/use-sound';
import { useSoundStore } from '@/store';
import { useSoundStore, useLoadingStore } from '@/store';
import { cn } from '@/helpers/styles';
import styles from './sound.module.css';
@ -37,6 +37,8 @@ export function Sound({
const volume = useSoundStore(state => state.sounds[id].volume);
const isSelected = useSoundStore(state => state.sounds[id].isSelected);
const isLoading = useLoadingStore(state => state.loaders[src]);
const sound = useSound(src, { loop: true, volume });
useEffect(() => {
@ -80,7 +82,7 @@ export function Sound({
>
<Favorite id={id} />
<div className={styles.icon}>
{sound.isLoading ? (
{isLoading ? (
<span className={styles.spinner}>
<ImSpinner9 />
</span>

View file

@ -1,6 +1,7 @@
import { useMemo, useEffect, useCallback, useState } from 'react';
import { Howl } from 'howler';
import { useLoadingStore } from '@/store';
import { useSSR } from './use-ssr';
export function useSound(
@ -8,7 +9,9 @@ export function useSound(
options: { loop?: boolean; volume?: number } = {},
) {
const [hasLoaded, setHasLoaded] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const isLoading = useLoadingStore(state => state.loaders[src]);
const setIsLoading = useLoadingStore(state => state.set);
const { isBrowser } = useSSR();
const sound = useMemo<Howl | null>(() => {
let sound: Howl | null = null;
@ -16,7 +19,7 @@ export function useSound(
if (isBrowser) {
sound = new Howl({
onload: () => {
setIsLoading(false);
setIsLoading(src, false);
setHasLoaded(true);
},
preload: false,
@ -25,7 +28,7 @@ export function useSound(
}
return sound;
}, [src, isBrowser]);
}, [src, isBrowser, setIsLoading]);
useEffect(() => {
if (sound) {
@ -41,7 +44,7 @@ export function useSound(
const play = useCallback(() => {
if (sound) {
if (!hasLoaded && !isLoading) {
setIsLoading(true);
setIsLoading(src, true);
sound.load();
}
@ -49,7 +52,7 @@ export function useSound(
sound.play();
}
}
}, [sound, hasLoaded, isLoading]);
}, [src, setIsLoading, sound, hasLoaded, isLoading]);
const stop = useCallback(() => {
if (sound) sound.stop();

View file

@ -1 +1,2 @@
export { useSoundStore } from './sound';
export { useLoadingStore } from './loading';

View file

@ -0,0 +1,13 @@
import { create } from 'zustand';
interface LoadingStore {
loaders: Record<string, boolean>;
set: (id: string, value: boolean) => void;
}
export const useLoadingStore = create<LoadingStore>()((set, get) => ({
loaders: {},
set(id: string, value: boolean) {
set({ loaders: { ...get().loaders, [id]: value } });
},
}));