@aippy/runtime 0.2.3 → 0.2.4-dev.10

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.
@@ -8,6 +8,7 @@
8
8
  */
9
9
  export { patchAudioContext } from './patchAudioContext';
10
10
  export type { AudioContextPatchOptions, AutoPauseOptions, MediaElementType, PatchedAudioContext, } from './types';
11
- export { createHiddenMediaElement, createHiddenVideoElement, isIOSDevice, isMediaStreamAudioSupported, } from './utils';
11
+ export { createHiddenMediaElement, createHiddenVideoElement, isMediaStreamAudioSupported, } from './utils';
12
12
  export { useAudioContext } from './useAudioContext';
13
13
  export type { UseAudioContextOptions, UseAudioContextReturn } from './useAudioContext';
14
+ export { isIOSDevice } from './utils';
@@ -1,4 +1,4 @@
1
- import { c as i, a as t, i as d, b as o, p as s, u as n } from "../useAudioContext-BKgy28A1.js";
1
+ import { c as i, a as t, b as d, i as o, p as s, u as n } from "../useAudioContext-CNQQSTab.js";
2
2
  export {
3
3
  i as createHiddenMediaElement,
4
4
  t as createHiddenVideoElement,
@@ -2,3 +2,4 @@ export * from './types';
2
2
  export * from './config';
3
3
  export * from './errors';
4
4
  export * from './version';
5
+ export * from './runtime';
@@ -1,45 +1,50 @@
1
- import { A as d, E as v, c as _ } from "../errors-CDEBaBxB.js";
2
- const o = {
1
+ import { a as d, A as f, C as u, E as A, R as _, b as m, c as R, p as g } from "../runtime-DjBdOttl.js";
2
+ const s = {
3
3
  mode: "development",
4
4
  debug: !1,
5
5
  apiBaseUrl: void 0,
6
6
  headers: {}
7
7
  };
8
- function r() {
8
+ function o() {
9
9
  const e = {};
10
10
  return typeof process < "u" && process.env && (process.env.NODE_ENV && (e.mode = process.env.NODE_ENV), process.env.AIPPY_DEBUG && (e.debug = process.env.AIPPY_DEBUG === "true"), process.env.AIPPY_API_BASE_URL && (e.apiBaseUrl = process.env.AIPPY_API_BASE_URL)), e;
11
11
  }
12
- function a(e) {
13
- const n = r();
12
+ function c(e) {
13
+ const n = o();
14
14
  return {
15
- ...o,
15
+ ...s,
16
16
  ...n,
17
17
  ...e,
18
18
  headers: {
19
- ...o.headers,
19
+ ...s.headers,
20
20
  ...n.headers,
21
21
  ...e?.headers
22
22
  }
23
23
  };
24
24
  }
25
- const s = "0.2.3", t = {
26
- version: s
27
- }, i = t.version, c = "@aippy/runtime";
25
+ const r = "0.2.4-dev.10", a = {
26
+ version: r
27
+ }, i = a.version, t = "@aippy/runtime";
28
28
  function p() {
29
29
  return {
30
- name: c,
30
+ name: t,
31
31
  version: i,
32
32
  buildTime: (/* @__PURE__ */ new Date()).toISOString()
33
33
  };
34
34
  }
35
35
  export {
36
- d as AippyRuntimeError,
37
- o as DEFAULT_CONFIG,
38
- v as ERROR_CODES,
39
- c as SDK_NAME,
36
+ d as AippyRuntime,
37
+ f as AippyRuntimeError,
38
+ u as Cancellable,
39
+ s as DEFAULT_CONFIG,
40
+ A as ERROR_CODES,
41
+ _ as ReceiveChannel,
42
+ t as SDK_NAME,
40
43
  i as VERSION,
41
- _ as createError,
42
- r as getConfigFromEnv,
44
+ m as aippyRuntime,
45
+ R as createError,
46
+ o as getConfigFromEnv,
43
47
  p as getVersionInfo,
44
- a as mergeConfig
48
+ c as mergeConfig,
49
+ g as processMotionData
45
50
  };
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Aippy Runtime - Unified runtime for native bridge communication
3
+ */
4
+ /**
5
+ * Cancellable class - For managing subscriptions
6
+ */
7
+ export declare class Cancellable {
8
+ private cancelFn?;
9
+ private cancelled;
10
+ constructor(cancelFn?: (() => void) | undefined);
11
+ cancel(): void;
12
+ get isCancelled(): boolean;
13
+ }
14
+ /**
15
+ * ReceiveChannel - Manages message receiving and subscription
16
+ */
17
+ export declare class ReceiveChannel {
18
+ private emitter;
19
+ /**
20
+ * Emit a message to subscribers
21
+ */
22
+ emit(message: {
23
+ endpoint: string;
24
+ payload: any;
25
+ }): void;
26
+ /**
27
+ * Subscribe to messages on a specific endpoint
28
+ */
29
+ subscribe(endpoint: string, callback: (payload: any) => void): Cancellable;
30
+ /**
31
+ * Subscribe to a single message (auto-unsubscribe after first message)
32
+ */
33
+ once(endpoint: string, callback: (payload: any) => void): Cancellable;
34
+ }
35
+ /**
36
+ * AippyRuntime - Main runtime class for native bridge communication
37
+ */
38
+ export declare class AippyRuntime {
39
+ receiveChannel: ReceiveChannel;
40
+ private seq;
41
+ private motionListeners;
42
+ private noListenersWarned;
43
+ /**
44
+ * Unified native data receiver - Routes to specific handlers based on message type
45
+ * Called by native code via: window.aippyRuntime.receiveMessage(message)
46
+ *
47
+ * Supports two message formats:
48
+ * 1. Motion: { command: "navigator.motion", endpoint: "0", data: { motion: {...} } }
49
+ * 2. Tweaks: { "tweakKey": { value: ..., type: ... }, ... }
50
+ */
51
+ receiveMessage(message: any): Promise<void>;
52
+ /**
53
+ * Check if message is Motion format
54
+ * Motion: { command: "navigator.motion", endpoint: string, data: object }
55
+ */
56
+ private isMotionMessage;
57
+ /**
58
+ * Check if message is Tweaks format
59
+ * Tweaks: { "key": { value: any, type?: string, ... }, ... }
60
+ */
61
+ private isTweaksMessage;
62
+ /**
63
+ * Create a subscription to native events
64
+ * @param handler - WebKit message handler (e.g., aippyListener)
65
+ * @param subscribePayload - Subscription parameters (e.g., { command: "navigator.motion", type: "motion" })
66
+ * @param callback - Callback to handle received data
67
+ * @returns Cancellable subscription
68
+ */
69
+ createSubscription(handler: any, subscribePayload: any, callback: (data: any) => void): Cancellable;
70
+ /**
71
+ * Add motion listener (convenience method)
72
+ * @param callback - Callback to handle motion data
73
+ * @returns Cleanup function
74
+ */
75
+ addMotionListener(callback: (data: any) => void): () => void;
76
+ /**
77
+ * Broadcast motion data to all registered listeners
78
+ * Called by processMotionData when iOS sends data directly
79
+ * @param data - Motion data from iOS
80
+ */
81
+ broadcastMotionData(data: any): void;
82
+ }
83
+ /**
84
+ * Process Motion data from iOS native layer
85
+ * Called by native code via: window.processMotionData(data)
86
+ *
87
+ * @param data - Motion data in simplified format
88
+ * Expected format: { motion: { gravity: {x, y, z}, acceleration: {...}, rotation: {...} } }
89
+ */
90
+ export declare function processMotionData(data: any): void;
91
+ /**
92
+ * Global runtime instance - Singleton pattern
93
+ */
94
+ export declare const aippyRuntime: AippyRuntime;
@@ -1,10 +1,10 @@
1
- var h = Object.defineProperty;
2
- var p = (n, e, t) => e in n ? h(n, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[e] = t;
3
- var m = (n, e, t) => p(n, typeof e != "symbol" ? e + "" : e, t);
4
- import { c as a } from "../errors-CDEBaBxB.js";
5
- class g {
1
+ var N = Object.defineProperty;
2
+ var R = (o, e, t) => e in o ? N(o, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : o[e] = t;
3
+ var E = (o, e, t) => R(o, typeof e != "symbol" ? e + "" : e, t);
4
+ import { c as a, b as O } from "../runtime-DjBdOttl.js";
5
+ class b {
6
6
  constructor() {
7
- m(this, "stream", null);
7
+ E(this, "stream", null);
8
8
  }
9
9
  /**
10
10
  * Check if camera is supported
@@ -43,20 +43,20 @@ class g {
43
43
  try {
44
44
  const t = document.createElement("video");
45
45
  t.srcObject = this.stream, t.play();
46
- const o = document.createElement("canvas"), i = o.getContext("2d");
47
- if (!i)
46
+ const i = document.createElement("canvas"), n = i.getContext("2d");
47
+ if (!n)
48
48
  throw a("Failed to get canvas context", "UNKNOWN_ERROR");
49
- o.width = e.width || t.videoWidth, o.height = e.height || t.videoHeight, i.drawImage(t, 0, 0, o.width, o.height);
50
- const r = e.format || "jpeg", c = e.quality === "high" ? 0.9 : e.quality === "medium" ? 0.7 : 0.5, s = await new Promise((u, w) => {
51
- o.toBlob((l) => {
52
- l ? u(l) : w(new Error("Failed to create blob"));
49
+ i.width = e.width || t.videoWidth, i.height = e.height || t.videoHeight, n.drawImage(t, 0, 0, i.width, i.height);
50
+ const r = e.format || "jpeg", c = e.quality === "high" ? 0.9 : e.quality === "medium" ? 0.7 : 0.5, s = await new Promise((m, p) => {
51
+ i.toBlob((w) => {
52
+ w ? m(w) : p(new Error("Failed to create blob"));
53
53
  }, `image/${r}`, c);
54
- }), d = o.toDataURL(`image/${r}`, c);
54
+ }), u = i.toDataURL(`image/${r}`, c);
55
55
  return {
56
56
  blob: s,
57
- dataUrl: d,
58
- width: o.width,
59
- height: o.height
57
+ dataUrl: u,
58
+ width: i.width,
59
+ height: i.height
60
60
  };
61
61
  } catch (t) {
62
62
  throw a(
@@ -72,8 +72,8 @@ class g {
72
72
  this.stream && (this.stream.getTracks().forEach((e) => e.stop()), this.stream = null);
73
73
  }
74
74
  }
75
- const f = new g();
76
- class v {
75
+ const W = new b();
76
+ class I {
77
77
  /**
78
78
  * Check if geolocation is supported
79
79
  */
@@ -86,8 +86,8 @@ class v {
86
86
  async getCurrentPosition(e = {}) {
87
87
  if (!this.isSupported())
88
88
  throw a("Geolocation API is not supported", "NOT_SUPPORTED");
89
- return new Promise((t, o) => {
90
- const i = {
89
+ return new Promise((t, i) => {
90
+ const n = {
91
91
  enableHighAccuracy: e.enableHighAccuracy ?? !0,
92
92
  timeout: e.timeout ?? 1e4,
93
93
  maximumAge: e.maximumAge ?? 6e4
@@ -119,9 +119,9 @@ class v {
119
119
  s = "Geolocation timeout";
120
120
  break;
121
121
  }
122
- o(a(s, c));
122
+ i(a(s, c));
123
123
  },
124
- i
124
+ n
125
125
  );
126
126
  });
127
127
  }
@@ -131,29 +131,29 @@ class v {
131
131
  watchPosition(e, t = {}) {
132
132
  if (!this.isSupported())
133
133
  throw a("Geolocation API is not supported", "NOT_SUPPORTED");
134
- const o = {
134
+ const i = {
135
135
  enableHighAccuracy: t.enableHighAccuracy ?? !0,
136
136
  timeout: t.timeout ?? 1e4,
137
137
  maximumAge: t.maximumAge ?? 6e4
138
138
  };
139
139
  return navigator.geolocation.watchPosition(
140
- (i) => {
140
+ (n) => {
141
141
  const r = {
142
- latitude: i.coords.latitude,
143
- longitude: i.coords.longitude,
144
- accuracy: i.coords.accuracy,
145
- altitude: i.coords.altitude ?? void 0,
146
- altitudeAccuracy: i.coords.altitudeAccuracy ?? void 0,
147
- heading: i.coords.heading ?? void 0,
148
- speed: i.coords.speed ?? void 0,
149
- timestamp: i.timestamp
142
+ latitude: n.coords.latitude,
143
+ longitude: n.coords.longitude,
144
+ accuracy: n.coords.accuracy,
145
+ altitude: n.coords.altitude ?? void 0,
146
+ altitudeAccuracy: n.coords.altitudeAccuracy ?? void 0,
147
+ heading: n.coords.heading ?? void 0,
148
+ speed: n.coords.speed ?? void 0,
149
+ timestamp: n.timestamp
150
150
  };
151
151
  e(r);
152
152
  },
153
- (i) => {
154
- console.error("Geolocation watch error:", i);
153
+ (n) => {
154
+ console.error("Geolocation watch error:", n);
155
155
  },
156
- o
156
+ i
157
157
  );
158
158
  }
159
159
  /**
@@ -163,19 +163,188 @@ class v {
163
163
  navigator.geolocation.clearWatch(e);
164
164
  }
165
165
  }
166
- const N = new v();
167
- class E {
166
+ const z = new I();
167
+ function v() {
168
+ return "DeviceMotionEvent" in window;
169
+ }
170
+ function y() {
171
+ return "DeviceOrientationEvent" in window;
172
+ }
173
+ function f() {
174
+ const o = typeof window < "u", e = o && !!window.webkit, t = e && !!window.webkit?.messageHandlers, i = t && !!window.webkit?.messageHandlers?.aippyListener;
175
+ return console.log("🔍 [Aippy Sensors] hasNativeBridge check:", {
176
+ hasWindow: o,
177
+ hasWebkit: e,
178
+ hasMessageHandlers: t,
179
+ hasAippyListener: i,
180
+ result: i
181
+ }), i;
182
+ }
183
+ function D() {
184
+ return typeof window < "u" && typeof window.orientation < "u" ? window.orientation : typeof window < "u" && window.screen?.orientation?.angle !== void 0 ? window.screen.orientation.angle : 0;
185
+ }
186
+ function P(o, e, t) {
187
+ switch (t) {
188
+ case 0:
189
+ return [o, e];
190
+ case 180:
191
+ return [-o, -e];
192
+ case 90:
193
+ return [e, -o];
194
+ case -90:
195
+ return [-e, o];
196
+ default:
197
+ return [o, e];
198
+ }
199
+ }
200
+ async function S() {
201
+ if (console.log("🔐 [Aippy Sensors] requestMotionPermission called"), f())
202
+ return console.log("✅ [Aippy Sensors] Native bridge available, skipping permission request"), !0;
203
+ if (!v())
204
+ return console.warn("❌ [Aippy Sensors] Device motion not supported"), !1;
205
+ const o = typeof DeviceMotionEvent < "u" && typeof DeviceMotionEvent.requestPermission == "function";
206
+ if (console.log("🔍 [Aippy Sensors] Permission API available:", o), o)
207
+ try {
208
+ console.log("🙏 [Aippy Sensors] Requesting device motion permission...");
209
+ const e = await DeviceMotionEvent.requestPermission();
210
+ return console.log("📋 [Aippy Sensors] Permission result:", e), e === "granted";
211
+ } catch (e) {
212
+ return console.warn("❌ [Aippy Sensors] Permission request failed:", e), !1;
213
+ }
214
+ return console.log("✅ [Aippy Sensors] No permission needed (granted by default)"), !0;
215
+ }
216
+ function L(o) {
217
+ console.log("🔧 [Aippy Sensors] watchMotionNative - Setting up native bridge listener");
218
+ const e = O.addMotionListener((t) => {
219
+ const i = D(), n = t.gravity?.x ?? 0, r = t.gravity?.y ?? 0, c = t.gravity?.z ?? 0, s = t.acceleration?.x ?? 0, u = t.acceleration?.y ?? 0, m = t.acceleration?.z ?? 0, [p, w] = P(n, r, i), [d, l] = P(s, u, i), g = -p, h = -w, A = {
220
+ gravity: {
221
+ x: g,
222
+ y: h,
223
+ z: c
224
+ // Z轴不受屏幕旋转影响
225
+ },
226
+ acceleration: {
227
+ x: d,
228
+ y: l,
229
+ z: m
230
+ // Z轴不受屏幕旋转影响
231
+ },
232
+ accelerationIncludingGravity: {
233
+ x: g + d,
234
+ y: h + l,
235
+ z: c + m
236
+ },
237
+ rotation: {
238
+ alpha: t.rotation?.alpha ?? 0,
239
+ beta: t.rotation?.beta ?? 0,
240
+ gamma: t.rotation?.gamma ?? 0
241
+ },
242
+ timestamp: Date.now()
243
+ };
244
+ o(A);
245
+ });
246
+ return console.log("✅ [Aippy Sensors] watchMotionNative - Listener setup complete"), e;
247
+ }
248
+ function U(o, e = !0) {
249
+ if (!y() && !v())
250
+ throw a("Device motion/orientation API is not supported", "NOT_SUPPORTED");
251
+ let t = !1, i = null, n = 0, r = 0, c = 0, s = { x: 0, y: 0, z: 0 };
252
+ const u = (d) => {
253
+ if (!t) return;
254
+ n = d.gamma ?? 0, r = d.beta ?? 0, c = d.alpha ?? 0;
255
+ const l = n / 90, g = r / 90, h = {
256
+ gravity: {
257
+ x: l,
258
+ y: g,
259
+ z: 0
260
+ // Z is not available from orientation
261
+ },
262
+ acceleration: s,
263
+ accelerationIncludingGravity: {
264
+ x: l + s.x,
265
+ y: g + s.y,
266
+ z: s.z
267
+ },
268
+ rotation: {
269
+ alpha: c,
270
+ beta: r,
271
+ gamma: n
272
+ },
273
+ timestamp: Date.now()
274
+ };
275
+ o(h);
276
+ }, m = (d) => {
277
+ t && (s = {
278
+ x: d.acceleration?.x ?? 0,
279
+ y: d.acceleration?.y ?? 0,
280
+ z: d.acceleration?.z ?? 0
281
+ });
282
+ }, p = async () => {
283
+ e && !await S() || (t = !0, window.addEventListener("deviceorientation", u), v() && window.addEventListener("devicemotion", m));
284
+ };
285
+ return (async () => {
286
+ if (typeof DeviceMotionEvent < "u" && typeof DeviceMotionEvent.requestPermission == "function" && e) {
287
+ const l = async () => {
288
+ i = null, await p();
289
+ };
290
+ window.addEventListener("click", l, { once: !0 }), window.addEventListener("touchstart", l, { once: !0 }), i = () => {
291
+ window.removeEventListener("click", l), window.removeEventListener("touchstart", l);
292
+ };
293
+ } else
294
+ await p();
295
+ })(), () => {
296
+ t = !1, window.removeEventListener("deviceorientation", u), window.removeEventListener("devicemotion", m), i && (i(), i = null);
297
+ };
298
+ }
299
+ function G(o, e = !0) {
300
+ const t = f();
301
+ return console.log(`🎯 [Aippy Sensors] watchMotion - Using ${t ? "NATIVE BRIDGE" : "WEB API"} mode`), t ? (console.log("📱 [Aippy Sensors] Starting native bridge motion listener"), L(o)) : (console.log("🌐 [Aippy Sensors] Starting Web API motion listener (may require permission)"), U(o, e));
302
+ }
303
+ function M(o) {
304
+ console.log("🔧 [Aippy Sensors] watchOrientationNative - Setting up native bridge listener");
305
+ const e = O.addMotionListener((t) => {
306
+ const i = {
307
+ alpha: t.rotation?.alpha ?? 0,
308
+ beta: t.rotation?.beta ?? 0,
309
+ gamma: t.rotation?.gamma ?? 0,
310
+ timestamp: Date.now()
311
+ };
312
+ o(i);
313
+ });
314
+ return console.log("✅ [Aippy Sensors] watchOrientationNative - Listener setup complete"), e;
315
+ }
316
+ function T(o) {
317
+ if (!y())
318
+ throw a("Device orientation API is not supported", "NOT_SUPPORTED");
319
+ const e = (t) => {
320
+ const i = {
321
+ alpha: t.alpha ?? 0,
322
+ beta: t.beta ?? 0,
323
+ gamma: t.gamma ?? 0,
324
+ timestamp: Date.now()
325
+ };
326
+ o(i);
327
+ };
328
+ return window.addEventListener("deviceorientation", e), () => {
329
+ window.removeEventListener("deviceorientation", e);
330
+ };
331
+ }
332
+ function H(o) {
333
+ const e = f();
334
+ return console.log(`🎯 [Aippy Sensors] watchOrientation - Using ${e ? "NATIVE BRIDGE" : "WEB API"} mode`), e ? (console.log("📱 [Aippy Sensors] Starting native bridge orientation listener"), M(o)) : (console.log("🌐 [Aippy Sensors] Starting Web API orientation listener"), T(o));
335
+ }
336
+ class k {
168
337
  /**
169
338
  * Check if device orientation is supported
170
339
  */
171
340
  isOrientationSupported() {
172
- return "DeviceOrientationEvent" in window;
341
+ return y();
173
342
  }
174
343
  /**
175
344
  * Check if device motion is supported
176
345
  */
177
346
  isMotionSupported() {
178
- return "DeviceMotionEvent" in window;
347
+ return v();
179
348
  }
180
349
  /**
181
350
  * Get device orientation data
@@ -184,30 +353,31 @@ class E {
184
353
  if (!this.isOrientationSupported())
185
354
  throw a("Device orientation API is not supported", "NOT_SUPPORTED");
186
355
  return new Promise((e, t) => {
187
- const o = (i) => {
188
- window.removeEventListener("deviceorientation", o), e({
189
- x: i.alpha ?? 0,
190
- y: i.beta ?? 0,
191
- z: i.gamma ?? 0,
356
+ const i = (n) => {
357
+ window.removeEventListener("deviceorientation", i), e({
358
+ x: n.alpha ?? 0,
359
+ y: n.beta ?? 0,
360
+ z: n.gamma ?? 0,
192
361
  timestamp: Date.now()
193
362
  });
194
363
  };
195
- window.addEventListener("deviceorientation", o), setTimeout(() => {
196
- window.removeEventListener("deviceorientation", o), t(a("Device orientation timeout", "UNKNOWN_ERROR"));
364
+ window.addEventListener("deviceorientation", i), setTimeout(() => {
365
+ window.removeEventListener("deviceorientation", i), t(a("Device orientation timeout", "UNKNOWN_ERROR"));
197
366
  }, 5e3);
198
367
  });
199
368
  }
200
369
  /**
201
370
  * Watch device orientation changes
371
+ * @deprecated Use watchOrientation() function instead
202
372
  */
203
373
  watchOrientation(e) {
204
374
  if (!this.isOrientationSupported())
205
375
  throw a("Device orientation API is not supported", "NOT_SUPPORTED");
206
- const t = (o) => {
376
+ const t = (i) => {
207
377
  e({
208
- x: o.alpha ?? 0,
209
- y: o.beta ?? 0,
210
- z: o.gamma ?? 0,
378
+ x: i.alpha ?? 0,
379
+ y: i.beta ?? 0,
380
+ z: i.gamma ?? 0,
211
381
  timestamp: Date.now()
212
382
  });
213
383
  };
@@ -222,30 +392,31 @@ class E {
222
392
  if (!this.isMotionSupported())
223
393
  throw a("Device motion API is not supported", "NOT_SUPPORTED");
224
394
  return new Promise((e, t) => {
225
- const o = (i) => {
226
- window.removeEventListener("devicemotion", o), e({
227
- x: i.acceleration?.x ?? 0,
228
- y: i.acceleration?.y ?? 0,
229
- z: i.acceleration?.z ?? 0,
395
+ const i = (n) => {
396
+ window.removeEventListener("devicemotion", i), e({
397
+ x: n.acceleration?.x ?? 0,
398
+ y: n.acceleration?.y ?? 0,
399
+ z: n.acceleration?.z ?? 0,
230
400
  timestamp: Date.now()
231
401
  });
232
402
  };
233
- window.addEventListener("devicemotion", o), setTimeout(() => {
234
- window.removeEventListener("devicemotion", o), t(a("Device motion timeout", "UNKNOWN_ERROR"));
403
+ window.addEventListener("devicemotion", i), setTimeout(() => {
404
+ window.removeEventListener("devicemotion", i), t(a("Device motion timeout", "UNKNOWN_ERROR"));
235
405
  }, 5e3);
236
406
  });
237
407
  }
238
408
  /**
239
409
  * Watch device motion changes
410
+ * @deprecated Use watchMotion() function instead
240
411
  */
241
412
  watchMotion(e) {
242
413
  if (!this.isMotionSupported())
243
414
  throw a("Device motion API is not supported", "NOT_SUPPORTED");
244
- const t = (o) => {
415
+ const t = (i) => {
245
416
  e({
246
- x: o.acceleration?.x ?? 0,
247
- y: o.acceleration?.y ?? 0,
248
- z: o.acceleration?.z ?? 0,
417
+ x: i.acceleration?.x ?? 0,
418
+ y: i.acceleration?.y ?? 0,
419
+ z: i.acceleration?.z ?? 0,
249
420
  timestamp: Date.now()
250
421
  });
251
422
  };
@@ -257,17 +428,11 @@ class E {
257
428
  * Request permission for motion sensors (iOS 13+)
258
429
  */
259
430
  async requestPermission() {
260
- if (!this.isMotionSupported())
261
- return !1;
262
- try {
263
- return (await navigator.permissions?.query({ name: "accelerometer" }))?.state === "granted";
264
- } catch {
265
- return !1;
266
- }
431
+ return S();
267
432
  }
268
433
  }
269
- const R = new E();
270
- class O {
434
+ const q = new k();
435
+ class _ {
271
436
  /**
272
437
  * Check if file system access is supported
273
438
  */
@@ -295,12 +460,12 @@ class O {
295
460
  )
296
461
  }] : void 0,
297
462
  multiple: e.multiple ?? !1
298
- }, o = await window.showOpenFilePicker(t), i = await Promise.all(
299
- o.map(async (r) => r.getFile())
463
+ }, i = await window.showOpenFilePicker(t), n = await Promise.all(
464
+ i.map(async (r) => r.getFile())
300
465
  );
301
466
  return {
302
- files: i,
303
- paths: i.map((r) => r.name)
467
+ files: n,
468
+ paths: n.map((r) => r.name)
304
469
  };
305
470
  } catch (t) {
306
471
  throw t instanceof Error && t.name === "AbortError" ? a("File picker was cancelled", "PERMISSION_DENIED") : a(
@@ -315,17 +480,17 @@ class O {
315
480
  async openFilePickerLegacy(e = {}) {
316
481
  if (!this.isLegacySupported())
317
482
  throw a("File input is not supported", "NOT_SUPPORTED");
318
- return new Promise((t, o) => {
319
- const i = document.createElement("input");
320
- i.type = "file", i.multiple = e.multiple ?? !1, i.accept = e.accept?.join(",") ?? "", i.onchange = (r) => {
483
+ return new Promise((t, i) => {
484
+ const n = document.createElement("input");
485
+ n.type = "file", n.multiple = e.multiple ?? !1, n.accept = e.accept?.join(",") ?? "", n.onchange = (r) => {
321
486
  const c = r.target, s = Array.from(c.files || []);
322
487
  t({
323
488
  files: s,
324
- paths: s.map((d) => d.name)
489
+ paths: s.map((u) => u.name)
325
490
  });
326
- }, i.oncancel = () => {
327
- o(a("File picker was cancelled", "PERMISSION_DENIED"));
328
- }, i.click();
491
+ }, n.oncancel = () => {
492
+ i(a("File picker was cancelled", "PERMISSION_DENIED"));
493
+ }, n.click();
329
494
  });
330
495
  }
331
496
  /**
@@ -339,11 +504,11 @@ class O {
339
504
  */
340
505
  async saveFile(e, t) {
341
506
  try {
342
- const o = URL.createObjectURL(e), i = document.createElement("a");
343
- i.href = o, i.download = t, document.body.appendChild(i), i.click(), document.body.removeChild(i), URL.revokeObjectURL(o);
344
- } catch (o) {
507
+ const i = URL.createObjectURL(e), n = document.createElement("a");
508
+ n.href = i, n.download = t, document.body.appendChild(n), n.click(), document.body.removeChild(n), URL.revokeObjectURL(i);
509
+ } catch (i) {
345
510
  throw a(
346
- `Failed to save file: ${o instanceof Error ? o.message : "Unknown error"}`,
511
+ `Failed to save file: ${i instanceof Error ? i.message : "Unknown error"}`,
347
512
  "UNKNOWN_ERROR"
348
513
  );
349
514
  }
@@ -352,30 +517,30 @@ class O {
352
517
  * Read file as text
353
518
  */
354
519
  async readAsText(e) {
355
- return new Promise((t, o) => {
356
- const i = new FileReader();
357
- i.onload = () => t(i.result), i.onerror = () => o(a("Failed to read file", "UNKNOWN_ERROR")), i.readAsText(e);
520
+ return new Promise((t, i) => {
521
+ const n = new FileReader();
522
+ n.onload = () => t(n.result), n.onerror = () => i(a("Failed to read file", "UNKNOWN_ERROR")), n.readAsText(e);
358
523
  });
359
524
  }
360
525
  /**
361
526
  * Read file as data URL
362
527
  */
363
528
  async readAsDataURL(e) {
364
- return new Promise((t, o) => {
365
- const i = new FileReader();
366
- i.onload = () => t(i.result), i.onerror = () => o(a("Failed to read file", "UNKNOWN_ERROR")), i.readAsDataURL(e);
529
+ return new Promise((t, i) => {
530
+ const n = new FileReader();
531
+ n.onload = () => t(n.result), n.onerror = () => i(a("Failed to read file", "UNKNOWN_ERROR")), n.readAsDataURL(e);
367
532
  });
368
533
  }
369
534
  }
370
- const S = new O();
371
- function D(n) {
535
+ const B = new _();
536
+ function C(o) {
372
537
  return new Promise((e) => {
373
538
  if ("vibrate" in navigator)
374
- navigator.vibrate(n), e();
539
+ navigator.vibrate(o), e();
375
540
  else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.aippyListener) {
376
541
  const t = {
377
542
  command: "navigator.vibrate",
378
- parameters: n
543
+ parameters: o
379
544
  };
380
545
  window.webkit.messageHandlers.aippyListener.postMessage(t), e();
381
546
  } else
@@ -383,13 +548,19 @@ function D(n) {
383
548
  });
384
549
  }
385
550
  export {
386
- g as CameraAPI,
387
- O as FileSystemAPI,
388
- v as GeolocationAPI,
389
- E as SensorsAPI,
390
- f as camera,
391
- S as fileSystem,
392
- N as geolocation,
393
- R as sensors,
394
- D as vibrate
551
+ b as CameraAPI,
552
+ _ as FileSystemAPI,
553
+ I as GeolocationAPI,
554
+ k as SensorsAPI,
555
+ W as camera,
556
+ B as fileSystem,
557
+ z as geolocation,
558
+ f as hasNativeBridge,
559
+ v as isMotionSupported,
560
+ y as isOrientationSupported,
561
+ S as requestMotionPermission,
562
+ q as sensors,
563
+ C as vibrate,
564
+ G as watchMotion,
565
+ H as watchOrientation
395
566
  };
@@ -1,6 +1,41 @@
1
- import { SensorData } from './types';
1
+ import { SensorData, MotionData, OrientationData } from './types';
2
2
  /**
3
- * Device sensors functionality wrapper
3
+ * Check if device motion is supported
4
+ */
5
+ export declare function isMotionSupported(): boolean;
6
+ /**
7
+ * Check if device orientation is supported
8
+ */
9
+ export declare function isOrientationSupported(): boolean;
10
+ /**
11
+ * Check if native bridge is available
12
+ */
13
+ export declare function hasNativeBridge(): boolean;
14
+ /**
15
+ * Request permission for motion sensors (iOS 13+)
16
+ * @returns Promise<boolean> - true if permission granted
17
+ */
18
+ export declare function requestMotionPermission(): Promise<boolean>;
19
+ /**
20
+ * Watch device motion changes with full motion data
21
+ * Automatically uses native bridge if available, otherwise falls back to Web API
22
+ *
23
+ * @param callback - Function to call with motion data
24
+ * @param autoRequestPermission - Automatically request permission on iOS (default: true, only for Web API)
25
+ * @returns Cleanup function to stop watching
26
+ */
27
+ export declare function watchMotion(callback: (data: MotionData) => void, autoRequestPermission?: boolean): () => void;
28
+ /**
29
+ * Watch device orientation changes
30
+ * Automatically uses native bridge if available, otherwise falls back to Web API
31
+ *
32
+ * @param callback - Function to call with orientation data
33
+ * @returns Cleanup function to stop watching
34
+ */
35
+ export declare function watchOrientation(callback: (data: OrientationData) => void): () => void;
36
+ /**
37
+ * Legacy SensorsAPI class for backward compatibility
38
+ * @deprecated Use watchMotion() and watchOrientation() functions instead
4
39
  */
5
40
  export declare class SensorsAPI {
6
41
  /**
@@ -17,6 +52,7 @@ export declare class SensorsAPI {
17
52
  getOrientation(): Promise<SensorData>;
18
53
  /**
19
54
  * Watch device orientation changes
55
+ * @deprecated Use watchOrientation() function instead
20
56
  */
21
57
  watchOrientation(callback: (data: SensorData) => void): () => void;
22
58
  /**
@@ -25,6 +61,7 @@ export declare class SensorsAPI {
25
61
  getMotion(): Promise<SensorData>;
26
62
  /**
27
63
  * Watch device motion changes
64
+ * @deprecated Use watchMotion() function instead
28
65
  */
29
66
  watchMotion(callback: (data: SensorData) => void): () => void;
30
67
  /**
@@ -33,6 +70,7 @@ export declare class SensorsAPI {
33
70
  requestPermission(): Promise<boolean>;
34
71
  }
35
72
  /**
36
- * Sensors API instance
73
+ * Sensors API instance (for backward compatibility)
74
+ * @deprecated Use watchMotion() and watchOrientation() functions instead
37
75
  */
38
76
  export declare const sensors: SensorsAPI;
@@ -58,6 +58,44 @@ export interface SensorData {
58
58
  /** Timestamp */
59
59
  timestamp: number;
60
60
  }
61
+ export interface MotionData {
62
+ /** Gravity vector (normalized, -1 to 1) */
63
+ gravity: {
64
+ x: number;
65
+ y: number;
66
+ z: number;
67
+ };
68
+ /** Linear acceleration (m/s²) */
69
+ acceleration: {
70
+ x: number;
71
+ y: number;
72
+ z: number;
73
+ };
74
+ /** Acceleration including gravity (m/s²) */
75
+ accelerationIncludingGravity: {
76
+ x: number;
77
+ y: number;
78
+ z: number;
79
+ };
80
+ /** Rotation rate (deg/s) */
81
+ rotation: {
82
+ alpha: number;
83
+ beta: number;
84
+ gamma: number;
85
+ };
86
+ /** Timestamp */
87
+ timestamp: number;
88
+ }
89
+ export interface OrientationData {
90
+ /** Rotation around Z axis (0-360°) */
91
+ alpha: number;
92
+ /** Rotation around X axis (-180 to 180°) */
93
+ beta: number;
94
+ /** Rotation around Y axis (-90 to 90°) */
95
+ gamma: number;
96
+ /** Timestamp */
97
+ timestamp: number;
98
+ }
61
99
  export interface FileSystemOptions {
62
100
  /** File types to accept */
63
101
  accept?: string[];
@@ -1,44 +1,55 @@
1
- import { DEFAULT_CONFIG as r, SDK_NAME as a, VERSION as t, getConfigFromEnv as s, getVersionInfo as i, mergeConfig as n } from "../core/index.js";
2
- import { A as m, E as c, c as f } from "../errors-CDEBaBxB.js";
3
- import { CameraAPI as A, FileSystemAPI as E, GeolocationAPI as S, SensorsAPI as l, camera as u, fileSystem as x, geolocation as I, sensors as P, vibrate as C } from "../device/index.js";
4
- import { c as R, a as y, P as D, b as M, p as O, d as b } from "../pwa-8DGmPqLV.js";
5
- import { a as F, b as w } from "../useTweaks-QxMRmg7i.js";
6
- import { c as T, a as V, i as _, b as k, p as G, u as H } from "../useAudioContext-BKgy28A1.js";
7
- import { reportScore as h, sendEvent as K, updateScore as L } from "../leaderboard/index.js";
1
+ import { DEFAULT_CONFIG as o, SDK_NAME as t, VERSION as r, getConfigFromEnv as i, getVersionInfo as s, mergeConfig as n } from "../core/index.js";
2
+ import { a as m, A as c, C as d, E as f, R as u, b as l, c as A, p as S } from "../runtime-DjBdOttl.js";
3
+ import { CameraAPI as C, FileSystemAPI as R, GeolocationAPI as x, SensorsAPI as M, camera as P, fileSystem as I, geolocation as g, hasNativeBridge as y, isMotionSupported as O, isOrientationSupported as b, requestMotionPermission as v, sensors as D, vibrate as h, watchMotion as w, watchOrientation as F } from "../device/index.js";
4
+ import { c as T, a as V, P as _, b as k, p as G, d as H } from "../pwa-8DGmPqLV.js";
5
+ import { a as q, b as B } from "../useTweaks-QxMRmg7i.js";
6
+ import { c as L, a as W, b as j, i as z, p as J, u as Q } from "../useAudioContext-CNQQSTab.js";
7
+ import { reportScore as Y, sendEvent as Z, updateScore as $ } from "../leaderboard/index.js";
8
8
  export {
9
- m as AippyRuntimeError,
10
- A as CameraAPI,
11
- r as DEFAULT_CONFIG,
12
- c as ERROR_CODES,
13
- E as FileSystemAPI,
14
- S as GeolocationAPI,
15
- R as PWAUtils,
16
- y as PerformanceMonitor,
17
- D as PlatformDetector,
18
- a as SDK_NAME,
19
- l as SensorsAPI,
20
- t as VERSION,
21
- F as aippyTweaks,
22
- w as aippyTweaksRuntime,
23
- u as camera,
24
- f as createError,
25
- T as createHiddenMediaElement,
26
- V as createHiddenVideoElement,
27
- x as fileSystem,
28
- I as geolocation,
29
- s as getConfigFromEnv,
30
- i as getVersionInfo,
31
- _ as isIOSDevice,
32
- k as isMediaStreamAudioSupported,
9
+ m as AippyRuntime,
10
+ c as AippyRuntimeError,
11
+ C as CameraAPI,
12
+ d as Cancellable,
13
+ o as DEFAULT_CONFIG,
14
+ f as ERROR_CODES,
15
+ R as FileSystemAPI,
16
+ x as GeolocationAPI,
17
+ T as PWAUtils,
18
+ V as PerformanceMonitor,
19
+ _ as PlatformDetector,
20
+ u as ReceiveChannel,
21
+ t as SDK_NAME,
22
+ M as SensorsAPI,
23
+ r as VERSION,
24
+ l as aippyRuntime,
25
+ q as aippyTweaks,
26
+ B as aippyTweaksRuntime,
27
+ P as camera,
28
+ A as createError,
29
+ L as createHiddenMediaElement,
30
+ W as createHiddenVideoElement,
31
+ I as fileSystem,
32
+ g as geolocation,
33
+ i as getConfigFromEnv,
34
+ s as getVersionInfo,
35
+ y as hasNativeBridge,
36
+ j as isIOSDevice,
37
+ z as isMediaStreamAudioSupported,
38
+ O as isMotionSupported,
39
+ b as isOrientationSupported,
33
40
  n as mergeConfig,
34
- G as patchAudioContext,
35
- M as performanceMonitor,
36
- O as platform,
37
- b as pwa,
38
- h as reportScore,
39
- K as sendEvent,
40
- P as sensors,
41
- L as updateScore,
42
- H as useAudioContext,
43
- C as vibrate
41
+ J as patchAudioContext,
42
+ k as performanceMonitor,
43
+ G as platform,
44
+ S as processMotionData,
45
+ H as pwa,
46
+ Y as reportScore,
47
+ v as requestMotionPermission,
48
+ Z as sendEvent,
49
+ D as sensors,
50
+ $ as updateScore,
51
+ Q as useAudioContext,
52
+ h as vibrate,
53
+ w as watchMotion,
54
+ F as watchOrientation
44
55
  };
@@ -0,0 +1,243 @@
1
+ var u = Object.defineProperty;
2
+ var m = (o, e, n) => e in o ? u(o, e, { enumerable: !0, configurable: !0, writable: !0, value: n }) : o[e] = n;
3
+ var r = (o, e, n) => m(o, typeof e != "symbol" ? e + "" : e, n);
4
+ class d extends Error {
5
+ constructor(n, i = "AIPPY_ERROR", t) {
6
+ super(n);
7
+ r(this, "code");
8
+ r(this, "context");
9
+ this.name = "AippyRuntimeError", this.code = i, this.context = t;
10
+ }
11
+ }
12
+ const R = {
13
+ NOT_SUPPORTED: "NOT_SUPPORTED",
14
+ PERMISSION_DENIED: "PERMISSION_DENIED",
15
+ INVALID_CONFIG: "INVALID_CONFIG",
16
+ NETWORK_ERROR: "NETWORK_ERROR",
17
+ UNKNOWN_ERROR: "UNKNOWN_ERROR"
18
+ };
19
+ function g(o, e = "UNKNOWN_ERROR", n) {
20
+ return new d(o, R[e], n);
21
+ }
22
+ class a {
23
+ constructor(e) {
24
+ r(this, "cancelled", !1);
25
+ this.cancelFn = e;
26
+ }
27
+ cancel() {
28
+ this.cancelled || (this.cancelled = !0, this.cancelFn?.());
29
+ }
30
+ get isCancelled() {
31
+ return this.cancelled;
32
+ }
33
+ }
34
+ class f {
35
+ constructor() {
36
+ r(this, "listeners", /* @__PURE__ */ new Map());
37
+ }
38
+ addEventListener(e, n) {
39
+ this.listeners.has(e) || this.listeners.set(e, []), this.listeners.get(e).push(n);
40
+ }
41
+ removeEventListener(e, n) {
42
+ const i = this.listeners.get(e);
43
+ if (i) {
44
+ const t = i.indexOf(n);
45
+ t > -1 && i.splice(t, 1);
46
+ }
47
+ }
48
+ emit(e, n) {
49
+ const i = this.listeners.get(e);
50
+ i && i.forEach((t) => t(n));
51
+ }
52
+ }
53
+ class y {
54
+ constructor() {
55
+ r(this, "emitter", new f());
56
+ }
57
+ /**
58
+ * Emit a message to subscribers
59
+ */
60
+ emit(e) {
61
+ this.emitter.emit(e.endpoint, e.payload);
62
+ }
63
+ /**
64
+ * Subscribe to messages on a specific endpoint
65
+ */
66
+ subscribe(e, n) {
67
+ const i = (t) => {
68
+ n(t);
69
+ };
70
+ return this.emitter.addEventListener(e, i), new a(() => {
71
+ this.emitter.removeEventListener(e, i);
72
+ });
73
+ }
74
+ /**
75
+ * Subscribe to a single message (auto-unsubscribe after first message)
76
+ */
77
+ once(e, n) {
78
+ const i = this.subscribe(e, (t) => {
79
+ i.cancel(), n(t);
80
+ });
81
+ return i;
82
+ }
83
+ }
84
+ class h {
85
+ constructor() {
86
+ r(this, "receiveChannel", new y());
87
+ r(this, "seq", 0);
88
+ r(this, "motionListeners", []);
89
+ r(this, "noListenersWarned", !1);
90
+ }
91
+ /**
92
+ * Unified native data receiver - Routes to specific handlers based on message type
93
+ * Called by native code via: window.aippyRuntime.receiveMessage(message)
94
+ *
95
+ * Supports two message formats:
96
+ * 1. Motion: { command: "navigator.motion", endpoint: "0", data: { motion: {...} } }
97
+ * 2. Tweaks: { "tweakKey": { value: ..., type: ... }, ... }
98
+ */
99
+ receiveMessage(e) {
100
+ return console.log("📩 [Aippy Runtime] receiveMessage called with:", e), !e || typeof e != "object" ? (console.warn("⚠️ [Aippy Runtime] Invalid message type:", typeof e), Promise.resolve()) : this.isMotionMessage(e) ? (console.log("✅ [Aippy Runtime] Detected MOTION message format, emitting to receive channel"), this.receiveChannel.emit({
101
+ endpoint: e.endpoint,
102
+ payload: e.data
103
+ }), Promise.resolve()) : this.isTweaksMessage(e) ? (console.log("✅ [Aippy Runtime] Detected TWEAKS message format, calling processNativeData"), typeof window < "u" && window.processNativeData && window.processNativeData(e), Promise.resolve()) : (console.warn("⚠️ [Aippy Runtime] Unknown message format:", e), Promise.resolve());
104
+ }
105
+ /**
106
+ * Check if message is Motion format
107
+ * Motion: { command: "navigator.motion", endpoint: string, data: object }
108
+ */
109
+ isMotionMessage(e) {
110
+ return typeof e == "object" && "command" in e && e.command === "navigator.motion" && "endpoint" in e && typeof e.endpoint == "string" && "data" in e && typeof e.data == "object" && e.data !== null;
111
+ }
112
+ /**
113
+ * Check if message is Tweaks format
114
+ * Tweaks: { "key": { value: any, type?: string, ... }, ... }
115
+ */
116
+ isTweaksMessage(e) {
117
+ if (typeof e != "object" || e === null || "endpoint" in e || "payload" in e)
118
+ return !1;
119
+ const n = Object.keys(e);
120
+ return n.length === 0 ? !1 : n.some((t) => {
121
+ const c = e[t];
122
+ return typeof c == "object" && c !== null && "value" in c;
123
+ });
124
+ }
125
+ /**
126
+ * Create a subscription to native events
127
+ * @param handler - WebKit message handler (e.g., aippyListener)
128
+ * @param subscribePayload - Subscription parameters (e.g., { command: "navigator.motion", type: "motion" })
129
+ * @param callback - Callback to handle received data
130
+ * @returns Cancellable subscription
131
+ */
132
+ createSubscription(e, n, i) {
133
+ const t = (this.seq++).toString(), c = {
134
+ command: n.command,
135
+ parameters: {
136
+ type: n.type,
137
+ action: "subscribe",
138
+ endpoint: t
139
+ }
140
+ };
141
+ console.log("📨 [Aippy Runtime] Creating subscription with message:", JSON.stringify(c, null, 2));
142
+ const l = this.receiveChannel.subscribe(t, (s) => {
143
+ if (console.log(`📬 [Aippy Runtime] Received data on endpoint ${t}:`, s), s.error !== void 0) {
144
+ console.warn("⚠️ [Aippy Runtime] Received error, skipping:", s.error);
145
+ return;
146
+ }
147
+ i(s);
148
+ });
149
+ try {
150
+ console.log("📤 [Aippy Runtime] Sending postMessage to native iOS:", c), e.postMessage(c), console.log("✅ [Aippy Runtime] postMessage sent successfully");
151
+ } catch (s) {
152
+ console.error("❌ [Aippy Runtime] Failed to send postMessage:", s);
153
+ }
154
+ return new a(() => {
155
+ console.log(`🔌 [Aippy Runtime] Unsubscribing from endpoint ${t}`), l.cancel();
156
+ try {
157
+ const s = {
158
+ command: n.command,
159
+ parameters: {
160
+ type: n.type,
161
+ action: "unsubscribe",
162
+ endpoint: t
163
+ }
164
+ };
165
+ e.postMessage(s), console.log("✅ [Aippy Runtime] Unsubscribe message sent:", s);
166
+ } catch (s) {
167
+ console.error("❌ [Aippy Runtime] Failed to send unsubscribe message:", s);
168
+ }
169
+ });
170
+ }
171
+ /**
172
+ * Add motion listener (convenience method)
173
+ * @param callback - Callback to handle motion data
174
+ * @returns Cleanup function
175
+ */
176
+ addMotionListener(e) {
177
+ console.log("🎬 [Aippy Runtime] addMotionListener called"), this.motionListeners.push(e), console.log(`📝 [Aippy Runtime] Total motion listeners: ${this.motionListeners.length}`);
178
+ const n = window.webkit?.messageHandlers?.aippyListener;
179
+ if (!n)
180
+ return console.warn("⚠️ [Aippy Runtime] No webkit message handler found, using fallback mode"), () => {
181
+ const t = this.motionListeners.indexOf(e);
182
+ t > -1 && this.motionListeners.splice(t, 1);
183
+ };
184
+ console.log("✅ [Aippy Runtime] Webkit handler found, creating subscription");
185
+ const i = this.createSubscription(
186
+ n,
187
+ {
188
+ command: "navigator.motion",
189
+ type: "motion"
190
+ },
191
+ (t) => {
192
+ console.log("📥 [Aippy Runtime] Received motion data from native:", t), t.motion && e(t.motion);
193
+ }
194
+ );
195
+ return () => {
196
+ console.log("🧹 [Aippy Runtime] Cleaning up motion listener"), i.cancel();
197
+ const t = this.motionListeners.indexOf(e);
198
+ t > -1 && this.motionListeners.splice(t, 1);
199
+ };
200
+ }
201
+ /**
202
+ * Broadcast motion data to all registered listeners
203
+ * Called by processMotionData when iOS sends data directly
204
+ * @param data - Motion data from iOS
205
+ */
206
+ broadcastMotionData(e) {
207
+ if (this.motionListeners.length === 0) {
208
+ this.noListenersWarned || (console.warn("⚠️ [Aippy Runtime] No motion listeners to broadcast to"), this.noListenersWarned = !0);
209
+ return;
210
+ }
211
+ const n = e.motion || e;
212
+ this.motionListeners.forEach((i) => {
213
+ try {
214
+ i(n);
215
+ } catch (t) {
216
+ console.error("⚠️ [Aippy Runtime] Error in motion listener:", t);
217
+ }
218
+ });
219
+ }
220
+ }
221
+ function w(o) {
222
+ if (!o || typeof o != "object") {
223
+ console.warn("⚠️ [Aippy Runtime] Invalid motion data type:", typeof o);
224
+ return;
225
+ }
226
+ if (!("motion" in o) || typeof o.motion != "object") {
227
+ console.warn("⚠️ [Aippy Runtime] Motion data missing valid motion field");
228
+ return;
229
+ }
230
+ p.broadcastMotionData(o);
231
+ }
232
+ const p = new h();
233
+ typeof window < "u" && (window.aippyRuntime = p, window.processMotionData = w);
234
+ export {
235
+ d as A,
236
+ a as C,
237
+ R as E,
238
+ y as R,
239
+ h as a,
240
+ p as b,
241
+ g as c,
242
+ w as p
243
+ };
@@ -215,9 +215,9 @@ function O(e = {}) {
215
215
  }
216
216
  export {
217
217
  C as a,
218
- P as b,
218
+ E as b,
219
219
  v as c,
220
- E as i,
220
+ P as i,
221
221
  S as p,
222
222
  O as u
223
223
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aippy/runtime",
3
- "version": "0.2.3",
3
+ "version": "0.2.4-dev.10",
4
4
  "description": "Aippy Runtime SDK - Runtime SDK for Aippy projects",
5
5
  "private": false,
6
6
  "type": "module",
@@ -44,30 +44,6 @@
44
44
  "publishConfig": {
45
45
  "access": "public"
46
46
  },
47
- "scripts": {
48
- "dev": "vite build --watch",
49
- "build": "vite build && find dist -name '*.d.ts.map' -delete",
50
- "type-check": "tsc --noEmit",
51
- "lint": "eslint src --ext .ts,.tsx",
52
- "lint:fix": "eslint src --ext .ts,.tsx --fix",
53
- "format": "prettier --write \"src/**/*.{ts,tsx,json,md}\"",
54
- "format:check": "prettier --check \"src/**/*.{ts,tsx,json,md}\"",
55
- "clean": "rm -rf dist",
56
- "prepublishOnly": "pnpm run clean && pnpm run type-check && pnpm run build",
57
- "publish:patch": "pnpm prepublishOnly && pnpm version patch && pnpm publish --no-git-checks",
58
- "publish:minor": "pnpm prepublishOnly && pnpm version minor && pnpm publish --no-git-checks",
59
- "publish:major": "pnpm prepublishOnly && pnpm version major && pnpm publish --no-git-checks",
60
- "publish:alpha": "pnpm prepublishOnly && pnpm version prerelease --preid=alpha && pnpm publish --tag alpha --no-git-checks",
61
- "publish:beta": "pnpm prepublishOnly && pnpm version prerelease --preid=beta && pnpm publish --tag beta --no-git-checks",
62
- "publish:rc": "pnpm prepublishOnly && pnpm version prerelease --preid=rc && pnpm publish --tag rc --no-git-checks",
63
- "publish:dev": "pnpm prepublishOnly && pnpm version prerelease --preid=dev && pnpm publish --tag dev --no-git-checks",
64
- "audit": "pnpm audit --audit-level moderate",
65
- "audit:fix": "pnpm audit --fix",
66
- "security:check": "pnpm audit && pnpm outdated",
67
- "prerelease": "pnpm run audit && pnpm run type-check && pnpm run lint && pnpm run build",
68
- "release:dry": "npm publish --dry-run",
69
- "test:build": "node -e \"require('./dist/index.js')\""
70
- },
71
47
  "keywords": [
72
48
  "aippy",
73
49
  "runtime",
@@ -106,5 +82,28 @@
106
82
  "engines": {
107
83
  "node": ">=20.0.0",
108
84
  "pnpm": ">=10.0.0"
85
+ },
86
+ "scripts": {
87
+ "dev": "vite build --watch",
88
+ "build": "vite build && find dist -name '*.d.ts.map' -delete",
89
+ "type-check": "tsc --noEmit",
90
+ "lint": "eslint src --ext .ts,.tsx",
91
+ "lint:fix": "eslint src --ext .ts,.tsx --fix",
92
+ "format": "prettier --write \"src/**/*.{ts,tsx,json,md}\"",
93
+ "format:check": "prettier --check \"src/**/*.{ts,tsx,json,md}\"",
94
+ "clean": "rm -rf dist",
95
+ "publish:patch": "pnpm prepublishOnly && pnpm version patch && pnpm publish --no-git-checks",
96
+ "publish:minor": "pnpm prepublishOnly && pnpm version minor && pnpm publish --no-git-checks",
97
+ "publish:major": "pnpm prepublishOnly && pnpm version major && pnpm publish --no-git-checks",
98
+ "publish:alpha": "pnpm prepublishOnly && pnpm version prerelease --preid=alpha && pnpm publish --tag alpha --no-git-checks",
99
+ "publish:beta": "pnpm prepublishOnly && pnpm version prerelease --preid=beta && pnpm publish --tag beta --no-git-checks",
100
+ "publish:rc": "pnpm prepublishOnly && pnpm version prerelease --preid=rc && pnpm publish --tag rc --no-git-checks",
101
+ "publish:dev": "pnpm prepublishOnly && pnpm version prerelease --preid=dev && pnpm publish --tag dev --no-git-checks",
102
+ "audit": "pnpm audit --audit-level moderate",
103
+ "audit:fix": "pnpm audit --fix",
104
+ "security:check": "pnpm audit && pnpm outdated",
105
+ "prerelease": "pnpm run audit && pnpm run type-check && pnpm run lint && pnpm run build",
106
+ "release:dry": "npm publish --dry-run",
107
+ "test:build": "node -e \"require('./dist/index.js')\""
109
108
  }
110
- }
109
+ }
@@ -1,26 +0,0 @@
1
- var e = Object.defineProperty;
2
- var o = (E, R, N) => R in E ? e(E, R, { enumerable: !0, configurable: !0, writable: !0, value: N }) : E[R] = N;
3
- var O = (E, R, N) => o(E, typeof R != "symbol" ? R + "" : R, N);
4
- class I extends Error {
5
- constructor(N, r = "AIPPY_ERROR", t) {
6
- super(N);
7
- O(this, "code");
8
- O(this, "context");
9
- this.name = "AippyRuntimeError", this.code = r, this.context = t;
10
- }
11
- }
12
- const _ = {
13
- NOT_SUPPORTED: "NOT_SUPPORTED",
14
- PERMISSION_DENIED: "PERMISSION_DENIED",
15
- INVALID_CONFIG: "INVALID_CONFIG",
16
- NETWORK_ERROR: "NETWORK_ERROR",
17
- UNKNOWN_ERROR: "UNKNOWN_ERROR"
18
- };
19
- function s(E, R = "UNKNOWN_ERROR", N) {
20
- return new I(E, _[R], N);
21
- }
22
- export {
23
- I as A,
24
- _ as E,
25
- s as c
26
- };