@webex/plugin-meetings 3.0.0-beta.115 → 3.0.0-beta.117
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 +23 -6
- package/dist/breakouts/breakout.js.map +1 -1
- package/dist/breakouts/index.js +178 -139
- package/dist/breakouts/index.js.map +1 -1
- package/dist/constants.js +1 -0
- package/dist/constants.js.map +1 -1
- package/dist/locus-info/mediaSharesUtils.js +15 -1
- package/dist/locus-info/mediaSharesUtils.js.map +1 -1
- package/dist/meeting/index.js +73 -103
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.js +3 -0
- package/dist/meeting/locusMediaRequest.js.map +1 -1
- package/dist/meeting/muteState.js +1 -1
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.js +27 -20
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/util.js +463 -426
- package/dist/meeting/util.js.map +1 -1
- package/dist/members/index.js +4 -1
- package/dist/members/index.js.map +1 -1
- package/dist/members/request.js +75 -45
- package/dist/members/request.js.map +1 -1
- package/dist/members/util.js +308 -317
- package/dist/members/util.js.map +1 -1
- package/dist/types/constants.d.ts +1 -0
- package/dist/types/meeting/index.d.ts +20 -21
- package/dist/types/meeting/locusMediaRequest.d.ts +2 -0
- package/dist/types/meeting/request.d.ts +16 -8
- package/dist/types/meeting/util.d.ts +75 -1
- package/dist/types/members/request.d.ts +56 -11
- package/dist/types/members/util.d.ts +209 -1
- package/package.json +19 -19
- package/src/breakouts/breakout.ts +26 -4
- package/src/breakouts/index.ts +32 -17
- package/src/constants.ts +1 -0
- package/src/locus-info/mediaSharesUtils.ts +16 -0
- package/src/meeting/index.ts +20 -42
- package/src/meeting/locusMediaRequest.ts +6 -0
- package/src/meeting/muteState.ts +1 -1
- package/src/meeting/request.ts +26 -17
- package/src/meeting/util.ts +446 -410
- package/src/members/index.ts +7 -1
- package/src/members/request.ts +61 -21
- package/src/members/util.ts +316 -326
- package/test/unit/spec/breakouts/breakout.ts +26 -7
- package/test/unit/spec/breakouts/index.ts +48 -3
- package/test/unit/spec/meeting/index.js +53 -33
- package/test/unit/spec/meeting/locusMediaRequest.ts +25 -3
- package/test/unit/spec/meeting/muteState.js +5 -2
- package/test/unit/spec/meeting/request.js +215 -42
- package/test/unit/spec/meeting/utils.js +151 -7
- package/test/unit/spec/members/index.js +22 -1
- package/test/unit/spec/members/request.js +167 -35
package/src/meeting/util.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import {isEmpty} from 'lodash';
|
|
2
1
|
import {LocalCameraTrack, LocalMicrophoneTrack} from '@webex/media-helpers';
|
|
3
2
|
|
|
3
|
+
import {cloneDeep} from 'lodash';
|
|
4
4
|
import {MeetingNotActiveError, UserNotJoinedError} from '../common/errors/webex-errors';
|
|
5
5
|
import Metrics from '../metrics';
|
|
6
6
|
import {eventType, trigger} from '../metrics/config';
|
|
7
|
-
import Media from '../media';
|
|
8
7
|
import LoggerProxy from '../common/logs/logger-proxy';
|
|
9
8
|
import {
|
|
10
9
|
INTENT_TO_JOIN,
|
|
@@ -22,499 +21,536 @@ import PermissionError from '../common/errors/permission';
|
|
|
22
21
|
import PasswordError from '../common/errors/password-error';
|
|
23
22
|
import CaptchaError from '../common/errors/captcha-error';
|
|
24
23
|
|
|
25
|
-
const MeetingUtil
|
|
24
|
+
const MeetingUtil = {
|
|
25
|
+
parseLocusJoin: (response) => {
|
|
26
|
+
const parsed: any = {};
|
|
27
|
+
|
|
28
|
+
// First todo: add check for existance
|
|
29
|
+
parsed.locus = response.body.locus;
|
|
30
|
+
parsed.mediaConnections = response.body.mediaConnections;
|
|
31
|
+
parsed.locusUrl = parsed.locus.url;
|
|
32
|
+
parsed.locusId = parsed.locus.url.split('/').pop();
|
|
33
|
+
parsed.selfId = parsed.locus.self.id;
|
|
34
|
+
|
|
35
|
+
// we need mediaId before making roap calls
|
|
36
|
+
parsed.mediaConnections.forEach((mediaConnection) => {
|
|
37
|
+
if (mediaConnection.mediaId) {
|
|
38
|
+
parsed.mediaId = mediaConnection.mediaId;
|
|
39
|
+
}
|
|
40
|
+
});
|
|
26
41
|
|
|
27
|
-
|
|
28
|
-
|
|
42
|
+
return parsed;
|
|
43
|
+
},
|
|
29
44
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
parsed.locusId = parsed.locus.url.split('/').pop();
|
|
35
|
-
parsed.selfId = parsed.locus.self.id;
|
|
45
|
+
remoteUpdateAudioVideo: (meeting, audioMuted?: boolean, videoMuted?: boolean) => {
|
|
46
|
+
if (!meeting) {
|
|
47
|
+
return Promise.reject(new ParameterError('You need a meeting object.'));
|
|
48
|
+
}
|
|
36
49
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
50
|
+
if (!meeting.locusMediaRequest) {
|
|
51
|
+
return Promise.reject(
|
|
52
|
+
new ParameterError(
|
|
53
|
+
'You need a meeting with a media connection, call Meeting.addMedia() first.'
|
|
54
|
+
)
|
|
55
|
+
);
|
|
41
56
|
}
|
|
42
|
-
});
|
|
43
57
|
|
|
44
|
-
|
|
45
|
-
|
|
58
|
+
Metrics.postEvent({event: eventType.MEDIA_REQUEST, meeting});
|
|
59
|
+
|
|
60
|
+
return meeting.locusMediaRequest
|
|
61
|
+
.send({
|
|
62
|
+
type: 'LocalMute',
|
|
63
|
+
selfUrl: meeting.selfUrl,
|
|
64
|
+
mediaId: meeting.mediaId,
|
|
65
|
+
sequence: meeting.locusInfo.sequence,
|
|
66
|
+
muteOptions: {
|
|
67
|
+
audioMuted,
|
|
68
|
+
videoMuted,
|
|
69
|
+
},
|
|
70
|
+
})
|
|
71
|
+
.then((response) => {
|
|
72
|
+
Metrics.postEvent({event: eventType.MEDIA_RESPONSE, meeting});
|
|
46
73
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (!meeting.locusMediaRequest) {
|
|
53
|
-
return Promise.reject(
|
|
54
|
-
new ParameterError(
|
|
55
|
-
'You need a meeting with a media connection, call Meeting.addMedia() first.'
|
|
56
|
-
)
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
Metrics.postEvent({event: eventType.MEDIA_REQUEST, meeting});
|
|
61
|
-
|
|
62
|
-
return meeting.locusMediaRequest
|
|
63
|
-
.send({
|
|
64
|
-
type: 'LocalMute',
|
|
65
|
-
selfUrl: meeting.selfUrl,
|
|
66
|
-
mediaId: meeting.mediaId,
|
|
67
|
-
muteOptions: {
|
|
68
|
-
audioMuted,
|
|
69
|
-
videoMuted,
|
|
70
|
-
},
|
|
71
|
-
})
|
|
72
|
-
.then((response) => {
|
|
73
|
-
Metrics.postEvent({event: eventType.MEDIA_RESPONSE, meeting});
|
|
74
|
-
|
|
75
|
-
return response?.body?.locus;
|
|
76
|
-
});
|
|
77
|
-
};
|
|
74
|
+
return response?.body?.locus;
|
|
75
|
+
});
|
|
76
|
+
},
|
|
78
77
|
|
|
79
|
-
|
|
78
|
+
hasOwner: (info) => info && info.owner,
|
|
80
79
|
|
|
81
|
-
|
|
80
|
+
isOwnerSelf: (owner, selfId) => owner === selfId,
|
|
82
81
|
|
|
83
|
-
|
|
84
|
-
err?.body?.errorCode && INTENT_TO_JOIN.includes(err.body.errorCode);
|
|
82
|
+
isPinOrGuest: (err) => err?.body?.errorCode && INTENT_TO_JOIN.includes(err.body.errorCode),
|
|
85
83
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
84
|
+
joinMeeting: (meeting, options) => {
|
|
85
|
+
if (!meeting) {
|
|
86
|
+
return Promise.reject(new ParameterError('You need a meeting object.'));
|
|
87
|
+
}
|
|
90
88
|
|
|
91
|
-
|
|
89
|
+
Metrics.postEvent({event: eventType.LOCUS_JOIN_REQUEST, meeting});
|
|
90
|
+
|
|
91
|
+
// eslint-disable-next-line no-warning-comments
|
|
92
|
+
// TODO: check if the meeting is in JOINING state
|
|
93
|
+
// if Joining state termintate the request as user might click multiple times
|
|
94
|
+
return meeting.meetingRequest
|
|
95
|
+
.joinMeeting({
|
|
96
|
+
inviteeAddress: meeting.meetingJoinUrl || meeting.sipUri,
|
|
97
|
+
meetingNumber: meeting.meetingNumber,
|
|
98
|
+
deviceUrl: meeting.deviceUrl,
|
|
99
|
+
locusUrl: meeting.locusUrl,
|
|
100
|
+
correlationId: meeting.correlationId,
|
|
101
|
+
roapMessage: options.roapMessage,
|
|
102
|
+
permissionToken: meeting.permissionToken,
|
|
103
|
+
resourceId: options.resourceId || null,
|
|
104
|
+
moderator: options.moderator,
|
|
105
|
+
pin: options.pin,
|
|
106
|
+
moveToResource: options.moveToResource,
|
|
107
|
+
preferTranscoding: !meeting.isMultistream,
|
|
108
|
+
asResourceOccupant: options.asResourceOccupant,
|
|
109
|
+
breakoutsSupported: options.breakoutsSupported,
|
|
110
|
+
locale: options.locale,
|
|
111
|
+
deviceCapabilities: options.deviceCapabilities,
|
|
112
|
+
})
|
|
113
|
+
.then((res) => {
|
|
114
|
+
Metrics.postEvent({
|
|
115
|
+
event: eventType.LOCUS_JOIN_RESPONSE,
|
|
116
|
+
meeting,
|
|
117
|
+
data: {
|
|
118
|
+
trigger: trigger.LOCI_UPDATE,
|
|
119
|
+
locus: res.body.locus,
|
|
120
|
+
mediaConnections: res.body.mediaConnections,
|
|
121
|
+
trackingId: res.headers.trackingid,
|
|
122
|
+
},
|
|
123
|
+
});
|
|
92
124
|
|
|
93
|
-
|
|
94
|
-
// TODO: check if the meeting is in JOINING state
|
|
95
|
-
// if Joining state termintate the request as user might click multiple times
|
|
96
|
-
return meeting.meetingRequest
|
|
97
|
-
.joinMeeting({
|
|
98
|
-
inviteeAddress: meeting.meetingJoinUrl || meeting.sipUri,
|
|
99
|
-
meetingNumber: meeting.meetingNumber,
|
|
100
|
-
deviceUrl: meeting.deviceUrl,
|
|
101
|
-
locusUrl: meeting.locusUrl,
|
|
102
|
-
correlationId: meeting.correlationId,
|
|
103
|
-
roapMessage: options.roapMessage,
|
|
104
|
-
permissionToken: meeting.permissionToken,
|
|
105
|
-
resourceId: options.resourceId || null,
|
|
106
|
-
moderator: options.moderator,
|
|
107
|
-
pin: options.pin,
|
|
108
|
-
moveToResource: options.moveToResource,
|
|
109
|
-
preferTranscoding: !meeting.isMultistream,
|
|
110
|
-
asResourceOccupant: options.asResourceOccupant,
|
|
111
|
-
breakoutsSupported: options.breakoutsSupported,
|
|
112
|
-
locale: options.locale,
|
|
113
|
-
deviceCapabilities: options.deviceCapabilities,
|
|
114
|
-
})
|
|
115
|
-
.then((res) => {
|
|
116
|
-
Metrics.postEvent({
|
|
117
|
-
event: eventType.LOCUS_JOIN_RESPONSE,
|
|
118
|
-
meeting,
|
|
119
|
-
data: {
|
|
120
|
-
trigger: trigger.LOCI_UPDATE,
|
|
121
|
-
locus: res.body.locus,
|
|
122
|
-
mediaConnections: res.body.mediaConnections,
|
|
123
|
-
trackingId: res.headers.trackingid,
|
|
124
|
-
},
|
|
125
|
+
return MeetingUtil.parseLocusJoin(res);
|
|
125
126
|
});
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
cleanUp: (meeting) => {
|
|
130
|
+
meeting.breakouts.cleanUp();
|
|
131
|
+
|
|
132
|
+
// make sure we send last metrics before we close the peerconnection
|
|
133
|
+
const stopStatsAnalyzer = meeting.statsAnalyzer
|
|
134
|
+
? meeting.statsAnalyzer.stopAnalyzer()
|
|
135
|
+
: Promise.resolve();
|
|
136
|
+
|
|
137
|
+
return stopStatsAnalyzer
|
|
138
|
+
.then(() => meeting.closeLocalStream())
|
|
139
|
+
.then(() => meeting.closeLocalShare())
|
|
140
|
+
.then(() => meeting.closeRemoteTracks())
|
|
141
|
+
.then(() => meeting.closePeerConnections())
|
|
142
|
+
.then(() => {
|
|
143
|
+
meeting.unsetLocalVideoTrack();
|
|
144
|
+
meeting.unsetLocalShareTrack();
|
|
145
|
+
meeting.unsetRemoteTracks();
|
|
146
|
+
meeting.unsetPeerConnections();
|
|
147
|
+
meeting.reconnectionManager.cleanUp();
|
|
148
|
+
})
|
|
149
|
+
.then(() => meeting.stopKeepAlive())
|
|
150
|
+
.then(() => meeting.updateLLMConnection());
|
|
151
|
+
},
|
|
152
|
+
|
|
153
|
+
disconnectPhoneAudio: (meeting, phoneUrl) => {
|
|
154
|
+
if (meeting.meetingState === FULL_STATE.INACTIVE) {
|
|
155
|
+
return Promise.reject(new MeetingNotActiveError());
|
|
156
|
+
}
|
|
126
157
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
// make sure we send last metrics before we close the peerconnection
|
|
135
|
-
const stopStatsAnalyzer = meeting.statsAnalyzer
|
|
136
|
-
? meeting.statsAnalyzer.stopAnalyzer()
|
|
137
|
-
: Promise.resolve();
|
|
138
|
-
|
|
139
|
-
return stopStatsAnalyzer
|
|
140
|
-
.then(() => meeting.closeLocalStream())
|
|
141
|
-
.then(() => meeting.closeLocalShare())
|
|
142
|
-
.then(() => meeting.closeRemoteTracks())
|
|
143
|
-
.then(() => meeting.closePeerConnections())
|
|
144
|
-
.then(() => {
|
|
145
|
-
meeting.unsetLocalVideoTrack();
|
|
146
|
-
meeting.unsetLocalShareTrack();
|
|
147
|
-
meeting.unsetRemoteTracks();
|
|
148
|
-
meeting.unsetPeerConnections();
|
|
149
|
-
meeting.reconnectionManager.cleanUp();
|
|
150
|
-
})
|
|
151
|
-
.then(() => meeting.stopKeepAlive())
|
|
152
|
-
.then(() => meeting.updateLLMConnection());
|
|
153
|
-
};
|
|
158
|
+
const options = {
|
|
159
|
+
locusUrl: meeting.locusUrl,
|
|
160
|
+
selfId: meeting.selfId,
|
|
161
|
+
correlationId: meeting.correlationId,
|
|
162
|
+
phoneUrl,
|
|
163
|
+
};
|
|
154
164
|
|
|
155
|
-
|
|
156
|
-
if (meeting.meetingState === FULL_STATE.INACTIVE) {
|
|
157
|
-
return Promise.reject(new MeetingNotActiveError());
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
const options = {
|
|
161
|
-
locusUrl: meeting.locusUrl,
|
|
162
|
-
selfId: meeting.selfId,
|
|
163
|
-
correlationId: meeting.correlationId,
|
|
164
|
-
phoneUrl,
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
return meeting.meetingRequest
|
|
168
|
-
.disconnectPhoneAudio(options)
|
|
169
|
-
.then((response) => {
|
|
170
|
-
if (response?.body?.locus) {
|
|
171
|
-
meeting.locusInfo.onFullLocus(response.body.locus);
|
|
172
|
-
}
|
|
173
|
-
})
|
|
174
|
-
.catch((err) => {
|
|
165
|
+
return meeting.meetingRequest.disconnectPhoneAudio(options).catch((err) => {
|
|
175
166
|
LoggerProxy.logger.error(
|
|
176
167
|
`Meeting:util#disconnectPhoneAudio --> An error occured while disconnecting phone audio in meeting ${meeting.id}, error: ${err}`
|
|
177
168
|
);
|
|
178
169
|
|
|
179
170
|
return Promise.reject(err);
|
|
180
171
|
});
|
|
181
|
-
}
|
|
172
|
+
},
|
|
173
|
+
|
|
174
|
+
// by default will leave on meeting's resourceId
|
|
175
|
+
// if you explicity want it not to leave on resource id, pass
|
|
176
|
+
// {resourceId: null}
|
|
177
|
+
// TODO: chris, you can modify this however you want
|
|
178
|
+
leaveMeeting: (meeting, options: any = {}) => {
|
|
179
|
+
if (meeting.meetingState === FULL_STATE.INACTIVE) {
|
|
180
|
+
// TODO: clean up if the meeting is already inactive
|
|
181
|
+
return Promise.reject(new MeetingNotActiveError());
|
|
182
|
+
}
|
|
182
183
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
// TODO: chris, you can modify this however you want
|
|
187
|
-
MeetingUtil.leaveMeeting = (meeting, options: any = {}) => {
|
|
188
|
-
if (meeting.meetingState === FULL_STATE.INACTIVE) {
|
|
189
|
-
// TODO: clean up if the meeting is already inactive
|
|
190
|
-
return Promise.reject(new MeetingNotActiveError());
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
if (MeetingUtil.isUserInLeftState(meeting.locusInfo)) {
|
|
194
|
-
return Promise.reject(new UserNotJoinedError());
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
const defaultOptions = {
|
|
198
|
-
locusUrl: meeting.locusUrl,
|
|
199
|
-
selfId: meeting.selfId,
|
|
200
|
-
correlationId: meeting.correlationId,
|
|
201
|
-
resourceId: meeting.resourceId,
|
|
202
|
-
deviceUrl: meeting.deviceUrl,
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
const leaveOptions = {...defaultOptions, ...options};
|
|
206
|
-
|
|
207
|
-
return meeting.meetingRequest
|
|
208
|
-
.leaveMeeting(leaveOptions)
|
|
209
|
-
.then((response) => {
|
|
210
|
-
if (response && response.body && response.body.locus) {
|
|
211
|
-
// && !options.moveMeeting) {
|
|
212
|
-
meeting.locusInfo.onFullLocus(response.body.locus);
|
|
213
|
-
}
|
|
184
|
+
if (MeetingUtil.isUserInLeftState(meeting.locusInfo)) {
|
|
185
|
+
return Promise.reject(new UserNotJoinedError());
|
|
186
|
+
}
|
|
214
187
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
188
|
+
const defaultOptions = {
|
|
189
|
+
locusUrl: meeting.locusUrl,
|
|
190
|
+
selfId: meeting.selfId,
|
|
191
|
+
correlationId: meeting.correlationId,
|
|
192
|
+
resourceId: meeting.resourceId,
|
|
193
|
+
deviceUrl: meeting.deviceUrl,
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
const leaveOptions = {...defaultOptions, ...options};
|
|
197
|
+
|
|
198
|
+
return meeting.meetingRequest
|
|
199
|
+
.leaveMeeting(leaveOptions)
|
|
200
|
+
.then(() => {
|
|
201
|
+
if (options.moveMeeting) {
|
|
202
|
+
return Promise.resolve();
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return MeetingUtil.cleanUp(meeting);
|
|
206
|
+
})
|
|
207
|
+
.catch((err) => {
|
|
208
|
+
// TODO: If the meeting state comes as LEFT or INACTIVE as response then
|
|
209
|
+
// 1) on leave clean up the meeting or simply do a sync on the meeting
|
|
210
|
+
// 2) If the error says meeting is inactive then destroy the meeting object
|
|
211
|
+
LoggerProxy.logger.error(
|
|
212
|
+
`Meeting:util#leaveMeeting --> An error occured while trying to leave meeting with an id of ${meeting.id}, error: ${err}`
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
return Promise.reject(err);
|
|
216
|
+
});
|
|
217
|
+
},
|
|
218
|
+
declineMeeting: (meeting, reason) =>
|
|
219
|
+
meeting.meetingRequest.declineMeeting({
|
|
220
|
+
locusUrl: meeting.locusUrl,
|
|
221
|
+
deviceUrl: meeting.deviceUrl,
|
|
222
|
+
reason,
|
|
223
|
+
}),
|
|
221
224
|
|
|
222
|
-
|
|
223
|
-
})
|
|
224
|
-
.catch((err) => {
|
|
225
|
-
// TODO: If the meeting state comes as LEFT or INACTIVE as response then
|
|
226
|
-
// 1) on leave clean up the meeting or simply do a sync on the meeting
|
|
227
|
-
// 2) If the error says meeting is inactive then destroy the meeting object
|
|
228
|
-
LoggerProxy.logger.error(
|
|
229
|
-
`Meeting:util#leaveMeeting --> An error occured while trying to leave meeting with an id of ${meeting.id}, error: ${err}`
|
|
230
|
-
);
|
|
225
|
+
isUserInLeftState: (locusInfo) => locusInfo.parsedLocus?.self?.state === _LEFT_,
|
|
231
226
|
|
|
232
|
-
|
|
233
|
-
});
|
|
234
|
-
};
|
|
235
|
-
MeetingUtil.declineMeeting = (meeting, reason) =>
|
|
236
|
-
meeting.meetingRequest.declineMeeting({
|
|
237
|
-
locusUrl: meeting.locusUrl,
|
|
238
|
-
deviceUrl: meeting.deviceUrl,
|
|
239
|
-
reason,
|
|
240
|
-
});
|
|
227
|
+
isUserInIdleState: (locusInfo) => locusInfo.parsedLocus?.self?.state === _IDLE_,
|
|
241
228
|
|
|
242
|
-
|
|
229
|
+
isUserInJoinedState: (locusInfo) => locusInfo.parsedLocus?.self?.state === _JOINED_,
|
|
243
230
|
|
|
244
|
-
|
|
231
|
+
isMediaEstablished: (currentMediaStatus) =>
|
|
232
|
+
currentMediaStatus &&
|
|
233
|
+
(currentMediaStatus.audio || currentMediaStatus.video || currentMediaStatus.share),
|
|
245
234
|
|
|
246
|
-
|
|
235
|
+
joinMeetingOptions: (meeting, options: any = {}) => {
|
|
236
|
+
meeting.resourceId = meeting.resourceId || options.resourceId;
|
|
247
237
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
238
|
+
if (meeting.requiredCaptcha) {
|
|
239
|
+
return Promise.reject(new CaptchaError());
|
|
240
|
+
}
|
|
241
|
+
if (meeting.passwordStatus === PASSWORD_STATUS.REQUIRED) {
|
|
242
|
+
return Promise.reject(new PasswordError());
|
|
243
|
+
}
|
|
251
244
|
|
|
252
|
-
|
|
253
|
-
|
|
245
|
+
if (options.pin) {
|
|
246
|
+
Metrics.postEvent({
|
|
247
|
+
event: eventType.PIN_COLLECTED,
|
|
248
|
+
meeting,
|
|
249
|
+
});
|
|
250
|
+
}
|
|
254
251
|
|
|
255
|
-
|
|
256
|
-
return
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
252
|
+
// normal join meeting, scenario A, D
|
|
253
|
+
return MeetingUtil.joinMeeting(meeting, options)
|
|
254
|
+
.then((response) => {
|
|
255
|
+
meeting.setLocus(response);
|
|
256
|
+
|
|
257
|
+
return Promise.resolve(response);
|
|
258
|
+
})
|
|
259
|
+
.catch((err) => {
|
|
260
|
+
// joining a claimed PMR that is not my own, scenario B
|
|
261
|
+
if (MeetingUtil.isPinOrGuest(err)) {
|
|
262
|
+
Metrics.postEvent({
|
|
263
|
+
event: eventType.PIN_PROMPT,
|
|
264
|
+
meeting,
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
// request host pin or non host for unclaimed PMR, start of Scenario C
|
|
268
|
+
// see https://sqbu-github.cisco.com/WebExSquared/locus/wiki/Locus-Lobby-and--IVR-Feature
|
|
269
|
+
return Promise.reject(new IntentToJoinError('Error Joining Meeting', err));
|
|
270
|
+
}
|
|
271
|
+
LoggerProxy.logger.error(
|
|
272
|
+
'Meeting:util#joinMeetingOptions --> Error joining the call, ',
|
|
273
|
+
err
|
|
274
|
+
);
|
|
275
|
+
|
|
276
|
+
return Promise.reject(new JoinMeetingError(options, 'Error Joining Meeting', err));
|
|
277
|
+
});
|
|
278
|
+
},
|
|
261
279
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
event: eventType.PIN_COLLECTED,
|
|
265
|
-
meeting,
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
// normal join meeting, scenario A, D
|
|
270
|
-
return MeetingUtil.joinMeeting(meeting, options)
|
|
271
|
-
.then((response) => {
|
|
272
|
-
meeting.setLocus(response);
|
|
273
|
-
|
|
274
|
-
return Promise.resolve(response);
|
|
275
|
-
})
|
|
276
|
-
.catch((err) => {
|
|
277
|
-
// joining a claimed PMR that is not my own, scenario B
|
|
278
|
-
if (MeetingUtil.isPinOrGuest(err)) {
|
|
279
|
-
Metrics.postEvent({
|
|
280
|
-
event: eventType.PIN_PROMPT,
|
|
281
|
-
meeting,
|
|
282
|
-
});
|
|
280
|
+
validateOptions: (options) => {
|
|
281
|
+
const {sendVideo, sendAudio, sendShare, localStream, localShare} = options;
|
|
283
282
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
}
|
|
288
|
-
LoggerProxy.logger.error('Meeting:util#joinMeetingOptions --> Error joining the call, ', err);
|
|
283
|
+
if (sendVideo && !MeetingUtil.getTrack(localStream).videoTrack) {
|
|
284
|
+
return Promise.reject(new ParameterError('please pass valid video streams'));
|
|
285
|
+
}
|
|
289
286
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
}
|
|
287
|
+
if (sendAudio && !MeetingUtil.getTrack(localStream).audioTrack) {
|
|
288
|
+
return Promise.reject(new ParameterError('please pass valid audio streams'));
|
|
289
|
+
}
|
|
293
290
|
|
|
294
|
-
MeetingUtil.
|
|
295
|
-
|
|
291
|
+
if (sendShare && !MeetingUtil.getTrack(localShare).videoTrack) {
|
|
292
|
+
return Promise.reject(new ParameterError('please pass valid share streams'));
|
|
293
|
+
}
|
|
296
294
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
}
|
|
295
|
+
return Promise.resolve();
|
|
296
|
+
},
|
|
300
297
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
298
|
+
getTrack: (stream) => {
|
|
299
|
+
let audioTrack = null;
|
|
300
|
+
let videoTrack = null;
|
|
301
|
+
let audioTracks = null;
|
|
302
|
+
let videoTracks = null;
|
|
304
303
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
304
|
+
if (!stream) {
|
|
305
|
+
return {audioTrack: null, videoTrack: null};
|
|
306
|
+
}
|
|
307
|
+
if (stream.getAudioTracks) {
|
|
308
|
+
audioTracks = stream.getAudioTracks();
|
|
309
|
+
}
|
|
310
|
+
if (stream.getVideoTracks) {
|
|
311
|
+
videoTracks = stream.getVideoTracks();
|
|
312
|
+
}
|
|
308
313
|
|
|
309
|
-
|
|
310
|
-
|
|
314
|
+
if (audioTracks && audioTracks.length > 0) {
|
|
315
|
+
[audioTrack] = audioTracks;
|
|
316
|
+
}
|
|
311
317
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
let audioTracks = null;
|
|
316
|
-
let videoTracks = null;
|
|
317
|
-
|
|
318
|
-
if (!stream) {
|
|
319
|
-
return {audioTrack: null, videoTrack: null};
|
|
320
|
-
}
|
|
321
|
-
if (stream.getAudioTracks) {
|
|
322
|
-
audioTracks = stream.getAudioTracks();
|
|
323
|
-
}
|
|
324
|
-
if (stream.getVideoTracks) {
|
|
325
|
-
videoTracks = stream.getVideoTracks();
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
if (audioTracks && audioTracks.length > 0) {
|
|
329
|
-
[audioTrack] = audioTracks;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
if (videoTracks && videoTracks.length > 0) {
|
|
333
|
-
[videoTrack] = videoTracks;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
return {audioTrack, videoTrack};
|
|
337
|
-
};
|
|
318
|
+
if (videoTracks && videoTracks.length > 0) {
|
|
319
|
+
[videoTrack] = videoTracks;
|
|
320
|
+
}
|
|
338
321
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
locusInfo.parsedLocus &&
|
|
342
|
-
locusInfo.parsedLocus.info &&
|
|
343
|
-
locusInfo.parsedLocus.info &&
|
|
344
|
-
locusInfo.parsedLocus.info.moderator;
|
|
322
|
+
return {audioTrack, videoTrack};
|
|
323
|
+
},
|
|
345
324
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
325
|
+
getModeratorFromLocusInfo: (locusInfo) =>
|
|
326
|
+
locusInfo &&
|
|
327
|
+
locusInfo.parsedLocus &&
|
|
328
|
+
locusInfo.parsedLocus.info &&
|
|
329
|
+
locusInfo.parsedLocus.info &&
|
|
330
|
+
locusInfo.parsedLocus.info.moderator,
|
|
352
331
|
|
|
353
|
-
|
|
354
|
-
|
|
332
|
+
getPolicyFromLocusInfo: (locusInfo) =>
|
|
333
|
+
locusInfo &&
|
|
334
|
+
locusInfo.parsedLocus &&
|
|
335
|
+
locusInfo.parsedLocus.info &&
|
|
336
|
+
locusInfo.parsedLocus.info &&
|
|
337
|
+
locusInfo.parsedLocus.info.policy,
|
|
355
338
|
|
|
356
|
-
|
|
357
|
-
|
|
339
|
+
getUserDisplayHintsFromLocusInfo: (locusInfo) =>
|
|
340
|
+
locusInfo?.parsedLocus?.info?.userDisplayHints || [],
|
|
358
341
|
|
|
359
|
-
|
|
360
|
-
displayHints.includes(DISPLAY_HINTS.ROSTER_WAITING_TO_JOIN);
|
|
342
|
+
canInviteNewParticipants: (displayHints) => displayHints.includes(DISPLAY_HINTS.ADD_GUEST),
|
|
361
343
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
displayHints.includes(DISPLAY_HINTS.LOCK_STATUS_UNLOCKED);
|
|
344
|
+
canAdmitParticipant: (displayHints) =>
|
|
345
|
+
displayHints.includes(DISPLAY_HINTS.ROSTER_WAITING_TO_JOIN),
|
|
365
346
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
347
|
+
canUserLock: (displayHints) =>
|
|
348
|
+
displayHints.includes(DISPLAY_HINTS.LOCK_CONTROL_LOCK) &&
|
|
349
|
+
displayHints.includes(DISPLAY_HINTS.LOCK_STATUS_UNLOCKED),
|
|
369
350
|
|
|
370
|
-
|
|
351
|
+
canUserUnlock: (displayHints) =>
|
|
352
|
+
displayHints.includes(DISPLAY_HINTS.LOCK_CONTROL_UNLOCK) &&
|
|
353
|
+
displayHints.includes(DISPLAY_HINTS.LOCK_STATUS_LOCKED),
|
|
371
354
|
|
|
372
|
-
|
|
373
|
-
displayHints.includes(DISPLAY_HINTS.LOWER_ALL_HANDS);
|
|
355
|
+
canUserRaiseHand: (displayHints) => displayHints.includes(DISPLAY_HINTS.RAISE_HAND),
|
|
374
356
|
|
|
375
|
-
|
|
376
|
-
displayHints.includes(DISPLAY_HINTS.LOWER_SOMEONE_ELSES_HAND);
|
|
357
|
+
canUserLowerAllHands: (displayHints) => displayHints.includes(DISPLAY_HINTS.LOWER_ALL_HANDS),
|
|
377
358
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
displayHints.includes(DISPLAY_HINTS.LEAVE_END_MEETING);
|
|
359
|
+
canUserLowerSomeoneElsesHand: (displayHints) =>
|
|
360
|
+
displayHints.includes(DISPLAY_HINTS.LOWER_SOMEONE_ELSES_HAND),
|
|
381
361
|
|
|
382
|
-
|
|
383
|
-
|
|
362
|
+
bothLeaveAndEndMeetingAvailable: (displayHints) =>
|
|
363
|
+
displayHints.includes(DISPLAY_HINTS.LEAVE_TRANSFER_HOST_END_MEETING) ||
|
|
364
|
+
displayHints.includes(DISPLAY_HINTS.LEAVE_END_MEETING),
|
|
384
365
|
|
|
385
|
-
|
|
386
|
-
displayHints.includes(DISPLAY_HINTS.UCF_SUPPRESS_BREAKOUTS_SUPPORT);
|
|
366
|
+
canManageBreakout: (displayHints) => displayHints.includes(DISPLAY_HINTS.BREAKOUT_MANAGEMENT),
|
|
387
367
|
|
|
388
|
-
|
|
389
|
-
|
|
368
|
+
isSuppressBreakoutSupport: (displayHints) =>
|
|
369
|
+
displayHints.includes(DISPLAY_HINTS.UCF_SUPPRESS_BREAKOUTS_SUPPORT),
|
|
390
370
|
|
|
391
|
-
|
|
392
|
-
|
|
371
|
+
canAdmitLobbyToBreakout: (displayHints) =>
|
|
372
|
+
!displayHints.includes(DISPLAY_HINTS.DISABLE_LOBBY_TO_BREAKOUT),
|
|
393
373
|
|
|
394
|
-
|
|
395
|
-
|
|
374
|
+
isBreakoutPreassignmentsEnabled: (displayHints) =>
|
|
375
|
+
!displayHints.includes(DISPLAY_HINTS.DISABLE_BREAKOUT_PREASSIGNMENTS),
|
|
396
376
|
|
|
397
|
-
|
|
398
|
-
if (actions && actions.canLock) {
|
|
399
|
-
return request.lockMeeting({locusUrl, lock: true});
|
|
400
|
-
}
|
|
377
|
+
canUserAskForHelp: (displayHints) => !displayHints.includes(DISPLAY_HINTS.DISABLE_ASK_FOR_HELP),
|
|
401
378
|
|
|
402
|
-
|
|
403
|
-
|
|
379
|
+
lockMeeting: (actions, request, locusUrl) => {
|
|
380
|
+
if (actions && actions.canLock) {
|
|
381
|
+
return request.lockMeeting({locusUrl, lock: true});
|
|
382
|
+
}
|
|
404
383
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
return request.lockMeeting({locusUrl, lock: false});
|
|
408
|
-
}
|
|
384
|
+
return Promise.reject(new PermissionError('Lock not allowed, due to joined property.'));
|
|
385
|
+
},
|
|
409
386
|
|
|
410
|
-
|
|
411
|
-
|
|
387
|
+
unlockMeeting: (actions, request, locusUrl) => {
|
|
388
|
+
if (actions && actions.canUnlock) {
|
|
389
|
+
return request.lockMeeting({locusUrl, lock: false});
|
|
390
|
+
}
|
|
412
391
|
|
|
413
|
-
|
|
414
|
-
|
|
392
|
+
return Promise.reject(new PermissionError('Unlock not allowed, due to joined property.'));
|
|
393
|
+
},
|
|
415
394
|
|
|
416
|
-
|
|
417
|
-
const
|
|
418
|
-
const {deviceId} = settings;
|
|
395
|
+
handleAudioLogging: (audioTrack: LocalMicrophoneTrack | null) => {
|
|
396
|
+
const LOG_HEADER = 'MeetingUtil#handleAudioLogging -->';
|
|
419
397
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
};
|
|
398
|
+
if (audioTrack) {
|
|
399
|
+
const settings = audioTrack.underlyingTrack.getSettings();
|
|
400
|
+
const {deviceId} = settings;
|
|
424
401
|
|
|
425
|
-
|
|
426
|
-
|
|
402
|
+
LoggerProxy.logger.log(LOG_HEADER, `deviceId = ${deviceId}`);
|
|
403
|
+
LoggerProxy.logger.log(LOG_HEADER, 'settings =', JSON.stringify(settings));
|
|
404
|
+
}
|
|
405
|
+
},
|
|
427
406
|
|
|
428
|
-
|
|
429
|
-
const
|
|
430
|
-
const {deviceId} = settings;
|
|
407
|
+
handleVideoLogging: (videoTrack: LocalCameraTrack | null) => {
|
|
408
|
+
const LOG_HEADER = 'MeetingUtil#handleVideoLogging -->';
|
|
431
409
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
};
|
|
410
|
+
if (videoTrack) {
|
|
411
|
+
const settings = videoTrack.underlyingTrack.getSettings();
|
|
412
|
+
const {deviceId} = settings;
|
|
436
413
|
|
|
437
|
-
|
|
438
|
-
|
|
414
|
+
LoggerProxy.logger.log(LOG_HEADER, `deviceId = ${deviceId}`);
|
|
415
|
+
LoggerProxy.logger.log(LOG_HEADER, 'settings =', JSON.stringify(settings));
|
|
416
|
+
}
|
|
417
|
+
},
|
|
439
418
|
|
|
440
|
-
devices
|
|
441
|
-
|
|
442
|
-
LoggerProxy.logger.log(LOG_HEADER, 'settings', JSON.stringify(device));
|
|
443
|
-
});
|
|
444
|
-
};
|
|
419
|
+
handleDeviceLogging: (devices = []) => {
|
|
420
|
+
const LOG_HEADER = 'MeetingUtil#handleDeviceLogging -->';
|
|
445
421
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
422
|
+
devices.forEach((device) => {
|
|
423
|
+
LoggerProxy.logger.log(LOG_HEADER, `deviceId = ${device.deviceId}`);
|
|
424
|
+
LoggerProxy.logger.log(LOG_HEADER, 'settings', JSON.stringify(device));
|
|
425
|
+
});
|
|
426
|
+
},
|
|
450
427
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
428
|
+
endMeetingForAll: (meeting) => {
|
|
429
|
+
if (meeting.meetingState === FULL_STATE.INACTIVE) {
|
|
430
|
+
return Promise.reject(new MeetingNotActiveError());
|
|
431
|
+
}
|
|
454
432
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
if (response && response.body && response.body.locus) {
|
|
459
|
-
meeting.locusInfo.onFullLocus(response.body.locus);
|
|
460
|
-
}
|
|
433
|
+
const endOptions = {
|
|
434
|
+
locusUrl: meeting.locusUrl,
|
|
435
|
+
};
|
|
461
436
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
437
|
+
return meeting.meetingRequest
|
|
438
|
+
.endMeetingForAll(endOptions)
|
|
439
|
+
.then(() => MeetingUtil.cleanUp(meeting))
|
|
440
|
+
.catch((err) => {
|
|
441
|
+
LoggerProxy.logger.error(
|
|
442
|
+
`Meeting:util#endMeetingForAll An error occured while trying to end meeting for all with an id of ${meeting.id}, error: ${err}`
|
|
443
|
+
);
|
|
469
444
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
}
|
|
445
|
+
return Promise.reject(err);
|
|
446
|
+
});
|
|
447
|
+
},
|
|
473
448
|
|
|
474
|
-
|
|
475
|
-
displayHints.includes(DISPLAY_HINTS.CAPTION_START);
|
|
449
|
+
canEnableClosedCaption: (displayHints) => displayHints.includes(DISPLAY_HINTS.CAPTION_START),
|
|
476
450
|
|
|
477
|
-
|
|
478
|
-
|
|
451
|
+
isSaveTranscriptsEnabled: (displayHints) =>
|
|
452
|
+
displayHints.includes(DISPLAY_HINTS.SAVE_TRANSCRIPTS_ENABLED),
|
|
479
453
|
|
|
480
|
-
|
|
481
|
-
|
|
454
|
+
canStartTranscribing: (displayHints) =>
|
|
455
|
+
displayHints.includes(DISPLAY_HINTS.TRANSCRIPTION_CONTROL_START),
|
|
482
456
|
|
|
483
|
-
|
|
484
|
-
|
|
457
|
+
canStopTranscribing: (displayHints) =>
|
|
458
|
+
displayHints.includes(DISPLAY_HINTS.TRANSCRIPTION_CONTROL_STOP),
|
|
485
459
|
|
|
486
|
-
|
|
487
|
-
|
|
460
|
+
isClosedCaptionActive: (displayHints) =>
|
|
461
|
+
displayHints.includes(DISPLAY_HINTS.CAPTION_STATUS_ACTIVE),
|
|
488
462
|
|
|
489
|
-
|
|
490
|
-
|
|
463
|
+
isWebexAssistantActive: (displayHints) =>
|
|
464
|
+
displayHints.includes(DISPLAY_HINTS.WEBEX_ASSISTANT_STATUS_ACTIVE),
|
|
491
465
|
|
|
492
|
-
|
|
493
|
-
displayHints.includes(DISPLAY_HINTS.ENABLE_CAPTION_PANEL);
|
|
466
|
+
canViewCaptionPanel: (displayHints) => displayHints.includes(DISPLAY_HINTS.ENABLE_CAPTION_PANEL),
|
|
494
467
|
|
|
495
|
-
|
|
496
|
-
|
|
468
|
+
isRealTimeTranslationEnabled: (displayHints) =>
|
|
469
|
+
displayHints.includes(DISPLAY_HINTS.DISPLAY_REAL_TIME_TRANSLATION),
|
|
497
470
|
|
|
498
|
-
|
|
499
|
-
|
|
471
|
+
canSelectSpokenLanguages: (displayHints) =>
|
|
472
|
+
displayHints.includes(DISPLAY_HINTS.DISPLAY_NON_ENGLISH_ASR),
|
|
500
473
|
|
|
501
|
-
|
|
502
|
-
displayHints.includes(DISPLAY_HINTS.WAITING_FOR_OTHERS);
|
|
474
|
+
waitingForOthersToJoin: (displayHints) => displayHints.includes(DISPLAY_HINTS.WAITING_FOR_OTHERS),
|
|
503
475
|
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
476
|
+
canSendReactions: (originalValue, displayHints) => {
|
|
477
|
+
if (displayHints.includes(DISPLAY_HINTS.REACTIONS_ACTIVE)) {
|
|
478
|
+
return true;
|
|
479
|
+
}
|
|
480
|
+
if (displayHints.includes(DISPLAY_HINTS.REACTIONS_INACTIVE)) {
|
|
481
|
+
return false;
|
|
482
|
+
}
|
|
511
483
|
|
|
512
|
-
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
|
|
484
|
+
return originalValue;
|
|
485
|
+
},
|
|
486
|
+
canUserRenameSelfAndObserved: (displayHints) =>
|
|
487
|
+
displayHints.includes(DISPLAY_HINTS.CAN_RENAME_SELF_AND_OBSERVED),
|
|
488
|
+
|
|
489
|
+
canUserRenameOthers: (displayHints) => displayHints.includes(DISPLAY_HINTS.CAN_RENAME_OTHERS),
|
|
516
490
|
|
|
517
|
-
|
|
518
|
-
|
|
491
|
+
/**
|
|
492
|
+
* Adds the current locus sequence information to a request body
|
|
493
|
+
* @param {Object} meeting The meeting object
|
|
494
|
+
* @param {Object} requestBody The body of a request to locus
|
|
495
|
+
* @returns {void}
|
|
496
|
+
*/
|
|
497
|
+
addSequence: (meeting, requestBody) => {
|
|
498
|
+
const sequence = meeting?.locusInfo?.sequence;
|
|
499
|
+
|
|
500
|
+
if (!sequence) {
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
requestBody.sequence = sequence;
|
|
505
|
+
},
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Updates the locus info for the meeting with the delta locus
|
|
509
|
+
* returned from requests that include the sequence information
|
|
510
|
+
* Returns the original response object
|
|
511
|
+
* @param {Object} meeting The meeting object
|
|
512
|
+
* @param {Object} response The response of the http request
|
|
513
|
+
* @returns {Object}
|
|
514
|
+
*/
|
|
515
|
+
updateLocusWithDelta: (meeting, response) => {
|
|
516
|
+
if (!meeting) {
|
|
517
|
+
return response;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
const locus = response?.body?.locus;
|
|
521
|
+
|
|
522
|
+
if (locus) {
|
|
523
|
+
meeting.locusInfo.onDeltaLocus(locus);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
return response;
|
|
527
|
+
},
|
|
528
|
+
|
|
529
|
+
generateLocusDeltaRequest: (originalMeeting) => {
|
|
530
|
+
const meetingRef = new WeakRef(originalMeeting);
|
|
531
|
+
|
|
532
|
+
const locusDeltaRequest = (originalOptions) => {
|
|
533
|
+
const meeting = meetingRef.deref();
|
|
534
|
+
|
|
535
|
+
if (!meeting) {
|
|
536
|
+
return Promise.resolve();
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
const options = cloneDeep(originalOptions);
|
|
540
|
+
|
|
541
|
+
if (!options.body) {
|
|
542
|
+
options.body = {};
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
MeetingUtil.addSequence(meeting, options.body);
|
|
546
|
+
|
|
547
|
+
return meeting
|
|
548
|
+
.request(options)
|
|
549
|
+
.then((response) => MeetingUtil.updateLocusWithDelta(meeting, response));
|
|
550
|
+
};
|
|
551
|
+
|
|
552
|
+
return locusDeltaRequest;
|
|
553
|
+
},
|
|
554
|
+
};
|
|
519
555
|
|
|
520
556
|
export default MeetingUtil;
|