feat: add basic fading effect

This commit is contained in:
MAZE 2024-04-30 17:47:49 +03:30
parent 7c57fb686b
commit 6ce766af47
4 changed files with 47 additions and 12 deletions

View file

@ -2,6 +2,7 @@ import { useEffect, useState, useRef, useMemo } from 'react';
import { Modal } from '@/components/modal'; import { Modal } from '@/components/modal';
import { Timer } from '@/components/timer'; import { Timer } from '@/components/timer';
import { dispatch } from '@/lib/event';
import { useSoundStore } from '@/store'; import { useSoundStore } from '@/store';
import { cn } from '@/helpers/styles'; import { cn } from '@/helpers/styles';
@ -56,7 +57,9 @@ export function SleepTimerModal({ onClose, show }: SleepTimerModalProps) {
useEffect(() => { useEffect(() => {
if (timeLeft === 0) { if (timeLeft === 0) {
setRunning(false); setRunning(false);
pause(); // pause();
dispatch('fadeOut', { duration: 5000 });
setTimeSpent(0); setTimeSpent(0);
if (timerId.current) clearInterval(timerId.current); if (timerId.current) clearInterval(timerId.current);

View file

@ -1,13 +1,16 @@
import { useMemo, useEffect, useCallback, useState } from 'react'; import { useMemo, useEffect, useCallback, useState } from 'react';
import { Howl } from 'howler'; import { Howl } from 'howler';
import { useLoadingStore } from '@/store'; import { useSoundStore, useLoadingStore } from '@/store';
import { subscribe } from '@/lib/event';
import { useSSR } from './use-ssr'; import { useSSR } from './use-ssr';
export function useSound( export function useSound(
src: string, src: string,
options: { loop?: boolean; volume?: number } = {}, options: { loop?: boolean; volume?: number } = {},
) { ) {
const pauseAll = useSoundStore(state => state.pause);
const [hasLoaded, setHasLoaded] = useState(false); const [hasLoaded, setHasLoaded] = useState(false);
const isLoading = useLoadingStore(state => state.loaders[src]); const isLoading = useLoadingStore(state => state.loaders[src]);
const setIsLoading = useLoadingStore(state => state.set); const setIsLoading = useLoadingStore(state => state.set);
@ -62,9 +65,28 @@ export function useSound(
if (sound) sound.pause(); if (sound) sound.pause();
}, [sound]); }, [sound]);
const fadeOut = useCallback(
(duration: number) => {
sound?.fade(sound.volume(), 0, duration);
setTimeout(() => {
pauseAll();
sound?.volume(options.volume || 0.5);
}, duration);
},
[options.volume, sound, pauseAll],
);
useEffect(() => {
const listener = (e: { duration: number }) => fadeOut(e.duration);
return subscribe('fadeOut', listener);
}, [fadeOut]);
const control = useMemo( const control = useMemo(
() => ({ isLoading, pause, play, stop }), () => ({ fadeOut, isLoading, pause, play, stop }),
[play, stop, pause, isLoading], [play, stop, pause, isLoading, fadeOut],
); );
return control; return control;

View file

@ -1,13 +1,23 @@
export function dispatch(eventName: string) { export function dispatch<T>(eventName: string, detail?: T) {
const event = new Event(eventName); const event = new CustomEvent(eventName, { detail });
document.dispatchEvent(event); document.dispatchEvent(event);
} }
export function subscribe(eventName: string, listener: () => void) { export function subscribe<T>(eventName: string, listener: (e: T) => void) {
document.addEventListener(eventName, listener); const handler = (event: Event) => {
if ('detail' in event) {
const payload = event.detail as T;
listener(payload);
}
};
document.addEventListener(eventName, handler);
return () => unsubscribe(eventName, handler);
} }
export function unsubscribe(eventName: string, listener: () => void) { export function unsubscribe(eventName: string, listener: (e: Event) => void) {
document.removeEventListener(eventName, listener); document.removeEventListener(eventName, listener);
} }

View file

@ -1,11 +1,11 @@
import { dispatch, subscribe, unsubscribe } from './event'; import { dispatch, subscribe } from './event';
export function closeModals() { export function closeModals() {
dispatch('closeModals'); dispatch('closeModals');
} }
export function onCloseModals(listener: () => void) { export function onCloseModals(listener: () => void) {
subscribe('closeModals', listener); const unsubscribe = subscribe('closeModals', listener);
return () => unsubscribe('closeModals', listener); return unsubscribe;
} }