@webex/plugin-meetings 3.0.0-beta.16 → 3.0.0-beta.18
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.
- package/dist/breakouts/breakout.js +116 -0
- package/dist/breakouts/breakout.js.map +1 -0
- package/dist/breakouts/collection.js +23 -0
- package/dist/breakouts/collection.js.map +1 -0
- package/dist/breakouts/index.js +226 -0
- package/dist/breakouts/index.js.map +1 -0
- package/dist/config.js +4 -1
- package/dist/config.js.map +1 -1
- package/dist/constants.js +43 -6
- package/dist/constants.js.map +1 -1
- package/dist/locus-info/controlsUtils.js +2 -1
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/index.js +48 -0
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/parser.js +1 -0
- package/dist/locus-info/parser.js.map +1 -1
- package/dist/locus-info/selfUtils.js +19 -11
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/media/index.js +3 -3
- package/dist/media/index.js.map +1 -1
- package/dist/media/properties.js +4 -4
- package/dist/media/properties.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +5 -1
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +652 -459
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/request.js +25 -44
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/request.type.js.map +1 -1
- package/dist/meeting/util.js +22 -57
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +2 -0
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meetings/index.js +28 -18
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/request.js +14 -12
- package/dist/meetings/request.js.map +1 -1
- package/dist/member/index.js +9 -0
- package/dist/member/index.js.map +1 -1
- package/dist/member/util.js +14 -1
- package/dist/member/util.js.map +1 -1
- package/dist/members/index.js +8 -6
- package/dist/members/index.js.map +1 -1
- package/dist/members/request.js +3 -1
- package/dist/members/request.js.map +1 -1
- package/dist/multistream/mediaRequestManager.js +46 -6
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/multistreamMedia.js +4 -0
- package/dist/multistream/multistreamMedia.js.map +1 -1
- package/dist/multistream/receiveSlot.js +3 -3
- package/dist/multistream/receiveSlot.js.map +1 -1
- package/dist/multistream/receiveSlotManager.js +8 -6
- package/dist/multistream/receiveSlotManager.js.map +1 -1
- package/dist/multistream/remoteMedia.js.map +1 -1
- package/dist/multistream/remoteMediaGroup.js.map +1 -1
- package/dist/multistream/remoteMediaManager.js +168 -63
- package/dist/multistream/remoteMediaManager.js.map +1 -1
- package/dist/reachability/index.js +63 -51
- package/dist/reachability/index.js.map +1 -1
- package/dist/reactions/constants.js +13 -0
- package/dist/reactions/constants.js.map +1 -0
- package/dist/reactions/reactions.type.js.map +1 -1
- package/dist/reconnection-manager/index.js +25 -12
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/recording-controller/enums.js +17 -0
- package/dist/recording-controller/enums.js.map +1 -0
- package/dist/recording-controller/index.js +343 -0
- package/dist/recording-controller/index.js.map +1 -0
- package/dist/recording-controller/util.js +63 -0
- package/dist/recording-controller/util.js.map +1 -0
- package/dist/roap/request.js +88 -68
- package/dist/roap/request.js.map +1 -1
- package/dist/roap/turnDiscovery.js +72 -47
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/statsAnalyzer/index.js +3 -3
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/dist/statsAnalyzer/mqaUtil.js +18 -6
- package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
- package/package.json +24 -19
- package/src/breakouts/README.md +190 -0
- package/src/breakouts/breakout.ts +110 -0
- package/src/breakouts/collection.ts +19 -0
- package/src/breakouts/index.ts +225 -0
- package/src/config.ts +4 -1
- package/src/constants.ts +39 -1
- package/src/locus-info/controlsUtils.ts +2 -0
- package/src/locus-info/index.ts +59 -1
- package/src/locus-info/parser.ts +1 -0
- package/src/locus-info/selfUtils.ts +8 -0
- package/src/media/index.ts +1 -2
- package/src/media/properties.ts +6 -9
- package/src/meeting/in-meeting-actions.ts +8 -0
- package/src/meeting/index.ts +360 -111
- package/src/meeting/request.ts +9 -31
- package/src/meeting/request.type.ts +2 -0
- package/src/meeting/util.ts +25 -60
- package/src/meeting-info/meeting-info-v2.ts +2 -0
- package/src/meetings/index.ts +10 -5
- package/src/meetings/request.ts +1 -1
- package/src/member/index.ts +9 -0
- package/src/member/util.ts +14 -1
- package/src/members/index.ts +1 -0
- package/src/members/request.ts +1 -0
- package/src/multistream/mediaRequestManager.ts +79 -15
- package/src/multistream/multistreamMedia.ts +4 -0
- package/src/multistream/receiveSlot.ts +17 -12
- package/src/multistream/receiveSlotManager.ts +22 -21
- package/src/multistream/remoteMedia.ts +1 -1
- package/src/multistream/remoteMediaGroup.ts +2 -2
- package/src/multistream/remoteMediaManager.ts +150 -37
- package/src/reachability/index.ts +16 -13
- package/src/reactions/constants.ts +4 -0
- package/src/reactions/reactions.type.ts +25 -0
- package/src/reconnection-manager/index.ts +18 -9
- package/src/recording-controller/enums.ts +8 -0
- package/src/recording-controller/index.ts +315 -0
- package/src/recording-controller/util.ts +58 -0
- package/src/roap/request.ts +78 -73
- package/src/roap/turnDiscovery.ts +8 -6
- package/src/statsAnalyzer/index.ts +4 -4
- package/src/statsAnalyzer/mqaUtil.ts +6 -0
- package/test/unit/spec/breakouts/breakout.ts +119 -0
- package/test/unit/spec/breakouts/collection.ts +15 -0
- package/test/unit/spec/breakouts/index.ts +293 -0
- package/test/unit/spec/locus-info/controlsUtils.js +20 -0
- package/test/unit/spec/locus-info/index.js +103 -0
- package/test/unit/spec/locus-info/selfConstant.js +25 -0
- package/test/unit/spec/locus-info/selfUtils.js +84 -0
- package/test/unit/spec/media/index.ts +1 -1
- package/test/unit/spec/media/properties.ts +9 -9
- package/test/unit/spec/meeting/effectsState.js +5 -1
- package/test/unit/spec/meeting/in-meeting-actions.ts +5 -1
- package/test/unit/spec/meeting/index.js +241 -50
- package/test/unit/spec/meeting/request.js +17 -0
- package/test/unit/spec/meeting/utils.js +28 -122
- package/test/unit/spec/meetings/index.js +1 -0
- package/test/unit/spec/member/util.js +26 -1
- package/test/unit/spec/multistream/mediaRequestManager.ts +312 -50
- package/test/unit/spec/multistream/receiveSlot.ts +6 -6
- package/test/unit/spec/multistream/receiveSlotManager.ts +13 -13
- package/test/unit/spec/multistream/remoteMedia.ts +2 -2
- package/test/unit/spec/multistream/remoteMediaGroup.ts +5 -5
- package/test/unit/spec/multistream/remoteMediaManager.ts +354 -65
- package/test/unit/spec/reachability/index.ts +58 -24
- package/test/unit/spec/reconnection-manager/index.js +42 -13
- package/test/unit/spec/recording-controller/index.js +231 -0
- package/test/unit/spec/recording-controller/util.js +102 -0
- package/test/unit/spec/roap/index.ts +2 -1
- package/test/unit/spec/roap/request.ts +114 -0
- package/test/unit/spec/roap/turnDiscovery.ts +45 -29
- package/test/unit/spec/stats-analyzer/index.js +2 -2
- package/test/utils/webex-test-users.js +1 -0
- package/tsconfig.json +6 -0
- package/dist/media/internal-media-core-wrapper.js +0 -18
- package/dist/media/internal-media-core-wrapper.js.map +0 -1
- package/src/media/internal-media-core-wrapper.ts +0 -9
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2015-2023 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
+
*/
|
|
4
|
+
import {WebexPlugin} from '@webex/webex-core';
|
|
5
|
+
import {debounce, forEach} from 'lodash';
|
|
6
|
+
import LoggerProxy from '../common/logs/logger-proxy';
|
|
7
|
+
|
|
8
|
+
import {BREAKOUTS, MEETINGS} from '../constants';
|
|
9
|
+
|
|
10
|
+
import Breakout from './breakout';
|
|
11
|
+
import BreakoutCollection from './collection';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @class Breakouts
|
|
15
|
+
*/
|
|
16
|
+
const Breakouts = WebexPlugin.extend({
|
|
17
|
+
namespace: MEETINGS,
|
|
18
|
+
|
|
19
|
+
collections: {
|
|
20
|
+
breakouts: BreakoutCollection,
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
props: {
|
|
24
|
+
allowBackToMain: 'boolean', // only present when in a breakout session
|
|
25
|
+
delayCloseTime: 'number', // appears once breakouts start
|
|
26
|
+
enableBreakoutSession: 'boolean', // appears from the moment you enable breakouts
|
|
27
|
+
groupId: 'string', // appears from the moment you enable breakouts
|
|
28
|
+
name: 'string', // only present when in a breakout session
|
|
29
|
+
sessionId: 'string', // appears from the moment you enable breakouts
|
|
30
|
+
sessionType: 'string', // appears from the moment you enable breakouts
|
|
31
|
+
startTime: 'string', // appears once breakouts start
|
|
32
|
+
status: 'string', // only present when in a breakout session
|
|
33
|
+
url: 'string', // appears from the moment you enable breakouts
|
|
34
|
+
locusUrl: 'string', // the current locus url
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
children: {
|
|
38
|
+
currentBreakoutSession: Breakout,
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
derived: {
|
|
42
|
+
isInMainSession: {
|
|
43
|
+
deps: ['sessionType'],
|
|
44
|
+
/**
|
|
45
|
+
* Returns true if the user is in the main session
|
|
46
|
+
* @returns {boolean}
|
|
47
|
+
*/
|
|
48
|
+
fn() {
|
|
49
|
+
return this.sessionType === BREAKOUTS.SESSION_TYPES.MAIN;
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* initialize for the breakouts
|
|
56
|
+
* @returns {void}
|
|
57
|
+
*/
|
|
58
|
+
initialize() {
|
|
59
|
+
this.listenTo(this, 'change:status', () => {
|
|
60
|
+
if (this.status === BREAKOUTS.STATUS.CLOSING) {
|
|
61
|
+
this.trigger(BREAKOUTS.EVENTS.BREAKOUTS_CLOSING);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
this.debouncedQueryRosters = debounce(this.queryRosters, 10, {
|
|
65
|
+
leading: true,
|
|
66
|
+
trailing: false,
|
|
67
|
+
});
|
|
68
|
+
this.listenTo(this.breakouts, 'add', () => {
|
|
69
|
+
this.debouncedQueryRosters();
|
|
70
|
+
});
|
|
71
|
+
this.listenToBroadcastMessages();
|
|
72
|
+
this.listenToBreakoutRosters();
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Calls this to clean up listeners
|
|
77
|
+
* @returns {void}
|
|
78
|
+
*/
|
|
79
|
+
cleanUp() {
|
|
80
|
+
this.stopListening();
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Update the current locus url of the meeting
|
|
85
|
+
* @param {string} locusUrl // locus url
|
|
86
|
+
* @returns {void}
|
|
87
|
+
*/
|
|
88
|
+
locusUrlUpdate(locusUrl) {
|
|
89
|
+
this.set('locusUrl', locusUrl);
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* The initial roster lists need to be queried because you don't
|
|
94
|
+
* get a breakout.roster event when you join the meeting
|
|
95
|
+
* @returns {void}
|
|
96
|
+
*/
|
|
97
|
+
queryRosters() {
|
|
98
|
+
this.webex
|
|
99
|
+
.request({uri: `${this.url}/roster`, qs: {locusUrl: btoa(this.locusUrl)}})
|
|
100
|
+
.then((result) => {
|
|
101
|
+
const {
|
|
102
|
+
body: {rosters},
|
|
103
|
+
} = result;
|
|
104
|
+
|
|
105
|
+
rosters.forEach(({locus}) => {
|
|
106
|
+
this.handleRosterUpdate(locus);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
this.trigger(BREAKOUTS.EVENTS.MEMBERS_UPDATE);
|
|
110
|
+
})
|
|
111
|
+
.catch((error) => {
|
|
112
|
+
LoggerProxy.logger.error('Meeting:breakouts#queryRosters failed', error);
|
|
113
|
+
});
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
*
|
|
118
|
+
* @param {Object} locus // locus object
|
|
119
|
+
* @returns {void}
|
|
120
|
+
*/
|
|
121
|
+
handleRosterUpdate(locus) {
|
|
122
|
+
const sessionId = locus.controls?.breakout?.sessionId;
|
|
123
|
+
|
|
124
|
+
const session = this.breakouts.get(sessionId);
|
|
125
|
+
|
|
126
|
+
if (!session) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
session.parseRoster(locus);
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Sets up listener for broadcast messages sent to the breakout session
|
|
135
|
+
* @returns {void}
|
|
136
|
+
*/
|
|
137
|
+
listenToBroadcastMessages() {
|
|
138
|
+
this.listenTo(this.webex.internal.llm, 'event:breakout.message', (event) => {
|
|
139
|
+
const {
|
|
140
|
+
data: {senderUserId, sentTime, message},
|
|
141
|
+
} = event;
|
|
142
|
+
|
|
143
|
+
this.trigger(BREAKOUTS.EVENTS.MESSAGE, {
|
|
144
|
+
senderUserId,
|
|
145
|
+
sentTime,
|
|
146
|
+
message,
|
|
147
|
+
// FIXME: This is only the current sessionId
|
|
148
|
+
// We'd need to check that the dataChannelUrl is still the same
|
|
149
|
+
// to guarantee that this message was sent to this session
|
|
150
|
+
sessionId: this.currentBreakoutSession.sessionId,
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Sets up a listener for roster messags from mecury
|
|
157
|
+
* @returns {void}
|
|
158
|
+
*/
|
|
159
|
+
listenToBreakoutRosters() {
|
|
160
|
+
this.listenTo(this.webex.internal.mercury, 'event:breakout.roster', (event) => {
|
|
161
|
+
this.handleRosterUpdate(event.data.locus);
|
|
162
|
+
this.trigger(BREAKOUTS.EVENTS.MEMBERS_UPDATE);
|
|
163
|
+
});
|
|
164
|
+
},
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Updates the information about the current breakout
|
|
168
|
+
* @param {Object} params
|
|
169
|
+
* @returns {void}
|
|
170
|
+
*/
|
|
171
|
+
updateBreakout(params) {
|
|
172
|
+
this.set(params);
|
|
173
|
+
|
|
174
|
+
this.set('currentBreakoutSession', {
|
|
175
|
+
sessionId: params.sessionId,
|
|
176
|
+
groupId: params.groupId,
|
|
177
|
+
name: params.name,
|
|
178
|
+
current: true,
|
|
179
|
+
sessionType: params.sessionType,
|
|
180
|
+
url: params.url,
|
|
181
|
+
[BREAKOUTS.SESSION_STATES.ACTIVE]: false,
|
|
182
|
+
[BREAKOUTS.SESSION_STATES.ALLOWED]: false,
|
|
183
|
+
[BREAKOUTS.SESSION_STATES.ALLOWED]: false,
|
|
184
|
+
[BREAKOUTS.SESSION_STATES.ASSIGNED_CURRENT]: false,
|
|
185
|
+
[BREAKOUTS.SESSION_STATES.REQUESTED]: false,
|
|
186
|
+
});
|
|
187
|
+
},
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Updates the information about available breakouts
|
|
191
|
+
* @param {Object} payload
|
|
192
|
+
* @returns {void}
|
|
193
|
+
*/
|
|
194
|
+
updateBreakoutSessions(payload) {
|
|
195
|
+
const breakouts = {};
|
|
196
|
+
|
|
197
|
+
if (payload.breakoutSessions) {
|
|
198
|
+
forEach(BREAKOUTS.SESSION_STATES, (state) => {
|
|
199
|
+
forEach(payload.breakoutSessions[state], (breakout) => {
|
|
200
|
+
const {sessionId} = breakout;
|
|
201
|
+
|
|
202
|
+
if (!breakouts[sessionId]) {
|
|
203
|
+
breakouts[sessionId] = breakout;
|
|
204
|
+
breakouts[sessionId][BREAKOUTS.SESSION_STATES.ACTIVE] = false;
|
|
205
|
+
breakouts[sessionId][BREAKOUTS.SESSION_STATES.ASSIGNED] = false;
|
|
206
|
+
breakouts[sessionId][BREAKOUTS.SESSION_STATES.ALLOWED] = false;
|
|
207
|
+
breakouts[sessionId][BREAKOUTS.SESSION_STATES.ASSIGNED_CURRENT] = false;
|
|
208
|
+
breakouts[sessionId][BREAKOUTS.SESSION_STATES.REQUESTED] = false;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
breakouts[sessionId][state] = true;
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
forEach(breakouts, (breakout: typeof Breakout) => {
|
|
217
|
+
// eslint-disable-next-line no-param-reassign
|
|
218
|
+
breakout.url = this.url;
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
this.breakouts.set(Object.values(breakouts));
|
|
222
|
+
},
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
export default Breakouts;
|
package/src/config.ts
CHANGED
|
@@ -93,7 +93,10 @@ export default {
|
|
|
93
93
|
enableMediaNegotiatedEvent: false,
|
|
94
94
|
enableUnifiedMeetings: false,
|
|
95
95
|
enableAdhocMeetings: false,
|
|
96
|
-
enableTurnDiscovery:
|
|
96
|
+
enableTurnDiscovery: true,
|
|
97
|
+
},
|
|
98
|
+
degradationPreferences: {
|
|
99
|
+
maxMacroblocksLimit: 32400,
|
|
97
100
|
},
|
|
98
101
|
},
|
|
99
102
|
};
|
package/src/constants.ts
CHANGED
|
@@ -288,6 +288,7 @@ export const EVENT_TRIGGERS = {
|
|
|
288
288
|
MEETING_STOPPED_RECORDING: 'meeting:recording:stopped',
|
|
289
289
|
MEETING_STARTED_RECEIVING_TRANSCRIPTION: 'meeting:receiveTranscription:started',
|
|
290
290
|
MEETING_STOPPED_RECEIVING_TRANSCRIPTION: 'meeting:receiveTranscription:stopped',
|
|
291
|
+
MEETING_RECEIVE_REACTIONS: 'meeting:receiveReactions',
|
|
291
292
|
MEETING_PAUSED_RECORDING: 'meeting:recording:paused',
|
|
292
293
|
MEETING_RESUMED_RECORDING: 'meeting:recording:resumed',
|
|
293
294
|
MEETING_ADDED: 'meeting:added',
|
|
@@ -304,6 +305,9 @@ export const EVENT_TRIGGERS = {
|
|
|
304
305
|
MEETING_SELF_IS_SHARING_BLOCKED: 'meeting:self:isSharingBlocked',
|
|
305
306
|
MEETING_CONTROLS_LAYOUT_UPDATE: 'meeting:layout:update',
|
|
306
307
|
MEETING_ENTRY_EXIT_TONE_UPDATE: 'meeting:entryExitTone:update',
|
|
308
|
+
MEETING_BREAKOUTS_UPDATE: 'meeting:breakouts:update',
|
|
309
|
+
MEETING_BREAKOUTS_CLOSING: 'meeting:breakouts:closing',
|
|
310
|
+
MEETING_BREAKOUTS_MESSAGE: 'meeting:breakouts:message',
|
|
307
311
|
MEMBERS_UPDATE: 'members:update',
|
|
308
312
|
MEMBERS_CONTENT_UPDATE: 'members:content:update',
|
|
309
313
|
MEMBERS_HOST_UPDATE: 'members:host:update',
|
|
@@ -331,7 +335,7 @@ export const EVENT_TRIGGERS = {
|
|
|
331
335
|
REMOTE_VIDEO_SOURCE_COUNT_CHANGED: 'media:remoteVideoSourceCountChanged',
|
|
332
336
|
REMOTE_AUDIO_SOURCE_COUNT_CHANGED: 'media:remoteAudioSourceCountChanged',
|
|
333
337
|
REMOTE_MEDIA_AUDIO_CREATED: 'media:remoteAudio:created',
|
|
334
|
-
REMOTE_MEDIA_SCREEN_SHARE_AUDIO_CREATED: 'media:
|
|
338
|
+
REMOTE_MEDIA_SCREEN_SHARE_AUDIO_CREATED: 'media:remoteScreenShareAudio:created',
|
|
335
339
|
REMOTE_MEDIA_VIDEO_LAYOUT_CHANGED: 'media:remoteVideo:layoutChanged',
|
|
336
340
|
};
|
|
337
341
|
|
|
@@ -514,11 +518,34 @@ export const LOCUS = {
|
|
|
514
518
|
SYNCDEBUG: 'sync_debug',
|
|
515
519
|
};
|
|
516
520
|
|
|
521
|
+
export const BREAKOUTS = {
|
|
522
|
+
STATUS: {
|
|
523
|
+
CLOSING: 'CLOSING',
|
|
524
|
+
},
|
|
525
|
+
EVENTS: {
|
|
526
|
+
BREAKOUTS_CLOSING: 'BREAKOUTS_CLOSING',
|
|
527
|
+
MESSAGE: 'MESSAGE',
|
|
528
|
+
MEMBERS_UPDATE: 'MEMBERS_UPDATE',
|
|
529
|
+
},
|
|
530
|
+
SESSION_TYPES: {
|
|
531
|
+
MAIN: 'MAIN',
|
|
532
|
+
},
|
|
533
|
+
SESSION_STATES: {
|
|
534
|
+
ACTIVE: 'active',
|
|
535
|
+
ASSIGNED: 'assigned',
|
|
536
|
+
ALLOWED: 'allowed',
|
|
537
|
+
ASSIGNED_CURRENT: 'assignedCurrent',
|
|
538
|
+
REQUESTED: 'requested',
|
|
539
|
+
},
|
|
540
|
+
BREAKOUTS_SUPPORTED: 'BREAKOUTS_SUPPORTED',
|
|
541
|
+
};
|
|
542
|
+
|
|
517
543
|
export const LOCUSINFO = {
|
|
518
544
|
EVENTS: {
|
|
519
545
|
CONTROLS_MEETING_LAYOUT_UPDATED: 'CONTROLS_MEETING_LAYOUT_UPDATED',
|
|
520
546
|
CONTROLS_RECORDING_UPDATED: 'CONTROLS_RECORDING_UPDATED',
|
|
521
547
|
CONTROLS_MEETING_TRANSCRIBE_UPDATED: 'CONTROLS_MEETING_TRANSCRIBE_UPDATED',
|
|
548
|
+
CONTROLS_MEETING_BREAKOUT_UPDATED: 'CONTROLS_MEETING_BREAKOUT_UPDATED',
|
|
522
549
|
CONTROLS_MEETING_CONTAINER_UPDATED: 'CONTROLS_MEETING_CONTAINER_UPDATED',
|
|
523
550
|
CONTROLS_ENTRY_EXIT_TONE_UPDATED: 'CONTROLS_ENTRY_EXIT_TONE_UPDATED',
|
|
524
551
|
SELF_UNADMITTED_GUEST: 'SELF_UNADMITTED_GUEST',
|
|
@@ -540,6 +567,9 @@ export const LOCUSINFO = {
|
|
|
540
567
|
EMBEDDED_APPS_UPDATED: 'EMBEDDED_APPS_UPDATED',
|
|
541
568
|
SELF_CANNOT_VIEW_PARTICIPANT_LIST_CHANGE: 'SELF_CANNOT_VIEW_PARTICIPANT_LIST_CHANGE',
|
|
542
569
|
SELF_IS_SHARING_BLOCKED_CHANGE: 'SELF_IS_SHARING_BLOCKED_CHANGE',
|
|
570
|
+
SELF_MEETING_BREAKOUTS_CHANGED: 'SELF_MEETING_BREAKOUTS_CHANGED',
|
|
571
|
+
MEDIA_INACTIVITY: 'MEDIA_INACTIVITY',
|
|
572
|
+
LINKS_SERVICES: 'LINKS_SERVICES',
|
|
543
573
|
},
|
|
544
574
|
};
|
|
545
575
|
|
|
@@ -552,6 +582,9 @@ export const LOCUSEVENT = {
|
|
|
552
582
|
// delta events
|
|
553
583
|
DIFFERENCE: 'locus.difference',
|
|
554
584
|
|
|
585
|
+
// Breakout sessions
|
|
586
|
+
BREAKOUT_ROSTER: 'breakout.roster',
|
|
587
|
+
|
|
555
588
|
// screen sharing
|
|
556
589
|
FLOOR_GRANTED: 'locus.floor_granted',
|
|
557
590
|
FLOOR_RELEASED: 'locus.floor_released',
|
|
@@ -724,6 +757,10 @@ export const DISPLAY_HINTS = {
|
|
|
724
757
|
TRANSCRIPTION_CONTROL_STOP: 'TRANSCRIPTION_CONTROL_STOP',
|
|
725
758
|
WEBEX_ASSISTANT_STATUS_ACTIVE: 'WEBEX_ASSISTANT_STATUS_ACTIVE',
|
|
726
759
|
WAITING_FOR_OTHERS: 'WAITING_FOR_OTHERS',
|
|
760
|
+
ENABLE_REACTIONS: 'ENABLE_REACTIONS',
|
|
761
|
+
DISABLE_REACTIONS: 'DISABLE_REACTIONS',
|
|
762
|
+
REACTIONS_ACTIVE: 'REACTIONS_ACTIVE',
|
|
763
|
+
REACTIONS_INACTIVE: 'REACTIONS_INACTIVE',
|
|
727
764
|
};
|
|
728
765
|
|
|
729
766
|
export const SELF_ROLES = {
|
|
@@ -814,6 +851,7 @@ export const RESOURCE = {
|
|
|
814
851
|
|
|
815
852
|
export const REACHABILITY = {
|
|
816
853
|
localStorage: 'reachability.result',
|
|
854
|
+
namespace: 'Reachability',
|
|
817
855
|
};
|
|
818
856
|
|
|
819
857
|
export const ROAP = {
|
|
@@ -92,6 +92,8 @@ ControlsUtils.getControls = (oldControls: any, newControls: any) => {
|
|
|
92
92
|
!isEqual(previous?.entryExitTone, current?.entryExitTone) &&
|
|
93
93
|
(previous?.entryExitTone || current?.entryExitTone)
|
|
94
94
|
),
|
|
95
|
+
|
|
96
|
+
hasBreakoutChanged: !isEqual(previous?.breakout, current?.breakout),
|
|
95
97
|
},
|
|
96
98
|
};
|
|
97
99
|
};
|
package/src/locus-info/index.ts
CHANGED
|
@@ -62,6 +62,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
62
62
|
mediaShares: any;
|
|
63
63
|
replace: any;
|
|
64
64
|
url: any;
|
|
65
|
+
services: any;
|
|
65
66
|
|
|
66
67
|
constructor(updateMeeting, webex, meetingId) {
|
|
67
68
|
super();
|
|
@@ -185,6 +186,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
185
186
|
this.updateSelf(locus.self, locus.participants);
|
|
186
187
|
this.updateHostInfo(locus.host);
|
|
187
188
|
this.updateMediaShares(locus.mediaShares);
|
|
189
|
+
this.updateServices(locus.links?.services);
|
|
188
190
|
}
|
|
189
191
|
|
|
190
192
|
/**
|
|
@@ -337,7 +339,14 @@ export default class LocusInfo extends EventsScope {
|
|
|
337
339
|
* @returns {undefined}
|
|
338
340
|
* @memberof LocusInfo
|
|
339
341
|
*/
|
|
340
|
-
updateLocusInfo(locus
|
|
342
|
+
updateLocusInfo(locus) {
|
|
343
|
+
if (locus.self?.reason === 'MOVED' && locus.self?.state === 'LEFT') {
|
|
344
|
+
// When moved to a breakout session locus sends a message for the previous locus
|
|
345
|
+
// indicating that we have been moved. It isn't helpful to continue parsing this
|
|
346
|
+
// as it gets interpreted as if we have left the call
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
|
|
341
350
|
this.updateControls(locus.controls);
|
|
342
351
|
this.updateConversationUrl(locus.conversationUrl, locus.info);
|
|
343
352
|
this.updateCreated(locus.created);
|
|
@@ -355,6 +364,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
355
364
|
this.updateMemberShip(locus.membership);
|
|
356
365
|
this.updateIdentifiers(locus.identities);
|
|
357
366
|
this.updateEmbeddedApps(locus.embeddedApps);
|
|
367
|
+
this.updateServices(locus.links?.services);
|
|
358
368
|
this.compareAndUpdate();
|
|
359
369
|
// update which required to compare different objects from locus
|
|
360
370
|
}
|
|
@@ -674,6 +684,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
674
684
|
hasMeetingContainerChanged,
|
|
675
685
|
hasTranscribeChanged,
|
|
676
686
|
hasEntryExitToneChanged,
|
|
687
|
+
hasBreakoutChanged,
|
|
677
688
|
},
|
|
678
689
|
current,
|
|
679
690
|
} = ControlsUtils.getControls(this.controls, controls);
|
|
@@ -737,6 +748,21 @@ export default class LocusInfo extends EventsScope {
|
|
|
737
748
|
);
|
|
738
749
|
}
|
|
739
750
|
|
|
751
|
+
if (hasBreakoutChanged) {
|
|
752
|
+
const {breakout} = current;
|
|
753
|
+
|
|
754
|
+
this.emitScoped(
|
|
755
|
+
{
|
|
756
|
+
file: 'locus-info',
|
|
757
|
+
function: 'updateControls',
|
|
758
|
+
},
|
|
759
|
+
LOCUSINFO.EVENTS.CONTROLS_MEETING_BREAKOUT_UPDATED,
|
|
760
|
+
{
|
|
761
|
+
breakout,
|
|
762
|
+
}
|
|
763
|
+
);
|
|
764
|
+
}
|
|
765
|
+
|
|
740
766
|
if (hasEntryExitToneChanged) {
|
|
741
767
|
const {entryExitTone} = current;
|
|
742
768
|
|
|
@@ -789,6 +815,27 @@ export default class LocusInfo extends EventsScope {
|
|
|
789
815
|
}
|
|
790
816
|
}
|
|
791
817
|
|
|
818
|
+
/**
|
|
819
|
+
* @param {Object} services
|
|
820
|
+
* @returns {undefined}
|
|
821
|
+
* @memberof LocusInfo
|
|
822
|
+
*/
|
|
823
|
+
updateServices(services: Record<'breakout' | 'record', {url: string}>) {
|
|
824
|
+
if (services && !isEqual(this.services, services)) {
|
|
825
|
+
this.services = services;
|
|
826
|
+
this.emitScoped(
|
|
827
|
+
{
|
|
828
|
+
file: 'locus-info',
|
|
829
|
+
function: 'updateServices',
|
|
830
|
+
},
|
|
831
|
+
LOCUSINFO.EVENTS.LINKS_SERVICES,
|
|
832
|
+
{
|
|
833
|
+
services,
|
|
834
|
+
}
|
|
835
|
+
);
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
|
|
792
839
|
/**
|
|
793
840
|
* @param {Object} fullState
|
|
794
841
|
* @returns {undefined}
|
|
@@ -1041,6 +1088,17 @@ export default class LocusInfo extends EventsScope {
|
|
|
1041
1088
|
);
|
|
1042
1089
|
}
|
|
1043
1090
|
|
|
1091
|
+
if (parsedSelves.updates.breakoutsChanged) {
|
|
1092
|
+
this.emitScoped(
|
|
1093
|
+
{
|
|
1094
|
+
file: 'locus-info',
|
|
1095
|
+
function: 'updateSelf',
|
|
1096
|
+
},
|
|
1097
|
+
LOCUSINFO.EVENTS.SELF_MEETING_BREAKOUTS_CHANGED,
|
|
1098
|
+
{breakoutSessions: parsedSelves.current.breakoutSessions}
|
|
1099
|
+
);
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1044
1102
|
if (parsedSelves.updates.isMediaInactiveOrReleased) {
|
|
1045
1103
|
this.emitScoped(
|
|
1046
1104
|
{
|
package/src/locus-info/parser.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* eslint-disable default-param-last */
|
|
2
2
|
|
|
3
|
+
import {isEqual} from 'lodash';
|
|
3
4
|
import {
|
|
4
5
|
_IDLE_,
|
|
5
6
|
_JOINED_,
|
|
@@ -60,12 +61,15 @@ SelfUtils.parse = (self: any, deviceId: string) => {
|
|
|
60
61
|
layout: SelfUtils.getLayout(self),
|
|
61
62
|
canNotViewTheParticipantList: SelfUtils.canNotViewTheParticipantList(self),
|
|
62
63
|
isSharingBlocked: SelfUtils.isSharingBlocked(self),
|
|
64
|
+
breakoutSessions: SelfUtils.getBreakouts(self),
|
|
63
65
|
};
|
|
64
66
|
}
|
|
65
67
|
|
|
66
68
|
return null;
|
|
67
69
|
};
|
|
68
70
|
|
|
71
|
+
SelfUtils.getBreakouts = (self) => self?.controls?.breakout?.sessions;
|
|
72
|
+
|
|
69
73
|
SelfUtils.getLayout = (self) =>
|
|
70
74
|
Array.isArray(self?.controls?.layouts) ? self.controls.layouts[0].type : undefined;
|
|
71
75
|
|
|
@@ -114,6 +118,7 @@ SelfUtils.getSelves = (oldSelf, newSelf, deviceId) => {
|
|
|
114
118
|
updates.canNotViewTheParticipantListChanged =
|
|
115
119
|
previous?.canNotViewTheParticipantList !== current.canNotViewTheParticipantList;
|
|
116
120
|
updates.isSharingBlockedChanged = previous?.isSharingBlocked !== current.isSharingBlocked;
|
|
121
|
+
updates.breakoutsChanged = SelfUtils.breakoutsChanged(previous, current);
|
|
117
122
|
|
|
118
123
|
return {
|
|
119
124
|
previous,
|
|
@@ -139,6 +144,9 @@ SelfUtils.isJoined = (self: any) => self?.state === _JOINED_;
|
|
|
139
144
|
SelfUtils.layoutChanged = (previous: any, current: any) =>
|
|
140
145
|
current?.layout && previous?.layout !== current?.layout;
|
|
141
146
|
|
|
147
|
+
SelfUtils.breakoutsChanged = (previous, current) =>
|
|
148
|
+
!isEqual(previous?.breakoutSessions, current?.breakoutSessions);
|
|
149
|
+
|
|
142
150
|
SelfUtils.isMediaInactive = (previous, current) => {
|
|
143
151
|
if (
|
|
144
152
|
previous &&
|
package/src/media/index.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
/* globals navigator */
|
|
5
5
|
|
|
6
|
+
import {RoapMediaConnection, MultistreamRoapMediaConnection} from '@webex/internal-media-core';
|
|
6
7
|
import LoggerProxy from '../common/logs/logger-proxy';
|
|
7
8
|
import {AUDIO_INPUT, VIDEO_INPUT, MEDIA_TRACK_CONSTRAINT} from '../constants';
|
|
8
9
|
import Config from '../config';
|
|
@@ -10,8 +11,6 @@ import StaticConfig from '../common/config';
|
|
|
10
11
|
import MediaError from '../common/errors/media';
|
|
11
12
|
import BrowserDetection from '../common/browser-detection';
|
|
12
13
|
|
|
13
|
-
import {RoapMediaConnection, MultistreamRoapMediaConnection} from './internal-media-core-wrapper';
|
|
14
|
-
|
|
15
14
|
const {isBrowser} = BrowserDetection();
|
|
16
15
|
|
|
17
16
|
/**
|
package/src/media/properties.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {ConnectionState, Event} from '@webex/internal-media-core';
|
|
2
2
|
|
|
3
3
|
import {MEETINGS, PC_BAIL_TIMEOUT, QUALITY_LEVELS} from '../constants';
|
|
4
4
|
import LoggerProxy from '../common/logs/logger-proxy';
|
|
@@ -214,13 +214,13 @@ export default class MediaProperties {
|
|
|
214
214
|
*/
|
|
215
215
|
waitForMediaConnectionConnected() {
|
|
216
216
|
const isConnected = () =>
|
|
217
|
-
this.webrtcMediaConnection.getConnectionState() ===
|
|
217
|
+
this.webrtcMediaConnection.getConnectionState() === ConnectionState.Connected;
|
|
218
218
|
|
|
219
219
|
if (isConnected()) {
|
|
220
220
|
return Promise.resolve();
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
-
return new Promise((resolve, reject) => {
|
|
223
|
+
return new Promise<void>((resolve, reject) => {
|
|
224
224
|
let timer;
|
|
225
225
|
|
|
226
226
|
const connectionStateListener = () => {
|
|
@@ -230,20 +230,17 @@ export default class MediaProperties {
|
|
|
230
230
|
|
|
231
231
|
if (isConnected()) {
|
|
232
232
|
clearTimeout(timer);
|
|
233
|
-
this.webrtcMediaConnection.off(
|
|
234
|
-
MC.Event.CONNECTION_STATE_CHANGED,
|
|
235
|
-
connectionStateListener
|
|
236
|
-
);
|
|
233
|
+
this.webrtcMediaConnection.off(Event.CONNECTION_STATE_CHANGED, connectionStateListener);
|
|
237
234
|
resolve();
|
|
238
235
|
}
|
|
239
236
|
};
|
|
240
237
|
|
|
241
238
|
timer = setTimeout(() => {
|
|
242
|
-
this.webrtcMediaConnection.off(
|
|
239
|
+
this.webrtcMediaConnection.off(Event.CONNECTION_STATE_CHANGED, connectionStateListener);
|
|
243
240
|
reject();
|
|
244
241
|
}, PC_BAIL_TIMEOUT);
|
|
245
242
|
|
|
246
|
-
this.webrtcMediaConnection.on(
|
|
243
|
+
this.webrtcMediaConnection.on(Event.CONNECTION_STATE_CHANGED, connectionStateListener);
|
|
247
244
|
});
|
|
248
245
|
}
|
|
249
246
|
|
|
@@ -31,6 +31,8 @@ interface IInMeetingActions {
|
|
|
31
31
|
isRealTimeTranslationEnabled?: boolean;
|
|
32
32
|
canSelectSpokenLanguages?: boolean;
|
|
33
33
|
waitingForOthersToJoin?: boolean;
|
|
34
|
+
canEnableReactions?: boolean;
|
|
35
|
+
canSendReactions?: boolean;
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
/**
|
|
@@ -83,6 +85,10 @@ export default class InMeetingActions implements IInMeetingActions {
|
|
|
83
85
|
|
|
84
86
|
waitingForOthersToJoin = null;
|
|
85
87
|
|
|
88
|
+
canEnableReactions = null;
|
|
89
|
+
|
|
90
|
+
canSendReactions = null;
|
|
91
|
+
|
|
86
92
|
/**
|
|
87
93
|
* Returns all meeting action options
|
|
88
94
|
* @returns {Object}
|
|
@@ -110,6 +116,8 @@ export default class InMeetingActions implements IInMeetingActions {
|
|
|
110
116
|
isRealTimeTranslationEnabled: this.isRealTimeTranslationEnabled,
|
|
111
117
|
canSelectSpokenLanguages: this.canSelectSpokenLanguages,
|
|
112
118
|
waitingForOthersToJoin: this.waitingForOthersToJoin,
|
|
119
|
+
canEnableReactions: this.canEnableReactions,
|
|
120
|
+
canSendReactions: this.canSendReactions,
|
|
113
121
|
});
|
|
114
122
|
|
|
115
123
|
/**
|