@wazo/sdk 0.37.30 → 0.37.34
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/wazo-sdk.js +4 -4
- package/esm/__tests__/api-client.test.js +30 -0
- package/esm/__tests__/web-rtc-client.test.js +57 -6
- package/esm/api/calld.js +30 -0
- package/esm/api-client.js +30 -0
- package/esm/checker/Checker.js +57 -6
- package/esm/checker/checks/aor.js +30 -0
- package/esm/checker/checks/api.js +30 -0
- package/esm/checker/checks/index.js +57 -6
- package/esm/checker/checks/webrtc-transport.js +57 -6
- package/esm/checker/checks/webrtc.js +57 -6
- package/esm/domain/AdHocAPIConference.js +30 -0
- package/esm/domain/CallSession.js +9 -1
- package/esm/domain/Features.js +30 -0
- package/esm/domain/MeetingStatus.js +29 -0
- package/esm/domain/Phone/CTIPhone.js +39 -1
- package/esm/domain/Phone/WebRTCPhone.js +43 -8
- package/esm/domain/__tests__/CallSession.test.js +41 -5
- package/esm/domain/__tests__/IndirectTransfer.test.js +9 -1
- package/esm/domain/__tests__/Room.test.js +9 -1
- package/esm/index.js +100 -14
- package/esm/service/CallApi.js +30 -0
- package/esm/service/getApiClient.js +30 -0
- package/esm/simple/Auth.js +100 -14
- package/esm/simple/Configuration.js +100 -14
- package/esm/simple/Directory.js +30 -0
- package/esm/simple/Phone.js +100 -14
- package/esm/simple/index.js +100 -14
- package/esm/simple/room/LocalParticipant.js +100 -14
- package/esm/simple/room/Participant.js +100 -14
- package/esm/simple/room/RemoteParticipant.js +100 -14
- package/esm/simple/room/Room.js +100 -14
- package/esm/simple/room/SipRoom.js +100 -14
- package/esm/simple/room/Stream.js +100 -14
- package/esm/simple/room/__tests__/RemoteParticipant.test.js +100 -14
- package/esm/simple/utils.js +100 -14
- package/esm/web-rtc-client.js +57 -6
- package/lib/__tests__/api-client.test.js +30 -0
- package/lib/__tests__/web-rtc-client.test.js +57 -6
- package/lib/api/calld.js +30 -0
- package/lib/api-client.js +30 -0
- package/lib/checker/Checker.js +57 -6
- package/lib/checker/checks/aor.js +30 -0
- package/lib/checker/checks/api.js +30 -0
- package/lib/checker/checks/index.js +57 -6
- package/lib/checker/checks/webrtc-transport.js +57 -6
- package/lib/checker/checks/webrtc.js +57 -6
- package/lib/domain/AdHocAPIConference.js +30 -0
- package/lib/domain/CallSession.js +9 -1
- package/lib/domain/Features.js +30 -0
- package/lib/domain/MeetingStatus.js +31 -0
- package/lib/domain/Phone/CTIPhone.js +39 -1
- package/lib/domain/Phone/WebRTCPhone.js +43 -8
- package/lib/domain/__tests__/CallSession.test.js +41 -5
- package/lib/domain/__tests__/IndirectTransfer.test.js +9 -1
- package/lib/domain/__tests__/Room.test.js +9 -1
- package/lib/index.js +100 -14
- package/lib/service/CallApi.js +30 -0
- package/lib/service/getApiClient.js +30 -0
- package/lib/simple/Auth.js +100 -14
- package/lib/simple/Configuration.js +100 -14
- package/lib/simple/Directory.js +30 -0
- package/lib/simple/Phone.js +100 -14
- package/lib/simple/index.js +100 -14
- package/lib/simple/room/LocalParticipant.js +100 -14
- package/lib/simple/room/Participant.js +100 -14
- package/lib/simple/room/RemoteParticipant.js +100 -14
- package/lib/simple/room/Room.js +100 -14
- package/lib/simple/room/SipRoom.js +100 -14
- package/lib/simple/room/Stream.js +100 -14
- package/lib/simple/room/__tests__/RemoteParticipant.test.js +100 -14
- package/lib/simple/utils.js +100 -14
- package/lib/web-rtc-client.js +57 -6
- package/package.json +1 -1
- package/src/api/calld.js +3 -0
- package/src/domain/CallSession.js +9 -1
- package/src/domain/MeetingStatus.js +27 -0
- package/src/domain/Phone/WebRTCPhone.js +34 -7
- package/src/domain/__tests__/CallSession.test.js +32 -4
- package/src/web-rtc-client.js +27 -6
|
@@ -4579,6 +4579,34 @@ var chatdMethods = (client , baseUrl ) => ({
|
|
|
4579
4579
|
client.get(`${baseUrl}/users/me/rooms/messages`, options),
|
|
4580
4580
|
});
|
|
4581
4581
|
|
|
4582
|
+
//
|
|
4583
|
+
|
|
4584
|
+
|
|
4585
|
+
|
|
4586
|
+
|
|
4587
|
+
|
|
4588
|
+
class MeetingStatus {
|
|
4589
|
+
|
|
4590
|
+
|
|
4591
|
+
|
|
4592
|
+
|
|
4593
|
+
constructor({
|
|
4594
|
+
full,
|
|
4595
|
+
} = {}) {
|
|
4596
|
+
this.full = full;
|
|
4597
|
+
|
|
4598
|
+
// Useful to compare instead of instanceof with minified code
|
|
4599
|
+
this.type = 'MeetingStatus';
|
|
4600
|
+
}
|
|
4601
|
+
|
|
4602
|
+
static parse(plain ) {
|
|
4603
|
+
return new MeetingStatus({
|
|
4604
|
+
full: plain.full,
|
|
4605
|
+
});
|
|
4606
|
+
}
|
|
4607
|
+
|
|
4608
|
+
}
|
|
4609
|
+
|
|
4582
4610
|
/* */
|
|
4583
4611
|
|
|
4584
4612
|
|
|
@@ -4773,6 +4801,8 @@ var calldMethods = (client , baseUrl ) => ({
|
|
|
4773
4801
|
client.put(`${baseUrl}/users/me/calls/${callId}/record/resume`, null, null,
|
|
4774
4802
|
ApiRequester.successResponseParser),
|
|
4775
4803
|
|
|
4804
|
+
guestGetMeetingStatus: (meetingUuid ) =>
|
|
4805
|
+
client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}/status`).then(MeetingStatus.parse),
|
|
4776
4806
|
});
|
|
4777
4807
|
|
|
4778
4808
|
//
|
|
@@ -5332,7 +5362,7 @@ const ON_NETWORK_STATS = 'onNetworkStats';
|
|
|
5332
5362
|
const ON_DISCONNECTED = 'onDisconnected';
|
|
5333
5363
|
class CanceledCallError extends Error {}
|
|
5334
5364
|
|
|
5335
|
-
const MAX_REGISTER_TRIES =
|
|
5365
|
+
const MAX_REGISTER_TRIES = 5;
|
|
5336
5366
|
|
|
5337
5367
|
|
|
5338
5368
|
|
|
@@ -5386,6 +5416,7 @@ class WebRTCClient extends Emitter {
|
|
|
5386
5416
|
|
|
5387
5417
|
|
|
5388
5418
|
|
|
5419
|
+
|
|
5389
5420
|
|
|
5390
5421
|
// sugar
|
|
5391
5422
|
|
|
@@ -5448,6 +5479,7 @@ class WebRTCClient extends Emitter {
|
|
|
5448
5479
|
this.conferences = {};
|
|
5449
5480
|
this.networkMonitoringInterval = {};
|
|
5450
5481
|
this.sessionNetworkStats = {};
|
|
5482
|
+
this.forceClosed = false;
|
|
5451
5483
|
|
|
5452
5484
|
this._boundOnHeartbeat = this._onHeartbeat.bind(this);
|
|
5453
5485
|
this.heartbeat = new Heartbeat(config.heartbeatDelay, config.heartbeatTimeout, config.maxHeartbeats);
|
|
@@ -5569,6 +5601,8 @@ class WebRTCClient extends Emitter {
|
|
|
5569
5601
|
skipRegister: this.skipRegister,
|
|
5570
5602
|
};
|
|
5571
5603
|
|
|
5604
|
+
this.forceClosed = false;
|
|
5605
|
+
|
|
5572
5606
|
if (this.skipRegister) {
|
|
5573
5607
|
logger.info('sdk webrtc skip register...', logInfo);
|
|
5574
5608
|
return Promise.resolve();
|
|
@@ -5593,7 +5627,15 @@ class WebRTCClient extends Emitter {
|
|
|
5593
5627
|
const registerOptions = this._isWeb() ? {} : { extraContactHeaderParams: ['mobility=mobile'] };
|
|
5594
5628
|
|
|
5595
5629
|
const onRegisterFailed = () => {
|
|
5596
|
-
logger.info('sdk webrtc registering failed', {
|
|
5630
|
+
logger.info('sdk webrtc registering failed', {
|
|
5631
|
+
tries,
|
|
5632
|
+
registerer: !!this.registerer,
|
|
5633
|
+
forceClosed: this.forceClosed,
|
|
5634
|
+
});
|
|
5635
|
+
if (this.forceClosed) {
|
|
5636
|
+
return;
|
|
5637
|
+
}
|
|
5638
|
+
|
|
5597
5639
|
this.connectionPromise = null;
|
|
5598
5640
|
if (this.registerer && this.registerer.waiting) {
|
|
5599
5641
|
this.registerer.waitingToggle(false);
|
|
@@ -5871,8 +5913,9 @@ class WebRTCClient extends Emitter {
|
|
|
5871
5913
|
}
|
|
5872
5914
|
}
|
|
5873
5915
|
|
|
5874
|
-
async close() {
|
|
5875
|
-
logger.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
|
|
5916
|
+
async close(force = false) {
|
|
5917
|
+
logger.info('sdk webrtc closing client', { userAgent: !!this.userAgent, force });
|
|
5918
|
+
this.forceClosed = force;
|
|
5876
5919
|
this._cleanupMedia();
|
|
5877
5920
|
this.connectionPromise = null;
|
|
5878
5921
|
|
|
@@ -5891,7 +5934,7 @@ class WebRTCClient extends Emitter {
|
|
|
5891
5934
|
this.userAgent.delegate = null;
|
|
5892
5935
|
this.userAgent.stateChange.removeAllListeners();
|
|
5893
5936
|
|
|
5894
|
-
await this._disconnectTransport();
|
|
5937
|
+
await this._disconnectTransport(force);
|
|
5895
5938
|
|
|
5896
5939
|
this._cleanupRegister();
|
|
5897
5940
|
|
|
@@ -7327,7 +7370,15 @@ class WebRTCClient extends Emitter {
|
|
|
7327
7370
|
return UserAgent.makeURI(`sip:${target}@${this.config.host}`);
|
|
7328
7371
|
}
|
|
7329
7372
|
|
|
7330
|
-
async _disconnectTransport() {
|
|
7373
|
+
async _disconnectTransport(force = false) {
|
|
7374
|
+
if (force) {
|
|
7375
|
+
// Bypass sip.js state machine that prevent to close WS with the state `Connecting`
|
|
7376
|
+
this.userAgent.transport.disconnectResolve = () => {};
|
|
7377
|
+
// eslint-disable-next-line
|
|
7378
|
+
this.userAgent.transport._ws.close(1000);
|
|
7379
|
+
return;
|
|
7380
|
+
}
|
|
7381
|
+
|
|
7331
7382
|
// Check if `disconnectPromise` is not present to avoid `Disconnect promise must not be defined` errors.
|
|
7332
7383
|
if (this.userAgent && this.userAgent.transport && !this.userAgent.transport.disconnectPromise) {
|
|
7333
7384
|
try {
|
|
@@ -4579,6 +4579,34 @@ var chatdMethods = (client , baseUrl ) => ({
|
|
|
4579
4579
|
client.get(`${baseUrl}/users/me/rooms/messages`, options),
|
|
4580
4580
|
});
|
|
4581
4581
|
|
|
4582
|
+
//
|
|
4583
|
+
|
|
4584
|
+
|
|
4585
|
+
|
|
4586
|
+
|
|
4587
|
+
|
|
4588
|
+
class MeetingStatus {
|
|
4589
|
+
|
|
4590
|
+
|
|
4591
|
+
|
|
4592
|
+
|
|
4593
|
+
constructor({
|
|
4594
|
+
full,
|
|
4595
|
+
} = {}) {
|
|
4596
|
+
this.full = full;
|
|
4597
|
+
|
|
4598
|
+
// Useful to compare instead of instanceof with minified code
|
|
4599
|
+
this.type = 'MeetingStatus';
|
|
4600
|
+
}
|
|
4601
|
+
|
|
4602
|
+
static parse(plain ) {
|
|
4603
|
+
return new MeetingStatus({
|
|
4604
|
+
full: plain.full,
|
|
4605
|
+
});
|
|
4606
|
+
}
|
|
4607
|
+
|
|
4608
|
+
}
|
|
4609
|
+
|
|
4582
4610
|
/* */
|
|
4583
4611
|
|
|
4584
4612
|
|
|
@@ -4773,6 +4801,8 @@ var calldMethods = (client , baseUrl ) => ({
|
|
|
4773
4801
|
client.put(`${baseUrl}/users/me/calls/${callId}/record/resume`, null, null,
|
|
4774
4802
|
ApiRequester.successResponseParser),
|
|
4775
4803
|
|
|
4804
|
+
guestGetMeetingStatus: (meetingUuid ) =>
|
|
4805
|
+
client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}/status`).then(MeetingStatus.parse),
|
|
4776
4806
|
});
|
|
4777
4807
|
|
|
4778
4808
|
//
|
|
@@ -5332,7 +5362,7 @@ const ON_NETWORK_STATS = 'onNetworkStats';
|
|
|
5332
5362
|
const ON_DISCONNECTED = 'onDisconnected';
|
|
5333
5363
|
class CanceledCallError extends Error {}
|
|
5334
5364
|
|
|
5335
|
-
const MAX_REGISTER_TRIES =
|
|
5365
|
+
const MAX_REGISTER_TRIES = 5;
|
|
5336
5366
|
|
|
5337
5367
|
|
|
5338
5368
|
|
|
@@ -5386,6 +5416,7 @@ class WebRTCClient extends Emitter {
|
|
|
5386
5416
|
|
|
5387
5417
|
|
|
5388
5418
|
|
|
5419
|
+
|
|
5389
5420
|
|
|
5390
5421
|
// sugar
|
|
5391
5422
|
|
|
@@ -5448,6 +5479,7 @@ class WebRTCClient extends Emitter {
|
|
|
5448
5479
|
this.conferences = {};
|
|
5449
5480
|
this.networkMonitoringInterval = {};
|
|
5450
5481
|
this.sessionNetworkStats = {};
|
|
5482
|
+
this.forceClosed = false;
|
|
5451
5483
|
|
|
5452
5484
|
this._boundOnHeartbeat = this._onHeartbeat.bind(this);
|
|
5453
5485
|
this.heartbeat = new Heartbeat(config.heartbeatDelay, config.heartbeatTimeout, config.maxHeartbeats);
|
|
@@ -5569,6 +5601,8 @@ class WebRTCClient extends Emitter {
|
|
|
5569
5601
|
skipRegister: this.skipRegister,
|
|
5570
5602
|
};
|
|
5571
5603
|
|
|
5604
|
+
this.forceClosed = false;
|
|
5605
|
+
|
|
5572
5606
|
if (this.skipRegister) {
|
|
5573
5607
|
logger.info('sdk webrtc skip register...', logInfo);
|
|
5574
5608
|
return Promise.resolve();
|
|
@@ -5593,7 +5627,15 @@ class WebRTCClient extends Emitter {
|
|
|
5593
5627
|
const registerOptions = this._isWeb() ? {} : { extraContactHeaderParams: ['mobility=mobile'] };
|
|
5594
5628
|
|
|
5595
5629
|
const onRegisterFailed = () => {
|
|
5596
|
-
logger.info('sdk webrtc registering failed', {
|
|
5630
|
+
logger.info('sdk webrtc registering failed', {
|
|
5631
|
+
tries,
|
|
5632
|
+
registerer: !!this.registerer,
|
|
5633
|
+
forceClosed: this.forceClosed,
|
|
5634
|
+
});
|
|
5635
|
+
if (this.forceClosed) {
|
|
5636
|
+
return;
|
|
5637
|
+
}
|
|
5638
|
+
|
|
5597
5639
|
this.connectionPromise = null;
|
|
5598
5640
|
if (this.registerer && this.registerer.waiting) {
|
|
5599
5641
|
this.registerer.waitingToggle(false);
|
|
@@ -5871,8 +5913,9 @@ class WebRTCClient extends Emitter {
|
|
|
5871
5913
|
}
|
|
5872
5914
|
}
|
|
5873
5915
|
|
|
5874
|
-
async close() {
|
|
5875
|
-
logger.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
|
|
5916
|
+
async close(force = false) {
|
|
5917
|
+
logger.info('sdk webrtc closing client', { userAgent: !!this.userAgent, force });
|
|
5918
|
+
this.forceClosed = force;
|
|
5876
5919
|
this._cleanupMedia();
|
|
5877
5920
|
this.connectionPromise = null;
|
|
5878
5921
|
|
|
@@ -5891,7 +5934,7 @@ class WebRTCClient extends Emitter {
|
|
|
5891
5934
|
this.userAgent.delegate = null;
|
|
5892
5935
|
this.userAgent.stateChange.removeAllListeners();
|
|
5893
5936
|
|
|
5894
|
-
await this._disconnectTransport();
|
|
5937
|
+
await this._disconnectTransport(force);
|
|
5895
5938
|
|
|
5896
5939
|
this._cleanupRegister();
|
|
5897
5940
|
|
|
@@ -7327,7 +7370,15 @@ class WebRTCClient extends Emitter {
|
|
|
7327
7370
|
return UserAgent.makeURI(`sip:${target}@${this.config.host}`);
|
|
7328
7371
|
}
|
|
7329
7372
|
|
|
7330
|
-
async _disconnectTransport() {
|
|
7373
|
+
async _disconnectTransport(force = false) {
|
|
7374
|
+
if (force) {
|
|
7375
|
+
// Bypass sip.js state machine that prevent to close WS with the state `Connecting`
|
|
7376
|
+
this.userAgent.transport.disconnectResolve = () => {};
|
|
7377
|
+
// eslint-disable-next-line
|
|
7378
|
+
this.userAgent.transport._ws.close(1000);
|
|
7379
|
+
return;
|
|
7380
|
+
}
|
|
7381
|
+
|
|
7331
7382
|
// Check if `disconnectPromise` is not present to avoid `Disconnect promise must not be defined` errors.
|
|
7332
7383
|
if (this.userAgent && this.userAgent.transport && !this.userAgent.transport.disconnectPromise) {
|
|
7333
7384
|
try {
|
|
@@ -4016,6 +4016,34 @@ var chatdMethods = (client , baseUrl ) => ({
|
|
|
4016
4016
|
client.get(`${baseUrl}/users/me/rooms/messages`, options),
|
|
4017
4017
|
});
|
|
4018
4018
|
|
|
4019
|
+
//
|
|
4020
|
+
|
|
4021
|
+
|
|
4022
|
+
|
|
4023
|
+
|
|
4024
|
+
|
|
4025
|
+
class MeetingStatus {
|
|
4026
|
+
|
|
4027
|
+
|
|
4028
|
+
|
|
4029
|
+
|
|
4030
|
+
constructor({
|
|
4031
|
+
full,
|
|
4032
|
+
} = {}) {
|
|
4033
|
+
this.full = full;
|
|
4034
|
+
|
|
4035
|
+
// Useful to compare instead of instanceof with minified code
|
|
4036
|
+
this.type = 'MeetingStatus';
|
|
4037
|
+
}
|
|
4038
|
+
|
|
4039
|
+
static parse(plain ) {
|
|
4040
|
+
return new MeetingStatus({
|
|
4041
|
+
full: plain.full,
|
|
4042
|
+
});
|
|
4043
|
+
}
|
|
4044
|
+
|
|
4045
|
+
}
|
|
4046
|
+
|
|
4019
4047
|
/* */
|
|
4020
4048
|
|
|
4021
4049
|
|
|
@@ -4210,6 +4238,8 @@ var calldMethods = (client , baseUrl ) => ({
|
|
|
4210
4238
|
client.put(`${baseUrl}/users/me/calls/${callId}/record/resume`, null, null,
|
|
4211
4239
|
ApiRequester.successResponseParser),
|
|
4212
4240
|
|
|
4241
|
+
guestGetMeetingStatus: (meetingUuid ) =>
|
|
4242
|
+
client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}/status`).then(MeetingStatus.parse),
|
|
4213
4243
|
});
|
|
4214
4244
|
|
|
4215
4245
|
//
|
|
@@ -368,13 +368,21 @@ class CallSession {
|
|
|
368
368
|
|
|
369
369
|
// Retro-compatibility: `answered` was a boolean before. We can reproduce the behaviour with a getter/setter
|
|
370
370
|
set answered(value ) {
|
|
371
|
-
this.answerTime = value ? new Date() : null;
|
|
371
|
+
this.answerTime = value ? this.answerTime || new Date() : null;
|
|
372
372
|
}
|
|
373
373
|
|
|
374
374
|
get answered() {
|
|
375
375
|
return !!this.answerTime;
|
|
376
376
|
}
|
|
377
377
|
|
|
378
|
+
toJSON() {
|
|
379
|
+
const jsonObj = { ...this };
|
|
380
|
+
// $FlowFixMe
|
|
381
|
+
jsonObj.answered = this.answered;
|
|
382
|
+
|
|
383
|
+
return jsonObj;
|
|
384
|
+
}
|
|
385
|
+
|
|
378
386
|
static parseCall(call ) {
|
|
379
387
|
return new CallSession({
|
|
380
388
|
callId: call.id,
|
package/esm/domain/Features.js
CHANGED
|
@@ -4016,6 +4016,34 @@ var chatdMethods = (client , baseUrl ) => ({
|
|
|
4016
4016
|
client.get(`${baseUrl}/users/me/rooms/messages`, options),
|
|
4017
4017
|
});
|
|
4018
4018
|
|
|
4019
|
+
//
|
|
4020
|
+
|
|
4021
|
+
|
|
4022
|
+
|
|
4023
|
+
|
|
4024
|
+
|
|
4025
|
+
class MeetingStatus {
|
|
4026
|
+
|
|
4027
|
+
|
|
4028
|
+
|
|
4029
|
+
|
|
4030
|
+
constructor({
|
|
4031
|
+
full,
|
|
4032
|
+
} = {}) {
|
|
4033
|
+
this.full = full;
|
|
4034
|
+
|
|
4035
|
+
// Useful to compare instead of instanceof with minified code
|
|
4036
|
+
this.type = 'MeetingStatus';
|
|
4037
|
+
}
|
|
4038
|
+
|
|
4039
|
+
static parse(plain ) {
|
|
4040
|
+
return new MeetingStatus({
|
|
4041
|
+
full: plain.full,
|
|
4042
|
+
});
|
|
4043
|
+
}
|
|
4044
|
+
|
|
4045
|
+
}
|
|
4046
|
+
|
|
4019
4047
|
/* */
|
|
4020
4048
|
|
|
4021
4049
|
|
|
@@ -4210,6 +4238,8 @@ var calldMethods = (client , baseUrl ) => ({
|
|
|
4210
4238
|
client.put(`${baseUrl}/users/me/calls/${callId}/record/resume`, null, null,
|
|
4211
4239
|
ApiRequester.successResponseParser),
|
|
4212
4240
|
|
|
4241
|
+
guestGetMeetingStatus: (meetingUuid ) =>
|
|
4242
|
+
client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}/status`).then(MeetingStatus.parse),
|
|
4213
4243
|
});
|
|
4214
4244
|
|
|
4215
4245
|
//
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
//
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class MeetingStatus {
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
constructor({
|
|
13
|
+
full,
|
|
14
|
+
} = {}) {
|
|
15
|
+
this.full = full;
|
|
16
|
+
|
|
17
|
+
// Useful to compare instead of instanceof with minified code
|
|
18
|
+
this.type = 'MeetingStatus';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
static parse(plain ) {
|
|
22
|
+
return new MeetingStatus({
|
|
23
|
+
full: plain.full,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export default MeetingStatus;
|
|
@@ -2042,13 +2042,21 @@ class CallSession {
|
|
|
2042
2042
|
|
|
2043
2043
|
// Retro-compatibility: `answered` was a boolean before. We can reproduce the behaviour with a getter/setter
|
|
2044
2044
|
set answered(value ) {
|
|
2045
|
-
this.answerTime = value ? new Date() : null;
|
|
2045
|
+
this.answerTime = value ? this.answerTime || new Date() : null;
|
|
2046
2046
|
}
|
|
2047
2047
|
|
|
2048
2048
|
get answered() {
|
|
2049
2049
|
return !!this.answerTime;
|
|
2050
2050
|
}
|
|
2051
2051
|
|
|
2052
|
+
toJSON() {
|
|
2053
|
+
const jsonObj = { ...this };
|
|
2054
|
+
// $FlowFixMe
|
|
2055
|
+
jsonObj.answered = this.answered;
|
|
2056
|
+
|
|
2057
|
+
return jsonObj;
|
|
2058
|
+
}
|
|
2059
|
+
|
|
2052
2060
|
static parseCall(call ) {
|
|
2053
2061
|
return new CallSession({
|
|
2054
2062
|
callId: call.id,
|
|
@@ -4407,6 +4415,34 @@ class IndirectTransfer {
|
|
|
4407
4415
|
}
|
|
4408
4416
|
}
|
|
4409
4417
|
|
|
4418
|
+
//
|
|
4419
|
+
|
|
4420
|
+
|
|
4421
|
+
|
|
4422
|
+
|
|
4423
|
+
|
|
4424
|
+
class MeetingStatus {
|
|
4425
|
+
|
|
4426
|
+
|
|
4427
|
+
|
|
4428
|
+
|
|
4429
|
+
constructor({
|
|
4430
|
+
full,
|
|
4431
|
+
} = {}) {
|
|
4432
|
+
this.full = full;
|
|
4433
|
+
|
|
4434
|
+
// Useful to compare instead of instanceof with minified code
|
|
4435
|
+
this.type = 'MeetingStatus';
|
|
4436
|
+
}
|
|
4437
|
+
|
|
4438
|
+
static parse(plain ) {
|
|
4439
|
+
return new MeetingStatus({
|
|
4440
|
+
full: plain.full,
|
|
4441
|
+
});
|
|
4442
|
+
}
|
|
4443
|
+
|
|
4444
|
+
}
|
|
4445
|
+
|
|
4410
4446
|
/* */
|
|
4411
4447
|
|
|
4412
4448
|
|
|
@@ -4601,6 +4637,8 @@ var calldMethods = (client , baseUrl ) => ({
|
|
|
4601
4637
|
client.put(`${baseUrl}/users/me/calls/${callId}/record/resume`, null, null,
|
|
4602
4638
|
ApiRequester.successResponseParser),
|
|
4603
4639
|
|
|
4640
|
+
guestGetMeetingStatus: (meetingUuid ) =>
|
|
4641
|
+
client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}/status`).then(MeetingStatus.parse),
|
|
4604
4642
|
});
|
|
4605
4643
|
|
|
4606
4644
|
//
|
|
@@ -390,13 +390,21 @@ class CallSession {
|
|
|
390
390
|
|
|
391
391
|
// Retro-compatibility: `answered` was a boolean before. We can reproduce the behaviour with a getter/setter
|
|
392
392
|
set answered(value ) {
|
|
393
|
-
this.answerTime = value ? new Date() : null;
|
|
393
|
+
this.answerTime = value ? this.answerTime || new Date() : null;
|
|
394
394
|
}
|
|
395
395
|
|
|
396
396
|
get answered() {
|
|
397
397
|
return !!this.answerTime;
|
|
398
398
|
}
|
|
399
399
|
|
|
400
|
+
toJSON() {
|
|
401
|
+
const jsonObj = { ...this };
|
|
402
|
+
// $FlowFixMe
|
|
403
|
+
jsonObj.answered = this.answered;
|
|
404
|
+
|
|
405
|
+
return jsonObj;
|
|
406
|
+
}
|
|
407
|
+
|
|
400
408
|
static parseCall(call ) {
|
|
401
409
|
return new CallSession({
|
|
402
410
|
callId: call.id,
|
|
@@ -1504,6 +1512,7 @@ class WebRTCPhone extends Emitter {
|
|
|
1504
1512
|
}
|
|
1505
1513
|
|
|
1506
1514
|
callSession.answerTime = new Date();
|
|
1515
|
+
this._updateCallSession(callSession);
|
|
1507
1516
|
this.eventEmitter.emit(ON_CALL_ACCEPTED, callSession, cameraEnabled);
|
|
1508
1517
|
|
|
1509
1518
|
return callSession;
|
|
@@ -1713,6 +1722,12 @@ class WebRTCPhone extends Emitter {
|
|
|
1713
1722
|
return Promise.resolve(null);
|
|
1714
1723
|
}
|
|
1715
1724
|
|
|
1725
|
+
const sipSessionId = this.getSipSessionIdFromCallSession(callSession);
|
|
1726
|
+
if (sipSessionId && !(sipSessionId in this.callSessions)) {
|
|
1727
|
+
logger.warn('Call session already ended or not found, can\'t accept it.', { sipSessionId });
|
|
1728
|
+
return Promise.resolve(null);
|
|
1729
|
+
}
|
|
1730
|
+
|
|
1716
1731
|
if (callSession.getId() in this.acceptedSessions) {
|
|
1717
1732
|
logger.warn('CallSession already accepted.', { id: callSession ? callSession.getId() : 'n/a' });
|
|
1718
1733
|
return Promise.resolve(callSession.sipCallId);
|
|
@@ -1720,6 +1735,7 @@ class WebRTCPhone extends Emitter {
|
|
|
1720
1735
|
|
|
1721
1736
|
this.shouldSendReinvite = false;
|
|
1722
1737
|
callSession.answerTime = new Date();
|
|
1738
|
+
this._updateCallSession(callSession);
|
|
1723
1739
|
this.acceptedSessions[callSession.getId()] = true;
|
|
1724
1740
|
|
|
1725
1741
|
this.eventEmitter.emit(ON_CALL_ANSWERED, callSession);
|
|
@@ -1819,7 +1835,7 @@ class WebRTCPhone extends Emitter {
|
|
|
1819
1835
|
// Hold current session if different from the current one (we don't want 2 sessions active at the same time).
|
|
1820
1836
|
if (this.currentSipSession && this.currentSipSession.id !== sipSession.id) {
|
|
1821
1837
|
logger.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
|
|
1822
|
-
this.holdSipSession(this.currentSipSession,
|
|
1838
|
+
this.holdSipSession(this.currentSipSession, this.currentCallSession);
|
|
1823
1839
|
}
|
|
1824
1840
|
|
|
1825
1841
|
const promise = this.unholdSipSession(sipSession, callSession, withEvent, isConference);
|
|
@@ -2030,6 +2046,7 @@ class WebRTCPhone extends Emitter {
|
|
|
2030
2046
|
}
|
|
2031
2047
|
const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
|
|
2032
2048
|
callSession.creationTime = new Date();
|
|
2049
|
+
this._updateCallSession(callSession);
|
|
2033
2050
|
|
|
2034
2051
|
this.eventEmitter.emit(ON_PLAY_PROGRESS_SOUND, this.audioOutputDeviceId, this.audioOutputVolume);
|
|
2035
2052
|
|
|
@@ -2171,7 +2188,7 @@ class WebRTCPhone extends Emitter {
|
|
|
2171
2188
|
return this.client && this.client.isConference(callSession.sipCallId);
|
|
2172
2189
|
}
|
|
2173
2190
|
|
|
2174
|
-
async close() {
|
|
2191
|
+
async close(force = false) {
|
|
2175
2192
|
logger.info('WebRTC close');
|
|
2176
2193
|
|
|
2177
2194
|
try {
|
|
@@ -2183,7 +2200,7 @@ class WebRTCPhone extends Emitter {
|
|
|
2183
2200
|
logger.error('WebRTC close, unregister error', e);
|
|
2184
2201
|
}
|
|
2185
2202
|
|
|
2186
|
-
this.client.close();
|
|
2203
|
+
this.client.close(force);
|
|
2187
2204
|
this.unbind();
|
|
2188
2205
|
|
|
2189
2206
|
this.incomingSessions = [];
|
|
@@ -2309,6 +2326,8 @@ class WebRTCPhone extends Emitter {
|
|
|
2309
2326
|
}
|
|
2310
2327
|
|
|
2311
2328
|
callSession.creationTime = new Date();
|
|
2329
|
+
this._updateCallSession(callSession);
|
|
2330
|
+
|
|
2312
2331
|
this.eventEmitter.emit(ON_CALL_INCOMING, callSession, wantsToDoVideo);
|
|
2313
2332
|
});
|
|
2314
2333
|
|
|
@@ -2333,9 +2352,17 @@ class WebRTCPhone extends Emitter {
|
|
|
2333
2352
|
});
|
|
2334
2353
|
|
|
2335
2354
|
this.client.on(this.client.ACCEPTED, (sipSession ) => {
|
|
2336
|
-
|
|
2355
|
+
const sessionId = this.getSipSessionId(sipSession);
|
|
2356
|
+
const hasSession = sessionId in this.callSessions;
|
|
2337
2357
|
|
|
2338
|
-
|
|
2358
|
+
logger.info('WebRTC call accepted', { sipId: sessionId, hasSession });
|
|
2359
|
+
|
|
2360
|
+
if (!hasSession) {
|
|
2361
|
+
logger.warn('Call accepted ignored, session is no longer present in the WebRtcPhone', { sessionId });
|
|
2362
|
+
return;
|
|
2363
|
+
}
|
|
2364
|
+
|
|
2365
|
+
this._onCallAccepted(sipSession, this.client.hasVideo(sessionId));
|
|
2339
2366
|
|
|
2340
2367
|
if (this.audioOutputDeviceId) {
|
|
2341
2368
|
this.client.changeAudioOutputDevice(this.audioOutputDeviceId);
|
|
@@ -2352,6 +2379,8 @@ class WebRTCPhone extends Emitter {
|
|
|
2352
2379
|
logger.info('WebRTC call rejected', session.id);
|
|
2353
2380
|
const callSession = this._createCallSession(session);
|
|
2354
2381
|
callSession.endTime = new Date();
|
|
2382
|
+
this._updateCallSession(callSession);
|
|
2383
|
+
|
|
2355
2384
|
this.eventEmitter.emit(ON_CALL_REJECTED, callSession);
|
|
2356
2385
|
});
|
|
2357
2386
|
|
|
@@ -2469,9 +2498,14 @@ class WebRTCPhone extends Emitter {
|
|
|
2469
2498
|
return this.client.getSipSessionId(sipSession);
|
|
2470
2499
|
}
|
|
2471
2500
|
|
|
2472
|
-
|
|
2501
|
+
getSipSessionIdFromCallSession(callSession ) {
|
|
2473
2502
|
const sipSession = this.findSipSession(callSession);
|
|
2474
|
-
|
|
2503
|
+
|
|
2504
|
+
return sipSession ? this.getSipSessionId(sipSession) : null;
|
|
2505
|
+
}
|
|
2506
|
+
|
|
2507
|
+
_updateCallSession(callSession ) {
|
|
2508
|
+
const sipSessionId = this.getSipSessionIdFromCallSession(callSession);
|
|
2475
2509
|
|
|
2476
2510
|
if (sipSessionId) {
|
|
2477
2511
|
this.callSessions[sipSessionId] = callSession;
|
|
@@ -2576,6 +2610,7 @@ class WebRTCPhone extends Emitter {
|
|
|
2576
2610
|
displayName: identity ? identity.displayName || number : number,
|
|
2577
2611
|
startTime: fromSession ? fromSession.startTime : new Date(),
|
|
2578
2612
|
creationTime: fromSession ? fromSession.creationTime : null,
|
|
2613
|
+
answerTime: fromSession ? fromSession.answerTime : null,
|
|
2579
2614
|
endTime: fromSession ? fromSession.endTime : null,
|
|
2580
2615
|
answered: state === SessionState.Established,
|
|
2581
2616
|
paused: this.client.isCallHeld(sipSession),
|
|
@@ -368,13 +368,21 @@ class CallSession {
|
|
|
368
368
|
|
|
369
369
|
// Retro-compatibility: `answered` was a boolean before. We can reproduce the behaviour with a getter/setter
|
|
370
370
|
set answered(value ) {
|
|
371
|
-
this.answerTime = value ? new Date() : null;
|
|
371
|
+
this.answerTime = value ? this.answerTime || new Date() : null;
|
|
372
372
|
}
|
|
373
373
|
|
|
374
374
|
get answered() {
|
|
375
375
|
return !!this.answerTime;
|
|
376
376
|
}
|
|
377
377
|
|
|
378
|
+
toJSON() {
|
|
379
|
+
const jsonObj = { ...this };
|
|
380
|
+
// $FlowFixMe
|
|
381
|
+
jsonObj.answered = this.answered;
|
|
382
|
+
|
|
383
|
+
return jsonObj;
|
|
384
|
+
}
|
|
385
|
+
|
|
378
386
|
static parseCall(call ) {
|
|
379
387
|
return new CallSession({
|
|
380
388
|
callId: call.id,
|
|
@@ -400,6 +408,8 @@ class CallSession {
|
|
|
400
408
|
}
|
|
401
409
|
}
|
|
402
410
|
|
|
411
|
+
const stringify = cs => JSON.parse(JSON.stringify(cs));
|
|
412
|
+
|
|
403
413
|
describe('CallSession domain', () => {
|
|
404
414
|
it('should update from another CallSession without data loss', () => {
|
|
405
415
|
const callSession = new CallSession({
|
|
@@ -438,7 +448,7 @@ describe('CallSession domain', () => {
|
|
|
438
448
|
expect(cs2.is(cs1)).toBeTruthy();
|
|
439
449
|
});
|
|
440
450
|
|
|
441
|
-
it('should set answerTime when setting answered', () => {
|
|
451
|
+
it('should set answerTime when setting answered to true', () => {
|
|
442
452
|
const cs1 = new CallSession({});
|
|
443
453
|
cs1.answered = true;
|
|
444
454
|
|
|
@@ -447,11 +457,37 @@ describe('CallSession domain', () => {
|
|
|
447
457
|
|
|
448
458
|
const cs3 = new CallSession({ answered: true });
|
|
449
459
|
|
|
450
|
-
expect(cs1.answered).
|
|
460
|
+
expect(cs1.answered).toEqual(true);
|
|
451
461
|
expect(cs1.answerTime).not.toBeNull();
|
|
452
|
-
expect(cs2.answered).
|
|
462
|
+
expect(cs2.answered).toEqual(true);
|
|
453
463
|
expect(cs2.answerTime).not.toBeNull();
|
|
454
|
-
expect(cs3.answered).
|
|
464
|
+
expect(cs3.answered).toEqual(true);
|
|
455
465
|
expect(cs3.answerTime).not.toBeNull();
|
|
466
|
+
|
|
467
|
+
const cs4 = stringify(cs1);
|
|
468
|
+
const cs5 = stringify(cs2);
|
|
469
|
+
const cs6 = stringify(cs3);
|
|
470
|
+
|
|
471
|
+
expect(cs4.answered).toEqual(true);
|
|
472
|
+
expect(cs5.answered).toEqual(true);
|
|
473
|
+
expect(cs6.answered).toEqual(true);
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
it('should reset answerTime when setting answered to false', () => {
|
|
477
|
+
const cs1 = new CallSession({});
|
|
478
|
+
cs1.answered = false;
|
|
479
|
+
|
|
480
|
+
const cs2 = new CallSession({ answered: false });
|
|
481
|
+
|
|
482
|
+
expect(cs1.answered).toEqual(false);
|
|
483
|
+
expect(cs1.answerTime).toBeNull();
|
|
484
|
+
expect(cs2.answered).toEqual(false);
|
|
485
|
+
expect(cs2.answerTime).toBeNull();
|
|
486
|
+
|
|
487
|
+
const cs4 = stringify(cs1);
|
|
488
|
+
const cs5 = stringify(cs2);
|
|
489
|
+
|
|
490
|
+
expect(cs4.answered).toEqual(false);
|
|
491
|
+
expect(cs5.answered).toEqual(false);
|
|
456
492
|
});
|
|
457
493
|
});
|