@telnyx/react-voice-commons-sdk 1.0.0 → 1.1.1
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/CHANGELOG.md +23 -0
- package/README.md +28 -7
- package/android/src/main/java/com/telnyx/react_voice_commons/CallForegroundService.kt +16 -2
- package/android/src/main/java/com/telnyx/react_voice_commons/TelnyxNotificationHelper.kt +345 -24
- package/android/src/main/java/com/telnyx/react_voice_commons/VoicePnBridgeModule.kt +19 -0
- package/android/src/main/java/com/telnyx/react_voice_commons/VoicePnManager.kt +19 -0
- package/ios/CallKitBridge.m +27 -1
- package/ios/CallKitBridge.swift +640 -125
- package/ios/README.md +2 -2
- package/ios/VoicePnBridge.m +6 -0
- package/ios/VoicePnBridge.swift +15 -0
- package/lib/callkit/callkit-coordinator.d.ts +39 -3
- package/lib/callkit/callkit-coordinator.js +561 -148
- package/lib/callkit/callkit.d.ts +7 -0
- package/lib/callkit/callkit.js +83 -11
- package/lib/hooks/useAppStateHandler.js +6 -2
- package/lib/internal/CallKitHandler.d.ts +3 -0
- package/lib/internal/CallKitHandler.js +52 -46
- package/lib/internal/calls/call-state-controller.d.ts +33 -1
- package/lib/internal/calls/call-state-controller.js +100 -28
- package/lib/internal/session/session-manager.d.ts +15 -1
- package/lib/internal/session/session-manager.js +214 -62
- package/lib/internal/voice-pn-bridge.d.ts +18 -0
- package/lib/internal/voice-pn-bridge.js +39 -0
- package/lib/models/call.js +35 -0
- package/lib/models/config.d.ts +10 -0
- package/lib/models/config.js +2 -0
- package/lib/telnyx-voice-app.js +85 -43
- package/lib/telnyx-voip-client.d.ts +46 -5
- package/lib/telnyx-voip-client.js +238 -22
- package/package.json +7 -5
- package/src/callkit/callkit-coordinator.ts +642 -160
- package/src/callkit/callkit.ts +110 -12
- package/src/hooks/useAppStateHandler.ts +7 -2
- package/src/internal/CallKitHandler.tsx +60 -55
- package/src/internal/calls/call-state-controller.ts +112 -29
- package/src/internal/session/session-manager.ts +260 -65
- package/src/internal/voice-pn-bridge.ts +47 -0
- package/src/models/call.ts +34 -0
- package/src/models/config.ts +10 -0
- package/src/telnyx-voice-app.tsx +96 -45
- package/src/telnyx-voip-client.ts +216 -24
- package/src/types/telnyx-sdk.d.ts +2 -1
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
import { Observable } from 'rxjs';
|
|
2
|
+
import { Platform } from 'react-native';
|
|
2
3
|
import { TelnyxConnectionState } from './models/connection-state';
|
|
3
4
|
import { Call } from './models/call';
|
|
4
5
|
import { TelnyxCallState } from './models/call-state';
|
|
5
6
|
import { Config, CredentialConfig, TokenConfig, validateConfig } from './models/config';
|
|
6
7
|
import { SessionManager } from './internal/session/session-manager';
|
|
7
|
-
import { CallStateController } from './internal/calls/call-state-controller';
|
|
8
|
+
import { CallStateController, type CustomHeaders } from './internal/calls/call-state-controller';
|
|
8
9
|
import { VoicePnBridge } from './internal/voice-pn-bridge';
|
|
9
10
|
|
|
10
11
|
const USE_TRICKLE_ICE_STORAGE_KEY = '@use_trickle_ice';
|
|
12
|
+
const PUSH_WHEN_ACTIVE_STORAGE_KEY = '@push_when_active';
|
|
11
13
|
const MISSED_CALL_NOTIFICATIONS_STORAGE_KEY = '@enable_missed_call_notifications';
|
|
14
|
+
const LEGACY_CALLKIT_ANSWER_KEY = '__legacy_callkit_answer__';
|
|
15
|
+
|
|
16
|
+
interface PendingCallKitAnswer {
|
|
17
|
+
callKitUUIDOrHeaders?: string | Record<string, string>;
|
|
18
|
+
customHeaders: Record<string, string>;
|
|
19
|
+
}
|
|
12
20
|
|
|
13
21
|
/**
|
|
14
22
|
* Configuration options for TelnyxVoipClient
|
|
@@ -39,7 +47,9 @@ export class TelnyxVoipClient {
|
|
|
39
47
|
private readonly _sessionManager: SessionManager;
|
|
40
48
|
private readonly _callStateController: CallStateController;
|
|
41
49
|
private readonly _options: Required<TelnyxVoipClientOptions>;
|
|
50
|
+
private readonly _pendingCallKitAnswers = new Map<string, PendingCallKitAnswer>();
|
|
42
51
|
private _disposed = false;
|
|
52
|
+
private _disposePromise?: Promise<void>;
|
|
43
53
|
|
|
44
54
|
/**
|
|
45
55
|
* Check if the app was launched from a push notification.
|
|
@@ -86,6 +96,7 @@ export class TelnyxVoipClient {
|
|
|
86
96
|
console.log(
|
|
87
97
|
'🔧 TelnyxVoipClient: Client ready, initializing call state controller listeners'
|
|
88
98
|
);
|
|
99
|
+
this._flushPendingCallKitAnswers();
|
|
89
100
|
this._callStateController.initializeClientListeners();
|
|
90
101
|
});
|
|
91
102
|
|
|
@@ -188,6 +199,71 @@ export class TelnyxVoipClient {
|
|
|
188
199
|
return this._callStateController.getCall(callId);
|
|
189
200
|
}
|
|
190
201
|
|
|
202
|
+
/**
|
|
203
|
+
* Explicitly set the active call for multi-call scenarios.
|
|
204
|
+
* @param callId The ID of the call to mark as active
|
|
205
|
+
*/
|
|
206
|
+
setActiveCall(callId: string): void {
|
|
207
|
+
this._throwIfDisposed();
|
|
208
|
+
this._callStateController.setActiveCall(callId);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Clear the explicitly selected active call and return to default selection.
|
|
213
|
+
*/
|
|
214
|
+
clearActiveCall(): void {
|
|
215
|
+
this._throwIfDisposed();
|
|
216
|
+
this._callStateController.clearActiveCall();
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Swap the current active call with a held call.
|
|
221
|
+
* On iOS this is coordinated through CallKit so native and SDK state stay aligned.
|
|
222
|
+
*
|
|
223
|
+
* @param targetCallId ID of the held call to make active
|
|
224
|
+
*/
|
|
225
|
+
async swapCalls(targetCallId: string): Promise<void> {
|
|
226
|
+
this._throwIfDisposed();
|
|
227
|
+
|
|
228
|
+
const activeCall = this.currentActiveCall;
|
|
229
|
+
const heldCall = this.getCall(targetCallId);
|
|
230
|
+
|
|
231
|
+
if (!activeCall || !heldCall || activeCall.callId === heldCall.callId) {
|
|
232
|
+
throw new Error('An active call and a different held call are required to swap calls');
|
|
233
|
+
}
|
|
234
|
+
if (activeCall.currentState !== TelnyxCallState.ACTIVE) {
|
|
235
|
+
throw new Error(`Cannot swap active call in state: ${activeCall.currentState}`);
|
|
236
|
+
}
|
|
237
|
+
if (heldCall.currentState !== TelnyxCallState.HELD) {
|
|
238
|
+
throw new Error(`Cannot swap target call in state: ${heldCall.currentState}`);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (Platform.OS === 'ios') {
|
|
242
|
+
const { callKitCoordinator } = await import('./callkit/callkit-coordinator');
|
|
243
|
+
if (callKitCoordinator.isAvailable()) {
|
|
244
|
+
const success = await callKitCoordinator.swapCallsFromUI(
|
|
245
|
+
activeCall.telnyxCall,
|
|
246
|
+
heldCall.telnyxCall
|
|
247
|
+
);
|
|
248
|
+
if (!success) {
|
|
249
|
+
throw new Error('CallKit failed to swap calls');
|
|
250
|
+
}
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
await activeCall.hold();
|
|
256
|
+
try {
|
|
257
|
+
await heldCall.resume();
|
|
258
|
+
this.setActiveCall(heldCall.callId);
|
|
259
|
+
} catch (error) {
|
|
260
|
+
await activeCall.resume().catch((resumeError) => {
|
|
261
|
+
console.error('Failed to restore active call after swap failure', resumeError);
|
|
262
|
+
});
|
|
263
|
+
throw error;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
191
267
|
/**
|
|
192
268
|
* Current session ID (UUID) for this connection.
|
|
193
269
|
*/
|
|
@@ -225,10 +301,12 @@ export class TelnyxVoipClient {
|
|
|
225
301
|
console.log('TelnyxVoipClient: Logging in with credentials for user:', config.sipUser);
|
|
226
302
|
}
|
|
227
303
|
|
|
228
|
-
const loginConfig = {
|
|
304
|
+
const loginConfig = await this._withNativeVoipPushToken({
|
|
229
305
|
...config,
|
|
230
306
|
useTrickleIce: config.useTrickleIce ?? this._options.useTrickleIce,
|
|
231
|
-
};
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
await VoicePnBridge.setIncomingCallRingtone(loginConfig.incomingCallRingtone);
|
|
232
310
|
|
|
233
311
|
// Store credentials for future reconnection
|
|
234
312
|
await this._storeCredentials(loginConfig);
|
|
@@ -257,10 +335,12 @@ export class TelnyxVoipClient {
|
|
|
257
335
|
console.log('TelnyxVoipClient: Logging in with token');
|
|
258
336
|
}
|
|
259
337
|
|
|
260
|
-
const loginConfig = {
|
|
338
|
+
const loginConfig = await this._withNativeVoipPushToken({
|
|
261
339
|
...config,
|
|
262
340
|
useTrickleIce: config.useTrickleIce ?? this._options.useTrickleIce,
|
|
263
|
-
};
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
await VoicePnBridge.setIncomingCallRingtone(loginConfig.incomingCallRingtone);
|
|
264
344
|
|
|
265
345
|
// Store token for future reconnection
|
|
266
346
|
await this._storeToken(loginConfig);
|
|
@@ -310,20 +390,30 @@ export class TelnyxVoipClient {
|
|
|
310
390
|
const storedCredentialToken = await AsyncStorage.getItem('@credential_token');
|
|
311
391
|
const storedPushToken = await AsyncStorage.getItem('@push_token');
|
|
312
392
|
const storedUseTrickleIce = await AsyncStorage.getItem(USE_TRICKLE_ICE_STORAGE_KEY);
|
|
393
|
+
const storedPushWhenActive = await AsyncStorage.getItem(PUSH_WHEN_ACTIVE_STORAGE_KEY);
|
|
313
394
|
const storedMissedCallNotifications = await AsyncStorage.getItem(
|
|
314
395
|
MISSED_CALL_NOTIFICATIONS_STORAGE_KEY
|
|
315
396
|
);
|
|
316
397
|
const useTrickleIce =
|
|
317
398
|
storedUseTrickleIce === null ? this._options.useTrickleIce : storedUseTrickleIce === 'true';
|
|
399
|
+
const pushWhenActive = storedPushWhenActive === 'true';
|
|
318
400
|
const enableMissedCallNotifications = storedMissedCallNotifications === 'true';
|
|
401
|
+
const nativePushToken =
|
|
402
|
+
Platform.OS === 'ios' ? (await VoicePnBridge.getVoipToken())?.trim() : null;
|
|
403
|
+
const pushNotificationDeviceToken = nativePushToken || storedPushToken;
|
|
404
|
+
|
|
405
|
+
if (nativePushToken && nativePushToken !== storedPushToken) {
|
|
406
|
+
await AsyncStorage.setItem('@push_token', nativePushToken);
|
|
407
|
+
}
|
|
319
408
|
|
|
320
409
|
// Check if we have credential-based authentication data
|
|
321
410
|
if (storedUsername && storedPassword) {
|
|
322
411
|
// Create credential config from stored data
|
|
323
412
|
const { createCredentialConfig } = require('./models/config');
|
|
324
413
|
const config = createCredentialConfig(storedUsername, storedPassword, {
|
|
325
|
-
pushNotificationDeviceToken
|
|
414
|
+
pushNotificationDeviceToken,
|
|
326
415
|
useTrickleIce,
|
|
416
|
+
pushWhenActive,
|
|
327
417
|
enableMissedCallNotifications,
|
|
328
418
|
});
|
|
329
419
|
|
|
@@ -343,8 +433,9 @@ export class TelnyxVoipClient {
|
|
|
343
433
|
// Create token config from stored data
|
|
344
434
|
const { createTokenConfig } = require('./models/config');
|
|
345
435
|
const config = createTokenConfig(storedCredentialToken, {
|
|
346
|
-
pushNotificationDeviceToken
|
|
436
|
+
pushNotificationDeviceToken,
|
|
347
437
|
useTrickleIce,
|
|
438
|
+
pushWhenActive,
|
|
348
439
|
enableMissedCallNotifications,
|
|
349
440
|
});
|
|
350
441
|
|
|
@@ -386,7 +477,7 @@ export class TelnyxVoipClient {
|
|
|
386
477
|
destination: string,
|
|
387
478
|
callerName?: string,
|
|
388
479
|
callerNumber?: string,
|
|
389
|
-
customHeaders?:
|
|
480
|
+
customHeaders?: CustomHeaders
|
|
390
481
|
): Promise<Call> {
|
|
391
482
|
this._throwIfDisposed();
|
|
392
483
|
|
|
@@ -484,20 +575,35 @@ export class TelnyxVoipClient {
|
|
|
484
575
|
* This should be called when the user answers from CallKit before the socket connection is established
|
|
485
576
|
* @param customHeaders Optional custom headers to include with the answer
|
|
486
577
|
*/
|
|
487
|
-
queueAnswerFromCallKit(
|
|
578
|
+
queueAnswerFromCallKit(
|
|
579
|
+
callKitUUIDOrHeaders?: string | Record<string, string>,
|
|
580
|
+
customHeaders: Record<string, string> = {}
|
|
581
|
+
): void {
|
|
488
582
|
this._throwIfDisposed();
|
|
489
583
|
|
|
490
584
|
if (this._options.debug) {
|
|
491
|
-
console.log('TelnyxVoipClient: Queuing answer action from CallKit',
|
|
585
|
+
console.log('TelnyxVoipClient: Queuing answer action from CallKit', {
|
|
586
|
+
callKitUUIDOrHeaders,
|
|
587
|
+
customHeaders,
|
|
588
|
+
});
|
|
492
589
|
}
|
|
493
590
|
|
|
494
591
|
const telnyxClient = this._sessionManager.telnyxClient;
|
|
495
592
|
if (telnyxClient && typeof (telnyxClient as any).queueAnswerFromCallKit === 'function') {
|
|
496
|
-
(telnyxClient as any).queueAnswerFromCallKit(customHeaders);
|
|
593
|
+
(telnyxClient as any).queueAnswerFromCallKit(callKitUUIDOrHeaders, customHeaders);
|
|
497
594
|
} else {
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
595
|
+
const normalizedUUID =
|
|
596
|
+
typeof callKitUUIDOrHeaders === 'string' ? callKitUUIDOrHeaders.toLowerCase() : undefined;
|
|
597
|
+
const actionKey = normalizedUUID ?? LEGACY_CALLKIT_ANSWER_KEY;
|
|
598
|
+
let retainedUUIDOrHeaders: string | Record<string, string> | undefined = normalizedUUID;
|
|
599
|
+
if (callKitUUIDOrHeaders && typeof callKitUUIDOrHeaders !== 'string') {
|
|
600
|
+
retainedUUIDOrHeaders = { ...callKitUUIDOrHeaders };
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
this._pendingCallKitAnswers.set(actionKey, {
|
|
604
|
+
callKitUUIDOrHeaders: retainedUUIDOrHeaders,
|
|
605
|
+
customHeaders: { ...customHeaders },
|
|
606
|
+
});
|
|
501
607
|
}
|
|
502
608
|
}
|
|
503
609
|
|
|
@@ -505,7 +611,7 @@ export class TelnyxVoipClient {
|
|
|
505
611
|
* Queue an end action for when the call invite arrives (for CallKit integration)
|
|
506
612
|
* This should be called when the user ends from CallKit before the socket connection is established
|
|
507
613
|
*/
|
|
508
|
-
queueEndFromCallKit(): void {
|
|
614
|
+
queueEndFromCallKit(callKitUUID?: string): void {
|
|
509
615
|
this._throwIfDisposed();
|
|
510
616
|
|
|
511
617
|
if (this._options.debug) {
|
|
@@ -514,7 +620,7 @@ export class TelnyxVoipClient {
|
|
|
514
620
|
|
|
515
621
|
const telnyxClient = this._sessionManager.telnyxClient;
|
|
516
622
|
if (telnyxClient && typeof (telnyxClient as any).queueEndFromCallKit === 'function') {
|
|
517
|
-
(telnyxClient as any).queueEndFromCallKit();
|
|
623
|
+
(telnyxClient as any).queueEndFromCallKit(callKitUUID);
|
|
518
624
|
} else {
|
|
519
625
|
console.warn(
|
|
520
626
|
'TelnyxVoipClient: TelnyxRTC client not available or method not found for queueEndFromCallKit'
|
|
@@ -522,6 +628,21 @@ export class TelnyxVoipClient {
|
|
|
522
628
|
}
|
|
523
629
|
}
|
|
524
630
|
|
|
631
|
+
/**
|
|
632
|
+
* Associate the next push-delivered INVITE with its app-facing CallKit UUID.
|
|
633
|
+
* The underlying signaling call ID remains unchanged.
|
|
634
|
+
* @internal
|
|
635
|
+
*/
|
|
636
|
+
setPushNotificationCallKitUUID(callKitUUID: string | null): void {
|
|
637
|
+
const telnyxClient = this._sessionManager.telnyxClient;
|
|
638
|
+
if (
|
|
639
|
+
telnyxClient &&
|
|
640
|
+
typeof (telnyxClient as any).setPushNotificationCallKitUUID === 'function'
|
|
641
|
+
) {
|
|
642
|
+
(telnyxClient as any).setPushNotificationCallKitUUID(callKitUUID);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
|
|
525
646
|
// ========== Lifecycle Methods ==========
|
|
526
647
|
|
|
527
648
|
/**
|
|
@@ -531,9 +652,9 @@ export class TelnyxVoipClient {
|
|
|
531
652
|
* This is particularly important for background clients that should be
|
|
532
653
|
* disposed after handling push notifications.
|
|
533
654
|
*/
|
|
534
|
-
dispose(): void {
|
|
535
|
-
if (this.
|
|
536
|
-
return;
|
|
655
|
+
async dispose(): Promise<void> {
|
|
656
|
+
if (this._disposePromise) {
|
|
657
|
+
return this._disposePromise;
|
|
537
658
|
}
|
|
538
659
|
|
|
539
660
|
if (this._options.debug) {
|
|
@@ -541,12 +662,73 @@ export class TelnyxVoipClient {
|
|
|
541
662
|
}
|
|
542
663
|
|
|
543
664
|
this._disposed = true;
|
|
544
|
-
this.
|
|
545
|
-
|
|
665
|
+
this._disposePromise = (async () => {
|
|
666
|
+
try {
|
|
667
|
+
await this._sessionManager.dispose();
|
|
668
|
+
} finally {
|
|
669
|
+
this._pendingCallKitAnswers.clear();
|
|
670
|
+
this._callStateController.dispose();
|
|
671
|
+
}
|
|
672
|
+
})();
|
|
673
|
+
|
|
674
|
+
return this._disposePromise;
|
|
546
675
|
}
|
|
547
676
|
|
|
548
677
|
// ========== Private Methods ==========
|
|
549
678
|
|
|
679
|
+
/**
|
|
680
|
+
* Forward answers captured during cold start as soon as SessionManager has
|
|
681
|
+
* created the TelnyxRTC instance. SessionManager invokes its ready callback
|
|
682
|
+
* before connect(), so the UUID-keyed action is present when the INVITE
|
|
683
|
+
* arrives.
|
|
684
|
+
*/
|
|
685
|
+
private _flushPendingCallKitAnswers(): void {
|
|
686
|
+
const telnyxClient = this._sessionManager.telnyxClient;
|
|
687
|
+
if (!telnyxClient || typeof (telnyxClient as any).queueAnswerFromCallKit !== 'function') {
|
|
688
|
+
return;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
for (const [actionKey, pendingAnswer] of this._pendingCallKitAnswers) {
|
|
692
|
+
try {
|
|
693
|
+
(telnyxClient as any).queueAnswerFromCallKit(
|
|
694
|
+
pendingAnswer.callKitUUIDOrHeaders,
|
|
695
|
+
pendingAnswer.customHeaders
|
|
696
|
+
);
|
|
697
|
+
this._pendingCallKitAnswers.delete(actionKey);
|
|
698
|
+
} catch (error) {
|
|
699
|
+
console.error('TelnyxVoipClient: Failed to restore pending CallKit answer', {
|
|
700
|
+
actionKey,
|
|
701
|
+
error,
|
|
702
|
+
});
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
/**
|
|
708
|
+
* Prefer an explicitly supplied token, otherwise hydrate it from PushKit's
|
|
709
|
+
* native storage. PushKit registration starts in AppDelegate before React
|
|
710
|
+
* mounts, so this removes the race between the JS token event and login.
|
|
711
|
+
*/
|
|
712
|
+
private async _withNativeVoipPushToken<T extends Config>(config: T): Promise<T> {
|
|
713
|
+
if (Platform.OS !== 'ios' || config.pushNotificationDeviceToken?.trim()) {
|
|
714
|
+
return config;
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
const nativePushToken = (await VoicePnBridge.getVoipToken())?.trim();
|
|
718
|
+
if (!nativePushToken) {
|
|
719
|
+
return config;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
if (this._options.debug) {
|
|
723
|
+
console.log('TelnyxVoipClient: Using PushKit token from native storage');
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
return {
|
|
727
|
+
...config,
|
|
728
|
+
pushNotificationDeviceToken: nativePushToken,
|
|
729
|
+
};
|
|
730
|
+
}
|
|
731
|
+
|
|
550
732
|
/**
|
|
551
733
|
* Store credential configuration for automatic reconnection
|
|
552
734
|
*/
|
|
@@ -560,6 +742,10 @@ export class TelnyxVoipClient {
|
|
|
560
742
|
USE_TRICKLE_ICE_STORAGE_KEY,
|
|
561
743
|
String(config.useTrickleIce ?? false)
|
|
562
744
|
);
|
|
745
|
+
await AsyncStorage.setItem(
|
|
746
|
+
PUSH_WHEN_ACTIVE_STORAGE_KEY,
|
|
747
|
+
String(config.pushWhenActive ?? false)
|
|
748
|
+
);
|
|
563
749
|
await AsyncStorage.setItem(
|
|
564
750
|
MISSED_CALL_NOTIFICATIONS_STORAGE_KEY,
|
|
565
751
|
String(config.enableMissedCallNotifications ?? false)
|
|
@@ -595,6 +781,10 @@ export class TelnyxVoipClient {
|
|
|
595
781
|
USE_TRICKLE_ICE_STORAGE_KEY,
|
|
596
782
|
String(config.useTrickleIce ?? false)
|
|
597
783
|
);
|
|
784
|
+
await AsyncStorage.setItem(
|
|
785
|
+
PUSH_WHEN_ACTIVE_STORAGE_KEY,
|
|
786
|
+
String(config.pushWhenActive ?? false)
|
|
787
|
+
);
|
|
598
788
|
await AsyncStorage.setItem(
|
|
599
789
|
MISSED_CALL_NOTIFICATIONS_STORAGE_KEY,
|
|
600
790
|
String(config.enableMissedCallNotifications ?? false)
|
|
@@ -654,10 +844,12 @@ export function createTelnyxVoipClient(options?: TelnyxVoipClientOptions): Telny
|
|
|
654
844
|
* Disposes the current singleton so that a subsequent call to
|
|
655
845
|
* `createTelnyxVoipClient()` will create a fresh instance.
|
|
656
846
|
*/
|
|
657
|
-
export function destroyTelnyxVoipClient(): void {
|
|
658
|
-
|
|
659
|
-
|
|
847
|
+
export async function destroyTelnyxVoipClient(): Promise<void> {
|
|
848
|
+
const sharedInstance = _sharedInstance;
|
|
849
|
+
|
|
850
|
+
if (sharedInstance) {
|
|
660
851
|
_sharedInstance = null;
|
|
852
|
+
await sharedInstance.dispose();
|
|
661
853
|
}
|
|
662
854
|
}
|
|
663
855
|
|
|
@@ -9,7 +9,7 @@ declare module '@telnyx/react-native-voice-sdk' {
|
|
|
9
9
|
export interface CallOptions {
|
|
10
10
|
callerIdName?: string;
|
|
11
11
|
callerIdNumber?: string;
|
|
12
|
-
customHeaders?:
|
|
12
|
+
customHeaders?: { name: string; value: string }[];
|
|
13
13
|
clientState?: string;
|
|
14
14
|
destinationNumber?: string;
|
|
15
15
|
audio?: boolean;
|
|
@@ -34,6 +34,7 @@ declare module '@telnyx/react-native-voice-sdk' {
|
|
|
34
34
|
debug?: boolean;
|
|
35
35
|
logLevel?: string;
|
|
36
36
|
pushNotificationDeviceToken?: string;
|
|
37
|
+
pushWhenActive?: boolean;
|
|
37
38
|
enableMissedCallNotifications?: boolean;
|
|
38
39
|
useTrickleIce?: boolean;
|
|
39
40
|
enableCallReports?: boolean;
|