yjz-web-sdk 1.0.11-beta.8 → 1.0.11-beta.9

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.
@@ -244,6 +244,7 @@ var FailCode = /* @__PURE__ */ ((FailCode2) => {
244
244
  FailCode2[FailCode2["KICK_OUT_ERR"] = 10016] = "KICK_OUT_ERR";
245
245
  FailCode2[FailCode2["STATE_ERR"] = 10017] = "STATE_ERR";
246
246
  FailCode2[FailCode2["OPTION_ERR"] = 10018] = "OPTION_ERR";
247
+ FailCode2[FailCode2["NO_OPTION_LONGTIME"] = 10019] = "NO_OPTION_LONGTIME";
247
248
  return FailCode2;
248
249
  })(FailCode || {});
249
250
  const FailInfoMap = {
@@ -318,7 +319,11 @@ const FailInfoMap = {
318
319
  [
319
320
  10018
320
321
  /* OPTION_ERR */
321
- ]: { type: "option_err", description: "投屏配置异常,请检查配置" }
322
+ ]: { type: "option_err", description: "投屏配置异常,请检查配置" },
323
+ [
324
+ 10019
325
+ /* NO_OPTION_LONGTIME */
326
+ ]: { type: "no_option_long_time", description: "云机长时间未操作,主动断开连接,点击重连恢复投屏" }
322
327
  };
323
328
  var CameraFailCode = /* @__PURE__ */ ((CameraFailCode2) => {
324
329
  CameraFailCode2[CameraFailCode2["LOCAL_STREAM_FAIL"] = 20001] = "LOCAL_STREAM_FAIL";
@@ -3563,6 +3568,7 @@ const formattedTime = (timestamp) => {
3563
3568
  return `${h}:${m}:${s}.${ms}`;
3564
3569
  };
3565
3570
  class WebRTCClient extends EventEmitter {
3571
+ // 最近一次触发时间戳
3566
3572
  constructor(config) {
3567
3573
  super();
3568
3574
  __publicField(this, "config");
@@ -3591,6 +3597,12 @@ class WebRTCClient extends EventEmitter {
3591
3597
  __publicField(this, "fileImage");
3592
3598
  __publicField(this, "reConnectTimer", null);
3593
3599
  __publicField(this, "canPushStream", false);
3600
+ __publicField(this, "idleTimer", null);
3601
+ __publicField(this, "retryCount", 0);
3602
+ // 当前重连里的 retry 次数
3603
+ __publicField(this, "MAX_RETRY_PER_RECONNECT", 2);
3604
+ // 每次重连最多 retry 2 次
3605
+ __publicField(this, "lastIdleResetTime", 0);
3594
3606
  __publicField(this, "startPushLocal", async (file) => {
3595
3607
  if (this.isPushingLocalStream || !file) return;
3596
3608
  try {
@@ -3644,13 +3656,23 @@ class WebRTCClient extends EventEmitter {
3644
3656
  handleAnswer(answerSdp) {
3645
3657
  setRemoteDescriptionWithHandleAnswer(this.peerConnection, answerSdp ?? "", () => {
3646
3658
  this.canPushStream = true;
3659
+ this.retryCount = 0;
3647
3660
  }, (_err) => {
3648
3661
  this.canPushStream = false;
3649
- this.reConnectTimer = setTimeout(async () => {
3650
- await createOffer(this.peerConnection, (sdp2) => {
3651
- this.emit(EmitType.sendOffer, sdp2);
3652
- });
3653
- }, 3e3);
3662
+ if (this.reConnectTimer) {
3663
+ clearTimeout(this.reConnectTimer);
3664
+ this.reConnectTimer = null;
3665
+ }
3666
+ if (this.retryCount < this.MAX_RETRY_PER_RECONNECT) {
3667
+ this.reConnectTimer = setTimeout(async () => {
3668
+ await createOffer(this.peerConnection, (sdp2) => {
3669
+ this.emit(EmitType.sendOffer, sdp2);
3670
+ });
3671
+ }, 3e3);
3672
+ this.retryCount++;
3673
+ } else {
3674
+ this.retryCount = 0;
3675
+ }
3654
3676
  });
3655
3677
  }
3656
3678
  handleIceCandidate(candidate) {
@@ -3699,6 +3721,7 @@ class WebRTCClient extends EventEmitter {
3699
3721
  const jsonString = JSON.stringify(channelData);
3700
3722
  const buffer = new TextEncoder().encode(jsonString).buffer;
3701
3723
  (_a = this.dataChannel) == null ? void 0 : _a.send(buffer);
3724
+ this.resetIdleTimer();
3702
3725
  channelData = null;
3703
3726
  }
3704
3727
  } catch (err) {
@@ -3741,6 +3764,7 @@ class WebRTCClient extends EventEmitter {
3741
3764
  clearTimeout(this.reConnectTimer);
3742
3765
  this.reConnectTimer = null;
3743
3766
  }
3767
+ this.clearIdleTimer();
3744
3768
  this.removeAllListeners();
3745
3769
  (_a = this.videoDataChannel) == null ? void 0 : _a.close();
3746
3770
  this.videoDataChannel = null;
@@ -3949,6 +3973,7 @@ class WebRTCClient extends EventEmitter {
3949
3973
  this.emit(EmitType.iceConnectionState, state);
3950
3974
  if (state === "connected") {
3951
3975
  this.checkStats();
3976
+ this.resetIdleTimer();
3952
3977
  }
3953
3978
  }, (err) => this.emit(EmitType.webrtcError, err));
3954
3979
  this.configDataChannel();
@@ -3977,6 +4002,7 @@ class WebRTCClient extends EventEmitter {
3977
4002
  }
3978
4003
  async handleDataChannelMessage(event) {
3979
4004
  const data = JSON.parse(event.data);
4005
+ this.resetIdleTimer();
3980
4006
  if (data.type === ChannelDataType.ActionCommandEvent) {
3981
4007
  const { action, value, cameraId } = JSON.parse(data.data);
3982
4008
  if (action === "ACTION_CONTROL_VIDEO") {
@@ -4009,6 +4035,7 @@ class WebRTCClient extends EventEmitter {
4009
4035
  }
4010
4036
  }
4011
4037
  checkStats() {
4038
+ if (this.statsTimer) return;
4012
4039
  this.statsTimer = setInterval(() => this.processStatsOptimized(), 1e3);
4013
4040
  }
4014
4041
  async processStatsOptimized() {
@@ -4221,6 +4248,33 @@ class WebRTCClient extends EventEmitter {
4221
4248
  this.fileVideo.src = "";
4222
4249
  }
4223
4250
  }
4251
+ resetIdleTimer() {
4252
+ const now = Date.now();
4253
+ const DEBOUNCE_MS = 2e3;
4254
+ if (now - this.lastIdleResetTime < DEBOUNCE_MS) {
4255
+ return;
4256
+ }
4257
+ this.lastIdleResetTime = now;
4258
+ if (this.idleTimer) {
4259
+ clearTimeout(this.idleTimer);
4260
+ }
4261
+ this.idleTimer = setTimeout(() => {
4262
+ this.emit(
4263
+ EmitType.webrtcError,
4264
+ createWebRtcError(
4265
+ FailCode.NO_OPTION_LONGTIME,
4266
+ createWebRtcError(FailCode.NO_OPTION_LONGTIME, "")
4267
+ )
4268
+ );
4269
+ }, this.config.operateTimeout);
4270
+ }
4271
+ /** 停止空闲计时器 */
4272
+ clearIdleTimer() {
4273
+ if (this.idleTimer) {
4274
+ clearTimeout(this.idleTimer);
4275
+ this.idleTimer = null;
4276
+ }
4277
+ }
4224
4278
  }
4225
4279
  class WebRTCConfig {
4226
4280
  constructor(options) {
@@ -4245,6 +4299,7 @@ class WebRTCConfig {
4245
4299
  __publicField(this, "turnKey");
4246
4300
  __publicField(this, "traceId", "");
4247
4301
  __publicField(this, "signAgain");
4302
+ __publicField(this, "operateTimeout");
4248
4303
  this.signalServerUrl = options.signalServerUrl || "";
4249
4304
  this.myId = options.myId || "";
4250
4305
  this.roomId = options.roomId || "";
@@ -4266,6 +4321,7 @@ class WebRTCConfig {
4266
4321
  this.isGroup = options.isGroup;
4267
4322
  this.traceId = options.traceId || "";
4268
4323
  this.signAgain = options.signAgain || true;
4324
+ this.operateTimeout = options.operateTimeout || 15 * 60 * 1e3;
4269
4325
  }
4270
4326
  }
4271
4327
  const testTurnServer = (turnConfig, timeoutMs = 1500) => {
@@ -4373,9 +4429,10 @@ class WebRTCSdk extends EventEmitter {
4373
4429
  __publicField(this, "options");
4374
4430
  __publicField(this, "isConnected", false);
4375
4431
  __publicField(this, "isConnecting", false);
4376
- // private connectCount: number = 0
4377
- // private MAX_COUNT: number = 1
4432
+ __publicField(this, "connectCount", 0);
4433
+ __publicField(this, "MAX_COUNT", 1);
4378
4434
  __publicField(this, "timeout", null);
4435
+ __publicField(this, "reconnectTimer", null);
4379
4436
  /**
4380
4437
  * 处理 signal 消息,根据不同消息类型分发到 webRTCClient 或直接触发 SDK 事件
4381
4438
  * @param message 信令消息
@@ -4621,6 +4678,24 @@ class WebRTCSdk extends EventEmitter {
4621
4678
  this.isConnecting = false;
4622
4679
  }
4623
4680
  }
4681
+ scheduleReconnect() {
4682
+ if (this.reconnectTimer) {
4683
+ Logger.warn("reconnect 已在调度中,跳过");
4684
+ return;
4685
+ }
4686
+ this.isConnected = false;
4687
+ const delay = 4e3 + Math.floor(Math.random() * 2e3);
4688
+ Logger.warn(`WebRTC 将在 ${delay}ms 后重连`);
4689
+ this.reconnectTimer = setTimeout(async () => {
4690
+ this.reconnectTimer = null;
4691
+ try {
4692
+ await this.reconnect();
4693
+ } catch (e) {
4694
+ Logger.error("错误信息:", "scheduleReconnect 执行失败");
4695
+ this.emit(EmitType.webrtcError, e);
4696
+ }
4697
+ }, delay);
4698
+ }
4624
4699
  async reconnect() {
4625
4700
  this.resetConfig();
4626
4701
  try {
@@ -4649,6 +4724,7 @@ class WebRTCSdk extends EventEmitter {
4649
4724
  this.emit(EmitType.iceConnectionState, state);
4650
4725
  if (state === "connected") {
4651
4726
  this.isConnected = true;
4727
+ this.clearReconnectTimer();
4652
4728
  }
4653
4729
  });
4654
4730
  (_f = this.webRTCClient) == null ? void 0 : _f.on(
@@ -4660,8 +4736,14 @@ class WebRTCSdk extends EventEmitter {
4660
4736
  (clipData) => this.emit(EmitType.cloudClipData, clipData)
4661
4737
  );
4662
4738
  (_h = this.webRTCClient) == null ? void 0 : _h.on(EmitType.webrtcError, (err) => {
4663
- Logger.error("错误信息:", `sdk调试错误日志======>`, err);
4664
- this.emit(EmitType.webrtcError, err);
4739
+ if (err.code === FailCode.ICE_STATE && this.connectCount < this.MAX_COUNT && this.isConnected) {
4740
+ this.connectCount++;
4741
+ this.emit(EmitType.reconnect);
4742
+ this.scheduleReconnect();
4743
+ } else {
4744
+ Logger.error("错误信息:", `sdk调试错误日志======>`, err);
4745
+ this.emit(EmitType.webrtcError, err);
4746
+ }
4665
4747
  });
4666
4748
  (_i = this.webRTCClient) == null ? void 0 : _i.on(EmitType.cameraError, (err) => {
4667
4749
  this.emit(EmitType.cameraError, err);
@@ -4790,7 +4872,7 @@ class WebRTCSdk extends EventEmitter {
4790
4872
  sendSignOut() {
4791
4873
  var _a, _b;
4792
4874
  if (!this.config) return;
4793
- console.log("sendSignOut===>主动断开连接");
4875
+ Logger.debug("调试信息:", `sendSignOut=========>主动断开连接`);
4794
4876
  if (this.config.connectorType === ConnectorType.LanForwarding) {
4795
4877
  const message = {
4796
4878
  type: SendType.GroupSignOut,
@@ -4854,6 +4936,12 @@ class WebRTCSdk extends EventEmitter {
4854
4936
  this.emit(EmitType.webrtcError, createWebRtcError(FailCode.DATACHANNEL_ERR, err));
4855
4937
  }
4856
4938
  }
4939
+ clearReconnectTimer() {
4940
+ if (this.reconnectTimer) {
4941
+ clearTimeout(this.reconnectTimer);
4942
+ this.reconnectTimer = null;
4943
+ }
4944
+ }
4857
4945
  }
4858
4946
  const META_SHIFT_ON = 1;
4859
4947
  const META_ALT_ON = 2;
@@ -12,12 +12,16 @@ export declare class WebRTCSdk extends EventEmitter {
12
12
  options: WebRTCConfigOptions;
13
13
  isConnected: boolean;
14
14
  isConnecting: boolean;
15
+ private connectCount;
16
+ private MAX_COUNT;
15
17
  private timeout;
18
+ private reconnectTimer;
16
19
  constructor(options: WebRTCConfigOptions);
17
20
  initConfig(): Promise<void>;
18
21
  /** 开始连接 signal 服务 */
19
22
  startConnection(): void;
20
23
  private prepareConnection;
24
+ private scheduleReconnect;
21
25
  reconnect(): Promise<void>;
22
26
  initConnectConfig(initConfig?: boolean): void;
23
27
  initSignalingClient(): void;
@@ -51,4 +55,5 @@ export declare class WebRTCSdk extends EventEmitter {
51
55
  sendPong(): void;
52
56
  sendSignOut(): void;
53
57
  groupSendAction(type: ChannelDataType, data: any): void;
58
+ private clearReconnectTimer;
54
59
  }
@@ -16,7 +16,8 @@ export declare enum FailCode {
16
16
  AUTH_FAILED = 10015,
17
17
  KICK_OUT_ERR = 10016,
18
18
  STATE_ERR = 10017,
19
- OPTION_ERR = 10018
19
+ OPTION_ERR = 10018,
20
+ NO_OPTION_LONGTIME = 10019
20
21
  }
21
22
  export declare const FailInfoMap: Record<FailCode, {
22
23
  type: string;
@@ -28,6 +28,10 @@ export declare class WebRTCClient extends EventEmitter {
28
28
  private fileImage?;
29
29
  private reConnectTimer;
30
30
  private canPushStream;
31
+ private idleTimer;
32
+ private retryCount;
33
+ private readonly MAX_RETRY_PER_RECONNECT;
34
+ private lastIdleResetTime;
31
35
  constructor(config: WebRTCConfig);
32
36
  startPush(useBackCamera?: boolean): Promise<void>;
33
37
  handleOffer(offerSdp: string): void;
@@ -60,4 +64,7 @@ export declare class WebRTCClient extends EventEmitter {
60
64
  getFileImage(): HTMLImageElement;
61
65
  /** 停止推流并释放资源 */
62
66
  stopLocal(): void;
67
+ private resetIdleTimer;
68
+ /** 停止空闲计时器 */
69
+ private clearIdleTimer;
63
70
  }
@@ -33,6 +33,7 @@ export interface WebRTCConfigOptions {
33
33
  cacheTimeout?: number;
34
34
  enableLogger?: boolean;
35
35
  loggerLevel?: LogLevel;
36
+ operateTimeout?: number;
36
37
  }
37
38
  export declare class WebRTCConfig {
38
39
  signalServerUrl: string;
@@ -56,5 +57,6 @@ export declare class WebRTCConfig {
56
57
  turnKey: Array<string>;
57
58
  traceId: string;
58
59
  signAgain: boolean;
60
+ operateTimeout: number;
59
61
  constructor(options: WebRTCConfigOptions);
60
62
  }
package/lib/uni-sdk.js CHANGED
@@ -10,7 +10,7 @@ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read fr
10
10
  var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
11
11
  var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
12
12
  var _screenStatus, _isComposing, _direction, _screenWidth, _screenHeight, _clarityLevel, _gestureMode;
13
- import { W as WheelData, t as transformCoordinate, A as ActionType, v as valueToPercentage, T as TouchData, g as getKeyEventData, I as InputData, i as isFunctionKey, E as EventEmitter, C as ChannelDataType, a as WebRTCSdk, b as EmitType, F as FailCode, c as ContainerDirection, K as KeyEventData, j as ActionCommandEventValue, h as ActionCommandEventType, d as ClarityData, G as GestureData } from "./ScreenControlUtil-hkrPNY6q.js";
13
+ import { W as WheelData, t as transformCoordinate, A as ActionType, v as valueToPercentage, T as TouchData, g as getKeyEventData, I as InputData, i as isFunctionKey, E as EventEmitter, C as ChannelDataType, a as WebRTCSdk, b as EmitType, F as FailCode, c as ContainerDirection, K as KeyEventData, j as ActionCommandEventValue, h as ActionCommandEventType, d as ClarityData, G as GestureData } from "./ScreenControlUtil-D4-BTCo9.js";
14
14
  var DocumentEvent = /* @__PURE__ */ ((DocumentEvent2) => {
15
15
  DocumentEvent2["KEY_DOWN"] = "keydown";
16
16
  DocumentEvent2["POINTER_ENTER"] = "pointerenter";
@@ -443,6 +443,7 @@ class MouseTouchControl {
443
443
  __publicField(this, "handleMouseEnter", (event) => {
444
444
  event.preventDefault();
445
445
  event.stopPropagation();
446
+ if (event.pointerType !== "mouse") return;
446
447
  if (event.buttons === 1 && !this.pointers.has(event.pointerId)) {
447
448
  if (this.remoteElement) {
448
449
  this.remoteElement.setPointerCapture(event.pointerId);
@@ -453,6 +454,7 @@ class MouseTouchControl {
453
454
  __publicField(this, "handleMouseLeave", (event) => {
454
455
  event.preventDefault();
455
456
  event.stopPropagation();
457
+ if (event.pointerType !== "mouse") return;
456
458
  if (this.pointers.has(event.pointerId)) {
457
459
  this.handlePointerEvent(event, ActionType.ACTION_UP, event.pointerId);
458
460
  if (this.remoteElement) {
@@ -561,6 +563,7 @@ class KeyboardControl {
561
563
  (_a = this.inputMethodEditorElement) == null ? void 0 : _a.blur();
562
564
  });
563
565
  __publicField(this, "handleKeyDown", (e) => {
566
+ e.preventDefault();
564
567
  const data = getKeyEventData(e);
565
568
  this.inputDataUpdateCallback(data);
566
569
  });
@@ -2,8 +2,8 @@
2
2
  var __defProp = Object.defineProperty;
3
3
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
4
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
- import { A as ActionType, C as ChannelDataType, W as WheelData, t as transformCoordinate, v as valueToPercentage, T as TouchData, I as InputData, i as isFunctionKey, g as getKeyEventData, E as EventEmitter, a as WebRTCSdk, b as EmitType, e as enableLog, s as setLogLevel, K as KeyEventData } from "./ScreenControlUtil-hkrPNY6q.js";
6
- import { h, j, f, d, l, c, F, G, k, m } from "./ScreenControlUtil-hkrPNY6q.js";
5
+ import { A as ActionType, C as ChannelDataType, W as WheelData, t as transformCoordinate, v as valueToPercentage, T as TouchData, I as InputData, i as isFunctionKey, g as getKeyEventData, E as EventEmitter, a as WebRTCSdk, b as EmitType, e as enableLog, s as setLogLevel, K as KeyEventData } from "./ScreenControlUtil-D4-BTCo9.js";
6
+ import { h, j, f, d, l, c, F, G, k, m } from "./ScreenControlUtil-D4-BTCo9.js";
7
7
  import { computed, onMounted, onUnmounted, ref, onBeforeUnmount, defineComponent, toRefs, createElementBlock, openBlock, createElementVNode, normalizeStyle, unref, createCommentVNode, normalizeClass } from "vue";
8
8
  function useCursorStyle(cursorType) {
9
9
  return computed(() => {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "yjz-web-sdk",
3
3
  "private": false,
4
- "version": "1.0.11-beta.8",
4
+ "version": "1.0.11-beta.9",
5
5
  "type": "module",
6
6
  "description": "针对于亚矩阵项目的云手机投屏和屏幕控制",
7
7
  "license": "Apache-2.0",