Press n or j to go to the next uncovered block, b, p or k for the previous block.
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 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | 1x 15x | import React, { createContext, useCallback } from 'react'; import { useGameStateContext } from '@lib/providers/GameState'; import { Game } from '@uniquegood/realworld-web-interface/lib/models/game'; interface BgmProviderProps { fileList: Game['fileList']; children: React.ReactNode; } const BgmContext = createContext<{ isExistBgm: boolean; isPlayingBgm: boolean; setIsPlayingBgm: (value: boolean) => unknown; }>({ isExistBgm: false, isPlayingBgm: true, setIsPlayingBgm: () => { // pass } }); export const useBgmContext = () => React.useContext(BgmContext); export function BgmProvider({ fileList, children }: BgmProviderProps) { const { gameStateForRender } = useGameStateContext(); const [isPlayingBgm, setIsPlayingBgm] = React.useState(false); const audioRef = React.useRef<HTMLAudioElement | null>(null); React.useEffect(() => { if (!audioRef.current) return; if (isPlayingBgm) { audioRef.current.play(); } else if (!isPlayingBgm) { audioRef.current.pause(); } }, [isPlayingBgm]); const bgmAudioId = React.useMemo( () => gameStateForRender.gameMeta.currentBgmAudioId, [gameStateForRender.gameMeta.currentBgmAudioId] ); React.useEffect(() => { if (!bgmAudioId) return; const src = fileList.find((file) => file.id === bgmAudioId)?.src; if (src) { if (!audioRef.current) { const audio = new Audio(); audio.src = src; audio.loop = true; audioRef.current = audio; audio .play() .then(() => { setIsPlayingBgm(true); }) .catch((e) => { if (e.name === 'NotAllowedError') { setIsPlayingBgm(false); alert('우측 상단의 버튼을 눌러 BGM(배경음악)을 끄거나 켤 수 있습니다.'); } }); } else { audioRef.current.src = src; if (isPlayingBgm) { audioRef.current.play(); } } } }, [bgmAudioId]); const handleVisibilityChange = useCallback(() => { if (!audioRef.current) return; if (document.hidden) { setIsPlayingBgm(false); } else if (!document.hidden) { setIsPlayingBgm(true); } }, [isPlayingBgm, document.hidden]); // 다른 탭 이동 또는 비활성화 시 배경 음악 중단 React.useEffect(() => { window.addEventListener('visibilitychange', handleVisibilityChange); return () => { window.removeEventListener('visibilitychange', handleVisibilityChange); }; }, []); const bgmContextValue = React.useMemo( () => ({ isExistBgm: Boolean(bgmAudioId), isPlayingBgm, setIsPlayingBgm }), [isPlayingBgm, setIsPlayingBgm] ); return <BgmContext.Provider value={bgmContextValue}>{children}</BgmContext.Provider>; } |