@kelnishi/satmouse-client 0.15.0 → 0.15.2
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.
- package/dist/core/index.cjs +52 -24
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.js +52 -24
- package/dist/core/index.js.map +1 -1
- package/dist/react/index.cjs +52 -24
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.js +52 -24
- package/dist/react/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/react/index.d.cts +0 -294
- package/dist/react/index.d.ts +0 -294
package/dist/react/index.js
CHANGED
|
@@ -262,9 +262,6 @@ var WebRTCAdapter = class {
|
|
|
262
262
|
onError = null;
|
|
263
263
|
pc = null;
|
|
264
264
|
signalingUrl;
|
|
265
|
-
/**
|
|
266
|
-
* @param signalingUrl — HTTP endpoint for SDP exchange (e.g., "http://127.0.0.1:18945/rtc/offer")
|
|
267
|
-
*/
|
|
268
265
|
constructor(signalingUrl) {
|
|
269
266
|
this.signalingUrl = signalingUrl;
|
|
270
267
|
}
|
|
@@ -272,18 +269,14 @@ var WebRTCAdapter = class {
|
|
|
272
269
|
if (typeof globalThis.RTCPeerConnection === "undefined") {
|
|
273
270
|
throw new Error("RTCPeerConnection not available");
|
|
274
271
|
}
|
|
275
|
-
this.pc = new RTCPeerConnection({
|
|
276
|
-
iceServers: []
|
|
277
|
-
// Local network, no STUN/TURN
|
|
278
|
-
});
|
|
272
|
+
this.pc = new RTCPeerConnection({ iceServers: [] });
|
|
279
273
|
this.pc.ondatachannel = (event) => {
|
|
280
274
|
const channel = event.channel;
|
|
281
275
|
if (channel.label === "spatial") {
|
|
282
276
|
channel.binaryType = "arraybuffer";
|
|
283
277
|
channel.onmessage = (e) => {
|
|
284
278
|
if (e.data instanceof ArrayBuffer && e.data.byteLength >= 20) {
|
|
285
|
-
|
|
286
|
-
this.onSpatialData?.(decoded);
|
|
279
|
+
this.onSpatialData?.(decodeBinaryFrame(e.data));
|
|
287
280
|
}
|
|
288
281
|
};
|
|
289
282
|
} else if (channel.label === "reliable") {
|
|
@@ -307,23 +300,16 @@ var WebRTCAdapter = class {
|
|
|
307
300
|
const offer = await this.pc.createOffer();
|
|
308
301
|
await this.pc.setLocalDescription(offer);
|
|
309
302
|
await this.waitForICE();
|
|
310
|
-
const
|
|
311
|
-
method: "POST",
|
|
312
|
-
body: this.pc.localDescription.sdp,
|
|
313
|
-
headers: { "Content-Type": "application/sdp" }
|
|
314
|
-
});
|
|
315
|
-
if (!response.ok) {
|
|
316
|
-
throw new Error(`Signaling failed: ${response.status}`);
|
|
317
|
-
}
|
|
318
|
-
const answerSdp = await response.text();
|
|
303
|
+
const answerSdp = await this.exchangeSDP(this.pc.localDescription.sdp);
|
|
319
304
|
await this.pc.setRemoteDescription({ type: "answer", sdp: answerSdp });
|
|
320
305
|
await new Promise((resolve, reject) => {
|
|
321
306
|
const timeout = setTimeout(() => reject(new Error("WebRTC connection timeout")), 1e4);
|
|
322
307
|
const check = () => {
|
|
323
|
-
|
|
308
|
+
const state = this.pc?.connectionState;
|
|
309
|
+
if (state === "connected") {
|
|
324
310
|
clearTimeout(timeout);
|
|
325
311
|
resolve();
|
|
326
|
-
} else if (
|
|
312
|
+
} else if (state === "failed") {
|
|
327
313
|
clearTimeout(timeout);
|
|
328
314
|
reject(new Error("WebRTC connection failed"));
|
|
329
315
|
}
|
|
@@ -331,9 +317,7 @@ var WebRTCAdapter = class {
|
|
|
331
317
|
this.pc.onconnectionstatechange = () => {
|
|
332
318
|
check();
|
|
333
319
|
const state = this.pc?.connectionState;
|
|
334
|
-
if (state === "disconnected" || state === "failed" || state === "closed")
|
|
335
|
-
this.onClose?.();
|
|
336
|
-
}
|
|
320
|
+
if (state === "disconnected" || state === "failed" || state === "closed") this.onClose?.();
|
|
337
321
|
};
|
|
338
322
|
check();
|
|
339
323
|
});
|
|
@@ -345,6 +329,44 @@ var WebRTCAdapter = class {
|
|
|
345
329
|
}
|
|
346
330
|
this.pc = null;
|
|
347
331
|
}
|
|
332
|
+
/** Exchange SDP: try fetch POST, fall back to popup window */
|
|
333
|
+
async exchangeSDP(offerSdp) {
|
|
334
|
+
try {
|
|
335
|
+
const res = await fetch(this.signalingUrl, {
|
|
336
|
+
method: "POST",
|
|
337
|
+
body: offerSdp,
|
|
338
|
+
headers: { "Content-Type": "application/sdp" }
|
|
339
|
+
});
|
|
340
|
+
if (res.ok) return await res.text();
|
|
341
|
+
} catch {
|
|
342
|
+
}
|
|
343
|
+
return this.exchangeSDPViaPopup(offerSdp);
|
|
344
|
+
}
|
|
345
|
+
exchangeSDPViaPopup(offerSdp) {
|
|
346
|
+
return new Promise((resolve, reject) => {
|
|
347
|
+
const offerB64 = btoa(offerSdp);
|
|
348
|
+
const baseUrl = this.signalingUrl.replace("/rtc/offer", "/rtc/connect-popup");
|
|
349
|
+
const url = `${baseUrl}?offer=${encodeURIComponent(offerB64)}`;
|
|
350
|
+
const popup = globalThis.open(url, "satmouse-rtc", "width=1,height=1,left=-100,top=-100");
|
|
351
|
+
if (!popup) {
|
|
352
|
+
reject(new Error("Popup blocked \u2014 user interaction required"));
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
const timeout = setTimeout(() => {
|
|
356
|
+
popup.close();
|
|
357
|
+
reject(new Error("WebRTC signaling timeout"));
|
|
358
|
+
}, 1e4);
|
|
359
|
+
const onMessage = (event) => {
|
|
360
|
+
if (event.data?.type === "satmouse-rtc-answer") {
|
|
361
|
+
clearTimeout(timeout);
|
|
362
|
+
globalThis.removeEventListener("message", onMessage);
|
|
363
|
+
popup.close();
|
|
364
|
+
resolve(event.data.answer);
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
globalThis.addEventListener("message", onMessage);
|
|
368
|
+
});
|
|
369
|
+
}
|
|
348
370
|
waitForICE() {
|
|
349
371
|
return new Promise((resolve) => {
|
|
350
372
|
if (!this.pc) return resolve();
|
|
@@ -502,12 +524,18 @@ var SatMouseConnection = class extends TypedEmitter {
|
|
|
502
524
|
if (!this.intentionalClose) this.scheduleReconnect();
|
|
503
525
|
};
|
|
504
526
|
try {
|
|
505
|
-
await
|
|
527
|
+
await Promise.race([
|
|
528
|
+
adapter.connect(),
|
|
529
|
+
new Promise(
|
|
530
|
+
(_, reject) => setTimeout(() => reject(new Error(`${adapter.protocol} connection timeout`)), 5e3)
|
|
531
|
+
)
|
|
532
|
+
]);
|
|
506
533
|
this.transport = adapter;
|
|
507
534
|
this.retryCount = 0;
|
|
508
535
|
this.setState("connected", adapter.protocol);
|
|
509
536
|
return true;
|
|
510
537
|
} catch (err) {
|
|
538
|
+
adapter.close();
|
|
511
539
|
this.emit("error", err instanceof Error ? err : new Error(String(err)));
|
|
512
540
|
return false;
|
|
513
541
|
}
|