@webex/plugin-meetings 3.8.1-web-workers-keepalive.1 → 3.9.0-next.1

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 (87) hide show
  1. package/dist/breakouts/breakout.js +1 -1
  2. package/dist/breakouts/index.js +1 -1
  3. package/dist/constants.js +24 -2
  4. package/dist/constants.js.map +1 -1
  5. package/dist/interpretation/index.js +1 -1
  6. package/dist/interpretation/siLanguage.js +1 -1
  7. package/dist/locus-info/index.js +39 -85
  8. package/dist/locus-info/index.js.map +1 -1
  9. package/dist/meeting/brbState.js +14 -12
  10. package/dist/meeting/brbState.js.map +1 -1
  11. package/dist/meeting/in-meeting-actions.js +6 -0
  12. package/dist/meeting/in-meeting-actions.js.map +1 -1
  13. package/dist/meeting/index.js +274 -140
  14. package/dist/meeting/index.js.map +1 -1
  15. package/dist/meeting/request.js +19 -0
  16. package/dist/meeting/request.js.map +1 -1
  17. package/dist/meeting/request.type.js.map +1 -1
  18. package/dist/meeting/type.js +7 -0
  19. package/dist/meeting/type.js.map +1 -0
  20. package/dist/meeting/util.js +68 -2
  21. package/dist/meeting/util.js.map +1 -1
  22. package/dist/meetings/index.js +35 -33
  23. package/dist/meetings/index.js.map +1 -1
  24. package/dist/member/index.js.map +1 -1
  25. package/dist/members/index.js +11 -9
  26. package/dist/members/index.js.map +1 -1
  27. package/dist/members/request.js +3 -3
  28. package/dist/members/request.js.map +1 -1
  29. package/dist/members/util.js +18 -6
  30. package/dist/members/util.js.map +1 -1
  31. package/dist/multistream/mediaRequestManager.js +1 -1
  32. package/dist/multistream/mediaRequestManager.js.map +1 -1
  33. package/dist/multistream/remoteMedia.js +34 -5
  34. package/dist/multistream/remoteMedia.js.map +1 -1
  35. package/dist/multistream/remoteMediaGroup.js +42 -2
  36. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  37. package/dist/multistream/sendSlotManager.js +32 -2
  38. package/dist/multistream/sendSlotManager.js.map +1 -1
  39. package/dist/types/constants.d.ts +22 -0
  40. package/dist/types/locus-info/index.d.ts +0 -9
  41. package/dist/types/meeting/brbState.d.ts +0 -1
  42. package/dist/types/meeting/in-meeting-actions.d.ts +6 -0
  43. package/dist/types/meeting/index.d.ts +40 -19
  44. package/dist/types/meeting/request.d.ts +9 -1
  45. package/dist/types/meeting/request.type.d.ts +74 -0
  46. package/dist/types/meeting/type.d.ts +9 -0
  47. package/dist/types/meeting/util.d.ts +3 -0
  48. package/dist/types/members/index.d.ts +10 -7
  49. package/dist/types/members/request.d.ts +1 -1
  50. package/dist/types/members/util.d.ts +7 -3
  51. package/dist/types/multistream/remoteMedia.d.ts +20 -1
  52. package/dist/types/multistream/remoteMediaGroup.d.ts +11 -0
  53. package/dist/types/multistream/sendSlotManager.d.ts +16 -0
  54. package/dist/webinar/index.js +1 -1
  55. package/package.json +22 -23
  56. package/src/constants.ts +23 -2
  57. package/src/locus-info/index.ts +48 -86
  58. package/src/meeting/brbState.ts +9 -7
  59. package/src/meeting/in-meeting-actions.ts +13 -0
  60. package/src/meeting/index.ts +165 -38
  61. package/src/meeting/request.ts +16 -0
  62. package/src/meeting/request.type.ts +64 -0
  63. package/src/meeting/type.ts +9 -0
  64. package/src/meeting/util.ts +73 -2
  65. package/src/meetings/index.ts +3 -2
  66. package/src/member/index.ts +1 -0
  67. package/src/members/index.ts +13 -10
  68. package/src/members/request.ts +2 -2
  69. package/src/members/util.ts +16 -4
  70. package/src/multistream/mediaRequestManager.ts +7 -7
  71. package/src/multistream/remoteMedia.ts +34 -4
  72. package/src/multistream/remoteMediaGroup.ts +37 -2
  73. package/src/multistream/sendSlotManager.ts +34 -2
  74. package/test/unit/spec/locus-info/index.js +199 -83
  75. package/test/unit/spec/meeting/brbState.ts +9 -9
  76. package/test/unit/spec/meeting/in-meeting-actions.ts +6 -0
  77. package/test/unit/spec/meeting/index.js +729 -80
  78. package/test/unit/spec/meeting/request.js +71 -0
  79. package/test/unit/spec/meeting/utils.js +122 -1
  80. package/test/unit/spec/meetings/index.js +2 -0
  81. package/test/unit/spec/members/index.js +68 -9
  82. package/test/unit/spec/members/request.js +2 -2
  83. package/test/unit/spec/members/utils.js +27 -7
  84. package/test/unit/spec/multistream/mediaRequestManager.ts +19 -6
  85. package/test/unit/spec/multistream/remoteMedia.ts +66 -2
  86. package/test/unit/spec/multistream/sendSlotManager.ts +59 -0
  87. package/test/unit/spec/reachability/index.ts +3 -1
@@ -0,0 +1,9 @@
1
+ export type Invitee = {
2
+ memberId: string;
3
+ emailAddress: string;
4
+ email: string;
5
+ phoneNumber: string;
6
+ roles: Array<string>;
7
+ skipEmailValidation?: boolean;
8
+ isInternalNumber?: boolean;
9
+ };
@@ -71,6 +71,9 @@ declare const MeetingUtil: {
71
71
  canStopTranscribing: (displayHints: any) => any;
72
72
  isClosedCaptionActive: (displayHints: any) => any;
73
73
  canStartManualCaption: (displayHints: any) => any;
74
+ isLocalRecordingStarted: (displayHints: any) => any;
75
+ isLocalRecordingStopped: (displayHints: any) => any;
76
+ isLocalRecordingPaused: (displayHints: any) => any;
74
77
  canStopManualCaption: (displayHints: any) => any;
75
78
  isManualCaptionActive: (displayHints: any) => any;
76
79
  isWebexAssistantActive: (displayHints: any) => any;
@@ -4,6 +4,7 @@ import MembersCollection from './collection';
4
4
  import { ReceiveSlotManager } from '../multistream/receiveSlotManager';
5
5
  import { MediaRequestManager } from '../multistream/mediaRequestManager';
6
6
  import { ServerRoleShape } from './types';
7
+ import { Invitee } from '../meeting/type';
7
8
  /**
8
9
  * @class Members
9
10
  */
@@ -212,26 +213,28 @@ export default class Members extends StatelessWebexPlugin {
212
213
  private update;
213
214
  /**
214
215
  * Adds a guest Member to the associated meeting
215
- * @param {String} invitee
216
+ * @param {Invitee} invitee
216
217
  * @param {Boolean} [alertIfActive]
217
218
  * @returns {Promise}
218
219
  * @memberof Members
219
220
  */
220
- addMember(invitee: any, alertIfActive?: boolean): any;
221
+ addMember(invitee: Invitee, alertIfActive?: boolean): any;
221
222
  /**
222
223
  * Cancels an outgoing PSTN call to the associated meeting
223
- * @param {String} invitee
224
+ * @param {Invitee} invitee
224
225
  * @returns {Promise}
225
226
  * @memberof Members
226
227
  */
227
- cancelPhoneInvite(invitee: any): any;
228
+ cancelPhoneInvite(invitee: Invitee): any;
228
229
  /**
229
- * Cancels an SIP call to the associated meeting
230
- * @param {String} invitee
230
+ * Cancels an SIP/phone call to the associated meeting
231
+ * @param {Invitee} invitee
232
+ * @param {String} invitee.memberId - The memberId of the invitee
233
+ * @param {Boolean} [invitee.isInternalNumber] - When cancel phone invitation, if the number is internal
231
234
  * @returns {Promise}
232
235
  * @memberof Members
233
236
  */
234
- cancelSIPInvite(invitee: any): any;
237
+ cancelInviteByMemberId(invitee: Invitee): any;
235
238
  /**
236
239
  * Admits waiting members (invited guests to meeting)
237
240
  * @param {Array} memberIds
@@ -136,5 +136,5 @@ export default class MembersRequest extends StatelessWebexPlugin {
136
136
  * @throws {Error} if the options are not valid and complete, must have invitee with memberId AND locusUrl
137
137
  * @memberof MembersRequest
138
138
  */
139
- cancelSIPInvite(options: any): Promise<any>;
139
+ cancelInviteByMemberId(options: any): Promise<any>;
140
140
  }
@@ -1,4 +1,5 @@
1
1
  import { RoleAssignmentOptions, RoleAssignmentRequest, ServerRoleShape } from './types';
2
+ import { Invitee } from '../meeting/type';
2
3
  declare const MembersUtil: {
3
4
  /**
4
5
  * @param {Object} invitee with emailAddress, email or phoneNumber
@@ -26,6 +27,7 @@ declare const MembersUtil: {
26
27
  */
27
28
  getAddMemberBody: (options: any) => {
28
29
  invitees: {
30
+ isInternalNumber?: any;
29
31
  roles?: any;
30
32
  address: any;
31
33
  }[];
@@ -55,13 +57,14 @@ declare const MembersUtil: {
55
57
  uri: any;
56
58
  body: {
57
59
  invitees: {
60
+ isInternalNumber?: any;
58
61
  roles?: any;
59
62
  address: any;
60
63
  }[];
61
64
  alertIfActive: any;
62
65
  };
63
66
  };
64
- isInvalidInvitee: (invitee: any) => boolean;
67
+ isInvalidInvitee: (invitee: Invitee) => boolean;
65
68
  getRemoveMemberRequestParams: (options: any) => {
66
69
  method: string;
67
70
  uri: string;
@@ -228,16 +231,17 @@ declare const MembersUtil: {
228
231
  }[];
229
232
  };
230
233
  };
231
- cancelSIPInviteOptions: (invitee: any, locusUrl: any) => {
234
+ cancelInviteByMemberIdOptions: (invitee: any, locusUrl: any) => {
232
235
  invitee: any;
233
236
  locusUrl: any;
234
237
  };
235
- generateCancelSIPInviteRequestParams: (options: any) => {
238
+ generateCancelInviteByMemberIdRequestParams: (options: any) => {
236
239
  method: string;
237
240
  uri: any;
238
241
  body: {
239
242
  actionType: string;
240
243
  invitees: {
244
+ isInternalNumber?: any;
241
245
  address: any;
242
246
  }[];
243
247
  };
@@ -7,9 +7,17 @@ export declare const RemoteMediaEvents: {
7
7
  Stopped: string;
8
8
  };
9
9
  export type RemoteVideoResolution = 'thumbnail' | 'very small' | 'small' | 'medium' | 'large' | 'best';
10
+ export declare const MAX_FS_VALUES: {
11
+ '90p': number;
12
+ '180p': number;
13
+ '360p': number;
14
+ '540p': number;
15
+ '720p': number;
16
+ '1080p': number;
17
+ };
10
18
  /**
11
19
  * Converts pane size into h264 maxFs
12
- * @param {PaneSize} paneSize
20
+ * @param {RemoteVideoResolution} paneSize
13
21
  * @returns {number}
14
22
  */
15
23
  export declare function getMaxFs(paneSize: RemoteVideoResolution): number;
@@ -29,6 +37,12 @@ export declare class RemoteMedia extends EventsScope {
29
37
  private readonly options;
30
38
  private mediaRequestId?;
31
39
  readonly id: RemoteMediaId;
40
+ /**
41
+ * The max frame size of the media request, used for logging and media requests.
42
+ * Set by setSizeHint() based on video element dimensions.
43
+ * When > 0, this value takes precedence over options.resolution in sendMediaRequest().
44
+ */
45
+ private maxFrameSize;
32
46
  /**
33
47
  * Constructs RemoteMedia instance
34
48
  *
@@ -45,6 +59,11 @@ export declare class RemoteMedia extends EventsScope {
45
59
  * @note width/height of 0 will be ignored
46
60
  */
47
61
  setSizeHint(width: any, height: any): void;
62
+ /**
63
+ * Get the current effective maxFs value that would be used in media requests
64
+ * @returns {number | undefined} The maxFs value, or undefined if no constraints
65
+ */
66
+ getEffectiveMaxFs(): number | undefined;
48
67
  /**
49
68
  * registers event listeners on the receive slot and forwards all the events
50
69
  */
@@ -45,5 +45,16 @@ export declare class RemoteMediaGroup {
45
45
  * @returns true if remote media is found
46
46
  */
47
47
  includes(remoteMedia: RemoteMedia, filter?: 'all' | 'pinned' | 'unpinned'): boolean;
48
+ /**
49
+ * Calculate the effective maxFs for the active speaker media request based on unpinned RemoteMedia instances
50
+ * @returns {number | undefined} The calculated maxFs value, or undefined if no constraints
51
+ * @private
52
+ */
53
+ private getEffectiveMaxFsForActiveSpeaker;
54
+ /**
55
+ * Get the current effective maxFs that would be used for the active speaker media request
56
+ * @returns {number | undefined} The effective maxFs value
57
+ */
58
+ getEffectiveMaxFs(): number | undefined;
48
59
  }
49
60
  export {};
@@ -1,7 +1,17 @@
1
1
  import { SendSlot, MediaType, LocalStream, MultistreamRoapMediaConnection, NamedMediaGroup, StreamState } from '@webex/internal-media-core';
2
+ /**
3
+ * This class is used to manage the sendSlots for the given media types.
4
+ */
2
5
  export default class SendSlotManager {
3
6
  private readonly slots;
4
7
  private readonly LoggerProxy;
8
+ private readonly sourceStateOverrides;
9
+ /**
10
+ * Constructor for SendSlotManager
11
+ *
12
+ * @param {any} LoggerProxy is used to log the messages
13
+ * @constructor
14
+ */
5
15
  constructor(LoggerProxy: any);
6
16
  /**
7
17
  * This method is used to create a sendSlot for the given mediaType and returns the created sendSlot
@@ -32,6 +42,12 @@ export default class SendSlotManager {
32
42
  * @returns {void}
33
43
  */
34
44
  setSourceStateOverride(mediaType: MediaType, state: StreamState | null): void;
45
+ /**
46
+ * Gets the source state override for the given media type.
47
+ * @param {MediaType} mediaType - The type of media to get the source state override for.
48
+ * @returns {StreamState | null} - The current source state override or null if not set.
49
+ */
50
+ private getSourceStateOverride;
35
51
  /**
36
52
  * This method publishes the given stream to the sendSlot for the given mediaType
37
53
  * @param {MediaType} mediaType MediaType of the sendSlot to which a stream needs to be published (AUDIO_MAIN/VIDEO_MAIN/AUDIO_SLIDES/VIDEO_SLIDES)
@@ -458,7 +458,7 @@ var Webinar = _webexCore.WebexPlugin.extend({
458
458
  }, _callee7);
459
459
  }))();
460
460
  },
461
- version: "3.8.1-web-workers-keepalive.1"
461
+ version: "3.9.0-next.1"
462
462
  });
463
463
  var _default = exports.default = Webinar;
464
464
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@webex/plugin-meetings",
3
3
  "description": "",
4
- "license": "Cisco EULA (https://www.cisco.com/c/en/us/products/end-user-license-agreement.html)",
4
+ "license": "Cisco's General Terms (https://www.cisco.com/site/us/en/about/legal/contract-experience/index.html)",
5
5
  "contributors": [
6
6
  "Adam Weeks <adweeks@cisco.com> (https://adamweeks.com/)",
7
7
  "Arun Ganeshan <arungane@cisco.com>",
@@ -43,13 +43,12 @@
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.1-web-workers-keepalive.1",
47
- "@webex/plugin-rooms": "3.8.1-web-workers-keepalive.1",
48
- "@webex/test-helper-chai": "3.8.1-web-workers-keepalive.1",
49
- "@webex/test-helper-mocha": "3.8.1-web-workers-keepalive.1",
50
- "@webex/test-helper-mock-webex": "3.8.1-web-workers-keepalive.1",
51
- "@webex/test-helper-retry": "3.8.1-web-workers-keepalive.1",
52
- "@webex/test-helper-test-users": "3.8.1-web-workers-keepalive.1",
46
+ "@webex/plugin-rooms": "3.8.1-next.15",
47
+ "@webex/test-helper-chai": "3.8.1-next.11",
48
+ "@webex/test-helper-mocha": "3.8.1-next.11",
49
+ "@webex/test-helper-mock-webex": "3.8.1-next.11",
50
+ "@webex/test-helper-retry": "3.8.1-next.11",
51
+ "@webex/test-helper-test-users": "3.8.1-next.11",
53
52
  "chai": "^4.3.4",
54
53
  "chai-as-promised": "^7.1.1",
55
54
  "eslint": "^8.24.0",
@@ -61,23 +60,23 @@
61
60
  "typescript": "^4.7.4"
62
61
  },
63
62
  "dependencies": {
64
- "@webex/common": "3.8.1-web-workers-keepalive.1",
63
+ "@webex/common": "3.8.1-next.11",
65
64
  "@webex/event-dictionary-ts": "^1.0.1819",
66
- "@webex/internal-media-core": "2.18.3",
67
- "@webex/internal-plugin-conversation": "3.8.1-web-workers-keepalive.1",
68
- "@webex/internal-plugin-device": "3.8.1-web-workers-keepalive.1",
69
- "@webex/internal-plugin-llm": "3.8.1-web-workers-keepalive.1",
70
- "@webex/internal-plugin-mercury": "3.8.1-web-workers-keepalive.1",
71
- "@webex/internal-plugin-metrics": "3.8.1-web-workers-keepalive.1",
72
- "@webex/internal-plugin-support": "3.8.1-web-workers-keepalive.1",
73
- "@webex/internal-plugin-user": "3.8.1-web-workers-keepalive.1",
74
- "@webex/internal-plugin-voicea": "3.8.1-web-workers-keepalive.1",
75
- "@webex/media-helpers": "3.8.1-web-workers-keepalive.1",
76
- "@webex/plugin-people": "3.8.1-web-workers-keepalive.1",
77
- "@webex/plugin-rooms": "3.8.1-web-workers-keepalive.1",
65
+ "@webex/internal-media-core": "2.18.5",
66
+ "@webex/internal-plugin-conversation": "3.8.1-next.18",
67
+ "@webex/internal-plugin-device": "3.8.1-next.15",
68
+ "@webex/internal-plugin-llm": "3.8.1-next.16",
69
+ "@webex/internal-plugin-mercury": "3.8.1-next.15",
70
+ "@webex/internal-plugin-metrics": "3.8.1-next.15",
71
+ "@webex/internal-plugin-support": "3.8.1-next.18",
72
+ "@webex/internal-plugin-user": "3.8.1-next.15",
73
+ "@webex/internal-plugin-voicea": "3.8.1-next.42",
74
+ "@webex/media-helpers": "3.8.1-next.16",
75
+ "@webex/plugin-people": "3.8.1-next.15",
76
+ "@webex/plugin-rooms": "3.8.1-next.15",
78
77
  "@webex/ts-sdp": "^1.8.1",
79
78
  "@webex/web-capabilities": "^1.6.0",
80
- "@webex/webex-core": "3.8.1-web-workers-keepalive.1",
79
+ "@webex/webex-core": "3.8.1-next.15",
81
80
  "ampersand-collection": "^2.0.2",
82
81
  "bowser": "^2.11.0",
83
82
  "btoa": "^1.2.1",
@@ -93,5 +92,5 @@
93
92
  "//": [
94
93
  "TODO: upgrade jwt-decode when moving to node 18"
95
94
  ],
96
- "version": "3.8.1-web-workers-keepalive.1"
95
+ "version": "3.9.0-next.1"
97
96
  }
package/src/constants.ts CHANGED
@@ -217,6 +217,7 @@ export const DIALER_REGEX = {
217
217
  PHONE_NUMBER:
218
218
  /^(?:(?:\+?1\s*(?:[.-]\s*)?)?(?:\(\s*([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9])\s*\)|([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]))\s*(?:[.-]\s*)?)?([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]{2})\s*(?:[.-]\s*)?([0-9]{4})(?:\s*(?:#|x\.?|ext\.?|extension)\s*(\d+))?$/,
219
219
  E164_FORMAT: /^\+[1-9]\d{1,14}$/,
220
+ INTERNAL_NUMBER: /^\d{1,14}$/,
220
221
  };
221
222
 
222
223
  // eslint-disable-next-line max-len
@@ -262,7 +263,6 @@ export const RECORDING_STATE = {
262
263
  PAUSED: 'paused',
263
264
  RESUMED: 'resumed',
264
265
  };
265
-
266
266
  export const SHARE_STATUS = {
267
267
  NO_SHARE: 'no_share',
268
268
  REMOTE_SHARE_ACTIVE: 'remote_share_active',
@@ -948,6 +948,9 @@ export const DISPLAY_HINTS = {
948
948
  PREMISE_RECORDING_CONTROL_PAUSE: 'PREMISE_RECORDING_CONTROL_PAUSE',
949
949
  PREMISE_RECORDING_CONTROL_STOP: 'PREMISE_RECORDING_CONTROL_STOP',
950
950
  PREMISE_RECORDING_CONTROL_RESUME: 'PREMISE_RECORDING_CONTROL_RESUME',
951
+ LOCAL_RECORDING_STATUS_STARTED: 'LOCAL_RECORDING_STATUS_STARTED',
952
+ LOCAL_RECORDING_STATUS_STOPPED: 'LOCAL_RECORDING_STATUS_STOPPED',
953
+ LOCAL_RECORDING_STATUS_PAUSED: 'LOCAL_RECORDING_STATUS_PAUSED',
951
954
  LOCK_CONTROL_UNLOCK: 'LOCK_CONTROL_UNLOCK',
952
955
  LOCK_CONTROL_LOCK: 'LOCK_CONTROL_LOCK',
953
956
  LOCK_STATUS_LOCKED: 'LOCK_STATUS_LOCKED',
@@ -987,7 +990,6 @@ export const DISPLAY_HINTS = {
987
990
  CAN_RENAME_SELF_AND_OBSERVED: 'CAN_RENAME_SELF_AND_OBSERVED',
988
991
  CAN_RENAME_OTHERS: 'CAN_RENAME_OTHERS',
989
992
  MOVE_TO_LOBBY: 'MOVE_TO_LOBBY',
990
-
991
993
  // breakout session
992
994
  BREAKOUT_MANAGEMENT: 'BREAKOUT_MANAGEMENT',
993
995
  BROADCAST_MESSAGE_TO_BREAKOUT: 'BROADCAST_MESSAGE_TO_BREAKOUT',
@@ -1188,6 +1190,7 @@ export const QUALITY_LEVELS = {
1188
1190
  HIGH: 'HIGH',
1189
1191
  '360p': '360p',
1190
1192
  '480p': '480p',
1193
+ '540p': '540p',
1191
1194
  '720p': '720p',
1192
1195
  '1080p': '1080p',
1193
1196
  };
@@ -1217,6 +1220,18 @@ export const AVAILABLE_RESOLUTIONS = {
1217
1220
  },
1218
1221
  },
1219
1222
  },
1223
+ '540p': {
1224
+ video: {
1225
+ width: {
1226
+ max: 960,
1227
+ ideal: 960,
1228
+ },
1229
+ height: {
1230
+ max: 540,
1231
+ ideal: 540,
1232
+ },
1233
+ },
1234
+ },
1220
1235
  '720p': {
1221
1236
  video: {
1222
1237
  width: {
@@ -1357,3 +1372,9 @@ export const INITIAL_REGISTRATION_STATUS = {
1357
1372
  mercuryConnect: false,
1358
1373
  checkH264Support: false,
1359
1374
  };
1375
+
1376
+ export const STAGE_MANAGER_TYPE = {
1377
+ LOGO: 0b001,
1378
+ BACKGROUND: 0b010,
1379
+ NAME_LABEL: 0b100,
1380
+ };
@@ -48,7 +48,6 @@ export default class LocusInfo extends EventsScope {
48
48
  aclUrl: any;
49
49
  baseSequence: any;
50
50
  created: any;
51
- deltaParticipants: any;
52
51
  identities: any;
53
52
  membership: any;
54
53
  participants: any;
@@ -99,6 +98,7 @@ export default class LocusInfo extends EventsScope {
99
98
  private doLocusSync(meeting: any) {
100
99
  let isDelta;
101
100
  let url;
101
+ let meetingDestroyed = false;
102
102
 
103
103
  if (this.locusParser.workingCopy.syncUrl) {
104
104
  url = this.locusParser.workingCopy.syncUrl;
@@ -134,32 +134,56 @@ export default class LocusInfo extends EventsScope {
134
134
 
135
135
  isDelta = false;
136
136
 
137
- return meeting.meetingRequest.getLocusDTO({url: meeting.locusUrl}).catch((err) => {
138
- LoggerProxy.logger.info(
139
- 'Locus-info:index#doLocusSync --> fallback full sync failed, destroying the meeting'
140
- );
141
- this.webex.meetings.destroy(meeting, MEETING_REMOVED_REASON.LOCUS_DTO_SYNC_FAILED);
142
- throw err;
143
- });
137
+ // Locus sometimes returns 403, for example if meeting has ended, no point trying the fallback to full sync in that case
138
+ if (e.statusCode !== 403) {
139
+ return meeting.meetingRequest.getLocusDTO({url: meeting.locusUrl}).catch((err) => {
140
+ LoggerProxy.logger.info(
141
+ 'Locus-info:index#doLocusSync --> fallback full sync failed, destroying the meeting'
142
+ );
143
+ this.webex.meetings.destroy(meeting, MEETING_REMOVED_REASON.LOCUS_DTO_SYNC_FAILED);
144
+ meetingDestroyed = true;
145
+ throw err;
146
+ });
147
+ }
148
+ LoggerProxy.logger.info(
149
+ 'Locus-info:index#doLocusSync --> got 403 from Locus, skipping fallback to full sync, destroying the meeting'
150
+ );
151
+ } else {
152
+ LoggerProxy.logger.info(
153
+ 'Locus-info:index#doLocusSync --> fallback full sync failed, destroying the meeting'
154
+ );
144
155
  }
145
- LoggerProxy.logger.info(
146
- 'Locus-info:index#doLocusSync --> fallback full sync failed, destroying the meeting'
147
- );
148
156
  this.webex.meetings.destroy(meeting, MEETING_REMOVED_REASON.LOCUS_DTO_SYNC_FAILED);
157
+ meetingDestroyed = true;
149
158
  throw e;
150
159
  })
151
160
  .then((res) => {
152
- if (isDelta) {
153
- if (!isEmpty(res.body)) {
154
- meeting.locusInfo.handleLocusDelta(res.body, meeting);
155
- } else {
161
+ if (isEmpty(res.body)) {
162
+ if (isDelta) {
156
163
  LoggerProxy.logger.info(
157
164
  'Locus-info:index#doLocusSync --> received empty body from syncUrl, so we already have latest Locus DTO'
158
165
  );
166
+ } else {
167
+ LoggerProxy.logger.info(
168
+ 'Locus-info:index#doLocusSync --> received empty body from full DTO sync request'
169
+ );
159
170
  }
160
- } else {
161
- meeting.locusInfo.onFullLocus(res.body);
171
+
172
+ return;
173
+ }
174
+
175
+ if (isDelta) {
176
+ if (res.body.baseSequence) {
177
+ meeting.locusInfo.handleLocusDelta(res.body, meeting);
178
+
179
+ return;
180
+ }
181
+ // in some cases Locus might return us full DTO even when we asked for a delta
182
+ LoggerProxy.logger.info(
183
+ 'Locus-info:index#doLocusSync --> got full DTO when we asked for delta'
184
+ );
162
185
  }
186
+ meeting.locusInfo.onFullLocus(res.body);
163
187
  })
164
188
  .catch((e) => {
165
189
  LoggerProxy.logger.info(
@@ -176,9 +200,11 @@ export default class LocusInfo extends EventsScope {
176
200
  });
177
201
  })
178
202
  .finally(() => {
179
- // Notify parser to resume processing delta events.
180
- // Any deltas in the queue that have now been superseded by this sync will simply be ignored
181
- this.locusParser.resume();
203
+ if (!meetingDestroyed) {
204
+ // Notify parser to resume processing delta events.
205
+ // Any deltas in the queue that have now been superseded by this sync will simply be ignored
206
+ this.locusParser.resume();
207
+ }
182
208
  });
183
209
  }
184
210
 
@@ -257,17 +283,6 @@ export default class LocusInfo extends EventsScope {
257
283
  * @property {Object} person - Contains person data.
258
284
  */
259
285
 
260
- /**
261
- * Stored participant changes between the last event and the current event.
262
- * All previously stored events are overwritten between events.
263
- *
264
- * @instance
265
- * @type {Array<DeltaParticipant>}
266
- * @private
267
- * @member LocusInfo
268
- */
269
- this.deltaParticipants = [];
270
-
271
286
  this.updateLocusCache(locus);
272
287
  // above section only updates the locusInfo object
273
288
  // The below section makes sure it updates the locusInfo as well as updates the meeting object
@@ -373,7 +388,6 @@ export default class LocusInfo extends EventsScope {
373
388
  return;
374
389
  }
375
390
 
376
- this.updateParticipantDeltas(locus.participants);
377
391
  this.scheduledMeeting = locus.meeting || null;
378
392
  this.participants = locus.participants;
379
393
  const isReplaceMembers = ControlsUtils.isNeedReplaceMembers(this.controls, locus.controls);
@@ -462,12 +476,12 @@ export default class LocusInfo extends EventsScope {
462
476
  this.updateCreated(locus.created);
463
477
  this.updateFullState(locus.fullState);
464
478
  this.updateHostInfo(locus.host);
479
+ this.updateLocusUrl(locus.url);
465
480
  this.updateMeetingInfo(locus.info, locus.self);
466
481
  this.updateMediaShares(locus.mediaShares);
467
482
  this.updateParticipantsUrl(locus.participantsUrl);
468
483
  this.updateReplace(locus.replace);
469
484
  this.updateSelf(locus.self);
470
- this.updateLocusUrl(locus.url);
471
485
  this.updateAclUrl(locus.aclUrl);
472
486
  this.updateBasequence(locus.baseSequence);
473
487
  this.updateSequence(locus.sequence);
@@ -728,55 +742,6 @@ export default class LocusInfo extends EventsScope {
728
742
  }
729
743
  }
730
744
 
731
- /**
732
- * Update the deltaParticipants property of this object based on a list of
733
- * provided participants.
734
- *
735
- * @param {Array} [participants] - The participants to update against.
736
- * @returns {void}
737
- */
738
- updateParticipantDeltas(participants: Array<any> = []) {
739
- // Used to find a participant within a participants collection.
740
- const findParticipant = (participant, collection) =>
741
- collection.find((item) => item.person.id === participant.person.id);
742
-
743
- // Generates an object that indicates which state properties have changed.
744
- const generateDelta = (prevState: any = {}, newState: any = {}) => {
745
- // Setup deltas.
746
- const deltas = {
747
- audioStatus: prevState.audioStatus !== newState.audioStatus,
748
- videoSlidesStatus: prevState.videoSlidesStatus !== newState.videoSlidesStatus,
749
- videoStatus: prevState.videoStatus !== newState.videoStatus,
750
- };
751
-
752
- // Clean the object
753
- Object.keys(deltas).forEach((key) => {
754
- if (deltas[key] !== true) {
755
- delete deltas[key];
756
- }
757
- });
758
-
759
- return deltas;
760
- };
761
-
762
- this.deltaParticipants = participants.reduce((collection, participant) => {
763
- const existingParticipant = findParticipant(participant, this.participants || []) || {};
764
-
765
- const delta = generateDelta(existingParticipant.status, participant.status);
766
-
767
- const changed = Object.keys(delta).length > 0;
768
-
769
- if (changed) {
770
- collection.push({
771
- person: participant.person,
772
- delta,
773
- });
774
- }
775
-
776
- return collection;
777
- }, []);
778
- }
779
-
780
745
  /**
781
746
  * update meeting's members
782
747
  * @param {Object} participants new participants object
@@ -1289,10 +1254,7 @@ export default class LocusInfo extends EventsScope {
1289
1254
  */
1290
1255
  updateMeetingInfo(info: object, self?: object) {
1291
1256
  const roles = self ? SelfUtils.getRoles(self) : this.parsedLocus.self?.roles || [];
1292
- if (
1293
- (info && !isEqual(this.info, info)) ||
1294
- (roles.length && !isEqual(this.roles, roles) && info)
1295
- ) {
1257
+ if ((info && !isEqual(this.info, info)) || (!isEqual(this.roles, roles) && info)) {
1296
1258
  const isJoined = SelfUtils.isJoined(self || this.parsedLocus.self);
1297
1259
  const parsedInfo = InfoUtils.getInfos(this.parsedLocus.info, info, roles, isJoined);
1298
1260
 
@@ -58,7 +58,13 @@ export class BrbState {
58
58
  public enable(enabled: boolean, sendSlotManager: SendSlotManager) {
59
59
  this.state.client.enabled = enabled;
60
60
 
61
- return this.applyClientStateToServer(sendSlotManager);
61
+ // Don't set the source state override if enabling brb fails
62
+ return this.applyClientStateToServer(sendSlotManager).then(() => {
63
+ sendSlotManager.setSourceStateOverride(
64
+ MediaType.VideoMain,
65
+ this.state.client.enabled ? 'away' : null
66
+ );
67
+ });
62
68
  }
63
69
 
64
70
  /**
@@ -92,7 +98,7 @@ export class BrbState {
92
98
 
93
99
  this.state.syncToServerInProgress = true;
94
100
 
95
- return this.sendLocalBrbStateToServer(sendSlotManager)
101
+ return this.sendLocalBrbStateToServer()
96
102
  .then(() => {
97
103
  this.state.syncToServerInProgress = false;
98
104
 
@@ -120,10 +126,9 @@ export class BrbState {
120
126
  /**
121
127
  * Send the local brb state to the server
122
128
  *
123
- * @param {SendSlotManager} sendSlotManager
124
129
  * @returns {Promise}
125
130
  */
126
- private async sendLocalBrbStateToServer(sendSlotManager: SendSlotManager) {
131
+ private async sendLocalBrbStateToServer() {
127
132
  const {enabled} = this.state.client;
128
133
 
129
134
  if (!this.meeting.isMultistream) {
@@ -153,9 +158,6 @@ export class BrbState {
153
158
  deviceUrl: this.meeting.deviceUrl,
154
159
  selfId: this.meeting.selfId,
155
160
  })
156
- .then(() => {
157
- sendSlotManager.setSourceStateOverride(MediaType.VideoMain, enabled ? 'away' : null);
158
- })
159
161
  .catch((error) => {
160
162
  LoggerProxy.logger.error('Meeting:brbState#sendLocalBrbStateToServer: Error ', error);
161
163
 
@@ -38,6 +38,10 @@ interface IInMeetingActions {
38
38
  isClosedCaptionActive?: boolean;
39
39
  canStartManualCaption?: boolean;
40
40
  canStopManualCaption?: boolean;
41
+ isLocalRecordingStarted?: boolean;
42
+ isLocalRecordingStopped?: boolean;
43
+ isLocalRecordingPaused?: boolean;
44
+
41
45
  isManualCaptionActive?: boolean;
42
46
  isSaveTranscriptsEnabled?: boolean;
43
47
  isWebexAssistantActive?: boolean;
@@ -173,6 +177,12 @@ export default class InMeetingActions implements IInMeetingActions {
173
177
 
174
178
  canStopManualCaption = null;
175
179
 
180
+ isLocalRecordingStopped = null;
181
+
182
+ isLocalRecordingStarted = null;
183
+
184
+ isLocalRecordingPaused = null;
185
+
176
186
  isManualCaptionActive = null;
177
187
 
178
188
  isSaveTranscriptsEnabled = null;
@@ -347,6 +357,9 @@ export default class InMeetingActions implements IInMeetingActions {
347
357
  canStopTranscribing: this.canStopTranscribing,
348
358
  isClosedCaptionActive: this.isClosedCaptionActive,
349
359
  canStartManualCaption: this.canStartManualCaption,
360
+ isLocalRecordingStarted: this.isLocalRecordingStarted,
361
+ isLocalRecordingStopped: this.isLocalRecordingStopped,
362
+ isLocalRecordingPaused: this.isLocalRecordingPaused,
350
363
  canStopManualCaption: this.canStopManualCaption,
351
364
  isManualCaptionActive: this.isManualCaptionActive,
352
365
  isSaveTranscriptsEnabled: this.isSaveTranscriptsEnabled,