@webex/plugin-meetings 3.8.0-next.5 → 3.8.0-next.51

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.
Files changed (133) hide show
  1. package/dist/breakouts/breakout.js +1 -1
  2. package/dist/breakouts/index.js +1 -1
  3. package/dist/config.js +1 -0
  4. package/dist/config.js.map +1 -1
  5. package/dist/constants.js +14 -1
  6. package/dist/constants.js.map +1 -1
  7. package/dist/controls-options-manager/enums.js +2 -0
  8. package/dist/controls-options-manager/enums.js.map +1 -1
  9. package/dist/controls-options-manager/types.js.map +1 -1
  10. package/dist/controls-options-manager/util.js +52 -0
  11. package/dist/controls-options-manager/util.js.map +1 -1
  12. package/dist/interpretation/index.js +1 -1
  13. package/dist/interpretation/siLanguage.js +1 -1
  14. package/dist/locus-info/controlsUtils.js +28 -10
  15. package/dist/locus-info/controlsUtils.js.map +1 -1
  16. package/dist/locus-info/index.js +20 -1
  17. package/dist/locus-info/index.js.map +1 -1
  18. package/dist/media/index.js +3 -15
  19. package/dist/media/index.js.map +1 -1
  20. package/dist/meeting/in-meeting-actions.js +11 -1
  21. package/dist/meeting/in-meeting-actions.js.map +1 -1
  22. package/dist/meeting/index.js +544 -324
  23. package/dist/meeting/index.js.map +1 -1
  24. package/dist/meeting/locusMediaRequest.js +26 -23
  25. package/dist/meeting/locusMediaRequest.js.map +1 -1
  26. package/dist/meeting/muteState.js +0 -2
  27. package/dist/meeting/muteState.js.map +1 -1
  28. package/dist/meeting/request.js +30 -0
  29. package/dist/meeting/request.js.map +1 -1
  30. package/dist/meeting/request.type.js.map +1 -1
  31. package/dist/meeting/util.js +27 -2
  32. package/dist/meeting/util.js.map +1 -1
  33. package/dist/meeting-info/meeting-info-v2.js +359 -60
  34. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  35. package/dist/meetings/index.js +69 -1
  36. package/dist/meetings/index.js.map +1 -1
  37. package/dist/meetings/util.js +14 -0
  38. package/dist/meetings/util.js.map +1 -1
  39. package/dist/member/index.js +10 -0
  40. package/dist/member/index.js.map +1 -1
  41. package/dist/member/util.js +3 -0
  42. package/dist/member/util.js.map +1 -1
  43. package/dist/metrics/constants.js +9 -0
  44. package/dist/metrics/constants.js.map +1 -1
  45. package/dist/reachability/clusterReachability.js +63 -27
  46. package/dist/reachability/clusterReachability.js.map +1 -1
  47. package/dist/reachability/index.js +112 -47
  48. package/dist/reachability/index.js.map +1 -1
  49. package/dist/reachability/reachability.types.js +14 -0
  50. package/dist/reachability/reachability.types.js.map +1 -1
  51. package/dist/reachability/request.js +19 -3
  52. package/dist/reachability/request.js.map +1 -1
  53. package/dist/reconnection-manager/index.js +2 -2
  54. package/dist/reconnection-manager/index.js.map +1 -1
  55. package/dist/recording-controller/util.js +5 -5
  56. package/dist/recording-controller/util.js.map +1 -1
  57. package/dist/roap/index.js.map +1 -1
  58. package/dist/roap/turnDiscovery.js +45 -27
  59. package/dist/roap/turnDiscovery.js.map +1 -1
  60. package/dist/roap/types.js +17 -0
  61. package/dist/roap/types.js.map +1 -0
  62. package/dist/types/config.d.ts +1 -0
  63. package/dist/types/constants.d.ts +10 -0
  64. package/dist/types/controls-options-manager/enums.d.ts +3 -1
  65. package/dist/types/controls-options-manager/types.d.ts +7 -1
  66. package/dist/types/locus-info/index.d.ts +1 -0
  67. package/dist/types/meeting/in-meeting-actions.d.ts +10 -0
  68. package/dist/types/meeting/index.d.ts +50 -3
  69. package/dist/types/meeting/muteState.d.ts +0 -1
  70. package/dist/types/meeting/request.d.ts +12 -1
  71. package/dist/types/meeting/request.type.d.ts +6 -0
  72. package/dist/types/meeting/util.d.ts +8 -1
  73. package/dist/types/meeting-info/meeting-info-v2.d.ts +80 -0
  74. package/dist/types/meetings/index.d.ts +29 -0
  75. package/dist/types/member/index.d.ts +1 -0
  76. package/dist/types/metrics/constants.d.ts +9 -0
  77. package/dist/types/reachability/clusterReachability.d.ts +15 -7
  78. package/dist/types/reachability/index.d.ts +10 -1
  79. package/dist/types/reachability/reachability.types.d.ts +5 -0
  80. package/dist/types/roap/index.d.ts +3 -2
  81. package/dist/types/roap/turnDiscovery.d.ts +5 -17
  82. package/dist/types/roap/types.d.ts +16 -0
  83. package/dist/webinar/index.js +1 -1
  84. package/package.json +22 -22
  85. package/src/config.ts +1 -0
  86. package/src/constants.ts +17 -0
  87. package/src/controls-options-manager/enums.ts +2 -0
  88. package/src/controls-options-manager/types.ts +11 -1
  89. package/src/controls-options-manager/util.ts +62 -0
  90. package/src/locus-info/controlsUtils.ts +44 -14
  91. package/src/locus-info/index.ts +23 -1
  92. package/src/media/index.ts +5 -21
  93. package/src/meeting/in-meeting-actions.ts +20 -0
  94. package/src/meeting/index.ts +351 -99
  95. package/src/meeting/locusMediaRequest.ts +33 -23
  96. package/src/meeting/muteState.ts +0 -2
  97. package/src/meeting/request.ts +36 -1
  98. package/src/meeting/request.type.ts +7 -0
  99. package/src/meeting/util.ts +27 -2
  100. package/src/meeting-info/meeting-info-v2.ts +247 -6
  101. package/src/meetings/index.ts +87 -1
  102. package/src/meetings/util.ts +18 -0
  103. package/src/member/index.ts +11 -0
  104. package/src/member/util.ts +3 -0
  105. package/src/metrics/constants.ts +9 -0
  106. package/src/reachability/clusterReachability.ts +73 -26
  107. package/src/reachability/index.ts +70 -1
  108. package/src/reachability/reachability.types.ts +6 -0
  109. package/src/reachability/request.ts +7 -0
  110. package/src/reconnection-manager/index.ts +2 -2
  111. package/src/recording-controller/util.ts +17 -13
  112. package/src/roap/index.ts +3 -7
  113. package/src/roap/turnDiscovery.ts +34 -39
  114. package/src/roap/types.ts +23 -0
  115. package/test/unit/spec/controls-options-manager/util.js +120 -0
  116. package/test/unit/spec/locus-info/controlsUtils.js +103 -9
  117. package/test/unit/spec/locus-info/index.js +28 -0
  118. package/test/unit/spec/media/index.ts +6 -16
  119. package/test/unit/spec/meeting/in-meeting-actions.ts +13 -4
  120. package/test/unit/spec/meeting/index.js +558 -145
  121. package/test/unit/spec/meeting/locusMediaRequest.ts +101 -88
  122. package/test/unit/spec/meeting/muteState.js +0 -2
  123. package/test/unit/spec/meeting/request.js +32 -1
  124. package/test/unit/spec/meeting/utils.js +123 -18
  125. package/test/unit/spec/meeting-info/meetinginfov2.js +443 -114
  126. package/test/unit/spec/meetings/index.js +96 -1
  127. package/test/unit/spec/member/index.js +7 -0
  128. package/test/unit/spec/member/util.js +24 -0
  129. package/test/unit/spec/reachability/clusterReachability.ts +88 -56
  130. package/test/unit/spec/reachability/index.ts +101 -0
  131. package/test/unit/spec/reachability/request.js +47 -2
  132. package/test/unit/spec/reconnection-manager/index.js +4 -4
  133. package/test/unit/spec/roap/turnDiscovery.ts +110 -28
@@ -45,10 +45,19 @@ declare const BEHAVIORAL_METRICS: {
45
45
  UPLOAD_LOGS_FAILURE: string;
46
46
  UPLOAD_LOGS_SUCCESS: string;
47
47
  RECEIVE_TRANSCRIPTION_FAILURE: string;
48
+ MEETING_IS_IN_PROGRESS_ERROR: string;
49
+ STATIC_MEETING_LINK_ALREADY_EXISTS_ERROR: string;
48
50
  FETCH_MEETING_INFO_V1_SUCCESS: string;
49
51
  FETCH_MEETING_INFO_V1_FAILURE: string;
52
+ ENABLE_STATIC_METTING_LINK_SUCCESS: string;
53
+ ENABLE_STATIC_METTING_LINK_FAILURE: string;
54
+ DISABLE_STATIC_MEETING_LINK_SUCCESS: string;
55
+ DISABLE_STATIC_MEETING_LINK_FAILURE: string;
50
56
  ADHOC_MEETING_SUCCESS: string;
51
57
  ADHOC_MEETING_FAILURE: string;
58
+ FETCH_STATIC_MEETING_LINK_SUCCESS: string;
59
+ FETCH_STATIC_MEETING_LINK_FAILURE: string;
60
+ MEETING_LINK_DOES_NOT_EXIST_ERROR: string;
52
61
  VERIFY_PASSWORD_SUCCESS: string;
53
62
  VERIFY_PASSWORD_ERROR: string;
54
63
  VERIFY_CAPTCHA_ERROR: string;
@@ -1,7 +1,7 @@
1
1
  import { ClusterNode } from './request';
2
2
  import EventsScope from '../common/events/events-scope';
3
3
  import { Enum } from '../constants';
4
- import { ClusterReachabilityResult } from './reachability.types';
4
+ import { ClusterReachabilityResult, NatType } from './reachability.types';
5
5
  export type ResultEventData = {
6
6
  protocol: 'udp' | 'tcp' | 'xtls';
7
7
  result: 'reachable' | 'unreachable' | 'untested';
@@ -12,9 +12,13 @@ export type ClientMediaIpsUpdatedEventData = {
12
12
  protocol: 'udp' | 'tcp' | 'xtls';
13
13
  clientMediaIPs: string[];
14
14
  };
15
+ export type NatTypeUpdatedEventData = {
16
+ natType: NatType;
17
+ };
15
18
  export declare const Events: {
16
19
  readonly resultReady: "resultReady";
17
20
  readonly clientMediaIpsUpdated: "clientMediaIpsUpdated";
21
+ readonly natTypeUpdated: "natTypeUpdated";
18
22
  };
19
23
  export type Events = Enum<typeof Events>;
20
24
  /**
@@ -29,8 +33,10 @@ export declare class ClusterReachability extends EventsScope {
29
33
  private pc?;
30
34
  private defer;
31
35
  private startTimestamp;
36
+ private srflxIceCandidates;
32
37
  readonly isVideoMesh: boolean;
33
38
  readonly name: any;
39
+ readonly reachedSubnets: Set<string>;
34
40
  /**
35
41
  * Constructor for ClusterReachability
36
42
  * @param {string} name cluster name
@@ -89,12 +95,6 @@ export declare class ClusterReachability extends EventsScope {
89
95
  * @returns {void}
90
96
  */
91
97
  private registerIceGatheringStateChangeListener;
92
- /**
93
- * Checks if we have the results for all the protocols (UDP and TCP)
94
- *
95
- * @returns {boolean} true if we have all results, false otherwise
96
- */
97
- private haveWeGotAllResults;
98
98
  /**
99
99
  * Saves the latency in the result for the given protocol and marks it as reachable,
100
100
  * emits the "resultReady" event if this is the first result for that protocol,
@@ -104,9 +104,17 @@ export declare class ClusterReachability extends EventsScope {
104
104
  * @param {string} protocol
105
105
  * @param {number} latency
106
106
  * @param {string|null} [publicIp]
107
+ * @param {string|null} [serverIp]
107
108
  * @returns {void}
108
109
  */
109
110
  private saveResult;
111
+ /**
112
+ * Determines NAT Type.
113
+ *
114
+ * @param {RTCIceCandidate} candidate
115
+ * @returns {void}
116
+ */
117
+ private determineNatType;
110
118
  /**
111
119
  * Registers a listener for the icecandidate event
112
120
  *
@@ -4,7 +4,7 @@
4
4
  import { Defer } from '@webex/common';
5
5
  import { IP_VERSION } from '../constants';
6
6
  import ReachabilityRequest, { ClusterList } from './request';
7
- import { ClusterReachabilityResult, ClientMediaPreferences, ReachabilityMetrics, ReachabilityReportV0, ReachabilityReportV1, ReachabilityResults, ReachabilityResultsForBackend, GetClustersTrigger } from './reachability.types';
7
+ import { ClusterReachabilityResult, ClientMediaPreferences, ReachabilityMetrics, ReachabilityReportV0, ReachabilityReportV1, ReachabilityResults, ReachabilityResultsForBackend, GetClustersTrigger, NatType } from './reachability.types';
8
8
  import { ClusterReachability } from './clusterReachability';
9
9
  import EventsScope from '../common/events/events-scope';
10
10
  /**
@@ -46,6 +46,7 @@ export default class Reachability extends EventsScope {
46
46
  };
47
47
  startTime: any;
48
48
  totalDuration: any;
49
+ natType: NatType;
49
50
  protected lastTrigger?: string;
50
51
  /**
51
52
  * Creates an instance of Reachability.
@@ -65,6 +66,14 @@ export default class Reachability extends EventsScope {
65
66
  clusters: ClusterList;
66
67
  joinCookie: any;
67
68
  }>;
69
+ /**
70
+ * Checks if the given subnet is reachable
71
+ * @param {string} mediaServerIp - media server ip
72
+ * @returns {boolean | null} true if reachable, false if not reachable, null if mediaServerIp is not provided
73
+ * @public
74
+ * @memberof Reachability
75
+ */
76
+ isSubnetReachable(mediaServerIp?: string): boolean | null;
68
77
  /**
69
78
  * Gets a list of media clusters from the backend and performs reachability checks on all the clusters
70
79
  * @param {string} trigger - explains the reason for starting reachability
@@ -4,6 +4,10 @@ export type TransportResult = {
4
4
  latencyInMilliseconds?: number;
5
5
  clientMediaIPs?: string[];
6
6
  };
7
+ export declare enum NatType {
8
+ Unknown = "unknown",
9
+ SymmetricNat = "symmetric-nat"
10
+ }
7
11
  export type ClusterReachabilityResult = {
8
12
  udp: TransportResult;
9
13
  tcp: TransportResult;
@@ -22,6 +26,7 @@ export type ReachabilityMetrics = {
22
26
  reachability_vmn_tcp_failed: number;
23
27
  reachability_vmn_xtls_success: number;
24
28
  reachability_vmn_xtls_failed: number;
29
+ natType: NatType;
25
30
  };
26
31
  /**
27
32
  * This is the type that matches what backend expects us to send to them. It is a bit weird, because
@@ -1,7 +1,8 @@
1
1
  import { StatelessWebexPlugin } from '@webex/webex-core';
2
- import TurnDiscovery, { TurnDiscoveryResult } from './turnDiscovery';
2
+ import TurnDiscovery from './turnDiscovery';
3
+ import { TurnDiscoveryResult } from './types';
3
4
  import Meeting from '../meeting';
4
- export { type TurnDiscoveryResult, type TurnServerInfo, type TurnDiscoverySkipReason, } from './turnDiscovery';
5
+ export { type TurnDiscoveryResult, type TurnServerInfo, type TurnDiscoverySkipReason } from './types';
5
6
  /**
6
7
  * Roap options
7
8
  * @typedef {Object} RoapOptions
@@ -1,21 +1,6 @@
1
- import { Enum } from '../constants';
2
1
  import RoapRequest from './request';
3
2
  import Meeting from '../meeting';
4
- declare const TurnDiscoverySkipReason: {
5
- readonly missingHttpResponse: "missing http response";
6
- readonly reachability: "reachability";
7
- readonly alreadyInProgress: "already in progress";
8
- };
9
- export type TurnDiscoverySkipReason = Enum<typeof TurnDiscoverySkipReason> | string | undefined;
10
- export type TurnServerInfo = {
11
- url: string;
12
- username: string;
13
- password: string;
14
- };
15
- export type TurnDiscoveryResult = {
16
- turnServerInfo?: TurnServerInfo;
17
- turnDiscoverySkippedReason: TurnDiscoverySkipReason;
18
- };
3
+ import { TurnDiscoverySkipReason, TurnDiscoveryResult } from './types';
19
4
  /**
20
5
  * Handles the process of finding out TURN server information from Linus.
21
6
  * This is achieved by sending a TURN_DISCOVERY_REQUEST.
@@ -25,6 +10,10 @@ export default class TurnDiscovery {
25
10
  private defer?;
26
11
  private turnInfo;
27
12
  private responseTimer?;
13
+ /** Resets the turnInfo structure to the defaults
14
+ * @returns {void}
15
+ */
16
+ private resetTurnInfo;
28
17
  /**
29
18
  * Constructor
30
19
  *
@@ -152,4 +141,3 @@ export default class TurnDiscovery {
152
141
  */
153
142
  doTurnDiscovery(meeting: Meeting, isReconnecting?: boolean, isForced?: boolean): Promise<TurnDiscoveryResult>;
154
143
  }
155
- export {};
@@ -0,0 +1,16 @@
1
+ import { Enum } from '../constants';
2
+ export declare const TurnDiscoverySkipReason: {
3
+ readonly missingHttpResponse: "missing http response";
4
+ readonly reachability: "reachability";
5
+ readonly alreadyInProgress: "already in progress";
6
+ };
7
+ export type TurnDiscoverySkipReason = Enum<typeof TurnDiscoverySkipReason> | string | undefined;
8
+ export type TurnServerInfo = {
9
+ urls: string[];
10
+ username: string;
11
+ password: string;
12
+ };
13
+ export type TurnDiscoveryResult = {
14
+ turnServerInfo?: TurnServerInfo;
15
+ turnDiscoverySkippedReason: TurnDiscoverySkipReason;
16
+ };
@@ -458,7 +458,7 @@ var Webinar = _webexCore.WebexPlugin.extend({
458
458
  }, _callee7);
459
459
  }))();
460
460
  },
461
- version: "3.8.0-next.5"
461
+ version: "3.8.0-next.51"
462
462
  });
463
463
  var _default = exports.default = Webinar;
464
464
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -43,13 +43,13 @@
43
43
  "@webex/eslint-config-legacy": "0.0.0",
44
44
  "@webex/jest-config-legacy": "0.0.0",
45
45
  "@webex/legacy-tools": "0.0.0",
46
- "@webex/plugin-meetings": "3.8.0-next.5",
47
- "@webex/plugin-rooms": "3.8.0-next.1",
48
- "@webex/test-helper-chai": "3.8.0-next.1",
49
- "@webex/test-helper-mocha": "3.8.0-next.1",
50
- "@webex/test-helper-mock-webex": "3.8.0-next.1",
51
- "@webex/test-helper-retry": "3.8.0-next.1",
52
- "@webex/test-helper-test-users": "3.8.0-next.1",
46
+ "@webex/plugin-meetings": "3.8.0-next.51",
47
+ "@webex/plugin-rooms": "3.8.0-next.19",
48
+ "@webex/test-helper-chai": "3.8.0-next.15",
49
+ "@webex/test-helper-mocha": "3.8.0-next.15",
50
+ "@webex/test-helper-mock-webex": "3.8.0-next.15",
51
+ "@webex/test-helper-retry": "3.8.0-next.15",
52
+ "@webex/test-helper-test-users": "3.8.0-next.15",
53
53
  "chai": "^4.3.4",
54
54
  "chai-as-promised": "^7.1.1",
55
55
  "eslint": "^8.24.0",
@@ -61,22 +61,22 @@
61
61
  "typescript": "^4.7.4"
62
62
  },
63
63
  "dependencies": {
64
- "@webex/common": "3.8.0-next.1",
64
+ "@webex/common": "3.8.0-next.15",
65
65
  "@webex/event-dictionary-ts": "^1.0.1688",
66
- "@webex/internal-media-core": "2.14.4",
67
- "@webex/internal-plugin-conversation": "3.8.0-next.1",
68
- "@webex/internal-plugin-device": "3.8.0-next.1",
69
- "@webex/internal-plugin-llm": "3.8.0-next.2",
70
- "@webex/internal-plugin-mercury": "3.8.0-next.1",
71
- "@webex/internal-plugin-metrics": "3.8.0-next.1",
72
- "@webex/internal-plugin-support": "3.8.0-next.1",
73
- "@webex/internal-plugin-user": "3.8.0-next.1",
74
- "@webex/internal-plugin-voicea": "3.8.0-next.5",
75
- "@webex/media-helpers": "3.8.0-next.1",
76
- "@webex/plugin-people": "3.8.0-next.1",
77
- "@webex/plugin-rooms": "3.8.0-next.1",
66
+ "@webex/internal-media-core": "2.14.7",
67
+ "@webex/internal-plugin-conversation": "3.8.0-next.19",
68
+ "@webex/internal-plugin-device": "3.8.0-next.15",
69
+ "@webex/internal-plugin-llm": "3.8.0-next.18",
70
+ "@webex/internal-plugin-mercury": "3.8.0-next.17",
71
+ "@webex/internal-plugin-metrics": "3.8.0-next.15",
72
+ "@webex/internal-plugin-support": "3.8.0-next.19",
73
+ "@webex/internal-plugin-user": "3.8.0-next.15",
74
+ "@webex/internal-plugin-voicea": "3.8.0-next.51",
75
+ "@webex/media-helpers": "3.8.0-next.16",
76
+ "@webex/plugin-people": "3.8.0-next.17",
77
+ "@webex/plugin-rooms": "3.8.0-next.19",
78
78
  "@webex/web-capabilities": "^1.4.0",
79
- "@webex/webex-core": "3.8.0-next.1",
79
+ "@webex/webex-core": "3.8.0-next.15",
80
80
  "ampersand-collection": "^2.0.2",
81
81
  "bowser": "^2.11.0",
82
82
  "btoa": "^1.2.1",
@@ -92,5 +92,5 @@
92
92
  "//": [
93
93
  "TODO: upgrade jwt-decode when moving to node 18"
94
94
  ],
95
- "version": "3.8.0-next.5"
95
+ "version": "3.8.0-next.51"
96
96
  }
package/src/config.ts CHANGED
@@ -95,6 +95,7 @@ export default {
95
95
  // This only applies to non-multistream meetings
96
96
  iceCandidatesGatheringTimeout: undefined,
97
97
  backendIpv6NativeSupport: false,
98
+ enableReachabilityChecks: true,
98
99
  reachabilityGetClusterTimeout: 5000,
99
100
  logUploadIntervalMultiplicationFactor: 0, // if set to 0 or undefined, logs won't be uploaded periodically, if you want periodic logs, recommended value is 1
100
101
  },
package/src/constants.ts CHANGED
@@ -369,6 +369,9 @@ export const EVENT_TRIGGERS = {
369
369
  MEETING_CONTROLS_MEETING_FULL_UPDATED: 'meeting:controls:meeting-full:updated',
370
370
  MEETING_CONTROLS_PRACTICE_SESSION_STATUS_UPDATED:
371
371
  'meeting:controls:practice-session-status:updated',
372
+ MEETING_CONTROLS_ANNOTATION_UPDATED: 'meeting:controls:annotation:updated',
373
+ MEETING_CONTROLS_REMOTE_DESKTOP_CONTROL_UPDATED:
374
+ 'meeting:controls:remote-desktop-control:updated',
372
375
  // Locus URL changed
373
376
  MEETING_LOCUS_URL_UPDATE: 'meeting:locus:locusUrl:update',
374
377
  MEETING_STREAM_PUBLISH_STATE_CHANGED: 'meeting:streamPublishStateChanged',
@@ -711,6 +714,8 @@ export const LOCUSINFO = {
711
714
  CONTROLS_PRACTICE_SESSION_STATUS_UPDATED: 'CONTROLS_PRACTICE_SESSION_STATUS_UPDATED',
712
715
  CONTROLS_VIDEO_CHANGED: 'CONTROLS_VIDEO_CHANGED',
713
716
  CONTROLS_STAGE_VIEW_UPDATED: 'CONTROLS_STAGE_VIEW_UPDATED',
717
+ CONTROLS_ANNOTATION_CHANGED: 'CONTROLS_ANNOTATION_CHANGED',
718
+ CONTROLS_REMOTE_DESKTOP_CONTROL_CHANGED: 'CONTROLS_REMOTE_DESKTOP_CONTROL_CHANGED',
714
719
  SELF_UNADMITTED_GUEST: 'SELF_UNADMITTED_GUEST',
715
720
  SELF_ADMITTED_GUEST: 'SELF_ADMITTED_GUEST',
716
721
  SELF_REMOTE_VIDEO_MUTE_STATUS_UPDATED: 'SELF_REMOTE_VIDEO_MUTE_STATUS_UPDATED',
@@ -904,6 +909,7 @@ export enum SELF_POLICY {
904
909
  ENFORCE_VIRTUAL_BACKGROUND = 'enforceVirtualBackground',
905
910
  SUPPORT_LOCAL_RECORD = 'supportLocalRecord',
906
911
  SUPPORT_NETWORK_BASED_RECORD = 'supportNetworkBasedRecord',
912
+ SUPPORT_PREMISE_RECORD = 'supportPremiseRecord',
907
913
  SUPPORT_REALTIME_CLOSE_CAPTION = 'supportRealtimeCloseCaption',
908
914
  SUPPORT_CHAT = 'supportChat',
909
915
  SUPPORT_DESKTOP_SHARE_REMOTE = 'supportDesktopShareRemote',
@@ -1025,6 +1031,17 @@ export const DISPLAY_HINTS = {
1025
1031
  PRACTICE_SESSION_OFF: 'PRACTICE_SESSION_OFF',
1026
1032
  SHOW_PRACTICE_SESSION_START: 'SHOW_PRACTICE_SESSION_START',
1027
1033
  SHOW_PRACTICE_SESSION_STOP: 'SHOW_PRACTICE_SESSION_STOP',
1034
+
1035
+ // Explicit consent for post meeting data
1036
+ SHOW_POST_MEETING_DATA_CONSENT_PROMPT: 'SHOW_POST_MEETING_DATA_CONSENT_PROMPT',
1037
+
1038
+ // Annotations
1039
+ ENABLE_ANNOTATION_MEETING_OPTION: 'ENABLE_ANNOTATION_MEETING_OPTION',
1040
+ DISABLE_ANNOTATION_MEETING_OPTION: 'DISABLE_ANNOTATION_MEETING_OPTION',
1041
+
1042
+ // Remote Desktop Control
1043
+ ENABLE_RDC_MEETING_OPTION: 'ENABLE_RDC_MEETING_OPTION',
1044
+ DISABLE_RDC_MEETING_OPTION: 'DISABLE_RDC_MEETING_OPTION',
1028
1045
  };
1029
1046
 
1030
1047
  export const INTERSTITIAL_DISPLAY_HINTS = [DISPLAY_HINTS.VOIP_IS_ENABLED];
@@ -12,6 +12,8 @@ enum Control {
12
12
  shareControl = 'shareControl',
13
13
  video = 'video',
14
14
  viewTheParticipantList = 'viewTheParticipantList',
15
+ annotation = 'annotation',
16
+ rdc = 'rdc',
15
17
  }
16
18
 
17
19
  export {Control, Setting};
@@ -40,13 +40,23 @@ export interface ViewTheParticipantListProperties {
40
40
  attendeeCount?: boolean;
41
41
  }
42
42
 
43
+ export interface AnnotationProperties {
44
+ enabled?: boolean;
45
+ }
46
+
47
+ export interface RemoteDesktopControlProperties {
48
+ enabled?: boolean;
49
+ }
50
+
43
51
  export type Properties =
44
52
  | AudioProperties
45
53
  | RaiseHandProperties
46
54
  | ReactionsProperties
47
55
  | ShareControlProperties
48
56
  | VideoProperties
49
- | ViewTheParticipantListProperties;
57
+ | ViewTheParticipantListProperties
58
+ | AnnotationProperties
59
+ | RemoteDesktopControlProperties;
50
60
 
51
61
  export interface ControlConfig<Props = Properties> {
52
62
  /**
@@ -7,6 +7,8 @@ import {
7
7
  ReactionsProperties,
8
8
  ViewTheParticipantListProperties,
9
9
  VideoProperties,
10
+ type RemoteDesktopControlProperties,
11
+ type AnnotationProperties,
10
12
  } from './types';
11
13
 
12
14
  /**
@@ -256,6 +258,52 @@ class Utils {
256
258
  return Utils.hasHints({requiredHints, displayHints});
257
259
  }
258
260
 
261
+ /**
262
+ * Validate if a annotation-scoped control is allowed to be sent to the service.
263
+ *
264
+ * @param {ControlConfig<AnnotationProperties>} control - Annotation control config to validate
265
+ * @param {Array<string>} displayHints - All available hints
266
+ * @returns {boolean} - True if all of the actions are allowed.
267
+ */
268
+ public static canUpdateAnnotation(
269
+ control: ControlConfig<AnnotationProperties>,
270
+ displayHints: Array<string>
271
+ ): boolean {
272
+ const requiredHints = [];
273
+
274
+ if (control.properties.enabled === true) {
275
+ requiredHints.push(DISPLAY_HINTS.ENABLE_ANNOTATION_MEETING_OPTION);
276
+ }
277
+ if (control.properties.enabled === false) {
278
+ requiredHints.push(DISPLAY_HINTS.DISABLE_ANNOTATION_MEETING_OPTION);
279
+ }
280
+
281
+ return Utils.hasHints({requiredHints, displayHints});
282
+ }
283
+
284
+ /**
285
+ * Validate if a rdc-scoped control is allowed to be sent to the service.
286
+ *
287
+ * @param {ControlConfig<RemoteDesktopControlProperties>} control - Remote Desktop Control config to validate
288
+ * @param {Array<string>} displayHints - All available hints
289
+ * @returns {boolean} - True if all of the actions are allowed.
290
+ */
291
+ public static canUpdateRemoteDesktopControl(
292
+ control: ControlConfig<RemoteDesktopControlProperties>,
293
+ displayHints: Array<string>
294
+ ): boolean {
295
+ const requiredHints = [];
296
+
297
+ if (control.properties.enabled === true) {
298
+ requiredHints.push(DISPLAY_HINTS.ENABLE_RDC_MEETING_OPTION);
299
+ }
300
+ if (control.properties.enabled === false) {
301
+ requiredHints.push(DISPLAY_HINTS.DISABLE_RDC_MEETING_OPTION);
302
+ }
303
+
304
+ return Utils.hasHints({requiredHints, displayHints});
305
+ }
306
+
259
307
  /**
260
308
  * Validate that a control can be sent to the service based on the provided
261
309
  * display hints.
@@ -301,6 +349,20 @@ class Utils {
301
349
  );
302
350
  break;
303
351
 
352
+ case Control.annotation:
353
+ determinant = Utils.canUpdateAnnotation(
354
+ control as ControlConfig<AnnotationProperties>,
355
+ displayHints
356
+ );
357
+ break;
358
+
359
+ case Control.rdc:
360
+ determinant = Utils.canUpdateRemoteDesktopControl(
361
+ control as ControlConfig<RemoteDesktopControlProperties>,
362
+ displayHints
363
+ );
364
+ break;
365
+
304
366
  default:
305
367
  determinant = false;
306
368
  }
@@ -1,5 +1,5 @@
1
1
  import {isEqual} from 'lodash';
2
- import {BREAKOUTS} from '../constants';
2
+ import {BREAKOUTS, MEETING_STATE} from '../constants';
3
3
 
4
4
  const ControlsUtils: any = {};
5
5
 
@@ -111,6 +111,18 @@ ControlsUtils.parse = (controls: any) => {
111
111
  };
112
112
  }
113
113
 
114
+ if (controls?.annotationControl) {
115
+ parsedControls.annotationControl = {
116
+ enabled: controls.annotationControl.enabled,
117
+ };
118
+ }
119
+
120
+ if (controls?.rdcControl) {
121
+ parsedControls.rdcControl = {
122
+ enabled: controls.rdcControl.enabled,
123
+ };
124
+ }
125
+
114
126
  return parsedControls;
115
127
  };
116
128
 
@@ -206,11 +218,17 @@ ControlsUtils.getControls = (oldControls: any, newControls: any) => {
206
218
  ),
207
219
 
208
220
  hasPracticeSessionEnabledChanged: !isEqual(
209
- previous?.practiceSession?.enabled,
210
- current?.practiceSession?.enabled
221
+ !!previous?.practiceSession?.enabled,
222
+ !!current?.practiceSession?.enabled
211
223
  ),
212
224
 
213
225
  hasStageViewChanged: !isEqual(previous?.videoLayout, current?.videoLayout),
226
+
227
+ hasAnnotationControlChanged:
228
+ current?.annotationControl?.enabled !== previous?.annotationControl?.enabled,
229
+
230
+ hasRemoteDesktopControlChanged:
231
+ current?.rdcControl?.enabled !== previous?.rdcControl?.enabled,
214
232
  },
215
233
  };
216
234
  };
@@ -242,30 +260,42 @@ ControlsUtils.isNeedReplaceMembers = (oldControls: any, controls: any) => {
242
260
  }
243
261
 
244
262
  return (
245
- oldControls.breakout.groupId !== controls.breakout.groupId ||
246
- oldControls.breakout.sessionId !== controls.breakout.sessionId
263
+ oldControls?.breakout?.groupId !== controls?.breakout?.groupId ||
264
+ oldControls?.breakout?.sessionId !== controls?.breakout?.sessionId
247
265
  );
248
266
  };
249
267
 
250
268
  /**
251
269
  * determine the switch status between breakout session and main session.
252
- * @param {LocusControls} oldControls
253
- * @param {LocusControls} controls
270
+ * @param {LocusInfo} oldLocus
271
+ * @param {LocusInfo} newLocus
254
272
  * @returns {Object}
255
273
  */
256
- ControlsUtils.getSessionSwitchStatus = (oldControls: any, controls: any) => {
274
+ ControlsUtils.getSessionSwitchStatus = (oldLocus: any, newLocus: any) => {
257
275
  const status = {isReturnToMain: false, isJoinToBreakout: false};
258
276
  // no breakout case
259
- if (!oldControls?.breakout || !controls?.breakout) {
277
+ if (!oldLocus.controls?.breakout || !newLocus.controls?.breakout) {
260
278
  return status;
261
279
  }
262
280
 
263
- status.isReturnToMain =
264
- oldControls.breakout.sessionType === BREAKOUTS.SESSION_TYPES.BREAKOUT &&
265
- controls.breakout.sessionType === BREAKOUTS.SESSION_TYPES.MAIN;
281
+ // It is used to fix the timing issue triggered when the creator leaves session to ensure that the member list is complete
282
+ const needUseCache = !!(
283
+ oldLocus.self?.isCreator &&
284
+ newLocus.participants?.length === 1 &&
285
+ newLocus.participants?.[0].isCreator &&
286
+ newLocus.participants?.[0].state === MEETING_STATE.STATES.JOINED &&
287
+ newLocus.controls?.breakout?.sessionType === BREAKOUTS.SESSION_TYPES.MAIN &&
288
+ newLocus.controls?.breakout?.groups?.length
289
+ );
290
+
291
+ const isReturnToMain =
292
+ oldLocus.controls.breakout.sessionType === BREAKOUTS.SESSION_TYPES.BREAKOUT &&
293
+ newLocus.controls.breakout.sessionType === BREAKOUTS.SESSION_TYPES.MAIN;
294
+
295
+ status.isReturnToMain = needUseCache || isReturnToMain;
266
296
  status.isJoinToBreakout =
267
- oldControls.breakout.sessionType === BREAKOUTS.SESSION_TYPES.MAIN &&
268
- controls.breakout.sessionType === BREAKOUTS.SESSION_TYPES.BREAKOUT;
297
+ oldLocus.controls.breakout.sessionType === BREAKOUTS.SESSION_TYPES.MAIN &&
298
+ newLocus.controls.breakout.sessionType === BREAKOUTS.SESSION_TYPES.BREAKOUT;
269
299
 
270
300
  return status;
271
301
  };
@@ -17,7 +17,9 @@ import {
17
17
  MEETING_REMOVED_REASON,
18
18
  CALL_REMOVED_REASON,
19
19
  RECORDING_STATE,
20
+ BREAKOUTS,
20
21
  } from '../constants';
22
+
21
23
  import InfoUtils from './infoUtils';
22
24
  import FullState from './fullState';
23
25
  import SelfUtils from './selfUtils';
@@ -67,6 +69,7 @@ export default class LocusInfo extends EventsScope {
67
69
  services: any;
68
70
  resources: any;
69
71
  mainSessionLocusCache: any;
72
+ self: any;
70
73
  /**
71
74
  * Constructor
72
75
  * @param {function} updateMeeting callback to update the meeting object from an object
@@ -814,6 +817,8 @@ export default class LocusInfo extends EventsScope {
814
817
  hasMeetingFullChanged,
815
818
  hasPracticeSessionEnabledChanged,
816
819
  hasStageViewChanged,
820
+ hasAnnotationControlChanged,
821
+ hasRemoteDesktopControlChanged,
817
822
  },
818
823
  current,
819
824
  } = ControlsUtils.getControls(this.controls, controls);
@@ -1049,6 +1054,22 @@ export default class LocusInfo extends EventsScope {
1049
1054
  );
1050
1055
  }
1051
1056
 
1057
+ if (hasAnnotationControlChanged) {
1058
+ this.emitScoped(
1059
+ {file: 'locus-info', function: 'updateControls'},
1060
+ LOCUSINFO.EVENTS.CONTROLS_ANNOTATION_CHANGED,
1061
+ {state: current.annotationControl}
1062
+ );
1063
+ }
1064
+
1065
+ if (hasRemoteDesktopControlChanged) {
1066
+ this.emitScoped(
1067
+ {file: 'locus-info', function: 'updateControls'},
1068
+ LOCUSINFO.EVENTS.CONTROLS_REMOTE_DESKTOP_CONTROL_CHANGED,
1069
+ {state: current.rdcControl}
1070
+ );
1071
+ }
1072
+
1052
1073
  this.controls = controls;
1053
1074
  }
1054
1075
  }
@@ -1706,7 +1727,8 @@ export default class LocusInfo extends EventsScope {
1706
1727
  * @memberof LocusInfo
1707
1728
  */
1708
1729
  getTheLocusToUpdate(newLocus: any) {
1709
- const switchStatus = ControlsUtils.getSessionSwitchStatus(this.controls, newLocus?.controls);
1730
+ const switchStatus = ControlsUtils.getSessionSwitchStatus(this, newLocus);
1731
+
1710
1732
  if (switchStatus.isReturnToMain && this.mainSessionLocusCache) {
1711
1733
  return cloneDeep(this.mainSessionLocusCache);
1712
1734
  }
@@ -21,6 +21,7 @@ import {MEDIA_TRACK_CONSTRAINT} from '../constants';
21
21
  import Config from '../config';
22
22
  import StaticConfig from '../common/config';
23
23
  import BrowserDetection from '../common/browser-detection';
24
+ import {TurnServerInfo} from '../roap/types';
24
25
 
25
26
  const {isBrowser} = BrowserDetection();
26
27
 
@@ -138,11 +139,7 @@ Media.createMediaConnection = (
138
139
  remoteQualityLevel?: 'LOW' | 'MEDIUM' | 'HIGH';
139
140
  enableRtx?: boolean;
140
141
  enableExtmap?: boolean;
141
- turnServerInfo?: {
142
- url: string;
143
- username: string;
144
- password: string;
145
- };
142
+ turnServerInfo?: TurnServerInfo;
146
143
  bundlePolicy?: BundlePolicy;
147
144
  iceCandidatesTimeout?: number;
148
145
  }
@@ -160,24 +157,11 @@ Media.createMediaConnection = (
160
157
 
161
158
  const iceServers = [];
162
159
 
163
- // we might not have any TURN server if TURN discovery failed or wasn't done or
164
- // we might get an empty TURN url if we land on a video mesh node
165
- if (turnServerInfo?.url) {
166
- if (!isBrowser('firefox')) {
167
- let bareTurnServer = turnServerInfo.url;
168
- bareTurnServer = bareTurnServer.replace('turns:', 'turn:');
169
- bareTurnServer = bareTurnServer.replace('443', '5004');
170
-
171
- iceServers.push({
172
- urls: bareTurnServer,
173
- username: turnServerInfo.username || '',
174
- credential: turnServerInfo.password || '',
175
- });
176
- }
177
-
160
+ // we might not have any TURN server if TURN discovery failed or wasn't done or we land on a video mesh node
161
+ if (turnServerInfo?.urls.length > 0) {
178
162
  // TURN-TLS server
179
163
  iceServers.push({
180
- urls: turnServerInfo.url,
164
+ urls: turnServerInfo.urls,
181
165
  username: turnServerInfo.username || '',
182
166
  credential: turnServerInfo.password || '',
183
167
  });