aboutsummaryrefslogtreecommitdiff
path: root/lib/audio/AudioPlayer.svelte
blob: d5aa1d0edfeddad1f0d69f17c0a89b71a0a4314f (plain)
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
<script lang="ts">
  import { onDestroy, onMount } from 'svelte'
  import { masterMuted, ambientVolume } from '@hollowdark/lib/audio/state'

  interface Props {
    src: string
    loop?: boolean
  }

  let { src, loop = false }: Props = $props()

  let audioEl: HTMLAudioElement | null = null
  let cleanupInteractionListeners: (() => void) | null = null

  onMount(async () => {
    if (!audioEl) return

    audioEl.volume = $ambientVolume
    audioEl.muted = $masterMuted

    try {
      await audioEl.play()
    } catch {
      const start = (): void => {
        audioEl?.play().catch(() => {})
      }
      document.addEventListener('click', start, { once: true, passive: true })
      document.addEventListener('keydown', start, { once: true, passive: true })
      document.addEventListener('touchstart', start, { once: true, passive: true })

      cleanupInteractionListeners = () => {
        document.removeEventListener('click', start)
        document.removeEventListener('keydown', start)
        document.removeEventListener('touchstart', start)
      }
    }
  })

  onDestroy(() => {
    cleanupInteractionListeners?.()
    if (audioEl) {
      audioEl.pause()
    }
  })

  $effect(() => {
    if (!audioEl) return
    audioEl.volume = $ambientVolume
    audioEl.muted = $masterMuted
  })
</script>

<audio bind:this={audioEl} {src} {loop} preload="auto"></audio>