File size: 2,354 Bytes
59c3ada
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import { useState, useRef, useCallback } from "react";

type AudioKeys = "pop" | "hover" | "music";
interface AudioPlayer {
  initAudio: () => boolean;
  playPopSound: () => void;
  playHoverSound: () => void;
  toggleMusic: () => void;
  playMusic: () => void;
  isMusicPlaying: boolean;
  isAudioReady: boolean;
}

const useAudioPlayer = (): AudioPlayer => {
  const audioRefs = useRef<Record<AudioKeys, HTMLAudioElement | null>>({
    pop: null,
    hover: null,
    music: null,
  });
  const [isReady, setIsReady] = useState<boolean>(false);
  const [isMusicPlaying, setIsMusicPlaying] = useState<boolean>(false);

  const initAudio = useCallback(() => {
    if (isReady) return true;
    try {
      audioRefs.current.pop = new Audio("/bubble.mp3");
      audioRefs.current.hover = new Audio("/hover.mp3");
      audioRefs.current.music = new Audio("/music.mp3");
      audioRefs.current.music.loop = true;
      audioRefs.current.music.volume = 0.1;
      setIsReady(true);
      return true;
    } catch {
      return false;
    }
  }, [isReady]);

  const playMusic = useCallback(() => {
    if (isReady && !isMusicPlaying) {
      audioRefs.current.music?.play().catch(() => {});
      setIsMusicPlaying(true);
    }
  }, [isReady, isMusicPlaying]);

  const toggleMusic = useCallback(
    (force?: boolean) => {
      if (!isReady || !audioRefs.current.music) return;

      const shouldBePlaying = force === undefined ? !isMusicPlaying : force;

      if (shouldBePlaying === isMusicPlaying) return;

      if (shouldBePlaying) {
        audioRefs.current.music?.play().catch(() => {});
      } else {
        audioRefs.current.music?.pause();
      }
      setIsMusicPlaying(shouldBePlaying);
    },
    [isReady, isMusicPlaying],
  );

  const playPopSound = useCallback(() => {
    if (!isReady || !audioRefs.current.pop) return;
    audioRefs.current.pop.currentTime = 0;
    audioRefs.current.pop.play().catch(() => {});
  }, [isReady]);

  const playHoverSound = useCallback(() => {
    if (!isReady || !audioRefs.current.hover) return;
    audioRefs.current.hover.currentTime = 0;
    audioRefs.current.hover.play().catch(() => {});
  }, [isReady]);

  return {
    initAudio,
    playPopSound,
    playHoverSound,
    toggleMusic,
    playMusic,
    isMusicPlaying,
    isAudioReady: isReady,
  };
};

export default useAudioPlayer;