@vgroup/dialbox 0.0.83 → 0.0.85

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.
@@ -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, of, Subscription, filter, interval } from 'rxjs';
6
6
  import * as i1 from '@angular/common/http';
7
7
  import { HttpHeaders, HttpParams, HttpClientModule } from '@angular/common/http';
8
+ import { catchError, switchMap, map, tap, shareReplay } from 'rxjs/operators';
8
9
  import { Device } from '@twilio/voice-sdk';
9
- import { catchError, switchMap, map } 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';
@@ -1387,85 +1387,60 @@ class TwilioService {
1387
1387
  this.isAvailableNumber = new BehaviorSubject(false);
1388
1388
  this.callerIdList = new BehaviorSubject([]);
1389
1389
  this.triggerSMSReload = new BehaviorSubject(false);
1390
- this.deviceInitialized = false;
1391
- this.initializationInProgress = false;
1392
- // Initialize immediately if token exists
1393
- this.token = localStorage.getItem('ext_token');
1394
- if (this.token) {
1395
- this.initializeTwilioDevice();
1396
- }
1397
- // Set up a polling mechanism to check for token availability
1398
- this.startTokenCheck();
1399
- }
1400
- startTokenCheck() {
1401
- // Check every 2 seconds if we have a token
1402
- this.tokenCheckInterval = setInterval(() => {
1403
- const currentToken = localStorage.getItem('ext_token');
1404
- if (currentToken && currentToken !== this.token) {
1405
- this.token = currentToken;
1406
- this.initializeTwilioDevice();
1407
- }
1408
- }, 2000);
1390
+ this.tokenInitialized = false;
1391
+ this.tokenInitialization$ = null;
1392
+ this.lastCallSid = null;
1393
+ this.lastCallTime = 0;
1394
+ this.CALL_DEBOUNCE_MS = 1000; // 1 second debounce
1395
+ this.initializeToken();
1396
+ }
1397
+ initializeToken() {
1398
+ if (this.tokenInitialized) {
1399
+ return this.tokenInitialization$ || of(null);
1400
+ }
1401
+ this.tokenInitialization$ = this.extensionService.getIncomingCallToken().pipe(tap((data) => {
1402
+ this.incomingCallToken = data.token;
1403
+ localStorage.setItem('in-token', data.token);
1404
+ this.tokenInitialized = true;
1405
+ this.initializeDevice();
1406
+ }), catchError(error => {
1407
+ console.error('Error initializing Twilio token:', error);
1408
+ return throwError(() => error);
1409
+ }), shareReplay(1) // Cache the result for subsequent subscribers
1410
+ );
1411
+ return this.tokenInitialization$;
1409
1412
  }
1410
- ngOnDestroy() {
1411
- if (this.tokenCheckInterval) {
1412
- clearInterval(this.tokenCheckInterval);
1413
+ initializeTwilioDevice() {
1414
+ if (this.tokenInitialized && this.incomingCallToken) {
1415
+ this.initializeDevice();
1416
+ }
1417
+ else {
1418
+ this.initializeToken().subscribe();
1413
1419
  }
1420
+ }
1421
+ initializeDevice() {
1414
1422
  if (this.device) {
1415
1423
  this.device.destroy();
1416
1424
  }
1417
- }
1418
- initializeTwilioDevice() {
1419
- // Prevent multiple initializations
1420
- if (this.deviceInitialized || this.initializationInProgress || !this.token) {
1425
+ if (!this.incomingCallToken) {
1426
+ console.error('No Twilio token available');
1421
1427
  return;
1422
1428
  }
1423
- this.initializationInProgress = true;
1424
- this.extensionService.getIncomingCallToken().subscribe({
1425
- next: (data) => {
1426
- try {
1427
- this.incomingCallToken = data.token;
1428
- localStorage.setItem('in-token', data.token);
1429
- // Destroy existing device if it exists
1430
- if (this.device) {
1431
- this.device.destroy();
1432
- }
1433
- // Initialize Twilio Device with required options
1434
- const deviceOptions = {
1435
- allowIncomingWhileBusy: true,
1436
- closeProtection: true
1437
- };
1438
- // Only add debug in development
1439
- if (!environment.production) {
1440
- deviceOptions.debug = false;
1441
- }
1442
- this.device = new Device(this.incomingCallToken, deviceOptions);
1443
- this.device.register();
1444
- this.deviceInitialized = true;
1445
- this.initializationInProgress = false;
1446
- console.log('Twilio Device initialized successfully');
1447
- this.setupDeviceEventHandlers();
1448
- }
1449
- catch (error) {
1450
- console.error('Error initializing Twilio Device:', error);
1451
- this.initializationInProgress = false;
1452
- // Retry after a delay
1453
- setTimeout(() => this.initializeTwilioDevice(), 5000);
1454
- }
1455
- },
1456
- error: (error) => {
1457
- console.error('Error getting Twilio token:', error);
1458
- this.initializationInProgress = false;
1459
- // Retry after a delay
1460
- setTimeout(() => this.initializeTwilioDevice(), 5000);
1461
- }
1429
+ this.device = new Device(this.incomingCallToken, {
1430
+ allowIncomingWhileBusy: true,
1431
+ closeProtection: true
1462
1432
  });
1463
- }
1464
- setupDeviceEventHandlers() {
1465
- if (!this.device)
1466
- return;
1433
+ this.device.register();
1467
1434
  this.device.on('incoming', (call) => {
1468
- console.log('Incoming call received:', call.parameters);
1435
+ const callSid = call.parameters?.['CallSid'];
1436
+ const now = Date.now();
1437
+ // Skip if this is a duplicate call within the debounce window
1438
+ if (callSid && callSid === this.lastCallSid && (now - this.lastCallTime) < this.CALL_DEBOUNCE_MS) {
1439
+ console.log('Skipping duplicate call:', callSid);
1440
+ return;
1441
+ }
1442
+ this.lastCallSid = callSid;
1443
+ this.lastCallTime = now;
1469
1444
  this.currentCall.next(call);
1470
1445
  this.callType.next('INCOMING');
1471
1446
  this.currentCallState.next('incoming');
@@ -1473,20 +1448,15 @@ class TwilioService {
1473
1448
  });
1474
1449
  this.device.on('error', (error) => {
1475
1450
  console.error('Twilio Device Error:', error);
1476
- this.deviceInitialized = false;
1477
- // Attempt to reinitialize on error
1478
- if (error.code === 31201 || error.code === 20101) {
1479
- console.log('Authentication error, reinitializing device...');
1480
- this.initializeTwilioDevice();
1481
- }
1451
+ // Reset initialization state on error to allow retry
1452
+ this.tokenInitialized = false;
1482
1453
  });
1483
1454
  this.device.on('registered', () => {
1484
- console.log('Twilio Device registered');
1485
- this.deviceInitialized = true;
1455
+ console.log('Twilio Device registered successfully');
1486
1456
  });
1487
1457
  this.device.on('unregistered', () => {
1488
1458
  console.log('Twilio Device unregistered');
1489
- this.deviceInitialized = false;
1459
+ this.tokenInitialized = false;
1490
1460
  });
1491
1461
  }
1492
1462
  // onIncomingCall(){
@@ -1610,43 +1580,63 @@ class IncomingCallComponent {
1610
1580
  this.closeIncomingCallDiv = new EventEmitter();
1611
1581
  this.incomingCallsNewList = new EventEmitter();
1612
1582
  this.selectedIncomingCallInfo = new EventEmitter();
1583
+ this.subscription = new Subscription();
1584
+ this.callHandled = new Set(); // Track handled calls by CallSid
1613
1585
  }
1614
1586
  ngOnInit() {
1615
- // this.twilioService.currentCall.subscribe((call: any) => {
1616
- // if (call) {
1617
- // this.twilioCallData = call;
1618
- // this.notificationSerivce.showNotification(call);
1619
- // // Handle the call UI
1620
- // }
1621
- // });
1622
1587
  try {
1623
- this.twilioService.currentCall.subscribe(call => {
1624
- if (call) {
1625
- this.twilioCallData = call;
1626
- this.twilioAuthId = call.customParameters.get('twilioAuthId');
1627
- if (!call.parameters) {
1628
- call.parameters = {};
1629
- }
1630
- this.sendIPforIncomingCall(this.twilioAuthId, '');
1631
- call.on('cancel', () => {
1632
- if (this.incomingCallData && this.incomingCallData.parameters && this.incomingCallData.parameters.CallSid) {
1633
- this.newIncomingCallsList = this.newIncomingCallsList.filter((item) => item.parameters && item.parameters.CallSid !== this.incomingCallData.parameters.CallSid);
1634
- }
1635
- this.rejectCallFromList(call);
1636
- });
1637
- call.on('disconnect', () => {
1638
- if (this.incomingCallData && this.incomingCallData.parameters && this.incomingCallData.parameters.CallSid) {
1639
- this.newIncomingCallsList = this.newIncomingCallsList.filter((item) => item.parameters && item.parameters.CallSid !== this.incomingCallData.parameters.CallSid);
1640
- }
1641
- this.rejectCallFromList(call);
1642
- });
1643
- }
1644
- });
1588
+ // Only handle the call if we have incomingCallData
1589
+ if (this.incomingCallData) {
1590
+ this.handleIncomingCall(this.incomingCallData);
1591
+ }
1592
+ // Subscribe to new calls
1593
+ this.subscription.add(this.twilioService.currentCall.pipe(
1594
+ // Filter out duplicate calls that we've already handled
1595
+ filter((call) => {
1596
+ if (!call)
1597
+ return false;
1598
+ const callSid = call.parameters['CallSid'];
1599
+ return callSid && !this.callHandled.has(callSid);
1600
+ })).subscribe(call => {
1601
+ this.handleIncomingCall(call);
1602
+ }));
1645
1603
  }
1646
1604
  catch (e) {
1647
- console.log(e);
1605
+ console.error('Error in incoming call handling:', e);
1648
1606
  }
1649
1607
  }
1608
+ handleIncomingCall(call) {
1609
+ if (!call)
1610
+ return;
1611
+ const callSid = call.parameters?.CallSid;
1612
+ if (!callSid || this.callHandled.has(callSid)) {
1613
+ return; // Skip if no CallSid or already handled
1614
+ }
1615
+ this.callHandled.add(callSid);
1616
+ this.twilioCallData = call;
1617
+ this.twilioAuthId = call.customParameters?.get('twilioAuthId');
1618
+ if (!call.parameters) {
1619
+ call.parameters = {};
1620
+ }
1621
+ // Send IP for the incoming call
1622
+ this.sendIPforIncomingCall(this.twilioAuthId, '');
1623
+ // Setup call event handlers
1624
+ const handleCallEnd = () => {
1625
+ if (callSid) {
1626
+ this.callHandled.delete(callSid);
1627
+ if (this.newIncomingCallsList) {
1628
+ this.newIncomingCallsList = this.newIncomingCallsList.filter((item) => item.parameters?.CallSid !== callSid);
1629
+ }
1630
+ }
1631
+ this.rejectCallFromList(call);
1632
+ };
1633
+ call.on('cancel', handleCallEnd);
1634
+ call.on('disconnect', handleCallEnd);
1635
+ }
1636
+ ngOnDestroy() {
1637
+ this.subscription.unsubscribe();
1638
+ this.callHandled.clear();
1639
+ }
1650
1640
  acceptCallFromList(data) {
1651
1641
  data.accept();
1652
1642
  // data.parameters['isCallConnected'] = true;
@@ -2283,28 +2273,7 @@ class DialboxComponent {
2283
2273
  return;
2284
2274
  this.token = localStorage.getItem('ext_token') || '';
2285
2275
  if (!this.token) {
2286
- console.warn('No authentication token found. Will retry initializing Twilio when token is available.');
2287
- // Clear any existing interval to prevent multiple intervals
2288
- if (this.twilioInitializationInterval) {
2289
- clearInterval(this.twilioInitializationInterval);
2290
- }
2291
- // Set up a check for when token becomes available
2292
- this.twilioInitializationInterval = setInterval(() => {
2293
- const newToken = localStorage.getItem('ext_token');
2294
- if (newToken) {
2295
- clearInterval(this.twilioInitializationInterval);
2296
- this.token = newToken;
2297
- this.initializeTwilio();
2298
- }
2299
- }, 2000);
2300
- // Add cleanup for this interval
2301
- this.subscriptions.add({
2302
- unsubscribe: () => {
2303
- if (this.twilioInitializationInterval) {
2304
- clearInterval(this.twilioInitializationInterval);
2305
- }
2306
- }
2307
- });
2276
+ console.error('No authentication token found');
2308
2277
  return;
2309
2278
  }
2310
2279
  this.isInitialized = true;
@@ -2423,10 +2392,8 @@ class DialboxComponent {
2423
2392
  // }
2424
2393
  ngOnInit() {
2425
2394
  try {
2426
- // Initialize Twilio when component loads
2427
- this.initializeTwilio();
2428
- // Get token and load initial data
2429
2395
  this.token = localStorage.getItem('ext_token') || '';
2396
+ //this.isCallInProgress = true;
2430
2397
  this.getContactList();
2431
2398
  this.getUserCallSetting();
2432
2399
  const sub1 = this.twilioService.dialNumberFromOtherModule.subscribe((contact) => {
@@ -3285,13 +3252,6 @@ class DialboxComponent {
3285
3252
  if (this.subscriptions) {
3286
3253
  this.subscriptions.unsubscribe();
3287
3254
  }
3288
- // Clear any active intervals
3289
- if (this.tokenCheckInterval) {
3290
- clearInterval(this.tokenCheckInterval);
3291
- }
3292
- if (this.twilioInitializationInterval) {
3293
- clearInterval(this.twilioInitializationInterval);
3294
- }
3295
3255
  // Clean up Twilio device when component is destroyed
3296
3256
  if (this.twilioService['device']) {
3297
3257
  this.twilioService['device'].destroy();