@vgroup/dialbox 0.0.49 → 0.0.51
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/esm2020/lib/service/extension.service.mjs +100 -33
- package/esm2020/lib/service/twilio.service.mjs +81 -21
- package/fesm2015/vgroup-dialbox.mjs +179 -52
- package/fesm2015/vgroup-dialbox.mjs.map +1 -1
- package/fesm2020/vgroup-dialbox.mjs +179 -52
- package/fesm2020/vgroup-dialbox.mjs.map +1 -1
- package/lib/service/extension.service.d.ts +5 -3
- package/lib/service/twilio.service.d.ts +2 -0
- package/package.json +1 -1
|
@@ -2,11 +2,11 @@ import * as i0 from '@angular/core';
|
|
|
2
2
|
import { Injectable, EventEmitter, Component, Input, Output, ViewChild, Inject, NgModule } from '@angular/core';
|
|
3
3
|
import swal from 'sweetalert2';
|
|
4
4
|
import { AsYouType } from 'libphonenumber-js';
|
|
5
|
-
import { throwError, BehaviorSubject, interval, Subscription } from 'rxjs';
|
|
5
|
+
import { throwError, BehaviorSubject, timer, interval, Subscription } from 'rxjs';
|
|
6
6
|
import * as i1 from '@angular/common/http';
|
|
7
7
|
import { HttpHeaders, HttpParams, HttpClientModule } from '@angular/common/http';
|
|
8
8
|
import { Device } from '@twilio/voice-sdk';
|
|
9
|
-
import { catchError,
|
|
9
|
+
import { catchError, map, switchMap } from 'rxjs/operators';
|
|
10
10
|
import * as i3$1 from '@angular/material/dialog';
|
|
11
11
|
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
|
12
12
|
import * as i5 from '@angular/router';
|
|
@@ -154,6 +154,22 @@ class ExtensionService {
|
|
|
154
154
|
this.isProfileUpdated = new BehaviorSubject(false);
|
|
155
155
|
this.callerIdSubject = new BehaviorSubject(null);
|
|
156
156
|
this.callerId$ = this.callerIdSubject.asObservable();
|
|
157
|
+
// initiateCall(payload: any): Observable<any> {
|
|
158
|
+
// return this.ipAddressService.getIpAddressInfo().pipe(
|
|
159
|
+
// switchMap(ipAddressInfo => {
|
|
160
|
+
// const params = {
|
|
161
|
+
// 'Content-Type': 'application/json',
|
|
162
|
+
// 'Auth-Key': 'Bearer ' + localStorage.getItem('ext_token'),
|
|
163
|
+
// 'ip-address': ipAddressInfo.ip,
|
|
164
|
+
// 'ip-country': ipAddressInfo.address.country
|
|
165
|
+
// };
|
|
166
|
+
// const httpOptions = { headers: new HttpHeaders(params) };
|
|
167
|
+
// return this.http.post<[]>(environment.apiUrl + '/utilities/ext/ur/initiate/call', payload, httpOptions);
|
|
168
|
+
// })
|
|
169
|
+
// );
|
|
170
|
+
// }
|
|
171
|
+
this.maxRetries = 3;
|
|
172
|
+
this.retryDelay = 2000; // 2 seconds
|
|
157
173
|
}
|
|
158
174
|
changeMessage(message) {
|
|
159
175
|
this.messageSource.next(message);
|
|
@@ -404,13 +420,34 @@ class ExtensionService {
|
|
|
404
420
|
const httpOptions = { headers: new HttpHeaders(params) };
|
|
405
421
|
return this.http.post(environment.apiUrl + '/utilities/softphone/purchase/number', dtModel, httpOptions);
|
|
406
422
|
}
|
|
407
|
-
fetchCallerId(token) {
|
|
408
|
-
|
|
423
|
+
fetchCallerId(token, retryCount = 0) {
|
|
424
|
+
if (!token) {
|
|
425
|
+
return throwError(() => new Error('No authentication token provided'));
|
|
426
|
+
}
|
|
427
|
+
const headers = new HttpHeaders({
|
|
409
428
|
'Content-Type': 'application/json',
|
|
410
|
-
'Auth-Key':
|
|
429
|
+
'Auth-Key': `Bearer ${token}`,
|
|
430
|
+
'Cache-Control': 'no-cache',
|
|
431
|
+
'Pragma': 'no-cache'
|
|
432
|
+
});
|
|
433
|
+
const httpOptions = {
|
|
434
|
+
headers: headers,
|
|
435
|
+
withCredentials: true,
|
|
436
|
+
observe: 'response'
|
|
411
437
|
};
|
|
412
|
-
|
|
413
|
-
|
|
438
|
+
return this.http.get(`${environment.apiUrl}/utilities/softphone/fetch/callerid`, httpOptions).pipe(map(response => {
|
|
439
|
+
if (!response.body) {
|
|
440
|
+
throw new Error('Empty response from server');
|
|
441
|
+
}
|
|
442
|
+
return response.body;
|
|
443
|
+
}), catchError(error => {
|
|
444
|
+
console.error('Error fetching caller ID:', error);
|
|
445
|
+
if (retryCount < this.maxRetries) {
|
|
446
|
+
console.log(`Retrying... (${retryCount + 1}/${this.maxRetries})`);
|
|
447
|
+
return timer(this.retryDelay).pipe(switchMap(() => this.fetchCallerId(token, retryCount + 1)));
|
|
448
|
+
}
|
|
449
|
+
return throwError(() => new Error(`Failed to fetch caller ID after ${this.maxRetries} attempts`));
|
|
450
|
+
}));
|
|
414
451
|
}
|
|
415
452
|
updateNumberLabel(token, dtModel) {
|
|
416
453
|
const params = {
|
|
@@ -565,36 +602,66 @@ class ExtensionService {
|
|
|
565
602
|
}
|
|
566
603
|
}));
|
|
567
604
|
}
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
// 'ip-address': ipAddressInfo.ip,
|
|
575
|
-
// 'ip-country': ipAddressInfo.address.country
|
|
576
|
-
// };
|
|
577
|
-
// const httpOptions = { headers: new HttpHeaders(params) };
|
|
578
|
-
// return this.http.post<[]>(environment.apiUrl + '/utilities/ext/ur/initiate/call', payload, httpOptions);
|
|
579
|
-
// })
|
|
580
|
-
// );
|
|
581
|
-
// }
|
|
582
|
-
getIncomingCallToken() {
|
|
583
|
-
const params = {
|
|
605
|
+
getIncomingCallToken(retryCount = 0) {
|
|
606
|
+
const token = localStorage.getItem('ext_token');
|
|
607
|
+
if (!token) {
|
|
608
|
+
return throwError(() => new Error('No authentication token found'));
|
|
609
|
+
}
|
|
610
|
+
const params = new HttpHeaders({
|
|
584
611
|
'Content-Type': 'application/json',
|
|
585
|
-
'Auth-Key':
|
|
612
|
+
'Auth-Key': `Bearer ${token}`,
|
|
613
|
+
'Cache-Control': 'no-cache',
|
|
614
|
+
'Pragma': 'no-cache'
|
|
615
|
+
});
|
|
616
|
+
const httpOptions = {
|
|
617
|
+
headers: params,
|
|
618
|
+
withCredentials: true,
|
|
619
|
+
observe: 'response'
|
|
586
620
|
};
|
|
587
|
-
|
|
588
|
-
|
|
621
|
+
return this.http.get(`${environment.apiUrl}/utilities/twilio/incomingcall/token/web`, httpOptions).pipe(map(response => {
|
|
622
|
+
if (!response.body) {
|
|
623
|
+
throw new Error('Empty response from server');
|
|
624
|
+
}
|
|
625
|
+
return response.body;
|
|
626
|
+
}), catchError(error => {
|
|
627
|
+
console.error('Error fetching Twilio token:', error);
|
|
628
|
+
if (retryCount < this.maxRetries) {
|
|
629
|
+
console.log(`Retrying... (${retryCount + 1}/${this.maxRetries})`);
|
|
630
|
+
return timer(this.retryDelay).pipe(switchMap(() => this.getIncomingCallToken(retryCount + 1)));
|
|
631
|
+
}
|
|
632
|
+
return throwError(() => new Error(`Failed to get Twilio token after ${this.maxRetries} attempts`));
|
|
633
|
+
}));
|
|
589
634
|
}
|
|
590
|
-
getOutgoingCallToken(payload) {
|
|
591
|
-
const
|
|
635
|
+
getOutgoingCallToken(payload, retryCount = 0) {
|
|
636
|
+
const token = localStorage.getItem('ext_token');
|
|
637
|
+
if (!token) {
|
|
638
|
+
return throwError(() => new Error('No authentication token found'));
|
|
639
|
+
}
|
|
640
|
+
const headers = new HttpHeaders({
|
|
592
641
|
'Content-Type': 'application/json',
|
|
593
|
-
'Auth-Key':
|
|
594
|
-
'c2c-request': window.location.hostname
|
|
642
|
+
'Auth-Key': `Bearer ${token}`,
|
|
643
|
+
'c2c-request': window.location.hostname,
|
|
644
|
+
'Cache-Control': 'no-cache',
|
|
645
|
+
'Pragma': 'no-cache'
|
|
646
|
+
});
|
|
647
|
+
const httpOptions = {
|
|
648
|
+
headers: headers,
|
|
649
|
+
withCredentials: true,
|
|
650
|
+
observe: 'response'
|
|
595
651
|
};
|
|
596
|
-
|
|
597
|
-
|
|
652
|
+
return this.http.post(`${environment.apiUrl}/utilities/ext/ur/generate/token`, payload, httpOptions).pipe(map(response => {
|
|
653
|
+
if (!response.body) {
|
|
654
|
+
throw new Error('Empty response from server');
|
|
655
|
+
}
|
|
656
|
+
return response.body;
|
|
657
|
+
}), catchError(error => {
|
|
658
|
+
console.error('Error fetching outgoing call token:', error);
|
|
659
|
+
if (retryCount < this.maxRetries) {
|
|
660
|
+
console.log(`Retrying... (${retryCount + 1}/${this.maxRetries})`);
|
|
661
|
+
return timer(this.retryDelay).pipe(switchMap(() => this.getOutgoingCallToken(payload, retryCount + 1)));
|
|
662
|
+
}
|
|
663
|
+
return throwError(() => new Error(`Failed to get outgoing call token after ${this.maxRetries} attempts`));
|
|
664
|
+
}));
|
|
598
665
|
}
|
|
599
666
|
getCallRecording(callSid) {
|
|
600
667
|
const headers = new HttpHeaders({
|
|
@@ -1315,29 +1382,89 @@ class TwilioService {
|
|
|
1315
1382
|
this.isAvailableNumber = new BehaviorSubject(false);
|
|
1316
1383
|
this.callerIdList = new BehaviorSubject([]);
|
|
1317
1384
|
this.triggerSMSReload = new BehaviorSubject(false);
|
|
1318
|
-
this.
|
|
1385
|
+
this.isInitialized = false;
|
|
1386
|
+
// Initialize when token is available
|
|
1387
|
+
if (this.token) {
|
|
1388
|
+
this.initializeTwilioDevice();
|
|
1389
|
+
}
|
|
1390
|
+
else {
|
|
1391
|
+
// If token is not available, listen for it
|
|
1392
|
+
const tokenCheck = setInterval(() => {
|
|
1393
|
+
const token = localStorage.getItem('ext_token');
|
|
1394
|
+
if (token) {
|
|
1395
|
+
this.token = token;
|
|
1396
|
+
this.initializeTwilioDevice();
|
|
1397
|
+
clearInterval(tokenCheck);
|
|
1398
|
+
}
|
|
1399
|
+
}, 1000);
|
|
1400
|
+
}
|
|
1319
1401
|
}
|
|
1320
1402
|
initializeTwilioDevice() {
|
|
1321
|
-
if (this.token) {
|
|
1322
|
-
|
|
1323
|
-
this.incomingCallToken = data.token;
|
|
1324
|
-
localStorage.setItem('in-token', data.token);
|
|
1325
|
-
this.device = new Device(this.incomingCallToken, {
|
|
1326
|
-
allowIncomingWhileBusy: true,
|
|
1327
|
-
// Add any other necessary options
|
|
1328
|
-
});
|
|
1329
|
-
this.device.register();
|
|
1330
|
-
this.device.on('incoming', (call) => {
|
|
1331
|
-
this.currentCall.next(call);
|
|
1332
|
-
this.callType.next('INCOMING');
|
|
1333
|
-
this.currentCallState.next('incoming');
|
|
1334
|
-
});
|
|
1335
|
-
this.device.on('error', (error) => {
|
|
1336
|
-
console.error('Twilio Device Error:', error);
|
|
1337
|
-
// Add error handling and reconnection logic
|
|
1338
|
-
});
|
|
1339
|
-
});
|
|
1403
|
+
if (this.isInitialized || !this.token) {
|
|
1404
|
+
return;
|
|
1340
1405
|
}
|
|
1406
|
+
console.log('Initializing Twilio Device...');
|
|
1407
|
+
this.extensionService.getIncomingCallToken().subscribe({
|
|
1408
|
+
next: (data) => {
|
|
1409
|
+
if (!data?.token) {
|
|
1410
|
+
console.error('No token received from server');
|
|
1411
|
+
return;
|
|
1412
|
+
}
|
|
1413
|
+
try {
|
|
1414
|
+
console.log('Setting up Twilio Device with token');
|
|
1415
|
+
this.incomingCallToken = data.token;
|
|
1416
|
+
localStorage.setItem('in-token', data.token);
|
|
1417
|
+
// Destroy existing device if any
|
|
1418
|
+
if (this.device) {
|
|
1419
|
+
this.device.destroy();
|
|
1420
|
+
}
|
|
1421
|
+
// Create new device instance
|
|
1422
|
+
this.device = new Device(data.token, {
|
|
1423
|
+
allowIncomingWhileBusy: true,
|
|
1424
|
+
closeProtection: true
|
|
1425
|
+
});
|
|
1426
|
+
// Set up event listeners
|
|
1427
|
+
this.setupDeviceListeners();
|
|
1428
|
+
// Register the device
|
|
1429
|
+
this.device.register();
|
|
1430
|
+
this.isInitialized = true;
|
|
1431
|
+
}
|
|
1432
|
+
catch (error) {
|
|
1433
|
+
console.error('Error initializing Twilio Device:', error);
|
|
1434
|
+
this.isInitialized = false;
|
|
1435
|
+
}
|
|
1436
|
+
},
|
|
1437
|
+
error: (error) => {
|
|
1438
|
+
console.error('Error getting Twilio token:', error);
|
|
1439
|
+
// Retry after delay
|
|
1440
|
+
setTimeout(() => this.initializeTwilioDevice(), 5000);
|
|
1441
|
+
}
|
|
1442
|
+
});
|
|
1443
|
+
}
|
|
1444
|
+
setupDeviceListeners() {
|
|
1445
|
+
if (!this.device)
|
|
1446
|
+
return;
|
|
1447
|
+
this.device.on('registered', () => {
|
|
1448
|
+
console.log('Twilio Device registered successfully');
|
|
1449
|
+
});
|
|
1450
|
+
this.device.on('incoming', (call) => {
|
|
1451
|
+
console.log('Incoming call received');
|
|
1452
|
+
this.currentCall.next(call);
|
|
1453
|
+
this.callType.next('INCOMING');
|
|
1454
|
+
this.currentCallState.next('incoming');
|
|
1455
|
+
});
|
|
1456
|
+
this.device.on('error', (error) => {
|
|
1457
|
+
console.error('Twilio Device Error:', error);
|
|
1458
|
+
this.isInitialized = false;
|
|
1459
|
+
// Attempt to reinitialize after delay
|
|
1460
|
+
setTimeout(() => this.initializeTwilioDevice(), 5000);
|
|
1461
|
+
});
|
|
1462
|
+
this.device.on('unregistered', () => {
|
|
1463
|
+
console.log('Twilio Device unregistered');
|
|
1464
|
+
this.isInitialized = false;
|
|
1465
|
+
// Attempt to re-register
|
|
1466
|
+
setTimeout(() => this.initializeTwilioDevice(), 5000);
|
|
1467
|
+
});
|
|
1341
1468
|
}
|
|
1342
1469
|
// onIncomingCall(){
|
|
1343
1470
|
// this.device.on('incoming', (call:any) => {
|