@webex/plugin-meetings 3.12.0-next.90 → 3.12.0-next.92

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.
@@ -869,7 +869,7 @@ var Webinar = _webexCore.WebexPlugin.extend({
869
869
  }, _callee1);
870
870
  }))();
871
871
  },
872
- version: "3.12.0-next.90"
872
+ version: "3.12.0-next.92"
873
873
  });
874
874
  var _default = exports.default = Webinar;
875
875
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -44,7 +44,7 @@
44
44
  "@webex/event-dictionary-ts": "^1.0.2181",
45
45
  "@webex/jest-config-legacy": "0.0.0",
46
46
  "@webex/legacy-tools": "0.0.0",
47
- "@webex/plugin-rooms": "3.12.0-next.30",
47
+ "@webex/plugin-rooms": "3.12.0-next.31",
48
48
  "@webex/test-helper-chai": "3.12.0-next.5",
49
49
  "@webex/test-helper-mocha": "3.12.0-next.5",
50
50
  "@webex/test-helper-mock-webex": "3.12.0-next.5",
@@ -63,20 +63,20 @@
63
63
  "dependencies": {
64
64
  "@webex/common": "3.12.0-next.5",
65
65
  "@webex/internal-media-core": "2.26.1",
66
- "@webex/internal-plugin-conversation": "3.12.0-next.30",
67
- "@webex/internal-plugin-device": "3.12.0-next.28",
68
- "@webex/internal-plugin-llm": "3.12.0-next.32",
69
- "@webex/internal-plugin-mercury": "3.12.0-next.29",
70
- "@webex/internal-plugin-metrics": "3.12.0-next.28",
71
- "@webex/internal-plugin-support": "3.12.0-next.30",
72
- "@webex/internal-plugin-user": "3.12.0-next.29",
73
- "@webex/internal-plugin-voicea": "3.12.0-next.32",
66
+ "@webex/internal-plugin-conversation": "3.12.0-next.31",
67
+ "@webex/internal-plugin-device": "3.12.0-next.29",
68
+ "@webex/internal-plugin-llm": "3.12.0-next.33",
69
+ "@webex/internal-plugin-mercury": "3.12.0-next.30",
70
+ "@webex/internal-plugin-metrics": "3.12.0-next.29",
71
+ "@webex/internal-plugin-support": "3.12.0-next.31",
72
+ "@webex/internal-plugin-user": "3.12.0-next.30",
73
+ "@webex/internal-plugin-voicea": "3.12.0-next.33",
74
74
  "@webex/media-helpers": "3.12.0-next.9",
75
- "@webex/plugin-people": "3.12.0-next.29",
76
- "@webex/plugin-rooms": "3.12.0-next.30",
75
+ "@webex/plugin-people": "3.12.0-next.30",
76
+ "@webex/plugin-rooms": "3.12.0-next.31",
77
77
  "@webex/ts-sdp": "^1.8.1",
78
78
  "@webex/web-capabilities": "^1.10.0",
79
- "@webex/webex-core": "3.12.0-next.28",
79
+ "@webex/webex-core": "3.12.0-next.29",
80
80
  "ampersand-collection": "^2.0.2",
81
81
  "bowser": "^2.11.0",
82
82
  "btoa": "^1.2.1",
@@ -94,5 +94,5 @@
94
94
  "//": [
95
95
  "TODO: upgrade jwt-decode when moving to node 18"
96
96
  ],
97
- "version": "3.12.0-next.90"
97
+ "version": "3.12.0-next.92"
98
98
  }
@@ -518,7 +518,7 @@ export default class LocusInfo extends EventsScope {
518
518
  this.updateControls(locus.controls, locus.self);
519
519
  this.updateLocusUrl(locus.url, ControlsUtils.isMainSessionDTO(locus));
520
520
  this.updateFullState(locus.fullState);
521
- this.updateMeetingInfo(locus.info);
521
+ this.updateMeetingInfo(locus.info, locus.self);
522
522
  this.updateEmbeddedApps(locus.embeddedApps);
523
523
  // self and participants generate sipUrl for 1:1 meeting
524
524
  this.updateSelf(locus.self);
@@ -2491,9 +2491,19 @@ export default class LocusInfo extends EventsScope {
2491
2491
  */
2492
2492
  updateMeetingInfo(info: object, self?: object) {
2493
2493
  const roles = self ? SelfUtils.getRoles(self) : this.parsedLocus.self?.roles || [];
2494
- if ((info && !isEqual(this.info, info)) || (!isEqual(this.roles, roles) && info)) {
2495
- const isJoined = SelfUtils.isJoined(self || this.parsedLocus.self);
2496
- const parsedInfo = InfoUtils.getInfos(this.parsedLocus.info, info, roles, isJoined);
2494
+ const isJoined = SelfUtils.isJoined(self || this.parsedLocus.self);
2495
+
2496
+ // The parsed userDisplayHints depend on info, roles and isJoined, so we must recompute
2497
+ // whenever any of them changes. A common case is self transitioning to JOINED via a delta
2498
+ // that doesn't carry an info section - in that case we fall back to the previously stored
2499
+ // info so the hints get reparsed with the new joined state (e.g. VIEW_THE_PARTICIPANT_LIST).
2500
+ const infoToParse = info || this.info;
2501
+ const infoChanged = info && !isEqual(this.info, info);
2502
+ const rolesChanged = !isEqual(this.roles, roles);
2503
+ const isJoinedChanged = SelfUtils.isJoined(this.parsedLocus.self) !== isJoined;
2504
+
2505
+ if (infoToParse && (infoChanged || rolesChanged || isJoinedChanged)) {
2506
+ const parsedInfo = InfoUtils.getInfos(this.parsedLocus.info, infoToParse, roles, isJoined);
2497
2507
 
2498
2508
  if (parsedInfo.updates.isLocked) {
2499
2509
  this.emitScoped(
@@ -2516,7 +2526,7 @@ export default class LocusInfo extends EventsScope {
2516
2526
  );
2517
2527
  }
2518
2528
 
2519
- this.info = info;
2529
+ this.info = infoToParse;
2520
2530
  this.parsedLocus.info = parsedInfo.current;
2521
2531
  // Parses the info and adds necessary values
2522
2532
  this.updateMeeting(parsedInfo.current);
@@ -2846,6 +2846,10 @@ describe('plugin-meetings', () => {
2846
2846
 
2847
2847
  let expectedMeeting;
2848
2848
 
2849
+ // simulate that updateSelf has been called previously (as happens in production)
2850
+ // so that parsedLocus.self reflects the joined state
2851
+ locusInfo.parsedLocus.self = {state: 'JOINED'};
2852
+
2849
2853
  /*
2850
2854
  When the event is triggered, it is required that the meeting has already
2851
2855
  been updated. This is why the meeting is being checked within the stubbed event emitter
@@ -2997,6 +3001,46 @@ describe('plugin-meetings', () => {
2997
3001
  // since self is not passed to updateMeetingInfo, MEETING_INFO_UPDATED should be triggered with isIntializing: true
2998
3002
  checkMeetingInfoUpdatedCalledForRoles(true, {isInitializing: true});
2999
3003
  });
3004
+
3005
+ // joined-section hints (like ROSTER_IN_MEETING) are filtered out while not joined, so they
3006
+ // are a good proxy for verifying that userDisplayHints get recomputed on a join transition
3007
+ [
3008
+ {
3009
+ name: 'the JOINED delta carries the info section',
3010
+ getSecondInfo: (info) => info,
3011
+ },
3012
+ {
3013
+ name: 'the JOINED delta omits the info section (falls back to stored info)',
3014
+ getSecondInfo: () => undefined,
3015
+ },
3016
+ ].forEach(({name, getSecondInfo}) => {
3017
+ it(`recomputes userDisplayHints when self transitions to JOINED with unchanged roles and ${name}`, () => {
3018
+ const info = cloneDeep(meetingInfo); // joined: ['ROSTER_IN_MEETING', 'LOCK_STATUS_UNLOCKED']
3019
+
3020
+ const notJoinedSelf = cloneDeep(self);
3021
+ notJoinedSelf.state = 'IDLE';
3022
+ notJoinedSelf.controls.role.roles = [];
3023
+
3024
+ const joinedSelf = cloneDeep(self);
3025
+ joinedSelf.state = 'JOINED';
3026
+ joinedSelf.controls.role.roles = [];
3027
+
3028
+ sinon.stub(locusInfo, 'emitScoped');
3029
+
3030
+ // first update while not joined: joined-section hints are filtered out
3031
+ locusInfo.updateMeetingInfo(info, notJoinedSelf);
3032
+ assert.notInclude(locusInfo.parsedLocus.info.userDisplayHints, 'ROSTER_IN_MEETING');
3033
+ assert.notInclude(locusInfo.parsedLocus.info.userDisplayHints, 'LOCK_STATUS_UNLOCKED');
3034
+
3035
+ // self transitions to JOINED - info and roles are unchanged
3036
+ locusInfo.updateMeetingInfo(getSecondInfo(info), joinedSelf);
3037
+
3038
+ // the hints must be recomputed with the new joined state
3039
+ assert.include(locusInfo.parsedLocus.info.userDisplayHints, 'ROSTER_IN_MEETING');
3040
+ assert.include(locusInfo.parsedLocus.info.userDisplayHints, 'LOCK_STATUS_UNLOCKED');
3041
+ checkMeetingInfoUpdatedCalled(true, {isInitializing: false});
3042
+ });
3043
+ });
3000
3044
  });
3001
3045
 
3002
3046
  describe('#updateMediaShares', () => {