@webex/plugin-meetings 3.0.0-beta.157 → 3.0.0-beta.159

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.
@@ -160,7 +160,7 @@ export type AddMediaOptions = {
160
160
 
161
161
  export const MEDIA_UPDATE_TYPE = {
162
162
  TRANSCODED_MEDIA_CONNECTION: 'TRANSCODED_MEDIA_CONNECTION',
163
- LAMBDA: 'LAMBDA',
163
+ SHARE_FLOOR_REQUEST: 'SHARE_FLOOR_REQUEST',
164
164
  UPDATE_MEDIA: 'UPDATE_MEDIA',
165
165
  };
166
166
 
@@ -1213,6 +1213,16 @@ export default class Meeting extends StatelessWebexPlugin {
1213
1213
  };
1214
1214
  }
1215
1215
 
1216
+ /**
1217
+ * returns meeting is joined
1218
+ * @private
1219
+ * @memberof Meeting
1220
+ * @returns {Boolean}
1221
+ */
1222
+ private isJoined() {
1223
+ return this.joinedWith?.state === 'JOINED';
1224
+ }
1225
+
1216
1226
  /**
1217
1227
  * Fetches meeting information.
1218
1228
  * @param {Object} options
@@ -1502,14 +1512,16 @@ export default class Meeting extends StatelessWebexPlugin {
1502
1512
  });
1503
1513
 
1504
1514
  this.breakouts.on(BREAKOUTS.EVENTS.ASK_RETURN_TO_MAIN, () => {
1505
- Trigger.trigger(
1506
- this,
1507
- {
1508
- file: 'meeting/index',
1509
- function: 'setUpBreakoutsListener',
1510
- },
1511
- EVENT_TRIGGERS.MEETING_BREAKOUTS_ASK_RETURN_TO_MAIN
1512
- );
1515
+ if (this.isJoined()) {
1516
+ Trigger.trigger(
1517
+ this,
1518
+ {
1519
+ file: 'meeting/index',
1520
+ function: 'setUpBreakoutsListener',
1521
+ },
1522
+ EVENT_TRIGGERS.MEETING_BREAKOUTS_ASK_RETURN_TO_MAIN
1523
+ );
1524
+ }
1513
1525
  });
1514
1526
 
1515
1527
  this.breakouts.on(BREAKOUTS.EVENTS.LEAVE_BREAKOUT, () => {
@@ -4178,7 +4190,7 @@ export default class Meeting extends StatelessWebexPlugin {
4178
4190
  // @ts-ignore - Fix type
4179
4191
  const {url, info: {datachannelUrl} = {}} = this.locusInfo;
4180
4192
 
4181
- const isJoined = this.joinedWith && this.joinedWith.state === 'JOINED';
4193
+ const isJoined = this.isJoined();
4182
4194
 
4183
4195
  // @ts-ignore - Fix type
4184
4196
  if (this.webex.internal.llm.isConnected()) {
@@ -5196,11 +5208,7 @@ export default class Meeting extends StatelessWebexPlugin {
5196
5208
  )
5197
5209
  .then(() => {
5198
5210
  if (localTracks?.screenShare?.video) {
5199
- this.enqueueMediaUpdate(MEDIA_UPDATE_TYPE.LAMBDA, {
5200
- lambda: async () => {
5201
- return this.requestScreenShareFloor();
5202
- },
5203
- });
5211
+ this.enqueueMediaUpdate(MEDIA_UPDATE_TYPE.SHARE_FLOOR_REQUEST);
5204
5212
  }
5205
5213
  })
5206
5214
  .then(() => this.mediaProperties.getCurrentConnectionType())
@@ -5296,12 +5304,7 @@ export default class Meeting extends StatelessWebexPlugin {
5296
5304
  * @private
5297
5305
  * @memberof Meeting
5298
5306
  */
5299
- private enqueueMediaUpdate(mediaUpdateType: string, options: any): Promise<void> {
5300
- if (mediaUpdateType === MEDIA_UPDATE_TYPE.LAMBDA && typeof options?.lambda !== 'function') {
5301
- return Promise.reject(
5302
- new Error('lambda must be specified when enqueuing MEDIA_UPDATE_TYPE.LAMBDA')
5303
- );
5304
- }
5307
+ private enqueueMediaUpdate(mediaUpdateType: string, options: any = {}): Promise<void> {
5305
5308
  const canUpdateMediaNow = this.canUpdateMedia();
5306
5309
 
5307
5310
  return new Promise((resolve, reject) => {
@@ -5365,8 +5368,8 @@ export default class Meeting extends StatelessWebexPlugin {
5365
5368
  case MEDIA_UPDATE_TYPE.TRANSCODED_MEDIA_CONNECTION:
5366
5369
  mediaUpdate = this.updateTranscodedMediaConnection();
5367
5370
  break;
5368
- case MEDIA_UPDATE_TYPE.LAMBDA:
5369
- mediaUpdate = options.lambda();
5371
+ case MEDIA_UPDATE_TYPE.SHARE_FLOOR_REQUEST:
5372
+ mediaUpdate = this.requestScreenShareFloor();
5370
5373
  break;
5371
5374
  case MEDIA_UPDATE_TYPE.UPDATE_MEDIA:
5372
5375
  mediaUpdate = this.updateMedia(options);
@@ -6641,7 +6644,7 @@ export default class Meeting extends StatelessWebexPlugin {
6641
6644
  LoggerProxy.logger.info(`${LOG_HEADER} starting`);
6642
6645
 
6643
6646
  if (!this.canUpdateMedia()) {
6644
- return this.enqueueMediaUpdate(MEDIA_UPDATE_TYPE.TRANSCODED_MEDIA_CONNECTION, {});
6647
+ return this.enqueueMediaUpdate(MEDIA_UPDATE_TYPE.TRANSCODED_MEDIA_CONNECTION);
6645
6648
  }
6646
6649
 
6647
6650
  return this.mediaProperties.webrtcMediaConnection
@@ -6770,11 +6773,7 @@ export default class Meeting extends StatelessWebexPlugin {
6770
6773
  // we're sending the http request to Locus to request the screen share floor
6771
6774
  // only after the SDP update, because that's how it's always been done for transcoded meetings
6772
6775
  // and also if sharing from the start, we need confluence to have been created
6773
- await this.enqueueMediaUpdate(MEDIA_UPDATE_TYPE.LAMBDA, {
6774
- lambda: async () => {
6775
- return this.requestScreenShareFloor();
6776
- },
6777
- });
6776
+ await this.enqueueMediaUpdate(MEDIA_UPDATE_TYPE.SHARE_FLOOR_REQUEST);
6778
6777
  }
6779
6778
  }
6780
6779
 
@@ -261,6 +261,9 @@ export default class Meetings extends WebexPlugin {
261
261
  const isSelfMoved = newLocus?.self?.state === _LEFT_ && newLocus?.self?.reason === _MOVED_;
262
262
  // @ts-ignore
263
263
  const deviceFromNewLocus = MeetingsUtil.getThisDevice(newLocus, this.webex.internal.device.url);
264
+ const isResourceMovedOnThisDevice =
265
+ deviceFromNewLocus?.state === _LEFT_ && deviceFromNewLocus?.reason === _MOVED_;
266
+
264
267
  const isNewLocusJoinThisDevice = MeetingsUtil.joinedOnThisDevice(
265
268
  meeting,
266
269
  newLocus,
@@ -300,9 +303,16 @@ export default class Meetings extends WebexPlugin {
300
303
 
301
304
  return false;
302
305
  }
303
- if (isSelfMoved && newLocus?.self?.removed) {
306
+ if (isSelfMoved && (newLocus?.self?.removed || isResourceMovedOnThisDevice)) {
307
+ LoggerProxy.logger.log(
308
+ 'Meetings:index#isNeedHandleMainLocus --> self moved main locus with self removed status or with device resource moved, not need to handle'
309
+ );
310
+
311
+ return false;
312
+ }
313
+ if (isSelfJoined && isResourceMovedOnThisDevice) {
304
314
  LoggerProxy.logger.log(
305
- 'Meetings:index#isNeedHandleMainLocus --> self moved main locus with self removed status, not need to handle'
315
+ 'Meetings:index#isNeedHandleMainLocus --> self device left&moved in main locus with self joined status, not need to handle'
306
316
  );
307
317
 
308
318
  return false;
@@ -2710,6 +2710,19 @@ describe('plugin-meetings', () => {
2710
2710
  });
2711
2711
  });
2712
2712
 
2713
+ describe("#isJoined", () => {
2714
+ it("should returns isJoined correctly", () => {
2715
+ meeting.joinedWith = undefined;
2716
+ assert.equal(meeting.isJoined(), false);
2717
+
2718
+ meeting.joinedWith = {state: "NOT_JOINED"};
2719
+ assert.equal(meeting.isJoined(), false);
2720
+
2721
+ meeting.joinedWith = {state: "JOINED"};
2722
+ assert.equal(meeting.isJoined(), true);
2723
+ });
2724
+ });
2725
+
2713
2726
  describe('#fetchMeetingInfo', () => {
2714
2727
  const FAKE_DESTINATION = 'something@somecompany.com';
2715
2728
  const FAKE_TYPE = _SIP_URI_;
@@ -4463,8 +4476,16 @@ describe('plugin-meetings', () => {
4463
4476
  );
4464
4477
  });
4465
4478
 
4479
+ it('should not trigger ASK_RETURN_TO_MAIN before joined', () => {
4480
+ TriggerProxy.trigger.reset();
4481
+ meeting.joinedWith = {state: "NOT_JOINED"};
4482
+ meeting.breakouts.trigger('ASK_RETURN_TO_MAIN');
4483
+ assert.notCalled(TriggerProxy.trigger);
4484
+ });
4485
+
4466
4486
  it('listens to the ask return to main event from breakouts and triggers the ask return to main event from meeting', () => {
4467
4487
  TriggerProxy.trigger.reset();
4488
+ meeting.joinedWith = {state: "JOINED"};
4468
4489
  meeting.breakouts.trigger('ASK_RETURN_TO_MAIN');
4469
4490
  assert.calledWith(
4470
4491
  TriggerProxy.trigger,
@@ -1083,7 +1083,7 @@ describe('plugin-meetings', () => {
1083
1083
  'meeting:meetingInfoAvailable'
1084
1084
  );
1085
1085
  };
1086
-
1086
+
1087
1087
  it('creates the meeting from a successful meeting info fetch promise testing', async () => {
1088
1088
  const meeting = await webex.meetings.createMeeting('test destination', 'test type');
1089
1089
 
@@ -1104,7 +1104,7 @@ describe('plugin-meetings', () => {
1104
1104
  permissionToken: 'PT',
1105
1105
  meetingJoinUrl: 'meetingJoinUrl',
1106
1106
  };
1107
-
1107
+
1108
1108
  assert.instanceOf(
1109
1109
  meeting,
1110
1110
  Meeting,
@@ -1112,7 +1112,7 @@ describe('plugin-meetings', () => {
1112
1112
  );
1113
1113
  checkCreateWithoutDelay(meeting, 'test destination', 'test type', infoExtraParamsProvided ? infoExtraParams : {}, expectedMeetingData);
1114
1114
  });
1115
-
1115
+
1116
1116
  it(`creates the meeting from a successful meeting info fetch with random delay${infoExtraParamsProvided ? ' with infoExtraParams' : ''}`, async () => {
1117
1117
  const FAKE_LOCUS_MEETING = {
1118
1118
  conversationUrl: 'locusConvURL',
@@ -1129,14 +1129,14 @@ describe('plugin-meetings', () => {
1129
1129
  active: false,
1130
1130
  },
1131
1131
  };
1132
-
1132
+
1133
1133
  const meeting = await webex.meetings.createMeeting(
1134
1134
  FAKE_LOCUS_MEETING,
1135
1135
  'test type',
1136
1136
  true,
1137
1137
  infoExtraParams
1138
1138
  );
1139
-
1139
+
1140
1140
  assert.instanceOf(
1141
1141
  meeting,
1142
1142
  Meeting,
@@ -1144,7 +1144,7 @@ describe('plugin-meetings', () => {
1144
1144
  );
1145
1145
  assert.notCalled(webex.meetings.meetingInfo.fetchMeetingInfo);
1146
1146
  assert.calledOnce(setTimeoutSpy);
1147
-
1147
+
1148
1148
  // Parse meeting info with locus object
1149
1149
  assert.equal(meeting.conversationUrl, 'locusConvURL');
1150
1150
  assert.equal(meeting.locusUrl, 'locusUrl');
@@ -1153,7 +1153,7 @@ describe('plugin-meetings', () => {
1153
1153
  assert.isUndefined(meeting.meetingJoinUrl);
1154
1154
  assert.equal(meeting.owner, 'locusOwner');
1155
1155
  assert.isUndefined(meeting.permissionToken);
1156
-
1156
+
1157
1157
  // Add meeting and send trigger
1158
1158
  assert.calledWith(MeetingsUtil.getMeetingAddedType, 'test type');
1159
1159
  assert.calledTwice(TriggerProxy.trigger);
@@ -1170,7 +1170,7 @@ describe('plugin-meetings', () => {
1170
1170
  type: 'test meeting added type',
1171
1171
  }
1172
1172
  );
1173
-
1173
+
1174
1174
  // When timer expires
1175
1175
  clock.tick(FAKE_TIME_TO_START);
1176
1176
  assert.calledWith(
@@ -1183,7 +1183,7 @@ describe('plugin-meetings', () => {
1183
1183
  undefined,
1184
1184
  infoExtraParamsProvided ? infoExtraParams : {}
1185
1185
  );
1186
-
1186
+
1187
1187
  // Parse meeting info is called again with new meeting info
1188
1188
  await testUtils.flushPromises();
1189
1189
  assert.equal(meeting.conversationUrl, 'locusConvURL');
@@ -1193,7 +1193,7 @@ describe('plugin-meetings', () => {
1193
1193
  assert.equal(meeting.meetingJoinUrl, 'meetingJoinUrl');
1194
1194
  assert.equal(meeting.owner, 'locusOwner');
1195
1195
  assert.equal(meeting.permissionToken, 'PT');
1196
-
1196
+
1197
1197
  assert.calledWith(
1198
1198
  TriggerProxy.trigger,
1199
1199
  meeting,
@@ -1744,7 +1744,41 @@ describe('plugin-meetings', () => {
1744
1744
  assert.equal(result, false);
1745
1745
  assert.calledWith(
1746
1746
  LoggerProxy.logger.log,
1747
- 'Meetings:index#isNeedHandleMainLocus --> self moved main locus with self removed status, not need to handle'
1747
+ 'Meetings:index#isNeedHandleMainLocus --> self moved main locus with self removed status or with device resource moved, not need to handle'
1748
+ );
1749
+ });
1750
+
1751
+ it('check self is moved and device resource removed, return false', () => {
1752
+ webex.meetings.meetingCollection.getActiveBreakoutLocus = sinon.stub().returns(null);
1753
+ newLocus.self.state = 'LEFT';
1754
+ newLocus.self.reason = 'MOVED';
1755
+ sinon.stub(MeetingsUtil, 'getThisDevice').returns({
1756
+ state: 'LEFT',
1757
+ reason: 'MOVED',
1758
+ });
1759
+ LoggerProxy.logger.log = sinon.stub();
1760
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1761
+ assert.equal(result, false);
1762
+ assert.calledWith(
1763
+ LoggerProxy.logger.log,
1764
+ 'Meetings:index#isNeedHandleMainLocus --> self moved main locus with self removed status or with device resource moved, not need to handle'
1765
+ );
1766
+ });
1767
+
1768
+ it('check self is joined but device resource removed, return false', () => {
1769
+ webex.meetings.meetingCollection.getActiveBreakoutLocus = sinon.stub().returns(null);
1770
+ sinon.stub(MeetingsUtil, 'joinedOnThisDevice').returns(false);
1771
+ newLocus.self.state = 'JOINED';
1772
+ sinon.stub(MeetingsUtil, 'getThisDevice').returns({
1773
+ state: 'LEFT',
1774
+ reason: 'MOVED',
1775
+ });
1776
+ LoggerProxy.logger.log = sinon.stub();
1777
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1778
+ assert.equal(result, false);
1779
+ assert.calledWith(
1780
+ LoggerProxy.logger.log,
1781
+ 'Meetings:index#isNeedHandleMainLocus --> self device left&moved in main locus with self joined status, not need to handle'
1748
1782
  );
1749
1783
  });
1750
1784
  });