@wazo/sdk 0.37.25 → 0.37.29

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.
Files changed (125) hide show
  1. package/README.md +96 -58
  2. package/dist/wazo-sdk.js +3 -3
  3. package/esm/__tests__/api-client.test.js +2 -2
  4. package/esm/__tests__/web-rtc-client.test.js +10 -5
  5. package/esm/api/agentd.js +1 -1
  6. package/esm/api/amid.js +1 -1
  7. package/esm/api/application.js +1 -1
  8. package/esm/api/auth.js +1 -1
  9. package/esm/api/call-logd.js +1 -1
  10. package/esm/api/calld.js +1 -1
  11. package/esm/api/chatd.js +1 -1
  12. package/esm/api/confd.js +1 -1
  13. package/esm/api/ctid-ng.js +1 -1
  14. package/esm/api/dird.js +2 -2
  15. package/esm/api/webhookd.js +1 -1
  16. package/esm/api-client.js +2 -2
  17. package/esm/checker/Checker.js +10 -5
  18. package/esm/checker/checks/aor.js +2 -2
  19. package/esm/checker/checks/api.js +2 -2
  20. package/esm/checker/checks/index.js +10 -5
  21. package/esm/checker/checks/wazo-websocket.js +1 -1
  22. package/esm/checker/checks/webrtc-transport.js +10 -5
  23. package/esm/checker/checks/webrtc.js +10 -5
  24. package/esm/domain/AdHocAPIConference.js +2 -2
  25. package/esm/domain/CallSession.js +29 -2
  26. package/esm/domain/Contact.js +1 -1
  27. package/esm/domain/Features.js +2 -2
  28. package/esm/domain/Phone/CTIPhone.js +31 -4
  29. package/esm/domain/Phone/WebRTCPhone.js +55 -6
  30. package/esm/domain/SFUNotAvailableError.js +9 -0
  31. package/esm/domain/__tests__/CallSession.test.js +46 -2
  32. package/esm/domain/__tests__/Contact.test.js +1 -1
  33. package/esm/domain/__tests__/IndirectTransfer.test.js +29 -2
  34. package/esm/domain/__tests__/Room.test.js +29 -2
  35. package/esm/index.js +75 -10
  36. package/esm/lib/WazoSessionDescriptionHandler.js +9 -4
  37. package/esm/service/CallApi.js +2 -2
  38. package/esm/service/IssueReporter.js +1 -1
  39. package/esm/service/__tests__/IssueReporter.test.js +1 -1
  40. package/esm/service/getApiClient.js +2 -2
  41. package/esm/simple/Auth.js +74 -10
  42. package/esm/simple/Configuration.js +74 -10
  43. package/esm/simple/Directory.js +2 -2
  44. package/esm/simple/Phone.js +74 -10
  45. package/esm/simple/Websocket.js +1 -1
  46. package/esm/simple/index.js +74 -10
  47. package/esm/simple/room/LocalParticipant.js +74 -10
  48. package/esm/simple/room/Participant.js +74 -10
  49. package/esm/simple/room/RemoteParticipant.js +74 -10
  50. package/esm/simple/room/Room.js +74 -10
  51. package/esm/simple/room/SipRoom.js +74 -10
  52. package/esm/simple/room/Stream.js +74 -10
  53. package/esm/simple/room/__tests__/RemoteParticipant.test.js +74 -10
  54. package/esm/simple/utils.js +74 -10
  55. package/esm/utils/__tests__/api-requester.test.js +1 -1
  56. package/esm/utils/api-requester.js +1 -1
  57. package/esm/web-rtc-client.js +10 -5
  58. package/esm/websocket-client.js +1 -1
  59. package/lib/__tests__/api-client.test.js +2 -2
  60. package/lib/__tests__/web-rtc-client.test.js +10 -5
  61. package/lib/api/agentd.js +1 -1
  62. package/lib/api/amid.js +1 -1
  63. package/lib/api/application.js +1 -1
  64. package/lib/api/auth.js +1 -1
  65. package/lib/api/call-logd.js +1 -1
  66. package/lib/api/calld.js +1 -1
  67. package/lib/api/chatd.js +1 -1
  68. package/lib/api/confd.js +1 -1
  69. package/lib/api/ctid-ng.js +1 -1
  70. package/lib/api/dird.js +2 -2
  71. package/lib/api/webhookd.js +1 -1
  72. package/lib/api-client.js +2 -2
  73. package/lib/checker/Checker.js +10 -5
  74. package/lib/checker/checks/aor.js +2 -2
  75. package/lib/checker/checks/api.js +2 -2
  76. package/lib/checker/checks/index.js +10 -5
  77. package/lib/checker/checks/wazo-websocket.js +1 -1
  78. package/lib/checker/checks/webrtc-transport.js +10 -5
  79. package/lib/checker/checks/webrtc.js +10 -5
  80. package/lib/domain/AdHocAPIConference.js +2 -2
  81. package/lib/domain/CallSession.js +29 -2
  82. package/lib/domain/Contact.js +1 -1
  83. package/lib/domain/Features.js +2 -2
  84. package/lib/domain/Phone/CTIPhone.js +31 -4
  85. package/lib/domain/Phone/WebRTCPhone.js +55 -5
  86. package/lib/domain/SFUNotAvailableError.js +11 -0
  87. package/lib/domain/__tests__/CallSession.test.js +46 -2
  88. package/lib/domain/__tests__/Contact.test.js +1 -1
  89. package/lib/domain/__tests__/IndirectTransfer.test.js +29 -2
  90. package/lib/domain/__tests__/Room.test.js +29 -2
  91. package/lib/index.js +75 -10
  92. package/lib/lib/WazoSessionDescriptionHandler.js +9 -4
  93. package/lib/service/CallApi.js +2 -2
  94. package/lib/service/IssueReporter.js +1 -1
  95. package/lib/service/__tests__/IssueReporter.test.js +1 -1
  96. package/lib/service/getApiClient.js +2 -2
  97. package/lib/simple/Auth.js +74 -10
  98. package/lib/simple/Configuration.js +74 -10
  99. package/lib/simple/Directory.js +2 -2
  100. package/lib/simple/Phone.js +74 -10
  101. package/lib/simple/Websocket.js +1 -1
  102. package/lib/simple/index.js +74 -10
  103. package/lib/simple/room/LocalParticipant.js +74 -10
  104. package/lib/simple/room/Participant.js +74 -10
  105. package/lib/simple/room/RemoteParticipant.js +74 -10
  106. package/lib/simple/room/Room.js +74 -10
  107. package/lib/simple/room/SipRoom.js +74 -10
  108. package/lib/simple/room/Stream.js +74 -10
  109. package/lib/simple/room/__tests__/RemoteParticipant.test.js +74 -10
  110. package/lib/simple/utils.js +74 -10
  111. package/lib/utils/__tests__/api-requester.test.js +1 -1
  112. package/lib/utils/api-requester.js +1 -1
  113. package/lib/web-rtc-client.js +10 -5
  114. package/lib/websocket-client.js +1 -1
  115. package/package.json +1 -1
  116. package/src/domain/CallSession.js +32 -4
  117. package/src/domain/Contact.js +1 -1
  118. package/src/domain/Phone/WebRTCPhone.js +24 -2
  119. package/src/domain/SFUNotAvailableError.js +7 -0
  120. package/src/domain/__tests__/CallSession.test.js +17 -0
  121. package/src/index.js +2 -0
  122. package/src/lib/WazoSessionDescriptionHandler.js +8 -3
  123. package/src/simple/Phone.js +2 -1
  124. package/src/simple/index.js +2 -0
  125. package/src/utils/api-requester.js +1 -1
@@ -473,7 +473,7 @@ const logger$c = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
473
473
 
474
474
  // Use a function here to be able to mock it in tests
475
475
  const realFetch = () => {
476
- if (typeof document !== 'undefined') {
476
+ if (typeof document !== 'undefined' && window.fetch) {
477
477
  // Browser
478
478
  return window.fetch;
479
479
  }
@@ -1933,7 +1933,7 @@ class Contact {
1933
1933
  this[key] = old[key] || this[key];
1934
1934
  });
1935
1935
 
1936
- if (old.lineState && !this.lineState) {
1936
+ if (old.lineState) {
1937
1937
  this.lineState = old.lineState;
1938
1938
  }
1939
1939
 
@@ -3258,13 +3258,16 @@ var updateFrom = (instance , from ) => {
3258
3258
 
3259
3259
 
3260
3260
 
3261
+
3261
3262
 
3262
3263
 
3263
3264
 
3264
3265
 
3265
3266
 
3267
+
3266
3268
 
3267
3269
 
3270
+
3268
3271
 
3269
3272
 
3270
3273
 
@@ -3281,6 +3284,7 @@ var updateFrom = (instance , from ) => {
3281
3284
 
3282
3285
 
3283
3286
 
3287
+
3284
3288
 
3285
3289
 
3286
3290
  class CallSession {
@@ -3300,10 +3304,14 @@ class CallSession {
3300
3304
 
3301
3305
 
3302
3306
 
3303
-
3307
+
3308
+
3309
+ // = creationTime
3304
3310
 
3305
3311
 
3306
3312
 
3313
+
3314
+
3307
3315
 
3308
3316
 
3309
3317
 
@@ -3339,6 +3347,8 @@ class CallSession {
3339
3347
 
3340
3348
 
3341
3349
 
3350
+
3351
+
3342
3352
 
3343
3353
  constructor({
3344
3354
  answered,
@@ -3352,6 +3362,8 @@ class CallSession {
3352
3362
  paused,
3353
3363
  ringing,
3354
3364
  startTime,
3365
+ creationTime,
3366
+ endTime,
3355
3367
  cameraEnabled,
3356
3368
  dialedExtension,
3357
3369
  sipCallId,
@@ -3364,12 +3376,16 @@ class CallSession {
3364
3376
  recording,
3365
3377
  recordingPaused,
3366
3378
  videoRemotelyDowngraded,
3379
+ sipSession,
3380
+ answerTime,
3367
3381
  } ) {
3368
3382
  this.callId = callId;
3369
3383
  this.sipCallId = sipCallId;
3370
3384
  this.displayName = displayName;
3371
3385
  this.number = number;
3386
+ this.creationTime = creationTime;
3372
3387
  this.startTime = startTime;
3388
+ this.endTime = endTime;
3373
3389
  this.isCaller = isCaller;
3374
3390
  this.answered = answered;
3375
3391
  this.answeredBySystem = answeredBySystem;
@@ -3388,6 +3404,8 @@ class CallSession {
3388
3404
  this.recording = recording || false;
3389
3405
  this.recordingPaused = recordingPaused || false;
3390
3406
  this.videoRemotelyDowngraded = videoRemotelyDowngraded;
3407
+ this.sipSession = sipSession;
3408
+ this.answerTime = answerTime || this.answerTime;
3391
3409
 
3392
3410
  // Useful to compare instead of instanceof with minified code
3393
3411
  this.type = 'CallSession';
@@ -3418,7 +3436,7 @@ class CallSession {
3418
3436
  }
3419
3437
 
3420
3438
  answer() {
3421
- this.answered = true;
3439
+ this.answerTime = new Date();
3422
3440
  }
3423
3441
 
3424
3442
  systemAnswer() {
@@ -3574,6 +3592,15 @@ class CallSession {
3574
3592
  return newFrom(callSession, CallSession);
3575
3593
  }
3576
3594
 
3595
+ // Retro-compatibility: `answered` was a boolean before. We can reproduce the behaviour with a getter/setter
3596
+ set answered(value ) {
3597
+ this.answerTime = value ? new Date() : null;
3598
+ }
3599
+
3600
+ get answered() {
3601
+ return !!this.answerTime;
3602
+ }
3603
+
3577
3604
  static parseCall(call ) {
3578
3605
  return new CallSession({
3579
3606
  callId: call.id,
@@ -6072,11 +6099,16 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
6072
6099
 
6073
6100
  // $FlowFixMe
6074
6101
  setRemoteSessionDescription(sessionDescription ) {
6075
- const result = super.setRemoteSessionDescription(sessionDescription);
6102
+ try {
6103
+ const result = super.setRemoteSessionDescription(sessionDescription);
6076
6104
 
6077
- this.eventEmitter.emit('setDescription', sessionDescription);
6105
+ this.eventEmitter.emit('setDescription', sessionDescription);
6078
6106
 
6079
- return result;
6107
+ return result;
6108
+ } catch (error) {
6109
+ this.logger.error('SessionDescriptionHandler.setRemoteSessionDescription error', error);
6110
+ throw error;
6111
+ }
6080
6112
  }
6081
6113
 
6082
6114
  // Overridden to avoid to fix ice-candidates missing in the SDP in react-native and chrome canary.
@@ -8728,6 +8760,7 @@ const ON_CAMERA_DISABLED = 'onCameraDisabled';
8728
8760
  const ON_CAMERA_RESUMED = 'onCameraResumed';
8729
8761
  const ON_CALL_CANCELED = 'onCallCanceled';
8730
8762
  const ON_CALL_FAILED = 'onCallFailed';
8763
+ const ON_CALL_REJECTED = 'onCallRejected';
8731
8764
  const ON_CALL_ENDED = 'onCallEnded';
8732
8765
  const ON_CALL_ENDING = 'onCallEnding';
8733
8766
  const ON_MESSAGE = 'onMessage';
@@ -8772,6 +8805,7 @@ const events = [
8772
8805
  ON_CAMERA_DISABLED,
8773
8806
  ON_CALL_FAILED,
8774
8807
  ON_CALL_ENDED,
8808
+ ON_CALL_REJECTED,
8775
8809
  ON_MESSAGE,
8776
8810
  ON_REINVITE,
8777
8811
  ON_TRACK,
@@ -9128,6 +9162,7 @@ class WebRTCPhone extends Emitter {
9128
9162
 
9129
9163
  // Should be called before `_onCallTerminated` or the callCount will not decrement...
9130
9164
  const callSession = this._createCallSession(sipSession);
9165
+ callSession.endTime = new Date();
9131
9166
  const wasCurrentSession = this._onCallTerminated(sipSession);
9132
9167
 
9133
9168
  return this.eventEmitter.emit(ON_CALL_ENDED, callSession, wasCurrentSession);
@@ -9323,6 +9358,7 @@ class WebRTCPhone extends Emitter {
9323
9358
  this.removeIncomingSessions(sipSessionId);
9324
9359
  }
9325
9360
 
9361
+ callSession.answerTime = new Date();
9326
9362
  this.eventEmitter.emit(ON_CALL_ACCEPTED, callSession, cameraEnabled);
9327
9363
 
9328
9364
  return callSession;
@@ -9380,6 +9416,7 @@ class WebRTCPhone extends Emitter {
9380
9416
  _onCallTerminated(sipSession ) {
9381
9417
  logger$7.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
9382
9418
 
9419
+ const sipSessionId = this.getSipSessionId(sipSession);
9383
9420
  const callSession = this._createCallSession(sipSession);
9384
9421
  const isCurrentSession = this.isCurrentCallSipSession(callSession);
9385
9422
  const isCurrentIncomingCall = callSession.is(this.getIncomingCallSession());
@@ -9397,7 +9434,6 @@ class WebRTCPhone extends Emitter {
9397
9434
  }, 5);
9398
9435
  }
9399
9436
 
9400
- const sipSessionId = this.getSipSessionId(sipSession);
9401
9437
  if (sipSessionId) {
9402
9438
  this.removeIncomingSessions(sipSessionId);
9403
9439
  }
@@ -9538,6 +9574,7 @@ class WebRTCPhone extends Emitter {
9538
9574
  }
9539
9575
 
9540
9576
  this.shouldSendReinvite = false;
9577
+ callSession.answerTime = new Date();
9541
9578
  this.acceptedSessions[callSession.getId()] = true;
9542
9579
 
9543
9580
  this.eventEmitter.emit(ON_CALL_ANSWERED, callSession);
@@ -9847,6 +9884,7 @@ class WebRTCPhone extends Emitter {
9847
9884
  return Promise.resolve(null);
9848
9885
  }
9849
9886
  const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
9887
+ callSession.creationTime = new Date();
9850
9888
 
9851
9889
  this.eventEmitter.emit(ON_PLAY_PROGRESS_SOUND, this.audioOutputDeviceId, this.audioOutputVolume);
9852
9890
 
@@ -10042,8 +10080,12 @@ class WebRTCPhone extends Emitter {
10042
10080
  }
10043
10081
 
10044
10082
  const sessionId = this.incomingSessions[0];
10083
+ const sipSession = this.client.getSipSession(sessionId);
10084
+ if (!sipSession) {
10085
+ return null;
10086
+ }
10045
10087
 
10046
- return this._createCallSession(this.client.getSipSession(sessionId));
10088
+ return this._createCallSession(sipSession);
10047
10089
  }
10048
10090
 
10049
10091
  sendMessage(sipSession = null, body , contentType = 'text/plain') {
@@ -10121,6 +10163,7 @@ class WebRTCPhone extends Emitter {
10121
10163
  callSession);
10122
10164
  }
10123
10165
 
10166
+ callSession.creationTime = new Date();
10124
10167
  this.eventEmitter.emit(ON_CALL_INCOMING, callSession, wantsToDoVideo);
10125
10168
  });
10126
10169
 
@@ -10160,6 +10203,13 @@ class WebRTCPhone extends Emitter {
10160
10203
  this.eventEmitter.emit(ON_CALL_ERROR, e);
10161
10204
  });
10162
10205
 
10206
+ this.client.on(this.client.REJECTED, session => {
10207
+ logger$7.info('WebRTC call rejected', session.id);
10208
+ const callSession = this._createCallSession(session);
10209
+ callSession.endTime = new Date();
10210
+ this.eventEmitter.emit(ON_CALL_REJECTED, callSession);
10211
+ });
10212
+
10163
10213
  this.client.on(this.client.UNREGISTERED, () => {
10164
10214
  logger$7.info('WebRTC unregistered');
10165
10215
  this.eventEmitter.emit(ON_UNREGISTERED);
@@ -10372,6 +10422,7 @@ class WebRTCPhone extends Emitter {
10372
10422
  const number = identity ? identity.uri._normal.user : null;
10373
10423
  const { state } = sipSession || {};
10374
10424
  const sessionId = this.getSipSessionId(sipSession);
10425
+ fromSession = fromSession || this.callSessions[sessionId];
10375
10426
 
10376
10427
  const callSession = new CallSession({
10377
10428
  callId: fromSession && fromSession.callId,
@@ -10379,6 +10430,8 @@ class WebRTCPhone extends Emitter {
10379
10430
  sipStatus: state,
10380
10431
  displayName: identity ? identity.displayName || number : number,
10381
10432
  startTime: fromSession ? fromSession.startTime : new Date(),
10433
+ creationTime: fromSession ? fromSession.creationTime : null,
10434
+ endTime: fromSession ? fromSession.endTime : null,
10382
10435
  answered: state === sessionState.SessionState.Established,
10383
10436
  paused: this.client.isCallHeld(sipSession),
10384
10437
  isCaller: 'incoming' in extra ? !extra.incoming : false,
@@ -10389,6 +10442,7 @@ class WebRTCPhone extends Emitter {
10389
10442
  videoMuted: fromSession ? fromSession.isVideoMuted() : false,
10390
10443
  recording: fromSession ? fromSession.isRecording() : false,
10391
10444
  recordingPaused: false, // @TODO
10445
+ sipSession,
10392
10446
  ...extra,
10393
10447
  });
10394
10448
 
@@ -10417,6 +10471,7 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
10417
10471
  ON_CAMERA_RESUMED: ON_CAMERA_RESUMED,
10418
10472
  ON_CALL_CANCELED: ON_CALL_CANCELED,
10419
10473
  ON_CALL_FAILED: ON_CALL_FAILED,
10474
+ ON_CALL_REJECTED: ON_CALL_REJECTED,
10420
10475
  ON_CALL_ENDED: ON_CALL_ENDED,
10421
10476
  ON_CALL_ENDING: ON_CALL_ENDING,
10422
10477
  ON_MESSAGE: ON_MESSAGE,
@@ -10446,6 +10501,14 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
10446
10501
  'default': WebRTCPhone
10447
10502
  });
10448
10503
 
10504
+ /* */
10505
+ class SFUNotAvailableError extends Error {
10506
+ constructor(message = 'Sorry your user is not configured to support video conference') {
10507
+ super(message);
10508
+ this.name = 'SFUNotAvailableError';
10509
+ }
10510
+ }
10511
+
10449
10512
  //
10450
10513
 
10451
10514
  const logger$6 = IssueReporter$1.loggerFor('simple-phone');
@@ -10830,7 +10893,7 @@ class Phone extends Emitter {
10830
10893
 
10831
10894
  checkSfu() {
10832
10895
  if (!this.hasSfu()) {
10833
- throw new Error('Sorry your user is not configured to support video conference');
10896
+ throw new SFUNotAvailableError();
10834
10897
  }
10835
10898
  }
10836
10899
 
@@ -12896,6 +12959,7 @@ const Wazo = {
12896
12959
  InvalidSubscription,
12897
12960
  InvalidAuthorization,
12898
12961
  CanceledCallError,
12962
+ SFUNotAvailableError,
12899
12963
  };
12900
12964
 
12901
12965
  if (window) {
@@ -475,7 +475,7 @@ const logger$c = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
475
475
 
476
476
  // Use a function here to be able to mock it in tests
477
477
  const realFetch = () => {
478
- if (typeof document !== 'undefined') {
478
+ if (typeof document !== 'undefined' && window.fetch) {
479
479
  // Browser
480
480
  return window.fetch;
481
481
  }
@@ -1935,7 +1935,7 @@ class Contact {
1935
1935
  this[key] = old[key] || this[key];
1936
1936
  });
1937
1937
 
1938
- if (old.lineState && !this.lineState) {
1938
+ if (old.lineState) {
1939
1939
  this.lineState = old.lineState;
1940
1940
  }
1941
1941
 
@@ -3260,13 +3260,16 @@ var updateFrom = (instance , from ) => {
3260
3260
 
3261
3261
 
3262
3262
 
3263
+
3263
3264
 
3264
3265
 
3265
3266
 
3266
3267
 
3267
3268
 
3269
+
3268
3270
 
3269
3271
 
3272
+
3270
3273
 
3271
3274
 
3272
3275
 
@@ -3283,6 +3286,7 @@ var updateFrom = (instance , from ) => {
3283
3286
 
3284
3287
 
3285
3288
 
3289
+
3286
3290
 
3287
3291
 
3288
3292
  class CallSession {
@@ -3302,10 +3306,14 @@ class CallSession {
3302
3306
 
3303
3307
 
3304
3308
 
3305
-
3309
+
3310
+
3311
+ // = creationTime
3306
3312
 
3307
3313
 
3308
3314
 
3315
+
3316
+
3309
3317
 
3310
3318
 
3311
3319
 
@@ -3341,6 +3349,8 @@ class CallSession {
3341
3349
 
3342
3350
 
3343
3351
 
3352
+
3353
+
3344
3354
 
3345
3355
  constructor({
3346
3356
  answered,
@@ -3354,6 +3364,8 @@ class CallSession {
3354
3364
  paused,
3355
3365
  ringing,
3356
3366
  startTime,
3367
+ creationTime,
3368
+ endTime,
3357
3369
  cameraEnabled,
3358
3370
  dialedExtension,
3359
3371
  sipCallId,
@@ -3366,12 +3378,16 @@ class CallSession {
3366
3378
  recording,
3367
3379
  recordingPaused,
3368
3380
  videoRemotelyDowngraded,
3381
+ sipSession,
3382
+ answerTime,
3369
3383
  } ) {
3370
3384
  this.callId = callId;
3371
3385
  this.sipCallId = sipCallId;
3372
3386
  this.displayName = displayName;
3373
3387
  this.number = number;
3388
+ this.creationTime = creationTime;
3374
3389
  this.startTime = startTime;
3390
+ this.endTime = endTime;
3375
3391
  this.isCaller = isCaller;
3376
3392
  this.answered = answered;
3377
3393
  this.answeredBySystem = answeredBySystem;
@@ -3390,6 +3406,8 @@ class CallSession {
3390
3406
  this.recording = recording || false;
3391
3407
  this.recordingPaused = recordingPaused || false;
3392
3408
  this.videoRemotelyDowngraded = videoRemotelyDowngraded;
3409
+ this.sipSession = sipSession;
3410
+ this.answerTime = answerTime || this.answerTime;
3393
3411
 
3394
3412
  // Useful to compare instead of instanceof with minified code
3395
3413
  this.type = 'CallSession';
@@ -3420,7 +3438,7 @@ class CallSession {
3420
3438
  }
3421
3439
 
3422
3440
  answer() {
3423
- this.answered = true;
3441
+ this.answerTime = new Date();
3424
3442
  }
3425
3443
 
3426
3444
  systemAnswer() {
@@ -3576,6 +3594,15 @@ class CallSession {
3576
3594
  return newFrom(callSession, CallSession);
3577
3595
  }
3578
3596
 
3597
+ // Retro-compatibility: `answered` was a boolean before. We can reproduce the behaviour with a getter/setter
3598
+ set answered(value ) {
3599
+ this.answerTime = value ? new Date() : null;
3600
+ }
3601
+
3602
+ get answered() {
3603
+ return !!this.answerTime;
3604
+ }
3605
+
3579
3606
  static parseCall(call ) {
3580
3607
  return new CallSession({
3581
3608
  callId: call.id,
@@ -6074,11 +6101,16 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
6074
6101
 
6075
6102
  // $FlowFixMe
6076
6103
  setRemoteSessionDescription(sessionDescription ) {
6077
- const result = super.setRemoteSessionDescription(sessionDescription);
6104
+ try {
6105
+ const result = super.setRemoteSessionDescription(sessionDescription);
6078
6106
 
6079
- this.eventEmitter.emit('setDescription', sessionDescription);
6107
+ this.eventEmitter.emit('setDescription', sessionDescription);
6080
6108
 
6081
- return result;
6109
+ return result;
6110
+ } catch (error) {
6111
+ this.logger.error('SessionDescriptionHandler.setRemoteSessionDescription error', error);
6112
+ throw error;
6113
+ }
6082
6114
  }
6083
6115
 
6084
6116
  // Overridden to avoid to fix ice-candidates missing in the SDP in react-native and chrome canary.
@@ -8730,6 +8762,7 @@ const ON_CAMERA_DISABLED = 'onCameraDisabled';
8730
8762
  const ON_CAMERA_RESUMED = 'onCameraResumed';
8731
8763
  const ON_CALL_CANCELED = 'onCallCanceled';
8732
8764
  const ON_CALL_FAILED = 'onCallFailed';
8765
+ const ON_CALL_REJECTED = 'onCallRejected';
8733
8766
  const ON_CALL_ENDED = 'onCallEnded';
8734
8767
  const ON_CALL_ENDING = 'onCallEnding';
8735
8768
  const ON_MESSAGE = 'onMessage';
@@ -8774,6 +8807,7 @@ const events = [
8774
8807
  ON_CAMERA_DISABLED,
8775
8808
  ON_CALL_FAILED,
8776
8809
  ON_CALL_ENDED,
8810
+ ON_CALL_REJECTED,
8777
8811
  ON_MESSAGE,
8778
8812
  ON_REINVITE,
8779
8813
  ON_TRACK,
@@ -9130,6 +9164,7 @@ class WebRTCPhone extends Emitter {
9130
9164
 
9131
9165
  // Should be called before `_onCallTerminated` or the callCount will not decrement...
9132
9166
  const callSession = this._createCallSession(sipSession);
9167
+ callSession.endTime = new Date();
9133
9168
  const wasCurrentSession = this._onCallTerminated(sipSession);
9134
9169
 
9135
9170
  return this.eventEmitter.emit(ON_CALL_ENDED, callSession, wasCurrentSession);
@@ -9325,6 +9360,7 @@ class WebRTCPhone extends Emitter {
9325
9360
  this.removeIncomingSessions(sipSessionId);
9326
9361
  }
9327
9362
 
9363
+ callSession.answerTime = new Date();
9328
9364
  this.eventEmitter.emit(ON_CALL_ACCEPTED, callSession, cameraEnabled);
9329
9365
 
9330
9366
  return callSession;
@@ -9382,6 +9418,7 @@ class WebRTCPhone extends Emitter {
9382
9418
  _onCallTerminated(sipSession ) {
9383
9419
  logger$7.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
9384
9420
 
9421
+ const sipSessionId = this.getSipSessionId(sipSession);
9385
9422
  const callSession = this._createCallSession(sipSession);
9386
9423
  const isCurrentSession = this.isCurrentCallSipSession(callSession);
9387
9424
  const isCurrentIncomingCall = callSession.is(this.getIncomingCallSession());
@@ -9399,7 +9436,6 @@ class WebRTCPhone extends Emitter {
9399
9436
  }, 5);
9400
9437
  }
9401
9438
 
9402
- const sipSessionId = this.getSipSessionId(sipSession);
9403
9439
  if (sipSessionId) {
9404
9440
  this.removeIncomingSessions(sipSessionId);
9405
9441
  }
@@ -9540,6 +9576,7 @@ class WebRTCPhone extends Emitter {
9540
9576
  }
9541
9577
 
9542
9578
  this.shouldSendReinvite = false;
9579
+ callSession.answerTime = new Date();
9543
9580
  this.acceptedSessions[callSession.getId()] = true;
9544
9581
 
9545
9582
  this.eventEmitter.emit(ON_CALL_ANSWERED, callSession);
@@ -9849,6 +9886,7 @@ class WebRTCPhone extends Emitter {
9849
9886
  return Promise.resolve(null);
9850
9887
  }
9851
9888
  const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
9889
+ callSession.creationTime = new Date();
9852
9890
 
9853
9891
  this.eventEmitter.emit(ON_PLAY_PROGRESS_SOUND, this.audioOutputDeviceId, this.audioOutputVolume);
9854
9892
 
@@ -10044,8 +10082,12 @@ class WebRTCPhone extends Emitter {
10044
10082
  }
10045
10083
 
10046
10084
  const sessionId = this.incomingSessions[0];
10085
+ const sipSession = this.client.getSipSession(sessionId);
10086
+ if (!sipSession) {
10087
+ return null;
10088
+ }
10047
10089
 
10048
- return this._createCallSession(this.client.getSipSession(sessionId));
10090
+ return this._createCallSession(sipSession);
10049
10091
  }
10050
10092
 
10051
10093
  sendMessage(sipSession = null, body , contentType = 'text/plain') {
@@ -10123,6 +10165,7 @@ class WebRTCPhone extends Emitter {
10123
10165
  callSession);
10124
10166
  }
10125
10167
 
10168
+ callSession.creationTime = new Date();
10126
10169
  this.eventEmitter.emit(ON_CALL_INCOMING, callSession, wantsToDoVideo);
10127
10170
  });
10128
10171
 
@@ -10162,6 +10205,13 @@ class WebRTCPhone extends Emitter {
10162
10205
  this.eventEmitter.emit(ON_CALL_ERROR, e);
10163
10206
  });
10164
10207
 
10208
+ this.client.on(this.client.REJECTED, session => {
10209
+ logger$7.info('WebRTC call rejected', session.id);
10210
+ const callSession = this._createCallSession(session);
10211
+ callSession.endTime = new Date();
10212
+ this.eventEmitter.emit(ON_CALL_REJECTED, callSession);
10213
+ });
10214
+
10165
10215
  this.client.on(this.client.UNREGISTERED, () => {
10166
10216
  logger$7.info('WebRTC unregistered');
10167
10217
  this.eventEmitter.emit(ON_UNREGISTERED);
@@ -10374,6 +10424,7 @@ class WebRTCPhone extends Emitter {
10374
10424
  const number = identity ? identity.uri._normal.user : null;
10375
10425
  const { state } = sipSession || {};
10376
10426
  const sessionId = this.getSipSessionId(sipSession);
10427
+ fromSession = fromSession || this.callSessions[sessionId];
10377
10428
 
10378
10429
  const callSession = new CallSession({
10379
10430
  callId: fromSession && fromSession.callId,
@@ -10381,6 +10432,8 @@ class WebRTCPhone extends Emitter {
10381
10432
  sipStatus: state,
10382
10433
  displayName: identity ? identity.displayName || number : number,
10383
10434
  startTime: fromSession ? fromSession.startTime : new Date(),
10435
+ creationTime: fromSession ? fromSession.creationTime : null,
10436
+ endTime: fromSession ? fromSession.endTime : null,
10384
10437
  answered: state === sessionState.SessionState.Established,
10385
10438
  paused: this.client.isCallHeld(sipSession),
10386
10439
  isCaller: 'incoming' in extra ? !extra.incoming : false,
@@ -10391,6 +10444,7 @@ class WebRTCPhone extends Emitter {
10391
10444
  videoMuted: fromSession ? fromSession.isVideoMuted() : false,
10392
10445
  recording: fromSession ? fromSession.isRecording() : false,
10393
10446
  recordingPaused: false, // @TODO
10447
+ sipSession,
10394
10448
  ...extra,
10395
10449
  });
10396
10450
 
@@ -10419,6 +10473,7 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
10419
10473
  ON_CAMERA_RESUMED: ON_CAMERA_RESUMED,
10420
10474
  ON_CALL_CANCELED: ON_CALL_CANCELED,
10421
10475
  ON_CALL_FAILED: ON_CALL_FAILED,
10476
+ ON_CALL_REJECTED: ON_CALL_REJECTED,
10422
10477
  ON_CALL_ENDED: ON_CALL_ENDED,
10423
10478
  ON_CALL_ENDING: ON_CALL_ENDING,
10424
10479
  ON_MESSAGE: ON_MESSAGE,
@@ -10448,6 +10503,14 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
10448
10503
  'default': WebRTCPhone
10449
10504
  });
10450
10505
 
10506
+ /* */
10507
+ class SFUNotAvailableError extends Error {
10508
+ constructor(message = 'Sorry your user is not configured to support video conference') {
10509
+ super(message);
10510
+ this.name = 'SFUNotAvailableError';
10511
+ }
10512
+ }
10513
+
10451
10514
  //
10452
10515
 
10453
10516
  const logger$6 = IssueReporter$1.loggerFor('simple-phone');
@@ -10832,7 +10895,7 @@ class Phone extends Emitter {
10832
10895
 
10833
10896
  checkSfu() {
10834
10897
  if (!this.hasSfu()) {
10835
- throw new Error('Sorry your user is not configured to support video conference');
10898
+ throw new SFUNotAvailableError();
10836
10899
  }
10837
10900
  }
10838
10901
 
@@ -12909,6 +12972,7 @@ const Wazo = {
12909
12972
  InvalidSubscription,
12910
12973
  InvalidAuthorization,
12911
12974
  CanceledCallError,
12975
+ SFUNotAvailableError,
12912
12976
  };
12913
12977
 
12914
12978
  if (window) {