@aippy/runtime 0.2.3-dev.1 โ†’ 0.2.4-dev.11

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 f, 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-dev.1", t = {
26
- version: s
27
- }, i = t.version, c = "@aippy/runtime";
25
+ const r = "0.2.4-dev.11", 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 AippyRuntime,
36
37
  f as AippyRuntimeError,
37
- o as DEFAULT_CONFIG,
38
- v as ERROR_CODES,
39
- c as SDK_NAME,
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 O = Object.defineProperty;
2
+ var S = (n, e, t) => e in n ? O(n, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[e] = t;
3
+ var h = (n, e, t) => S(n, typeof e != "symbol" ? e + "" : e, t);
4
+ import { c as s, b as A } from "../runtime-DjBdOttl.js";
5
+ class N {
6
6
  constructor() {
7
- m(this, "stream", null);
7
+ h(this, "stream", null);
8
8
  }
9
9
  /**
10
10
  * Check if camera is supported
@@ -17,7 +17,7 @@ class g {
17
17
  */
18
18
  async getStream(e = {}) {
19
19
  if (!this.isSupported())
20
- throw a("Camera API is not supported", "NOT_SUPPORTED");
20
+ throw s("Camera API is not supported", "NOT_SUPPORTED");
21
21
  try {
22
22
  const t = {
23
23
  video: {
@@ -28,7 +28,7 @@ class g {
28
28
  };
29
29
  return this.stream = await navigator.mediaDevices.getUserMedia(t), this.stream;
30
30
  } catch (t) {
31
- throw a(
31
+ throw s(
32
32
  `Failed to access camera: ${t instanceof Error ? t.message : "Unknown error"}`,
33
33
  "PERMISSION_DENIED"
34
34
  );
@@ -39,27 +39,27 @@ class g {
39
39
  */
40
40
  async capturePhoto(e = {}) {
41
41
  if (!this.stream)
42
- throw a("No camera stream available", "NOT_SUPPORTED");
42
+ throw s("No camera stream available", "NOT_SUPPORTED");
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)
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"));
53
- }, `image/${r}`, c);
54
- }), d = o.toDataURL(`image/${r}`, c);
46
+ const i = document.createElement("canvas"), o = i.getContext("2d");
47
+ if (!o)
48
+ throw s("Failed to get canvas context", "UNKNOWN_ERROR");
49
+ i.width = e.width || t.videoWidth, i.height = e.height || t.videoHeight, o.drawImage(t, 0, 0, i.width, i.height);
50
+ const r = e.format || "jpeg", d = e.quality === "high" ? 0.9 : e.quality === "medium" ? 0.7 : 0.5, a = await new Promise((l, u) => {
51
+ i.toBlob((m) => {
52
+ m ? l(m) : u(new Error("Failed to create blob"));
53
+ }, `image/${r}`, d);
54
+ }), c = i.toDataURL(`image/${r}`, d);
55
55
  return {
56
- blob: s,
57
- dataUrl: d,
58
- width: o.width,
59
- height: o.height
56
+ blob: a,
57
+ dataUrl: c,
58
+ width: i.width,
59
+ height: i.height
60
60
  };
61
61
  } catch (t) {
62
- throw a(
62
+ throw s(
63
63
  `Failed to capture photo: ${t instanceof Error ? t.message : "Unknown error"}`,
64
64
  "UNKNOWN_ERROR"
65
65
  );
@@ -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 T = new N();
76
+ class R {
77
77
  /**
78
78
  * Check if geolocation is supported
79
79
  */
@@ -85,16 +85,16 @@ class v {
85
85
  */
86
86
  async getCurrentPosition(e = {}) {
87
87
  if (!this.isSupported())
88
- throw a("Geolocation API is not supported", "NOT_SUPPORTED");
89
- return new Promise((t, o) => {
90
- const i = {
88
+ throw s("Geolocation API is not supported", "NOT_SUPPORTED");
89
+ return new Promise((t, i) => {
90
+ const o = {
91
91
  enableHighAccuracy: e.enableHighAccuracy ?? !0,
92
92
  timeout: e.timeout ?? 1e4,
93
93
  maximumAge: e.maximumAge ?? 6e4
94
94
  };
95
95
  navigator.geolocation.getCurrentPosition(
96
96
  (r) => {
97
- const c = {
97
+ const d = {
98
98
  latitude: r.coords.latitude,
99
99
  longitude: r.coords.longitude,
100
100
  accuracy: r.coords.accuracy,
@@ -104,24 +104,24 @@ class v {
104
104
  speed: r.coords.speed ?? void 0,
105
105
  timestamp: r.timestamp
106
106
  };
107
- t(c);
107
+ t(d);
108
108
  },
109
109
  (r) => {
110
- let c = "UNKNOWN_ERROR", s = "Unknown geolocation error";
110
+ let d = "UNKNOWN_ERROR", a = "Unknown geolocation error";
111
111
  switch (r.code) {
112
112
  case r.PERMISSION_DENIED:
113
- c = "PERMISSION_DENIED", s = "Geolocation permission denied";
113
+ d = "PERMISSION_DENIED", a = "Geolocation permission denied";
114
114
  break;
115
115
  case r.POSITION_UNAVAILABLE:
116
- s = "Position unavailable";
116
+ a = "Position unavailable";
117
117
  break;
118
118
  case r.TIMEOUT:
119
- s = "Geolocation timeout";
119
+ a = "Geolocation timeout";
120
120
  break;
121
121
  }
122
- o(a(s, c));
122
+ i(s(a, d));
123
123
  },
124
- i
124
+ o
125
125
  );
126
126
  });
127
127
  }
@@ -130,30 +130,30 @@ class v {
130
130
  */
131
131
  watchPosition(e, t = {}) {
132
132
  if (!this.isSupported())
133
- throw a("Geolocation API is not supported", "NOT_SUPPORTED");
134
- const o = {
133
+ throw s("Geolocation API is not supported", "NOT_SUPPORTED");
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
+ (o) => {
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: o.coords.latitude,
143
+ longitude: o.coords.longitude,
144
+ accuracy: o.coords.accuracy,
145
+ altitude: o.coords.altitude ?? void 0,
146
+ altitudeAccuracy: o.coords.altitudeAccuracy ?? void 0,
147
+ heading: o.coords.heading ?? void 0,
148
+ speed: o.coords.speed ?? void 0,
149
+ timestamp: o.timestamp
150
150
  };
151
151
  e(r);
152
152
  },
153
- (i) => {
154
- console.error("Geolocation watch error:", i);
153
+ (o) => {
154
+ console.error("Geolocation watch error:", o);
155
155
  },
156
- o
156
+ i
157
157
  );
158
158
  }
159
159
  /**
@@ -163,51 +163,215 @@ class v {
163
163
  navigator.geolocation.clearWatch(e);
164
164
  }
165
165
  }
166
- const N = new v();
167
- class E {
166
+ const x = new R();
167
+ function w() {
168
+ return "DeviceMotionEvent" in window;
169
+ }
170
+ function v() {
171
+ return "DeviceOrientationEvent" in window;
172
+ }
173
+ function f() {
174
+ const n = typeof window < "u", e = n && !!window.webkit, t = e && !!window.webkit?.messageHandlers, i = t && !!window.webkit?.messageHandlers?.aippyListener;
175
+ return console.log("๐Ÿ” [Aippy Sensors] hasNativeBridge check:", {
176
+ hasWindow: n,
177
+ hasWebkit: e,
178
+ hasMessageHandlers: t,
179
+ hasAippyListener: i,
180
+ result: i
181
+ }), i;
182
+ }
183
+ function I() {
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 y(n, e, t) {
187
+ switch (t) {
188
+ case 0:
189
+ return [n, e];
190
+ case 180:
191
+ return [-n, -e];
192
+ case 90:
193
+ return [-e, n];
194
+ case -90:
195
+ return [e, -n];
196
+ default:
197
+ return [n, e];
198
+ }
199
+ }
200
+ async function E() {
201
+ if (console.log("๐Ÿ” [Aippy Sensors] requestMotionPermission called"), f())
202
+ return console.log("โœ… [Aippy Sensors] Native bridge available, skipping permission request"), !0;
203
+ if (!w())
204
+ return console.warn("โŒ [Aippy Sensors] Device motion not supported"), !1;
205
+ const n = typeof DeviceMotionEvent < "u" && typeof DeviceMotionEvent.requestPermission == "function";
206
+ if (console.log("๐Ÿ” [Aippy Sensors] Permission API available:", n), n)
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 b(n) {
217
+ console.log("๐Ÿ”ง [Aippy Sensors] watchMotionNative - Setting up native bridge listener");
218
+ const e = A.addMotionListener((t) => {
219
+ const i = I(), o = t.gravity?.x ?? 0, r = t.gravity?.y ?? 0, d = t.gravity?.z ?? 0, a = t.acceleration?.x ?? 0, c = t.acceleration?.y ?? 0, l = t.acceleration?.z ?? 0, [u, m] = y(o, r, i), [p, g] = y(a, c, i), P = {
220
+ gravity: {
221
+ x: u,
222
+ y: m,
223
+ z: d
224
+ // Z่ฝดไธๅ—ๅฑๅน•ๆ—‹่ฝฌๅฝฑๅ“
225
+ },
226
+ acceleration: {
227
+ x: p,
228
+ y: g,
229
+ z: l
230
+ // Z่ฝดไธๅ—ๅฑๅน•ๆ—‹่ฝฌๅฝฑๅ“
231
+ },
232
+ accelerationIncludingGravity: {
233
+ x: u + p,
234
+ y: m + g,
235
+ z: d + l
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
+ n(P);
245
+ });
246
+ return console.log("โœ… [Aippy Sensors] watchMotionNative - Listener setup complete"), e;
247
+ }
248
+ function D(n, e = !0) {
249
+ if (!w())
250
+ throw s("Device motion API is not supported", "NOT_SUPPORTED");
251
+ let t = !1, i = null;
252
+ const o = (a) => {
253
+ if (!t) return;
254
+ const c = {
255
+ gravity: {
256
+ x: a.acceleration?.x ?? 0,
257
+ y: a.acceleration?.y ?? 0,
258
+ z: a.acceleration?.z ?? 0
259
+ },
260
+ acceleration: {
261
+ x: a.acceleration?.x ?? 0,
262
+ y: a.acceleration?.y ?? 0,
263
+ z: a.acceleration?.z ?? 0
264
+ },
265
+ accelerationIncludingGravity: {
266
+ x: a.accelerationIncludingGravity?.x ?? 0,
267
+ y: a.accelerationIncludingGravity?.y ?? 0,
268
+ z: a.accelerationIncludingGravity?.z ?? 0
269
+ },
270
+ rotation: {
271
+ alpha: a.rotationRate?.alpha ?? 0,
272
+ beta: a.rotationRate?.beta ?? 0,
273
+ gamma: a.rotationRate?.gamma ?? 0
274
+ },
275
+ timestamp: Date.now()
276
+ };
277
+ if (a.acceleration) {
278
+ const l = a.accelerationIncludingGravity, u = a.acceleration;
279
+ c.gravity = {
280
+ x: (l?.x ?? 0) - (u?.x ?? 0),
281
+ y: (l?.y ?? 0) - (u?.y ?? 0),
282
+ z: (l?.z ?? 0) - (u?.z ?? 0)
283
+ };
284
+ } else {
285
+ const l = a.accelerationIncludingGravity, u = 9.8;
286
+ c.gravity = {
287
+ x: (l?.x ?? 0) / u,
288
+ y: (l?.y ?? 0) / u,
289
+ z: (l?.z ?? 0) / u
290
+ };
291
+ }
292
+ n(c);
293
+ }, r = async () => {
294
+ e && !await E() || (t = !0, window.addEventListener("devicemotion", o));
295
+ };
296
+ return (async () => {
297
+ if (typeof DeviceMotionEvent < "u" && typeof DeviceMotionEvent.requestPermission == "function" && e) {
298
+ const c = async () => {
299
+ i = null, await r();
300
+ };
301
+ window.addEventListener("click", c, { once: !0 }), window.addEventListener("touchstart", c, { once: !0 }), i = () => {
302
+ window.removeEventListener("click", c), window.removeEventListener("touchstart", c);
303
+ };
304
+ } else
305
+ await r();
306
+ })(), () => {
307
+ t = !1, window.removeEventListener("devicemotion", o), i && (i(), i = null);
308
+ };
309
+ }
310
+ function _(n, e = !0) {
311
+ const t = f();
312
+ return console.log(`๐ŸŽฏ [Aippy Sensors] watchMotion - Using ${t ? "NATIVE BRIDGE" : "WEB API"} mode`), t ? (console.log("๐Ÿ“ฑ [Aippy Sensors] Starting native bridge motion listener"), b(n)) : (console.log("๐ŸŒ [Aippy Sensors] Starting Web API motion listener (may require permission)"), D(n, e));
313
+ }
314
+ function F(n) {
315
+ if (!v())
316
+ throw s("Device orientation API is not supported", "NOT_SUPPORTED");
317
+ const e = (t) => {
318
+ const i = {
319
+ alpha: t.alpha ?? 0,
320
+ beta: t.beta ?? 0,
321
+ gamma: t.gamma ?? 0,
322
+ timestamp: Date.now()
323
+ };
324
+ n(i);
325
+ };
326
+ return window.addEventListener("deviceorientation", e), () => {
327
+ window.removeEventListener("deviceorientation", e);
328
+ };
329
+ }
330
+ class U {
168
331
  /**
169
332
  * Check if device orientation is supported
170
333
  */
171
334
  isOrientationSupported() {
172
- return "DeviceOrientationEvent" in window;
335
+ return v();
173
336
  }
174
337
  /**
175
338
  * Check if device motion is supported
176
339
  */
177
340
  isMotionSupported() {
178
- return "DeviceMotionEvent" in window;
341
+ return w();
179
342
  }
180
343
  /**
181
344
  * Get device orientation data
182
345
  */
183
346
  async getOrientation() {
184
347
  if (!this.isOrientationSupported())
185
- throw a("Device orientation API is not supported", "NOT_SUPPORTED");
348
+ throw s("Device orientation API is not supported", "NOT_SUPPORTED");
186
349
  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,
350
+ const i = (o) => {
351
+ window.removeEventListener("deviceorientation", i), e({
352
+ x: o.alpha ?? 0,
353
+ y: o.beta ?? 0,
354
+ z: o.gamma ?? 0,
192
355
  timestamp: Date.now()
193
356
  });
194
357
  };
195
- window.addEventListener("deviceorientation", o), setTimeout(() => {
196
- window.removeEventListener("deviceorientation", o), t(a("Device orientation timeout", "UNKNOWN_ERROR"));
358
+ window.addEventListener("deviceorientation", i), setTimeout(() => {
359
+ window.removeEventListener("deviceorientation", i), t(s("Device orientation timeout", "UNKNOWN_ERROR"));
197
360
  }, 5e3);
198
361
  });
199
362
  }
200
363
  /**
201
364
  * Watch device orientation changes
365
+ * @deprecated Use watchOrientation() function instead
202
366
  */
203
367
  watchOrientation(e) {
204
368
  if (!this.isOrientationSupported())
205
- throw a("Device orientation API is not supported", "NOT_SUPPORTED");
206
- const t = (o) => {
369
+ throw s("Device orientation API is not supported", "NOT_SUPPORTED");
370
+ const t = (i) => {
207
371
  e({
208
- x: o.alpha ?? 0,
209
- y: o.beta ?? 0,
210
- z: o.gamma ?? 0,
372
+ x: i.alpha ?? 0,
373
+ y: i.beta ?? 0,
374
+ z: i.gamma ?? 0,
211
375
  timestamp: Date.now()
212
376
  });
213
377
  };
@@ -220,32 +384,33 @@ class E {
220
384
  */
221
385
  async getMotion() {
222
386
  if (!this.isMotionSupported())
223
- throw a("Device motion API is not supported", "NOT_SUPPORTED");
387
+ throw s("Device motion API is not supported", "NOT_SUPPORTED");
224
388
  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,
389
+ const i = (o) => {
390
+ window.removeEventListener("devicemotion", i), e({
391
+ x: o.acceleration?.x ?? 0,
392
+ y: o.acceleration?.y ?? 0,
393
+ z: o.acceleration?.z ?? 0,
230
394
  timestamp: Date.now()
231
395
  });
232
396
  };
233
- window.addEventListener("devicemotion", o), setTimeout(() => {
234
- window.removeEventListener("devicemotion", o), t(a("Device motion timeout", "UNKNOWN_ERROR"));
397
+ window.addEventListener("devicemotion", i), setTimeout(() => {
398
+ window.removeEventListener("devicemotion", i), t(s("Device motion timeout", "UNKNOWN_ERROR"));
235
399
  }, 5e3);
236
400
  });
237
401
  }
238
402
  /**
239
403
  * Watch device motion changes
404
+ * @deprecated Use watchMotion() function instead
240
405
  */
241
406
  watchMotion(e) {
242
407
  if (!this.isMotionSupported())
243
- throw a("Device motion API is not supported", "NOT_SUPPORTED");
244
- const t = (o) => {
408
+ throw s("Device motion API is not supported", "NOT_SUPPORTED");
409
+ const t = (i) => {
245
410
  e({
246
- x: o.acceleration?.x ?? 0,
247
- y: o.acceleration?.y ?? 0,
248
- z: o.acceleration?.z ?? 0,
411
+ x: i.acceleration?.x ?? 0,
412
+ y: i.acceleration?.y ?? 0,
413
+ z: i.acceleration?.z ?? 0,
249
414
  timestamp: Date.now()
250
415
  });
251
416
  };
@@ -257,17 +422,11 @@ class E {
257
422
  * Request permission for motion sensors (iOS 13+)
258
423
  */
259
424
  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
- }
425
+ return E();
267
426
  }
268
427
  }
269
- const R = new E();
270
- class O {
428
+ const z = new U();
429
+ class M {
271
430
  /**
272
431
  * Check if file system access is supported
273
432
  */
@@ -285,7 +444,7 @@ class O {
285
444
  */
286
445
  async openFilePicker(e = {}) {
287
446
  if (!this.isSupported())
288
- throw a("File System Access API is not supported", "NOT_SUPPORTED");
447
+ throw s("File System Access API is not supported", "NOT_SUPPORTED");
289
448
  try {
290
449
  const t = {
291
450
  types: e.accept ? [{
@@ -295,15 +454,15 @@ class O {
295
454
  )
296
455
  }] : void 0,
297
456
  multiple: e.multiple ?? !1
298
- }, o = await window.showOpenFilePicker(t), i = await Promise.all(
299
- o.map(async (r) => r.getFile())
457
+ }, i = await window.showOpenFilePicker(t), o = await Promise.all(
458
+ i.map(async (r) => r.getFile())
300
459
  );
301
460
  return {
302
- files: i,
303
- paths: i.map((r) => r.name)
461
+ files: o,
462
+ paths: o.map((r) => r.name)
304
463
  };
305
464
  } catch (t) {
306
- throw t instanceof Error && t.name === "AbortError" ? a("File picker was cancelled", "PERMISSION_DENIED") : a(
465
+ throw t instanceof Error && t.name === "AbortError" ? s("File picker was cancelled", "PERMISSION_DENIED") : s(
307
466
  `Failed to open file picker: ${t instanceof Error ? t.message : "Unknown error"}`,
308
467
  "PERMISSION_DENIED"
309
468
  );
@@ -314,18 +473,18 @@ class O {
314
473
  */
315
474
  async openFilePickerLegacy(e = {}) {
316
475
  if (!this.isLegacySupported())
317
- 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) => {
321
- const c = r.target, s = Array.from(c.files || []);
476
+ throw s("File input is not supported", "NOT_SUPPORTED");
477
+ return new Promise((t, i) => {
478
+ const o = document.createElement("input");
479
+ o.type = "file", o.multiple = e.multiple ?? !1, o.accept = e.accept?.join(",") ?? "", o.onchange = (r) => {
480
+ const d = r.target, a = Array.from(d.files || []);
322
481
  t({
323
- files: s,
324
- paths: s.map((d) => d.name)
482
+ files: a,
483
+ paths: a.map((c) => c.name)
325
484
  });
326
- }, i.oncancel = () => {
327
- o(a("File picker was cancelled", "PERMISSION_DENIED"));
328
- }, i.click();
485
+ }, o.oncancel = () => {
486
+ i(s("File picker was cancelled", "PERMISSION_DENIED"));
487
+ }, o.click();
329
488
  });
330
489
  }
331
490
  /**
@@ -339,11 +498,11 @@ class O {
339
498
  */
340
499
  async saveFile(e, t) {
341
500
  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) {
345
- throw a(
346
- `Failed to save file: ${o instanceof Error ? o.message : "Unknown error"}`,
501
+ const i = URL.createObjectURL(e), o = document.createElement("a");
502
+ o.href = i, o.download = t, document.body.appendChild(o), o.click(), document.body.removeChild(o), URL.revokeObjectURL(i);
503
+ } catch (i) {
504
+ throw s(
505
+ `Failed to save file: ${i instanceof Error ? i.message : "Unknown error"}`,
347
506
  "UNKNOWN_ERROR"
348
507
  );
349
508
  }
@@ -352,23 +511,23 @@ class O {
352
511
  * Read file as text
353
512
  */
354
513
  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);
514
+ return new Promise((t, i) => {
515
+ const o = new FileReader();
516
+ o.onload = () => t(o.result), o.onerror = () => i(s("Failed to read file", "UNKNOWN_ERROR")), o.readAsText(e);
358
517
  });
359
518
  }
360
519
  /**
361
520
  * Read file as data URL
362
521
  */
363
522
  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);
523
+ return new Promise((t, i) => {
524
+ const o = new FileReader();
525
+ o.onload = () => t(o.result), o.onerror = () => i(s("Failed to read file", "UNKNOWN_ERROR")), o.readAsDataURL(e);
367
526
  });
368
527
  }
369
528
  }
370
- const S = new O();
371
- function D(n) {
529
+ const G = new M();
530
+ function W(n) {
372
531
  return new Promise((e) => {
373
532
  if ("vibrate" in navigator)
374
533
  navigator.vibrate(n), e();
@@ -383,13 +542,19 @@ function D(n) {
383
542
  });
384
543
  }
385
544
  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
545
+ N as CameraAPI,
546
+ M as FileSystemAPI,
547
+ R as GeolocationAPI,
548
+ U as SensorsAPI,
549
+ T as camera,
550
+ G as fileSystem,
551
+ x as geolocation,
552
+ f as hasNativeBridge,
553
+ w as isMotionSupported,
554
+ v as isOrientationSupported,
555
+ E as requestMotionPermission,
556
+ z as sensors,
557
+ W as vibrate,
558
+ _ as watchMotion,
559
+ F as watchOrientation
395
560
  };
@@ -1,6 +1,39 @@
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
+ * @param callback - Function to call with orientation data
31
+ * @returns Cleanup function to stop watching
32
+ */
33
+ export declare function watchOrientation(callback: (data: OrientationData) => void): () => void;
34
+ /**
35
+ * Legacy SensorsAPI class for backward compatibility
36
+ * @deprecated Use watchMotion() and watchOrientation() functions instead
4
37
  */
5
38
  export declare class SensorsAPI {
6
39
  /**
@@ -17,6 +50,7 @@ export declare class SensorsAPI {
17
50
  getOrientation(): Promise<SensorData>;
18
51
  /**
19
52
  * Watch device orientation changes
53
+ * @deprecated Use watchOrientation() function instead
20
54
  */
21
55
  watchOrientation(callback: (data: SensorData) => void): () => void;
22
56
  /**
@@ -25,6 +59,7 @@ export declare class SensorsAPI {
25
59
  getMotion(): Promise<SensorData>;
26
60
  /**
27
61
  * Watch device motion changes
62
+ * @deprecated Use watchMotion() function instead
28
63
  */
29
64
  watchMotion(callback: (data: SensorData) => void): () => void;
30
65
  /**
@@ -33,6 +68,7 @@ export declare class SensorsAPI {
33
68
  requestPermission(): Promise<boolean>;
34
69
  }
35
70
  /**
36
- * Sensors API instance
71
+ * Sensors API instance (for backward compatibility)
72
+ * @deprecated Use watchMotion() and watchOrientation() functions instead
37
73
  */
38
74
  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-dev.1",
3
+ "version": "0.2.4-dev.11",
4
4
  "description": "Aippy Runtime SDK - Runtime SDK for Aippy projects",
5
5
  "private": false,
6
6
  "type": "module",
@@ -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
- };