@cuemath/leap 3.5.41-m-2 → 3.5.41-m-3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { useRef as
|
|
1
|
+
import { useRef as T, useEffect as x, useCallback as i } from "react";
|
|
2
2
|
const R = (V, p = !0) => {
|
|
3
|
-
const n =
|
|
3
|
+
const n = T(null), h = T({}), o = T({}), s = T({});
|
|
4
4
|
x(() => {
|
|
5
5
|
try {
|
|
6
6
|
const e = window.AudioContext || window.webkitAudioContext;
|
|
@@ -22,7 +22,7 @@ const R = (V, p = !0) => {
|
|
|
22
22
|
}
|
|
23
23
|
}, []), A = i(
|
|
24
24
|
async (e) => {
|
|
25
|
-
if (!(!n.current ||
|
|
25
|
+
if (!(!n.current || h.current[e]))
|
|
26
26
|
try {
|
|
27
27
|
const t = V[e];
|
|
28
28
|
if (!t) throw new Error(`No URL found for sound key: ${e}`);
|
|
@@ -33,9 +33,9 @@ const R = (V, p = !0) => {
|
|
|
33
33
|
if (!r.ok)
|
|
34
34
|
throw new Error(`HTTP error! status: ${r.status}`);
|
|
35
35
|
const c = await r.arrayBuffer(), u = await n.current.decodeAudioData(c);
|
|
36
|
-
|
|
36
|
+
h.current[e] = u;
|
|
37
37
|
} catch (t) {
|
|
38
|
-
console.error(`Failed to load sound "${e}":`, t),
|
|
38
|
+
console.error(`Failed to load sound "${e}":`, t), h.current[e] = null;
|
|
39
39
|
}
|
|
40
40
|
},
|
|
41
41
|
[V]
|
|
@@ -46,16 +46,16 @@ const R = (V, p = !0) => {
|
|
|
46
46
|
}, []), w = i(
|
|
47
47
|
(e, t, r = 0.5, c = !0) => {
|
|
48
48
|
if (!n.current) return;
|
|
49
|
-
|
|
49
|
+
s.current[e] && (clearTimeout(s.current[e]), delete s.current[e]);
|
|
50
50
|
const u = n.current.currentTime;
|
|
51
|
-
t.gainNode.gain.cancelScheduledValues(u), t.gainNode.gain.setValueAtTime(t.gainNode.gain.value, u), t.gainNode.gain.linearRampToValueAtTime(0, u + r), c && (
|
|
51
|
+
t.gainNode.gain.cancelScheduledValues(u), t.gainNode.gain.setValueAtTime(t.gainNode.gain.value, u), t.gainNode.gain.linearRampToValueAtTime(0, u + r), c && (s.current[e] = window.setTimeout(() => {
|
|
52
52
|
var l;
|
|
53
53
|
try {
|
|
54
54
|
t.source.stop();
|
|
55
55
|
} catch (f) {
|
|
56
56
|
console.warn("Error stopping sound:", f);
|
|
57
57
|
}
|
|
58
|
-
((l = o.current[e]) == null ? void 0 : l.source) === t.source && delete o.current[e], delete
|
|
58
|
+
((l = o.current[e]) == null ? void 0 : l.source) === t.source && delete o.current[e], delete s.current[e];
|
|
59
59
|
}, r * 1e3));
|
|
60
60
|
},
|
|
61
61
|
[]
|
|
@@ -75,35 +75,41 @@ const R = (V, p = !0) => {
|
|
|
75
75
|
});
|
|
76
76
|
return;
|
|
77
77
|
}
|
|
78
|
-
if (o.current[e] && !r)
|
|
79
|
-
|
|
78
|
+
if (o.current[e] && !r) {
|
|
79
|
+
try {
|
|
80
|
+
o.current[e].source.stop();
|
|
81
|
+
} catch (a) {
|
|
82
|
+
console.log(a);
|
|
83
|
+
}
|
|
84
|
+
delete o.current[e];
|
|
85
|
+
}
|
|
80
86
|
await m(), await A(e);
|
|
81
|
-
const f =
|
|
87
|
+
const f = h.current[e];
|
|
82
88
|
if (!f) {
|
|
83
89
|
console.warn(`No buffer available for sound: ${e}`);
|
|
84
90
|
return;
|
|
85
91
|
}
|
|
86
92
|
if (o.current[e] && r) {
|
|
87
|
-
|
|
93
|
+
s.current[e] && (clearTimeout(s.current[e]), delete s.current[e]), g(o.current[e].gainNode, l);
|
|
88
94
|
return;
|
|
89
95
|
}
|
|
90
96
|
if (o.current[e]) {
|
|
91
|
-
const
|
|
97
|
+
const a = o.current[e];
|
|
92
98
|
try {
|
|
93
|
-
|
|
99
|
+
a.source.stop();
|
|
94
100
|
} catch (d) {
|
|
95
101
|
console.warn("Error stopping existing sound:", d);
|
|
96
102
|
}
|
|
97
103
|
delete o.current[e];
|
|
98
104
|
}
|
|
99
105
|
try {
|
|
100
|
-
const
|
|
101
|
-
|
|
106
|
+
const a = n.current.createBufferSource(), d = n.current.createGain();
|
|
107
|
+
a.buffer = f, a.loop = r, a.connect(d).connect(n.current.destination), u ? (d.gain.setValueAtTime(0, n.current.currentTime), g(d, l)) : d.gain.setValueAtTime(c, n.current.currentTime), a.start(), o.current[e] = { source: a, gainNode: d, loop: r }, r || (a.onended = () => {
|
|
102
108
|
var C;
|
|
103
|
-
((C = o.current[e]) == null ? void 0 : C.source) ===
|
|
109
|
+
((C = o.current[e]) == null ? void 0 : C.source) === a && delete o.current[e];
|
|
104
110
|
});
|
|
105
|
-
} catch (
|
|
106
|
-
console.error(`Failed to play sound "${e}":`,
|
|
111
|
+
} catch (a) {
|
|
112
|
+
console.error(`Failed to play sound "${e}":`, a);
|
|
107
113
|
}
|
|
108
114
|
},
|
|
109
115
|
[p, m, A, g]
|
|
@@ -117,7 +123,7 @@ const R = (V, p = !0) => {
|
|
|
117
123
|
} catch (f) {
|
|
118
124
|
console.warn("Error stopping sound:", f);
|
|
119
125
|
}
|
|
120
|
-
delete o.current[e],
|
|
126
|
+
delete o.current[e], s.current[e] && (clearTimeout(s.current[e]), delete s.current[e]);
|
|
121
127
|
} else
|
|
122
128
|
w(e, l, u);
|
|
123
129
|
},
|
|
@@ -143,7 +149,7 @@ const R = (V, p = !0) => {
|
|
|
143
149
|
[m, g, w]
|
|
144
150
|
);
|
|
145
151
|
return x(() => {
|
|
146
|
-
const e =
|
|
152
|
+
const e = s.current;
|
|
147
153
|
return () => {
|
|
148
154
|
Object.values(e).forEach((t) => {
|
|
149
155
|
t && clearTimeout(t);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-audio-player.js","sources":["../../../../src/features/hooks/use-audio-player/use-audio-player.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react';\n\nimport { type IActiveSound, type IAudioConfig, type IAudioOptions } from './use-audio-player-types';\n\ndeclare global {\n interface Window {\n webkitAudioContext?: typeof AudioContext;\n }\n}\n\nexport const useAudioPlayer = (audioConfig: IAudioConfig, canPlayAudio: boolean = true) => {\n const audioContext = useRef<AudioContext | null>(null);\n const bufferCache = useRef<Record<string, AudioBuffer | null>>({});\n const activeSounds = useRef<Partial<Record<string, IActiveSound>>>({});\n const fadeTimeouts = useRef<Partial<Record<string, number>>>({});\n\n useEffect(() => {\n try {\n const AudioContextClass = window.AudioContext || window.webkitAudioContext;\n\n audioContext.current = new AudioContextClass();\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn('Failed to create AudioContext:', error);\n }\n\n return () => {\n if (audioContext.current && audioContext.current.state !== 'closed') {\n audioContext.current.close();\n }\n };\n }, []);\n\n const resumeAudioContext = useCallback(async () => {\n if (audioContext.current?.state === 'suspended') {\n try {\n await audioContext.current.resume();\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn('Failed to resume AudioContext:', error);\n }\n }\n }, []);\n\n const loadSound = useCallback(\n async (key: string): Promise<void> => {\n if (!audioContext.current || bufferCache.current[key]) return;\n\n try {\n const url = audioConfig[key];\n\n if (!url) throw new Error(`No URL found for sound key: ${key}`);\n\n const response = await fetch(url, {\n mode: 'cors',\n credentials: 'omit',\n });\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n const arrayBuffer = await response.arrayBuffer();\n const audioBuffer = await audioContext.current.decodeAudioData(arrayBuffer);\n\n bufferCache.current[key] = audioBuffer;\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error(`Failed to load sound \"${key}\":`, error);\n bufferCache.current[key] = null;\n }\n },\n [audioConfig],\n );\n\n const fadeIn = useCallback((gainNode: GainNode, duration: number = 0.5) => {\n if (!audioContext.current) return;\n\n const now = audioContext.current.currentTime;\n\n gainNode.gain.cancelScheduledValues(now);\n gainNode.gain.setValueAtTime(gainNode.gain.value, now);\n gainNode.gain.linearRampToValueAtTime(1, now + duration);\n }, []);\n\n const fadeOut = useCallback(\n (key: string, sound: IActiveSound, duration: number = 0.5, shouldStop: boolean = true) => {\n if (!audioContext.current) return;\n\n if (fadeTimeouts.current[key]) {\n clearTimeout(fadeTimeouts.current[key]);\n delete fadeTimeouts.current[key];\n }\n\n const now = audioContext.current.currentTime;\n\n sound.gainNode.gain.cancelScheduledValues(now);\n sound.gainNode.gain.setValueAtTime(sound.gainNode.gain.value, now);\n sound.gainNode.gain.linearRampToValueAtTime(0, now + duration);\n\n if (shouldStop) {\n fadeTimeouts.current[key] = window.setTimeout(() => {\n try {\n sound.source.stop();\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn('Error stopping sound:', error);\n }\n\n if (activeSounds.current[key]?.source === sound.source) {\n delete activeSounds.current[key];\n }\n delete fadeTimeouts.current[key];\n }, duration * 1000);\n }\n },\n [],\n );\n\n const play = useCallback(\n async (key: string, options: IAudioOptions = {}): Promise<void> => {\n const {\n loop = false,\n volume = 1,\n fadeIn: shouldFadeIn = false,\n fadeDuration = 0.5,\n } = options;\n\n if (!audioContext.current || !canPlayAudio) {\n // eslint-disable-next-line no-console\n console.warn('Cannot play sound:', {\n key,\n hasContext: !!audioContext.current,\n canPlayAudio,\n });\n\n return;\n }\n\n if (activeSounds.current[key] && !loop) {\n return;\n }\n\n await resumeAudioContext();\n await loadSound(key);\n\n const buffer = bufferCache.current[key];\n\n if (!buffer) {\n // eslint-disable-next-line no-console\n console.warn(`No buffer available for sound: ${key}`);\n\n return;\n }\n\n if (activeSounds.current[key] && loop) {\n if (fadeTimeouts.current[key]) {\n clearTimeout(fadeTimeouts.current[key]);\n delete fadeTimeouts.current[key];\n }\n fadeIn(activeSounds.current[key]!.gainNode, fadeDuration);\n\n return;\n }\n\n if (activeSounds.current[key]) {\n const existingSound = activeSounds.current[key];\n\n try {\n existingSound!.source.stop();\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn('Error stopping existing sound:', error);\n }\n delete activeSounds.current[key];\n }\n\n try {\n const source = audioContext.current.createBufferSource();\n const gainNode = audioContext.current.createGain();\n\n source.buffer = buffer;\n source.loop = loop;\n source.connect(gainNode).connect(audioContext.current.destination);\n\n if (shouldFadeIn) {\n gainNode.gain.setValueAtTime(0, audioContext.current.currentTime);\n fadeIn(gainNode, fadeDuration);\n } else {\n gainNode.gain.setValueAtTime(volume, audioContext.current.currentTime);\n }\n\n source.start();\n activeSounds.current[key] = { source, gainNode, loop };\n\n if (!loop) {\n source.onended = () => {\n if (activeSounds.current[key]?.source === source) {\n delete activeSounds.current[key];\n }\n };\n }\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error(`Failed to play sound \"${key}\":`, error);\n }\n },\n [canPlayAudio, resumeAudioContext, loadSound, fadeIn],\n );\n\n const stop = useCallback(\n async (\n key: string,\n options: { immediately?: boolean; fadeOut?: boolean; fadeDuration?: number } = {},\n ): Promise<void> => {\n const { immediately = true, fadeOut: shouldFadeOut = false, fadeDuration = 0.5 } = options;\n\n const sound = activeSounds.current[key];\n\n if (!sound) return;\n\n if (immediately && !shouldFadeOut) {\n try {\n sound.source.stop();\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn('Error stopping sound:', error);\n }\n\n delete activeSounds.current[key];\n if (fadeTimeouts.current[key]) {\n clearTimeout(fadeTimeouts.current[key]);\n delete fadeTimeouts.current[key];\n }\n } else {\n fadeOut(key, sound, fadeDuration);\n }\n },\n [fadeOut],\n );\n\n const stopAll = useCallback(\n (options: { immediately?: boolean; fadeOut?: boolean } = {}) => {\n const soundKeys = Object.keys(activeSounds.current);\n\n soundKeys.forEach(key => stop(key, options));\n },\n [stop],\n );\n\n const isPlaying = useCallback((key: string): boolean => {\n return !!activeSounds.current[key];\n }, []);\n\n const setVolume = useCallback((key: string, volume: number, duration: number = 0) => {\n const sound = activeSounds.current[key];\n\n if (!sound || !audioContext.current) return;\n\n const now = audioContext.current.currentTime;\n\n if (duration > 0) {\n sound.gainNode.gain.cancelScheduledValues(now);\n sound.gainNode.gain.setValueAtTime(sound.gainNode.gain.value, now);\n sound.gainNode.gain.linearRampToValueAtTime(volume, now + duration);\n } else {\n sound.gainNode.gain.setValueAtTime(volume, now);\n }\n }, []);\n\n const handleVisibilityChange = useCallback(\n (backgroundSounds: Set<string> = new Set(), fadeOnHide: boolean = true) => {\n if (!fadeOnHide) return;\n\n if (document.visibilityState === 'visible') {\n resumeAudioContext();\n Object.values(activeSounds.current).forEach(sound => {\n if (sound) {\n fadeIn(sound.gainNode);\n }\n });\n } else {\n Object.entries(activeSounds.current).forEach(([key, sound]) => {\n if (sound) {\n if (backgroundSounds.has(key)) {\n fadeOut(key, sound, 0.5, false);\n } else {\n fadeOut(key, sound);\n }\n }\n });\n }\n },\n [resumeAudioContext, fadeIn, fadeOut],\n );\n\n useEffect(() => {\n const timeouts = fadeTimeouts.current;\n\n return () => {\n Object.values(timeouts).forEach(id => {\n if (id) clearTimeout(id);\n });\n };\n }, []);\n\n return {\n play,\n stop,\n stopAll,\n isPlaying,\n setVolume,\n handleVisibilityChange,\n loadSound,\n resumeAudioContext,\n };\n};\n"],"names":["useAudioPlayer","audioConfig","canPlayAudio","audioContext","useRef","bufferCache","activeSounds","fadeTimeouts","useEffect","AudioContextClass","error","resumeAudioContext","useCallback","_a","loadSound","key","url","response","arrayBuffer","audioBuffer","fadeIn","gainNode","duration","now","fadeOut","sound","shouldStop","play","options","loop","volume","shouldFadeIn","fadeDuration","buffer","existingSound","source","stop","immediately","shouldFadeOut","stopAll","isPlaying","setVolume","handleVisibilityChange","backgroundSounds","fadeOnHide","timeouts","id"],"mappings":";AAUO,MAAMA,IAAiB,CAACC,GAA2BC,IAAwB,OAAS;AACnF,QAAAC,IAAeC,EAA4B,IAAI,GAC/CC,IAAcD,EAA2C,CAAA,CAAE,GAC3DE,IAAeF,EAA8C,CAAA,CAAE,GAC/DG,IAAeH,EAAwC,CAAA,CAAE;AAE/D,EAAAI,EAAU,MAAM;AACV,QAAA;AACI,YAAAC,IAAoB,OAAO,gBAAgB,OAAO;AAE3C,MAAAN,EAAA,UAAU,IAAIM;aACpBC,GAAO;AAEN,cAAA,KAAK,kCAAkCA,CAAK;AAAA,IACtD;AAEA,WAAO,MAAM;AACX,MAAIP,EAAa,WAAWA,EAAa,QAAQ,UAAU,YACzDA,EAAa,QAAQ;IACvB;AAAA,EAEJ,GAAG,CAAE,CAAA;AAEC,QAAAQ,IAAqBC,EAAY,YAAY;;AAC7C,UAAAC,IAAAV,EAAa,YAAb,gBAAAU,EAAsB,WAAU;AAC9B,UAAA;AACI,cAAAV,EAAa,QAAQ;eACpBO,GAAO;AAEN,gBAAA,KAAK,kCAAkCA,CAAK;AAAA,MACtD;AAAA,EAEJ,GAAG,CAAE,CAAA,GAECI,IAAYF;AAAA,IAChB,OAAOG,MAA+B;AACpC,UAAI,GAACZ,EAAa,WAAWE,EAAY,QAAQU,CAAG;AAEhD,YAAA;AACI,gBAAAC,IAAMf,EAAYc,CAAG;AAE3B,cAAI,CAACC,EAAK,OAAM,IAAI,MAAM,+BAA+BD,CAAG,EAAE;AAExD,gBAAAE,IAAW,MAAM,MAAMD,GAAK;AAAA,YAChC,MAAM;AAAA,YACN,aAAa;AAAA,UAAA,CACd;AAEG,cAAA,CAACC,EAAS;AACZ,kBAAM,IAAI,MAAM,uBAAuBA,EAAS,MAAM,EAAE;AAGpD,gBAAAC,IAAc,MAAMD,EAAS,eAC7BE,IAAc,MAAMhB,EAAa,QAAQ,gBAAgBe,CAAW;AAE9D,UAAAb,EAAA,QAAQU,CAAG,IAAII;AAAA,iBACpBT,GAAO;AAEd,kBAAQ,MAAM,yBAAyBK,CAAG,MAAML,CAAK,GACzCL,EAAA,QAAQU,CAAG,IAAI;AAAA,QAC7B;AAAA,IACF;AAAA,IACA,CAACd,CAAW;AAAA,EAAA,GAGRmB,IAASR,EAAY,CAACS,GAAoBC,IAAmB,QAAQ;AACrE,QAAA,CAACnB,EAAa,QAAS;AAErB,UAAAoB,IAAMpB,EAAa,QAAQ;AAExB,IAAAkB,EAAA,KAAK,sBAAsBE,CAAG,GACvCF,EAAS,KAAK,eAAeA,EAAS,KAAK,OAAOE,CAAG,GACrDF,EAAS,KAAK,wBAAwB,GAAGE,IAAMD,CAAQ;AAAA,EACzD,GAAG,CAAE,CAAA,GAECE,IAAUZ;AAAA,IACd,CAACG,GAAaU,GAAqBH,IAAmB,KAAKI,IAAsB,OAAS;AACpF,UAAA,CAACvB,EAAa,QAAS;AAEvB,MAAAI,EAAa,QAAQQ,CAAG,MACb,aAAAR,EAAa,QAAQQ,CAAG,CAAC,GAC/B,OAAAR,EAAa,QAAQQ,CAAG;AAG3B,YAAAQ,IAAMpB,EAAa,QAAQ;AAE3B,MAAAsB,EAAA,SAAS,KAAK,sBAAsBF,CAAG,GAC7CE,EAAM,SAAS,KAAK,eAAeA,EAAM,SAAS,KAAK,OAAOF,CAAG,GACjEE,EAAM,SAAS,KAAK,wBAAwB,GAAGF,IAAMD,CAAQ,GAEzDI,MACFnB,EAAa,QAAQQ,CAAG,IAAI,OAAO,WAAW,MAAM;;AAC9C,YAAA;AACF,UAAAU,EAAM,OAAO;iBACNf,GAAO;AAEN,kBAAA,KAAK,yBAAyBA,CAAK;AAAA,QAC7C;AAEA,UAAIG,IAAAP,EAAa,QAAQS,CAAG,MAAxB,gBAAAF,EAA2B,YAAWY,EAAM,UACvC,OAAAnB,EAAa,QAAQS,CAAG,GAE1B,OAAAR,EAAa,QAAQQ,CAAG;AAAA,MAAA,GAC9BO,IAAW,GAAI;AAAA,IAEtB;AAAA,IACA,CAAC;AAAA,EAAA,GAGGK,IAAOf;AAAA,IACX,OAAOG,GAAaa,IAAyB,OAAsB;AAC3D,YAAA;AAAA,QACJ,MAAAC,IAAO;AAAA,QACP,QAAAC,IAAS;AAAA,QACT,QAAQC,IAAe;AAAA,QACvB,cAAAC,IAAe;AAAA,MACb,IAAAJ;AAEJ,UAAI,CAACzB,EAAa,WAAW,CAACD,GAAc;AAE1C,gBAAQ,KAAK,sBAAsB;AAAA,UACjC,KAAAa;AAAA,UACA,YAAY,CAAC,CAACZ,EAAa;AAAA,UAC3B,cAAAD;AAAA,QAAA,CACD;AAED;AAAA,MACF;AAEA,UAAII,EAAa,QAAQS,CAAG,KAAK,CAACc;AAChC;AAGF,YAAMlB,EAAmB,GACzB,MAAMG,EAAUC,CAAG;AAEb,YAAAkB,IAAS5B,EAAY,QAAQU,CAAG;AAEtC,UAAI,CAACkB,GAAQ;AAEH,gBAAA,KAAK,kCAAkClB,CAAG,EAAE;AAEpD;AAAA,MACF;AAEA,UAAIT,EAAa,QAAQS,CAAG,KAAKc,GAAM;AACjC,QAAAtB,EAAa,QAAQQ,CAAG,MACb,aAAAR,EAAa,QAAQQ,CAAG,CAAC,GAC/B,OAAAR,EAAa,QAAQQ,CAAG,IAEjCK,EAAOd,EAAa,QAAQS,CAAG,EAAG,UAAUiB,CAAY;AAExD;AAAA,MACF;AAEI,UAAA1B,EAAa,QAAQS,CAAG,GAAG;AACvB,cAAAmB,IAAgB5B,EAAa,QAAQS,CAAG;AAE1C,YAAA;AACF,UAAAmB,EAAe,OAAO;iBACfxB,GAAO;AAEN,kBAAA,KAAK,kCAAkCA,CAAK;AAAA,QACtD;AACO,eAAAJ,EAAa,QAAQS,CAAG;AAAA,MACjC;AAEI,UAAA;AACI,cAAAoB,IAAShC,EAAa,QAAQ,mBAAmB,GACjDkB,IAAWlB,EAAa,QAAQ,WAAW;AAEjD,QAAAgC,EAAO,SAASF,GAChBE,EAAO,OAAON,GACdM,EAAO,QAAQd,CAAQ,EAAE,QAAQlB,EAAa,QAAQ,WAAW,GAE7D4B,KACFV,EAAS,KAAK,eAAe,GAAGlB,EAAa,QAAQ,WAAW,GAChEiB,EAAOC,GAAUW,CAAY,KAE7BX,EAAS,KAAK,eAAeS,GAAQ3B,EAAa,QAAQ,WAAW,GAGvEgC,EAAO,MAAM,GACb7B,EAAa,QAAQS,CAAG,IAAI,EAAE,QAAAoB,GAAQ,UAAAd,GAAU,MAAAQ,KAE3CA,MACHM,EAAO,UAAU,MAAM;;AACrB,YAAItB,IAAAP,EAAa,QAAQS,CAAG,MAAxB,gBAAAF,EAA2B,YAAWsB,KACjC,OAAA7B,EAAa,QAAQS,CAAG;AAAA,QACjC;AAAA,eAGGL,GAAO;AAEd,gBAAQ,MAAM,yBAAyBK,CAAG,MAAML,CAAK;AAAA,MACvD;AAAA,IACF;AAAA,IACA,CAACR,GAAcS,GAAoBG,GAAWM,CAAM;AAAA,EAAA,GAGhDgB,IAAOxB;AAAA,IACX,OACEG,GACAa,IAA+E,OAC7D;AACZ,YAAA,EAAE,aAAAS,IAAc,IAAM,SAASC,IAAgB,IAAO,cAAAN,IAAe,IAAQ,IAAAJ,GAE7EH,IAAQnB,EAAa,QAAQS,CAAG;AAEtC,UAAKU;AAED,YAAAY,KAAe,CAACC,GAAe;AAC7B,cAAA;AACF,YAAAb,EAAM,OAAO;mBACNf,GAAO;AAEN,oBAAA,KAAK,yBAAyBA,CAAK;AAAA,UAC7C;AAEO,iBAAAJ,EAAa,QAAQS,CAAG,GAC3BR,EAAa,QAAQQ,CAAG,MACb,aAAAR,EAAa,QAAQQ,CAAG,CAAC,GAC/B,OAAAR,EAAa,QAAQQ,CAAG;AAAA,QACjC;AAEQ,UAAAS,EAAAT,GAAKU,GAAOO,CAAY;AAAA,IAEpC;AAAA,IACA,CAACR,CAAO;AAAA,EAAA,GAGJe,IAAU3B;AAAA,IACd,CAACgB,IAAwD,CAAA,MAAO;AAG9D,MAFkB,OAAO,KAAKtB,EAAa,OAAO,EAExC,QAAQ,CAAAS,MAAOqB,EAAKrB,GAAKa,CAAO,CAAC;AAAA,IAC7C;AAAA,IACA,CAACQ,CAAI;AAAA,EAAA,GAGDI,IAAY5B,EAAY,CAACG,MACtB,CAAC,CAACT,EAAa,QAAQS,CAAG,GAChC,CAAE,CAAA,GAEC0B,IAAY7B,EAAY,CAACG,GAAae,GAAgBR,IAAmB,MAAM;AAC7E,UAAAG,IAAQnB,EAAa,QAAQS,CAAG;AAEtC,QAAI,CAACU,KAAS,CAACtB,EAAa,QAAS;AAE/B,UAAAoB,IAAMpB,EAAa,QAAQ;AAEjC,IAAImB,IAAW,KACPG,EAAA,SAAS,KAAK,sBAAsBF,CAAG,GAC7CE,EAAM,SAAS,KAAK,eAAeA,EAAM,SAAS,KAAK,OAAOF,CAAG,GACjEE,EAAM,SAAS,KAAK,wBAAwBK,GAAQP,IAAMD,CAAQ,KAElEG,EAAM,SAAS,KAAK,eAAeK,GAAQP,CAAG;AAAA,EAElD,GAAG,CAAE,CAAA,GAECmB,IAAyB9B;AAAA,IAC7B,CAAC+B,IAAgC,oBAAI,OAAOC,IAAsB,OAAS;AACzE,MAAKA,MAED,SAAS,oBAAoB,aACZjC,KACnB,OAAO,OAAOL,EAAa,OAAO,EAAE,QAAQ,CAASmB,MAAA;AACnD,QAAIA,KACFL,EAAOK,EAAM,QAAQ;AAAA,MACvB,CACD,KAEM,OAAA,QAAQnB,EAAa,OAAO,EAAE,QAAQ,CAAC,CAACS,GAAKU,CAAK,MAAM;AAC7D,QAAIA,MACEkB,EAAiB,IAAI5B,CAAG,IAClBS,EAAAT,GAAKU,GAAO,KAAK,EAAK,IAE9BD,EAAQT,GAAKU,CAAK;AAAA,MAEtB,CACD;AAAA,IAEL;AAAA,IACA,CAACd,GAAoBS,GAAQI,CAAO;AAAA,EAAA;AAGtC,SAAAhB,EAAU,MAAM;AACd,UAAMqC,IAAWtC,EAAa;AAE9B,WAAO,MAAM;AACX,aAAO,OAAOsC,CAAQ,EAAE,QAAQ,CAAMC,MAAA;AAChC,QAAAA,kBAAiBA,CAAE;AAAA,MAAA,CACxB;AAAA,IAAA;AAAA,EAEL,GAAG,CAAE,CAAA,GAEE;AAAA,IACL,MAAAnB;AAAA,IACA,MAAAS;AAAA,IACA,SAAAG;AAAA,IACA,WAAAC;AAAA,IACA,WAAAC;AAAA,IACA,wBAAAC;AAAA,IACA,WAAA5B;AAAA,IACA,oBAAAH;AAAA,EAAA;AAEJ;"}
|
|
1
|
+
{"version":3,"file":"use-audio-player.js","sources":["../../../../src/features/hooks/use-audio-player/use-audio-player.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react';\n\nimport { type IActiveSound, type IAudioConfig, type IAudioOptions } from './use-audio-player-types';\n\ndeclare global {\n interface Window {\n webkitAudioContext?: typeof AudioContext;\n }\n}\n\nexport const useAudioPlayer = (audioConfig: IAudioConfig, canPlayAudio: boolean = true) => {\n const audioContext = useRef<AudioContext | null>(null);\n const bufferCache = useRef<Record<string, AudioBuffer | null>>({});\n const activeSounds = useRef<Partial<Record<string, IActiveSound>>>({});\n const fadeTimeouts = useRef<Partial<Record<string, number>>>({});\n\n useEffect(() => {\n try {\n const AudioContextClass = window.AudioContext || window.webkitAudioContext;\n\n audioContext.current = new AudioContextClass();\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn('Failed to create AudioContext:', error);\n }\n\n return () => {\n if (audioContext.current && audioContext.current.state !== 'closed') {\n audioContext.current.close();\n }\n };\n }, []);\n\n const resumeAudioContext = useCallback(async () => {\n if (audioContext.current?.state === 'suspended') {\n try {\n await audioContext.current.resume();\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn('Failed to resume AudioContext:', error);\n }\n }\n }, []);\n\n const loadSound = useCallback(\n async (key: string): Promise<void> => {\n if (!audioContext.current || bufferCache.current[key]) return;\n\n try {\n const url = audioConfig[key];\n\n if (!url) throw new Error(`No URL found for sound key: ${key}`);\n\n const response = await fetch(url, {\n mode: 'cors',\n credentials: 'omit',\n });\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n const arrayBuffer = await response.arrayBuffer();\n const audioBuffer = await audioContext.current.decodeAudioData(arrayBuffer);\n\n bufferCache.current[key] = audioBuffer;\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error(`Failed to load sound \"${key}\":`, error);\n bufferCache.current[key] = null;\n }\n },\n [audioConfig],\n );\n\n const fadeIn = useCallback((gainNode: GainNode, duration: number = 0.5) => {\n if (!audioContext.current) return;\n\n const now = audioContext.current.currentTime;\n\n gainNode.gain.cancelScheduledValues(now);\n gainNode.gain.setValueAtTime(gainNode.gain.value, now);\n gainNode.gain.linearRampToValueAtTime(1, now + duration);\n }, []);\n\n const fadeOut = useCallback(\n (key: string, sound: IActiveSound, duration: number = 0.5, shouldStop: boolean = true) => {\n if (!audioContext.current) return;\n\n if (fadeTimeouts.current[key]) {\n clearTimeout(fadeTimeouts.current[key]);\n delete fadeTimeouts.current[key];\n }\n\n const now = audioContext.current.currentTime;\n\n sound.gainNode.gain.cancelScheduledValues(now);\n sound.gainNode.gain.setValueAtTime(sound.gainNode.gain.value, now);\n sound.gainNode.gain.linearRampToValueAtTime(0, now + duration);\n\n if (shouldStop) {\n fadeTimeouts.current[key] = window.setTimeout(() => {\n try {\n sound.source.stop();\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn('Error stopping sound:', error);\n }\n\n if (activeSounds.current[key]?.source === sound.source) {\n delete activeSounds.current[key];\n }\n delete fadeTimeouts.current[key];\n }, duration * 1000);\n }\n },\n [],\n );\n\n const play = useCallback(\n async (key: string, options: IAudioOptions = {}): Promise<void> => {\n const {\n loop = false,\n volume = 1,\n fadeIn: shouldFadeIn = false,\n fadeDuration = 0.5,\n } = options;\n\n if (!audioContext.current || !canPlayAudio) {\n // eslint-disable-next-line no-console\n console.warn('Cannot play sound:', {\n key,\n hasContext: !!audioContext.current,\n canPlayAudio,\n });\n\n return;\n }\n\n if (activeSounds.current[key] && !loop) {\n try {\n activeSounds.current[key]!.source.stop();\n } catch (error) {\n // eslint-disable-next-line no-console\n console.log(error);\n }\n delete activeSounds.current[key];\n }\n\n await resumeAudioContext();\n await loadSound(key);\n\n const buffer = bufferCache.current[key];\n\n if (!buffer) {\n // eslint-disable-next-line no-console\n console.warn(`No buffer available for sound: ${key}`);\n\n return;\n }\n\n if (activeSounds.current[key] && loop) {\n if (fadeTimeouts.current[key]) {\n clearTimeout(fadeTimeouts.current[key]);\n delete fadeTimeouts.current[key];\n }\n fadeIn(activeSounds.current[key]!.gainNode, fadeDuration);\n\n return;\n }\n\n if (activeSounds.current[key]) {\n const existingSound = activeSounds.current[key];\n\n try {\n existingSound!.source.stop();\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn('Error stopping existing sound:', error);\n }\n delete activeSounds.current[key];\n }\n\n try {\n const source = audioContext.current.createBufferSource();\n const gainNode = audioContext.current.createGain();\n\n source.buffer = buffer;\n source.loop = loop;\n source.connect(gainNode).connect(audioContext.current.destination);\n\n if (shouldFadeIn) {\n gainNode.gain.setValueAtTime(0, audioContext.current.currentTime);\n fadeIn(gainNode, fadeDuration);\n } else {\n gainNode.gain.setValueAtTime(volume, audioContext.current.currentTime);\n }\n\n source.start();\n activeSounds.current[key] = { source, gainNode, loop };\n\n if (!loop) {\n source.onended = () => {\n if (activeSounds.current[key]?.source === source) {\n delete activeSounds.current[key];\n }\n };\n }\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error(`Failed to play sound \"${key}\":`, error);\n }\n },\n [canPlayAudio, resumeAudioContext, loadSound, fadeIn],\n );\n\n const stop = useCallback(\n async (\n key: string,\n options: { immediately?: boolean; fadeOut?: boolean; fadeDuration?: number } = {},\n ): Promise<void> => {\n const { immediately = true, fadeOut: shouldFadeOut = false, fadeDuration = 0.5 } = options;\n\n const sound = activeSounds.current[key];\n\n if (!sound) return;\n\n if (immediately && !shouldFadeOut) {\n try {\n sound.source.stop();\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn('Error stopping sound:', error);\n }\n\n delete activeSounds.current[key];\n if (fadeTimeouts.current[key]) {\n clearTimeout(fadeTimeouts.current[key]);\n delete fadeTimeouts.current[key];\n }\n } else {\n fadeOut(key, sound, fadeDuration);\n }\n },\n [fadeOut],\n );\n\n const stopAll = useCallback(\n (options: { immediately?: boolean; fadeOut?: boolean } = {}) => {\n const soundKeys = Object.keys(activeSounds.current);\n\n soundKeys.forEach(key => stop(key, options));\n },\n [stop],\n );\n\n const isPlaying = useCallback((key: string): boolean => {\n return !!activeSounds.current[key];\n }, []);\n\n const setVolume = useCallback((key: string, volume: number, duration: number = 0) => {\n const sound = activeSounds.current[key];\n\n if (!sound || !audioContext.current) return;\n\n const now = audioContext.current.currentTime;\n\n if (duration > 0) {\n sound.gainNode.gain.cancelScheduledValues(now);\n sound.gainNode.gain.setValueAtTime(sound.gainNode.gain.value, now);\n sound.gainNode.gain.linearRampToValueAtTime(volume, now + duration);\n } else {\n sound.gainNode.gain.setValueAtTime(volume, now);\n }\n }, []);\n\n const handleVisibilityChange = useCallback(\n (backgroundSounds: Set<string> = new Set(), fadeOnHide: boolean = true) => {\n if (!fadeOnHide) return;\n\n if (document.visibilityState === 'visible') {\n resumeAudioContext();\n Object.values(activeSounds.current).forEach(sound => {\n if (sound) {\n fadeIn(sound.gainNode);\n }\n });\n } else {\n Object.entries(activeSounds.current).forEach(([key, sound]) => {\n if (sound) {\n if (backgroundSounds.has(key)) {\n fadeOut(key, sound, 0.5, false);\n } else {\n fadeOut(key, sound);\n }\n }\n });\n }\n },\n [resumeAudioContext, fadeIn, fadeOut],\n );\n\n useEffect(() => {\n const timeouts = fadeTimeouts.current;\n\n return () => {\n Object.values(timeouts).forEach(id => {\n if (id) clearTimeout(id);\n });\n };\n }, []);\n\n return {\n play,\n stop,\n stopAll,\n isPlaying,\n setVolume,\n handleVisibilityChange,\n loadSound,\n resumeAudioContext,\n };\n};\n"],"names":["useAudioPlayer","audioConfig","canPlayAudio","audioContext","useRef","bufferCache","activeSounds","fadeTimeouts","useEffect","AudioContextClass","error","resumeAudioContext","useCallback","_a","loadSound","key","url","response","arrayBuffer","audioBuffer","fadeIn","gainNode","duration","now","fadeOut","sound","shouldStop","play","options","loop","volume","shouldFadeIn","fadeDuration","buffer","existingSound","source","stop","immediately","shouldFadeOut","stopAll","isPlaying","setVolume","handleVisibilityChange","backgroundSounds","fadeOnHide","timeouts","id"],"mappings":"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"}
|