@aippy/runtime 0.3.2 → 0.3.3-dev.0

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.
@@ -0,0 +1,380 @@
1
+ var U = Object.defineProperty;
2
+ var j = (e, t, s) => t in e ? U(e, t, { enumerable: !0, configurable: !0, writable: !0, value: s }) : e[t] = s;
3
+ var h = (e, t, s) => j(e, typeof t != "symbol" ? t + "" : t, s);
4
+ import { useState as C, useRef as L, useEffect as P, useCallback as T } from "react";
5
+ function _() {
6
+ const e = navigator.userAgent;
7
+ return !!(/iPad|iPhone|iPod/.test(e) || navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1);
8
+ }
9
+ function B() {
10
+ try {
11
+ if (!window.AudioContext)
12
+ return !1;
13
+ const e = new AudioContext(), t = typeof e.createMediaStreamDestination == "function";
14
+ return e.close(), t;
15
+ } catch {
16
+ return !1;
17
+ }
18
+ }
19
+ function F(e = "video", t = !1) {
20
+ const s = document.createElement(e);
21
+ return s.muted = !1, s.autoplay = !0, e === "video" && (s.playsInline = !0), t ? s.style.cssText = "position:fixed;bottom:10px;right:10px;width:200px;background:#ff0000;z-index:9999;" : s.style.cssText = "position:fixed;width:1px;height:1px;opacity:0;pointer-events:none;", s;
22
+ }
23
+ class N {
24
+ constructor(t, s, a, m = !1) {
25
+ h(this, "analyser");
26
+ h(this, "dataArray");
27
+ h(this, "rafId", null);
28
+ h(this, "silenceStartTime", 0);
29
+ h(this, "isPaused", !1);
30
+ h(this, "lastCheckTime", 0);
31
+ h(this, "silenceThreshold");
32
+ h(this, "silenceDuration");
33
+ h(this, "checkInterval");
34
+ h(this, "debug");
35
+ /**
36
+ * Check audio levels and pause/resume as needed
37
+ */
38
+ h(this, "check", () => {
39
+ const t = performance.now();
40
+ t - this.lastCheckTime >= this.checkInterval && (this.lastCheckTime = t, this.getAudioLevel() < this.silenceThreshold ? this.silenceStartTime === 0 ? this.silenceStartTime = t : t - this.silenceStartTime >= this.silenceDuration && !this.isPaused && this.pauseMedia() : (this.silenceStartTime = 0, this.isPaused && this.resumeMedia())), this.rafId = requestAnimationFrame(this.check);
41
+ });
42
+ this.audioContext = t, this.mediaElement = s, this.silenceThreshold = a.silenceThreshold, this.silenceDuration = a.silenceDuration, this.checkInterval = a.checkInterval, this.debug = m, this.analyser = t.createAnalyser(), this.analyser.fftSize = 512, this.analyser.smoothingTimeConstant = 0.3, this.dataArray = new Uint8Array(this.analyser.frequencyBinCount);
43
+ }
44
+ /**
45
+ * Connect the detector to the audio stream
46
+ */
47
+ connect(t) {
48
+ t.connect(this.analyser);
49
+ }
50
+ /**
51
+ * Start monitoring audio levels
52
+ */
53
+ start() {
54
+ this.rafId === null && (this.lastCheckTime = performance.now(), this.check());
55
+ }
56
+ /**
57
+ * Stop monitoring
58
+ */
59
+ stop() {
60
+ this.rafId !== null && (cancelAnimationFrame(this.rafId), this.rafId = null);
61
+ }
62
+ /**
63
+ * Cleanup resources
64
+ */
65
+ dispose() {
66
+ this.stop(), this.analyser.disconnect();
67
+ }
68
+ /**
69
+ * Get current audio level (0-1)
70
+ */
71
+ getAudioLevel() {
72
+ this.analyser.getByteTimeDomainData(this.dataArray);
73
+ let t = 0;
74
+ for (let s = 0; s < this.dataArray.length; s++) {
75
+ const a = (this.dataArray[s] - 128) / 128;
76
+ t += a * a;
77
+ }
78
+ return Math.sqrt(t / this.dataArray.length);
79
+ }
80
+ /**
81
+ * Pause media element to stop audio output
82
+ */
83
+ pauseMedia() {
84
+ try {
85
+ this.mediaElement.pause(), this.isPaused = !0;
86
+ } catch (t) {
87
+ console.error("[AudioSilenceDetector] Failed to pause:", t);
88
+ }
89
+ }
90
+ resumeMedia() {
91
+ try {
92
+ this.audioContext.state === "running" && this.mediaElement.play().catch((s) => {
93
+ this.debug && console.warn("[AudioSilenceDetector] Failed to resume:", s);
94
+ }), this.isPaused = !1;
95
+ } catch (t) {
96
+ console.error("[AudioSilenceDetector] Failed to resume:", t);
97
+ }
98
+ }
99
+ }
100
+ const E = /* @__PURE__ */ new WeakSet();
101
+ function R(e, t = {}) {
102
+ if (E.has(e))
103
+ return e;
104
+ const {
105
+ forceEnable: s = !1,
106
+ autoCleanup: a = !0,
107
+ debug: m = !1,
108
+ mediaElementType: g = "video",
109
+ autoPause: f = {}
110
+ } = t, u = {
111
+ enabled: f.enabled ?? !0,
112
+ silenceThreshold: f.silenceThreshold ?? 1e-3,
113
+ silenceDuration: f.silenceDuration ?? 50,
114
+ checkInterval: f.checkInterval ?? 16
115
+ }, b = s || _();
116
+ let l = !1;
117
+ const o = (n) => Object.defineProperty(n, "_isUnlocked", {
118
+ get: () => l,
119
+ enumerable: !0,
120
+ configurable: !0
121
+ }), c = async () => {
122
+ const n = e.state;
123
+ (n === "suspended" || n === "interrupted") && await e.resume();
124
+ };
125
+ let y = [];
126
+ function S() {
127
+ const n = () => {
128
+ const O = e.state;
129
+ (O === "interrupted" || O === "suspended") && (l = !1);
130
+ };
131
+ e.addEventListener("statechange", n);
132
+ const d = (O) => {
133
+ O.persisted && (l = !1);
134
+ };
135
+ window.addEventListener("pageshow", d);
136
+ const M = () => {
137
+ try {
138
+ e.suspend();
139
+ } catch {
140
+ }
141
+ l = !1;
142
+ };
143
+ window.addEventListener("pagehide", M);
144
+ const x = () => {
145
+ if (document.visibilityState === "hidden") {
146
+ try {
147
+ e.suspend();
148
+ } catch {
149
+ }
150
+ l = !1;
151
+ }
152
+ };
153
+ document.addEventListener("visibilitychange", x), y = [
154
+ () => e.removeEventListener("statechange", n),
155
+ () => window.removeEventListener("pageshow", d),
156
+ () => window.removeEventListener("pagehide", M),
157
+ () => document.removeEventListener("visibilitychange", x)
158
+ ];
159
+ }
160
+ function D() {
161
+ y.forEach((n) => n()), y = [];
162
+ }
163
+ if (!b) {
164
+ const n = Object.assign(e, {
165
+ unlock: async () => {
166
+ await c(), l = !0;
167
+ },
168
+ cleanup: () => {
169
+ try {
170
+ D();
171
+ } catch {
172
+ }
173
+ E.delete(e);
174
+ },
175
+ isPatched: !1,
176
+ originalDestination: e.destination
177
+ });
178
+ return o(n), S(), E.add(e), n;
179
+ }
180
+ if (!B()) {
181
+ console.warn(
182
+ "[AudioContext] MediaStreamAudioDestinationNode not supported, falling back to native"
183
+ );
184
+ const n = Object.assign(e, {
185
+ unlock: async () => {
186
+ await c(), l = !0;
187
+ },
188
+ cleanup: () => {
189
+ try {
190
+ D();
191
+ } catch {
192
+ }
193
+ E.delete(e);
194
+ },
195
+ isPatched: !1,
196
+ originalDestination: e.destination
197
+ });
198
+ return o(n), S(), E.add(e), n;
199
+ }
200
+ const A = e.destination, I = e.createMediaStreamDestination(), v = e.createGain();
201
+ v.gain.value = 1, v.connect(I);
202
+ const r = F(g, m);
203
+ r.srcObject = I.stream, document.body.appendChild(r);
204
+ let i = null;
205
+ u.enabled && (i = new N(
206
+ e,
207
+ r,
208
+ u,
209
+ m
210
+ ), i.connect(v)), Object.defineProperty(e, "destination", {
211
+ get: () => v,
212
+ enumerable: !0,
213
+ configurable: !0
214
+ }), "maxChannelCount" in v || Object.defineProperty(v, "maxChannelCount", {
215
+ get: () => A.maxChannelCount,
216
+ enumerable: !0
217
+ });
218
+ const p = async () => {
219
+ try {
220
+ await r.play(), await c(), i && i.start(), l = !0;
221
+ } catch (n) {
222
+ throw n instanceof DOMException && n.name === "NotAllowedError" || console.error("[AudioContext] Unlock failed:", n), n;
223
+ }
224
+ }, w = () => {
225
+ try {
226
+ D(), i && (i.dispose(), i = null), r.pause(), r.srcObject = null, r.remove();
227
+ } catch (n) {
228
+ console.error("[AudioContext] Cleanup error:", n);
229
+ }
230
+ E.delete(e);
231
+ };
232
+ if (a) {
233
+ const n = e.close.bind(e);
234
+ e.close = async () => (w(), n());
235
+ }
236
+ const k = Object.assign(e, {
237
+ unlock: p,
238
+ cleanup: w,
239
+ isPatched: !0,
240
+ originalDestination: A
241
+ });
242
+ return o(k), S(), E.add(e), k;
243
+ }
244
+ function q(e = {}) {
245
+ const { autoUnlock: t = !0, ...s } = e, [a, m] = C(null), [g, f] = C(!1), u = L(null);
246
+ P(() => {
247
+ const o = new AudioContext(), c = R(o, s);
248
+ return u.current = c, m(c), () => {
249
+ u.current = null, c.cleanup(), c.close();
250
+ };
251
+ }, []), P(() => {
252
+ if (!a) return;
253
+ const o = () => f(a._isUnlocked);
254
+ a.addEventListener("statechange", o);
255
+ const c = (y) => {
256
+ y.persisted && o();
257
+ };
258
+ return window.addEventListener("pageshow", c), () => {
259
+ a.removeEventListener("statechange", o), window.removeEventListener("pageshow", c);
260
+ };
261
+ }, [a]);
262
+ const b = T(() => u.current, []), l = T(async () => {
263
+ const o = u.current;
264
+ if (o)
265
+ try {
266
+ await o.unlock(), f(!0);
267
+ } catch (c) {
268
+ if (c instanceof DOMException && c.name === "NotAllowedError")
269
+ return;
270
+ console.warn("Failed to unlock audio:", c);
271
+ }
272
+ }, []);
273
+ return P(() => {
274
+ if (!t || !a) return;
275
+ const o = async (c) => {
276
+ c.isTrusted && (u.current?._isUnlocked || await l());
277
+ };
278
+ return document.addEventListener("click", o, { capture: !0 }), document.addEventListener("touchstart", o, { capture: !0 }), () => {
279
+ document.removeEventListener("click", o, { capture: !0 }), document.removeEventListener("touchstart", o, { capture: !0 });
280
+ };
281
+ }, [t, a, l]), { audioContext: a, isUnlocked: g, unlock: l, getAudioContext: b };
282
+ }
283
+ function H(e, t = {}) {
284
+ const { preload: s = !1, volume: a = 1, ...m } = t, { audioContext: g, isUnlocked: f, unlock: u, getAudioContext: b } = q(m), l = L(/* @__PURE__ */ new Map()), o = L(/* @__PURE__ */ new Map()), c = L(/* @__PURE__ */ new Map()), y = L(e);
285
+ y.current = e;
286
+ const S = L(a);
287
+ S.current = a, P(() => {
288
+ !s || !g || !f || Object.entries(y.current).forEach(([r, i]) => {
289
+ l.current.has(r) || D(g, r, i).catch(() => {
290
+ });
291
+ });
292
+ }, [s, g, f]);
293
+ function D(r, i, p) {
294
+ const w = l.current.get(i);
295
+ if (w) return Promise.resolve(w);
296
+ const k = o.current.get(i);
297
+ if (k) return k;
298
+ const n = z(r, p).then((d) => (l.current.set(i, d), o.current.delete(i), d)).catch((d) => {
299
+ throw o.current.delete(i), d;
300
+ });
301
+ return o.current.set(i, n), n;
302
+ }
303
+ const A = T((r) => {
304
+ const i = c.current.get(r);
305
+ if (i) {
306
+ try {
307
+ i.source.stop();
308
+ } catch {
309
+ }
310
+ try {
311
+ i.source.disconnect(), i.gain.disconnect();
312
+ } catch {
313
+ }
314
+ c.current.delete(r);
315
+ }
316
+ }, []), I = T(() => {
317
+ c.current.forEach((r) => {
318
+ try {
319
+ r.source.stop();
320
+ } catch {
321
+ }
322
+ try {
323
+ r.source.disconnect(), r.gain.disconnect();
324
+ } catch {
325
+ }
326
+ }), c.current.clear();
327
+ }, []), v = T(async (r, i) => {
328
+ const p = b();
329
+ if (!p) return null;
330
+ p._isUnlocked || await u();
331
+ const w = y.current[r];
332
+ if (!w)
333
+ return console.warn(`[useSound] Unknown sound name: "${r}"`), null;
334
+ let k;
335
+ try {
336
+ k = await D(p, r, w);
337
+ } catch (M) {
338
+ return console.warn(`[useSound] Failed to load "${r}":`, M), null;
339
+ }
340
+ A(r);
341
+ const n = p.createBufferSource();
342
+ n.buffer = k, n.loop = i?.loop ?? !1;
343
+ const d = p.createGain();
344
+ return d.gain.value = (i?.volume ?? 1) * S.current, n.connect(d), d.connect(p.destination), n.start(), c.current.set(r, { source: n, gain: d }), n.onended = () => {
345
+ c.current.get(r)?.source === n && c.current.delete(r);
346
+ }, () => A(r);
347
+ }, [b, u, A]);
348
+ return P(() => () => {
349
+ c.current.forEach((r) => {
350
+ try {
351
+ r.source.stop();
352
+ } catch {
353
+ }
354
+ try {
355
+ r.source.disconnect(), r.gain.disconnect();
356
+ } catch {
357
+ }
358
+ }), c.current.clear();
359
+ }, []), {
360
+ play: v,
361
+ stop: A,
362
+ stopAll: I,
363
+ isReady: !!g && f,
364
+ audioContext: g,
365
+ unlock: u,
366
+ getAudioContext: b
367
+ };
368
+ }
369
+ async function z(e, t) {
370
+ const a = await (await fetch(t)).arrayBuffer();
371
+ return e.decodeAudioData(a);
372
+ }
373
+ export {
374
+ H as a,
375
+ _ as b,
376
+ F as c,
377
+ B as i,
378
+ R as p,
379
+ q as u
380
+ };
@@ -1,5 +1,5 @@
1
- import { c as o, u as s } from "../hooks-CDo6slfY.js";
2
- import { getAuthTokenAsync as f } from "../bridge-CqV1iP30.js";
1
+ import { c as o, u as s } from "../hooks-D5lkty5r.js";
2
+ import { g as f } from "../bridge-CtB9L5kL.js";
3
3
  import { i as t } from "../app-version-checker-Bz7FrEZz.js";
4
4
  export {
5
5
  o as clearUserInfoCache,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aippy/runtime",
3
- "version": "0.3.2",
3
+ "version": "0.3.3-dev.0",
4
4
  "description": "Aippy Runtime SDK - Runtime SDK for Aippy projects",
5
5
  "private": false,
6
6
  "type": "module",
@@ -1,219 +0,0 @@
1
- var D = Object.defineProperty;
2
- var b = (e, t, n) => t in e ? D(e, t, { enumerable: !0, configurable: !0, writable: !0, value: n }) : e[t] = n;
3
- var i = (e, t, n) => b(e, typeof t != "symbol" ? t + "" : t, n);
4
- import { useState as k, useRef as w, useEffect as p } from "react";
5
- function T() {
6
- const e = navigator.userAgent;
7
- return !!(/iPad|iPhone|iPod/.test(e) || navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1);
8
- }
9
- function P() {
10
- try {
11
- if (!window.AudioContext)
12
- return !1;
13
- const e = new AudioContext(), t = typeof e.createMediaStreamDestination == "function";
14
- return e.close(), t;
15
- } catch {
16
- return !1;
17
- }
18
- }
19
- function E(e = "video", t = !1) {
20
- const n = document.createElement(e);
21
- return n.muted = !1, n.autoplay = !0, e === "video" && (n.playsInline = !0), t ? n.style.cssText = "position:fixed;bottom:10px;right:10px;width:200px;background:#ff0000;z-index:9999;" : n.style.cssText = "position:fixed;width:1px;height:1px;opacity:0;pointer-events:none;", n;
22
- }
23
- class I {
24
- constructor(t, n, s, o = !1) {
25
- i(this, "analyser");
26
- i(this, "dataArray");
27
- i(this, "rafId", null);
28
- i(this, "silenceStartTime", 0);
29
- i(this, "isPaused", !1);
30
- i(this, "lastCheckTime", 0);
31
- i(this, "silenceThreshold");
32
- i(this, "silenceDuration");
33
- i(this, "checkInterval");
34
- i(this, "debug");
35
- /**
36
- * Check audio levels and pause/resume as needed
37
- */
38
- i(this, "check", () => {
39
- const t = performance.now();
40
- t - this.lastCheckTime >= this.checkInterval && (this.lastCheckTime = t, this.getAudioLevel() < this.silenceThreshold ? this.silenceStartTime === 0 ? this.silenceStartTime = t : t - this.silenceStartTime >= this.silenceDuration && !this.isPaused && this.pauseMedia() : (this.silenceStartTime = 0, this.isPaused && this.resumeMedia())), this.rafId = requestAnimationFrame(this.check);
41
- });
42
- this.audioContext = t, this.mediaElement = n, this.silenceThreshold = s.silenceThreshold, this.silenceDuration = s.silenceDuration, this.checkInterval = s.checkInterval, this.debug = o, this.analyser = t.createAnalyser(), this.analyser.fftSize = 512, this.analyser.smoothingTimeConstant = 0.3, this.dataArray = new Uint8Array(this.analyser.frequencyBinCount);
43
- }
44
- /**
45
- * Connect the detector to the audio stream
46
- */
47
- connect(t) {
48
- t.connect(this.analyser);
49
- }
50
- /**
51
- * Start monitoring audio levels
52
- */
53
- start() {
54
- this.rafId === null && (this.lastCheckTime = performance.now(), this.check());
55
- }
56
- /**
57
- * Stop monitoring
58
- */
59
- stop() {
60
- this.rafId !== null && (cancelAnimationFrame(this.rafId), this.rafId = null);
61
- }
62
- /**
63
- * Cleanup resources
64
- */
65
- dispose() {
66
- this.stop(), this.analyser.disconnect();
67
- }
68
- /**
69
- * Get current audio level (0-1)
70
- */
71
- getAudioLevel() {
72
- this.analyser.getByteTimeDomainData(this.dataArray);
73
- let t = 0;
74
- for (let n = 0; n < this.dataArray.length; n++) {
75
- const s = (this.dataArray[n] - 128) / 128;
76
- t += s * s;
77
- }
78
- return Math.sqrt(t / this.dataArray.length);
79
- }
80
- /**
81
- * Pause media element to stop audio output
82
- */
83
- pauseMedia() {
84
- try {
85
- this.mediaElement.pause(), this.isPaused = !0;
86
- } catch (t) {
87
- console.error("[AudioSilenceDetector] Failed to pause:", t);
88
- }
89
- }
90
- /**
91
- * Resume media element playback
92
- */
93
- resumeMedia() {
94
- try {
95
- this.audioContext.state === "running" && this.mediaElement.play().catch((t) => {
96
- this.debug && console.warn("[AudioSilenceDetector] Failed to resume:", t);
97
- }), this.isPaused = !1;
98
- } catch (t) {
99
- console.error("[AudioSilenceDetector] Failed to resume:", t);
100
- }
101
- }
102
- }
103
- function S(e, t = {}) {
104
- const {
105
- forceEnable: n = !1,
106
- autoCleanup: s = !0,
107
- debug: o = !1,
108
- mediaElementType: m = "video",
109
- autoPause: d = {}
110
- } = t, h = {
111
- enabled: d.enabled ?? !0,
112
- silenceThreshold: d.silenceThreshold ?? 1e-3,
113
- silenceDuration: d.silenceDuration ?? 50,
114
- checkInterval: d.checkInterval ?? 16
115
- };
116
- if (!(n || T()))
117
- return Object.assign(e, {
118
- unlock: async () => {
119
- e.state === "suspended" && await e.resume();
120
- },
121
- cleanup: () => {
122
- },
123
- isPatched: !1,
124
- originalDestination: e.destination
125
- });
126
- if (!P())
127
- return console.warn(
128
- "[AudioContext] MediaStreamAudioDestinationNode not supported, falling back to native"
129
- ), Object.assign(e, {
130
- unlock: async () => e.resume(),
131
- cleanup: () => {
132
- },
133
- isPatched: !1,
134
- originalDestination: e.destination
135
- });
136
- const c = e.destination, y = e.createMediaStreamDestination(), f = e.createGain();
137
- f.gain.value = 1, f.connect(y);
138
- const l = E(m, o);
139
- l.srcObject = y.stream, document.body.appendChild(l);
140
- let u = null;
141
- h.enabled && (u = new I(
142
- e,
143
- l,
144
- h,
145
- o
146
- ), u.connect(f)), Object.defineProperty(e, "destination", {
147
- get: () => f,
148
- enumerable: !0,
149
- configurable: !0
150
- }), "maxChannelCount" in f || Object.defineProperty(f, "maxChannelCount", {
151
- get: () => c.maxChannelCount,
152
- enumerable: !0
153
- });
154
- let g = !1;
155
- const v = async () => {
156
- if (!g)
157
- try {
158
- await l.play(), e.state === "suspended" && await e.resume(), u && u.start(), g = !0;
159
- } catch (a) {
160
- throw a instanceof DOMException && a.name === "NotAllowedError" || console.error("[AudioContext] Unlock failed:", a), a;
161
- }
162
- }, A = () => {
163
- try {
164
- u && (u.dispose(), u = null), l.pause(), l.srcObject = null, l.remove();
165
- } catch (a) {
166
- console.error("[AudioContext] Cleanup error:", a);
167
- }
168
- };
169
- if (s) {
170
- const a = e.close.bind(e);
171
- e.close = async () => (A(), a());
172
- }
173
- return Object.assign(e, {
174
- unlock: v,
175
- cleanup: A,
176
- isPatched: !0,
177
- originalDestination: c
178
- });
179
- }
180
- function C(e = {}) {
181
- const { autoUnlock: t = !0, ...n } = e, [s, o] = k(null), [m, d] = k(!1), h = w(null);
182
- return p(() => {
183
- const r = new AudioContext(), c = S(r, n);
184
- return o(c), () => {
185
- c.cleanup(), c.close();
186
- };
187
- }, []), p(() => {
188
- s && (h.current = async () => {
189
- if (!m)
190
- try {
191
- await s.unlock(), d(!0);
192
- } catch (r) {
193
- if (r instanceof DOMException && r.name === "NotAllowedError")
194
- return;
195
- console.warn("Failed to unlock audio:", r);
196
- }
197
- });
198
- }, [s, m]), p(() => {
199
- if (!t || !s) return;
200
- const r = async (c) => {
201
- c.isTrusted && await h.current?.();
202
- };
203
- return document.addEventListener("click", r, { once: !0, capture: !0 }), document.addEventListener("touchstart", r, { once: !0, capture: !0 }), () => {
204
- document.removeEventListener("click", r, { capture: !0 }), document.removeEventListener("touchstart", r, { capture: !0 });
205
- };
206
- }, [t, s]), {
207
- audioContext: s,
208
- isUnlocked: m,
209
- unlock: h.current || (async () => {
210
- })
211
- };
212
- }
213
- export {
214
- T as a,
215
- E as c,
216
- P as i,
217
- S as p,
218
- C as u
219
- };