@telnyx/react-voice-commons-sdk 1.1.1 → 1.2.0
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 +38 -1
- package/TelnyxVoiceCommons.podspec +3 -3
- package/ios/CallKitBridge.swift +126 -44
- package/lib/callkit/callkit-coordinator.d.ts +19 -0
- package/lib/callkit/callkit-coordinator.js +105 -5
- package/lib/index.d.ts +4 -1
- package/lib/index.js +9 -0
- package/lib/internal/calls/call-state-controller.d.ts +1 -0
- package/lib/internal/calls/call-state-controller.js +35 -1
- package/lib/internal/ice-servers-storage.d.ts +9 -0
- package/lib/internal/ice-servers-storage.js +37 -0
- package/lib/internal/sdk-identity.d.ts +4 -0
- package/lib/internal/sdk-identity.js +60 -0
- package/lib/internal/session/session-manager.d.ts +7 -2
- package/lib/internal/session/session-manager.js +35 -4
- package/lib/internal/signaling-environment.d.ts +13 -0
- package/lib/internal/signaling-environment.js +18 -0
- package/lib/models/call.d.ts +23 -2
- package/lib/models/call.js +37 -2
- package/lib/models/config.d.ts +28 -0
- package/lib/telnyx-voip-client.d.ts +4 -2
- package/lib/telnyx-voip-client.js +60 -2
- package/package.json +3 -4
- package/src/callkit/callkit-coordinator.ts +129 -7
- package/src/index.ts +6 -1
- package/src/internal/calls/call-state-controller.ts +41 -2
- package/src/internal/ice-servers-storage.ts +37 -0
- package/src/internal/sdk-identity.ts +6 -0
- package/src/internal/session/session-manager.ts +38 -4
- package/src/internal/signaling-environment.ts +20 -0
- package/src/models/call.ts +44 -2
- package/src/models/config.ts +30 -0
- package/src/telnyx-voip-client.ts +60 -3
- package/src/types/telnyx-sdk.d.ts +67 -2
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { TelnyxEnvironment } from '../models/config';
|
|
2
|
+
|
|
3
|
+
export const SIGNALING_ENVIRONMENT_STORAGE_KEY = '@telnyx_signaling_environment';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Resolves the signaling environment for a stored-config restore.
|
|
7
|
+
*
|
|
8
|
+
* An explicit stored selection always wins. A missing or invalid stored value
|
|
9
|
+
* (e.g. credentials persisted by an older Commons version) falls back to the
|
|
10
|
+
* client's configured default, and only then to production.
|
|
11
|
+
*/
|
|
12
|
+
export function resolveStoredEnvironment(
|
|
13
|
+
storedEnvironment: string | null | undefined,
|
|
14
|
+
defaultEnvironment?: TelnyxEnvironment
|
|
15
|
+
): TelnyxEnvironment {
|
|
16
|
+
if (storedEnvironment === 'development' || storedEnvironment === 'production') {
|
|
17
|
+
return storedEnvironment;
|
|
18
|
+
}
|
|
19
|
+
return defaultEnvironment ?? 'production';
|
|
20
|
+
}
|
package/src/models/call.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { BehaviorSubject, Observable } from 'rxjs';
|
|
|
2
2
|
import { distinctUntilChanged, map } from 'rxjs/operators';
|
|
3
3
|
import { TelnyxCallState, CallStateHelpers } from './call-state';
|
|
4
4
|
import { Call as TelnyxCall } from '@telnyx/react-native-voice-sdk';
|
|
5
|
+
import type { CallQualityMetrics } from '@telnyx/react-native-voice-sdk';
|
|
5
6
|
import { Platform } from 'react-native';
|
|
6
7
|
|
|
7
8
|
/**
|
|
@@ -16,6 +17,10 @@ export class Call {
|
|
|
16
17
|
private readonly _isMuted = new BehaviorSubject<boolean>(false);
|
|
17
18
|
private readonly _isHeld = new BehaviorSubject<boolean>(false);
|
|
18
19
|
private readonly _duration = new BehaviorSubject<number>(0);
|
|
20
|
+
private readonly _qualityMetrics = new BehaviorSubject<CallQualityMetrics | null>(null);
|
|
21
|
+
private readonly _onQualityMetrics = (metrics: CallQualityMetrics) => {
|
|
22
|
+
this._qualityMetrics.next(metrics);
|
|
23
|
+
};
|
|
19
24
|
|
|
20
25
|
private _durationTimer?: NodeJS.Timeout;
|
|
21
26
|
private _startTime?: Date;
|
|
@@ -113,7 +118,7 @@ export class Call {
|
|
|
113
118
|
/**
|
|
114
119
|
* Custom headers received from the WebRTC INVITE message.
|
|
115
120
|
* These headers are passed during call initiation and can contain application-specific information.
|
|
116
|
-
* Format
|
|
121
|
+
* Format: `[{"name": "X-Header-Name", "value": "Value"}]`; header names must start with `X-`.
|
|
117
122
|
*/
|
|
118
123
|
get inviteCustomHeaders(): { name: string; value: string }[] | null {
|
|
119
124
|
return this._telnyxCall.inviteCustomHeaders;
|
|
@@ -122,7 +127,7 @@ export class Call {
|
|
|
122
127
|
/**
|
|
123
128
|
* Custom headers received from the WebRTC ANSWER message.
|
|
124
129
|
* These headers are passed during call acceptance and can contain application-specific information.
|
|
125
|
-
* Format
|
|
130
|
+
* Format: `[{"name": "X-Header-Name", "value": "Value"}]`; header names must start with `X-`.
|
|
126
131
|
*/
|
|
127
132
|
get answerCustomHeaders(): { name: string; value: string }[] | null {
|
|
128
133
|
return this._telnyxCall.answerCustomHeaders;
|
|
@@ -136,6 +141,19 @@ export class Call {
|
|
|
136
141
|
return this._telnyxCall;
|
|
137
142
|
}
|
|
138
143
|
|
|
144
|
+
/**
|
|
145
|
+
* Inject an ICE failure into the underlying SDK recovery flow for manual
|
|
146
|
+
* testing. The underlying SDK accepts this only when debug mode is enabled.
|
|
147
|
+
*
|
|
148
|
+
* @returns true when a recovery episode was started.
|
|
149
|
+
*/
|
|
150
|
+
simulateIceFailureForTesting(): boolean {
|
|
151
|
+
const testableCall = this._telnyxCall as TelnyxCall & {
|
|
152
|
+
simulateIceFailureForTesting?: () => boolean;
|
|
153
|
+
};
|
|
154
|
+
return testableCall.simulateIceFailureForTesting?.() ?? false;
|
|
155
|
+
}
|
|
156
|
+
|
|
139
157
|
/**
|
|
140
158
|
* Observable stream of call state changes
|
|
141
159
|
*/
|
|
@@ -164,6 +182,23 @@ export class Call {
|
|
|
164
182
|
return this._duration.asObservable().pipe(distinctUntilChanged());
|
|
165
183
|
}
|
|
166
184
|
|
|
185
|
+
/**
|
|
186
|
+
* Observable stream of call quality metrics updates.
|
|
187
|
+
* Emits `null` initially, then a {@link CallQualityMetrics} object
|
|
188
|
+
* each time the underlying SDK collects a new sample.
|
|
189
|
+
*/
|
|
190
|
+
get qualityMetrics$(): Observable<CallQualityMetrics | null> {
|
|
191
|
+
return this._qualityMetrics.asObservable().pipe(distinctUntilChanged());
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Current call quality metrics (synchronous access).
|
|
196
|
+
* Returns `null` until the first metrics sample is collected.
|
|
197
|
+
*/
|
|
198
|
+
get currentQualityMetrics(): CallQualityMetrics | null {
|
|
199
|
+
return this._qualityMetrics.value;
|
|
200
|
+
}
|
|
201
|
+
|
|
167
202
|
/**
|
|
168
203
|
* Observable that emits true when the call can be answered
|
|
169
204
|
*/
|
|
@@ -413,10 +448,12 @@ export class Call {
|
|
|
413
448
|
*/
|
|
414
449
|
dispose(): void {
|
|
415
450
|
this._stopDurationTimer();
|
|
451
|
+
this._telnyxCall.off?.('telnyx.call.qualityMetrics', this._onQualityMetrics);
|
|
416
452
|
this._callState.complete();
|
|
417
453
|
this._isMuted.complete();
|
|
418
454
|
this._isHeld.complete();
|
|
419
455
|
this._duration.complete();
|
|
456
|
+
this._qualityMetrics.complete();
|
|
420
457
|
}
|
|
421
458
|
|
|
422
459
|
/**
|
|
@@ -518,6 +555,11 @@ export class Call {
|
|
|
518
555
|
}
|
|
519
556
|
}
|
|
520
557
|
});
|
|
558
|
+
|
|
559
|
+
// Forward quality metrics from the underlying SDK
|
|
560
|
+
// Subscribe to the event rather than the single onQualityMetrics slot, so
|
|
561
|
+
// an app can still set that callback on the underlying call.
|
|
562
|
+
this._telnyxCall.on('telnyx.call.qualityMetrics', this._onQualityMetrics);
|
|
521
563
|
}
|
|
522
564
|
|
|
523
565
|
/**
|
package/src/models/config.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import type { TelnyxIceServer } from '@telnyx/react-native-voice-sdk';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Configuration for credential-based authentication
|
|
3
5
|
*/
|
|
6
|
+
export type TelnyxEnvironment = 'production' | 'development';
|
|
7
|
+
|
|
4
8
|
export interface CredentialConfig {
|
|
5
9
|
type: 'credential';
|
|
6
10
|
sipUser: string;
|
|
@@ -15,14 +19,27 @@ export interface CredentialConfig {
|
|
|
15
19
|
incomingCallRingtone?: string;
|
|
16
20
|
/** Enable Trickle ICE. Default: false */
|
|
17
21
|
useTrickleIce?: boolean;
|
|
22
|
+
/** Signaling environment. Default: production */
|
|
23
|
+
environment?: TelnyxEnvironment;
|
|
18
24
|
/** Enable automatic call quality reporting. Default: true */
|
|
19
25
|
enableCallReports?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Deliver real-time call quality metrics on `Call.qualityMetrics$` while a
|
|
28
|
+
* call is active. Also enabled by `debug`. Default: false
|
|
29
|
+
*/
|
|
30
|
+
enableQualityMetrics?: boolean;
|
|
20
31
|
/** Stats collection interval in seconds. Default: 5 */
|
|
21
32
|
callReportInterval?: number;
|
|
22
33
|
/** Minimum log level for call reports: 'debug' | 'info' | 'warn' | 'error'. Default: 'debug' */
|
|
23
34
|
callReportLogLevel?: string;
|
|
24
35
|
/** Max log entries per call. Default: 1000 */
|
|
25
36
|
callReportMaxLogEntries?: number;
|
|
37
|
+
/**
|
|
38
|
+
* Custom ICE servers (STUN/TURN) for WebRTC peer connections.
|
|
39
|
+
* When provided, overrides the Telnyx production defaults.
|
|
40
|
+
* When omitted, the SDK uses Telnyx defaults (STUN → TURN UDP → TURN TCP → TURNS 443).
|
|
41
|
+
*/
|
|
42
|
+
iceServers?: TelnyxIceServer[];
|
|
26
43
|
}
|
|
27
44
|
|
|
28
45
|
/**
|
|
@@ -41,14 +58,27 @@ export interface TokenConfig {
|
|
|
41
58
|
incomingCallRingtone?: string;
|
|
42
59
|
/** Enable Trickle ICE. Default: false */
|
|
43
60
|
useTrickleIce?: boolean;
|
|
61
|
+
/** Signaling environment. Default: production */
|
|
62
|
+
environment?: TelnyxEnvironment;
|
|
44
63
|
/** Enable automatic call quality reporting. Default: true */
|
|
45
64
|
enableCallReports?: boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Deliver real-time call quality metrics on `Call.qualityMetrics$` while a
|
|
67
|
+
* call is active. Also enabled by `debug`. Default: false
|
|
68
|
+
*/
|
|
69
|
+
enableQualityMetrics?: boolean;
|
|
46
70
|
/** Stats collection interval in seconds. Default: 5 */
|
|
47
71
|
callReportInterval?: number;
|
|
48
72
|
/** Minimum log level for call reports: 'debug' | 'info' | 'warn' | 'error'. Default: 'debug' */
|
|
49
73
|
callReportLogLevel?: string;
|
|
50
74
|
/** Max log entries per call. Default: 1000 */
|
|
51
75
|
callReportMaxLogEntries?: number;
|
|
76
|
+
/**
|
|
77
|
+
* Custom ICE servers (STUN/TURN) for WebRTC peer connections.
|
|
78
|
+
* When provided, overrides the Telnyx production defaults.
|
|
79
|
+
* When omitted, the SDK uses Telnyx defaults (STUN → TURN UDP → TURN TCP → TURNS 443).
|
|
80
|
+
*/
|
|
81
|
+
iceServers?: TelnyxIceServer[];
|
|
52
82
|
}
|
|
53
83
|
|
|
54
84
|
/**
|
|
@@ -3,14 +3,26 @@ import { Platform } from 'react-native';
|
|
|
3
3
|
import { TelnyxConnectionState } from './models/connection-state';
|
|
4
4
|
import { Call } from './models/call';
|
|
5
5
|
import { TelnyxCallState } from './models/call-state';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
Config,
|
|
8
|
+
CredentialConfig,
|
|
9
|
+
TelnyxEnvironment,
|
|
10
|
+
TokenConfig,
|
|
11
|
+
validateConfig,
|
|
12
|
+
} from './models/config';
|
|
7
13
|
import { SessionManager } from './internal/session/session-manager';
|
|
14
|
+
import {
|
|
15
|
+
SIGNALING_ENVIRONMENT_STORAGE_KEY,
|
|
16
|
+
resolveStoredEnvironment,
|
|
17
|
+
} from './internal/signaling-environment';
|
|
8
18
|
import { CallStateController, type CustomHeaders } from './internal/calls/call-state-controller';
|
|
9
19
|
import { VoicePnBridge } from './internal/voice-pn-bridge';
|
|
20
|
+
import { ICE_SERVERS_STORAGE_KEY, parseStoredIceServers } from './internal/ice-servers-storage';
|
|
10
21
|
|
|
11
22
|
const USE_TRICKLE_ICE_STORAGE_KEY = '@use_trickle_ice';
|
|
12
23
|
const PUSH_WHEN_ACTIVE_STORAGE_KEY = '@push_when_active';
|
|
13
24
|
const MISSED_CALL_NOTIFICATIONS_STORAGE_KEY = '@enable_missed_call_notifications';
|
|
25
|
+
const QUALITY_METRICS_STORAGE_KEY = '@enable_quality_metrics';
|
|
14
26
|
const LEGACY_CALLKIT_ANSWER_KEY = '__legacy_callkit_answer__';
|
|
15
27
|
|
|
16
28
|
interface PendingCallKitAnswer {
|
|
@@ -30,6 +42,9 @@ export interface TelnyxVoipClientOptions {
|
|
|
30
42
|
|
|
31
43
|
/** Enable Trickle ICE for calls created by this client */
|
|
32
44
|
useTrickleIce?: boolean;
|
|
45
|
+
|
|
46
|
+
/** Signaling environment used for connections - default: production */
|
|
47
|
+
environment?: TelnyxEnvironment;
|
|
33
48
|
}
|
|
34
49
|
|
|
35
50
|
/**
|
|
@@ -84,11 +99,12 @@ export class TelnyxVoipClient {
|
|
|
84
99
|
enableAppStateManagement: true,
|
|
85
100
|
debug: false,
|
|
86
101
|
useTrickleIce: false,
|
|
102
|
+
environment: 'production',
|
|
87
103
|
...options,
|
|
88
104
|
};
|
|
89
105
|
|
|
90
106
|
// Initialize core components
|
|
91
|
-
this._sessionManager = new SessionManager();
|
|
107
|
+
this._sessionManager = new SessionManager({ defaultEnvironment: this._options.environment });
|
|
92
108
|
this._callStateController = new CallStateController(this._sessionManager);
|
|
93
109
|
|
|
94
110
|
// Set up callback to initialize call state controller listeners when client is ready
|
|
@@ -304,6 +320,7 @@ export class TelnyxVoipClient {
|
|
|
304
320
|
const loginConfig = await this._withNativeVoipPushToken({
|
|
305
321
|
...config,
|
|
306
322
|
useTrickleIce: config.useTrickleIce ?? this._options.useTrickleIce,
|
|
323
|
+
environment: config.environment ?? this._options.environment,
|
|
307
324
|
});
|
|
308
325
|
|
|
309
326
|
await VoicePnBridge.setIncomingCallRingtone(loginConfig.incomingCallRingtone);
|
|
@@ -338,6 +355,7 @@ export class TelnyxVoipClient {
|
|
|
338
355
|
const loginConfig = await this._withNativeVoipPushToken({
|
|
339
356
|
...config,
|
|
340
357
|
useTrickleIce: config.useTrickleIce ?? this._options.useTrickleIce,
|
|
358
|
+
environment: config.environment ?? this._options.environment,
|
|
341
359
|
});
|
|
342
360
|
|
|
343
361
|
await VoicePnBridge.setIncomingCallRingtone(loginConfig.incomingCallRingtone);
|
|
@@ -372,7 +390,7 @@ export class TelnyxVoipClient {
|
|
|
372
390
|
* This method is used for auto-reconnection scenarios where the app
|
|
373
391
|
* comes back to the foreground and needs to restore the connection.
|
|
374
392
|
*
|
|
375
|
-
* @returns
|
|
393
|
+
* @returns Whether reconnection was successful.
|
|
376
394
|
*/
|
|
377
395
|
async loginFromStoredConfig(): Promise<boolean> {
|
|
378
396
|
this._throwIfDisposed();
|
|
@@ -394,10 +412,15 @@ export class TelnyxVoipClient {
|
|
|
394
412
|
const storedMissedCallNotifications = await AsyncStorage.getItem(
|
|
395
413
|
MISSED_CALL_NOTIFICATIONS_STORAGE_KEY
|
|
396
414
|
);
|
|
415
|
+
const storedEnvironment = await AsyncStorage.getItem(SIGNALING_ENVIRONMENT_STORAGE_KEY);
|
|
416
|
+
const storedQualityMetrics = await AsyncStorage.getItem(QUALITY_METRICS_STORAGE_KEY);
|
|
417
|
+
const iceServers = parseStoredIceServers(await AsyncStorage.getItem(ICE_SERVERS_STORAGE_KEY));
|
|
397
418
|
const useTrickleIce =
|
|
398
419
|
storedUseTrickleIce === null ? this._options.useTrickleIce : storedUseTrickleIce === 'true';
|
|
399
420
|
const pushWhenActive = storedPushWhenActive === 'true';
|
|
400
421
|
const enableMissedCallNotifications = storedMissedCallNotifications === 'true';
|
|
422
|
+
const enableQualityMetrics = storedQualityMetrics === 'true';
|
|
423
|
+
const environment = resolveStoredEnvironment(storedEnvironment, this._options.environment);
|
|
401
424
|
const nativePushToken =
|
|
402
425
|
Platform.OS === 'ios' ? (await VoicePnBridge.getVoipToken())?.trim() : null;
|
|
403
426
|
const pushNotificationDeviceToken = nativePushToken || storedPushToken;
|
|
@@ -415,6 +438,9 @@ export class TelnyxVoipClient {
|
|
|
415
438
|
useTrickleIce,
|
|
416
439
|
pushWhenActive,
|
|
417
440
|
enableMissedCallNotifications,
|
|
441
|
+
enableQualityMetrics,
|
|
442
|
+
environment,
|
|
443
|
+
iceServers,
|
|
418
444
|
});
|
|
419
445
|
|
|
420
446
|
if (this._options.debug) {
|
|
@@ -437,6 +463,9 @@ export class TelnyxVoipClient {
|
|
|
437
463
|
useTrickleIce,
|
|
438
464
|
pushWhenActive,
|
|
439
465
|
enableMissedCallNotifications,
|
|
466
|
+
enableQualityMetrics,
|
|
467
|
+
environment,
|
|
468
|
+
iceServers,
|
|
440
469
|
});
|
|
441
470
|
|
|
442
471
|
if (this._options.debug) {
|
|
@@ -750,6 +779,20 @@ export class TelnyxVoipClient {
|
|
|
750
779
|
MISSED_CALL_NOTIFICATIONS_STORAGE_KEY,
|
|
751
780
|
String(config.enableMissedCallNotifications ?? false)
|
|
752
781
|
);
|
|
782
|
+
await AsyncStorage.setItem(
|
|
783
|
+
QUALITY_METRICS_STORAGE_KEY,
|
|
784
|
+
String(config.enableQualityMetrics ?? false)
|
|
785
|
+
);
|
|
786
|
+
await AsyncStorage.setItem(
|
|
787
|
+
SIGNALING_ENVIRONMENT_STORAGE_KEY,
|
|
788
|
+
config.environment ?? this._options.environment ?? 'production'
|
|
789
|
+
);
|
|
790
|
+
|
|
791
|
+
if (config.iceServers) {
|
|
792
|
+
await AsyncStorage.setItem(ICE_SERVERS_STORAGE_KEY, JSON.stringify(config.iceServers));
|
|
793
|
+
} else {
|
|
794
|
+
await AsyncStorage.removeItem(ICE_SERVERS_STORAGE_KEY);
|
|
795
|
+
}
|
|
753
796
|
|
|
754
797
|
if (config.pushNotificationDeviceToken) {
|
|
755
798
|
await AsyncStorage.setItem('@push_token', config.pushNotificationDeviceToken);
|
|
@@ -789,6 +832,20 @@ export class TelnyxVoipClient {
|
|
|
789
832
|
MISSED_CALL_NOTIFICATIONS_STORAGE_KEY,
|
|
790
833
|
String(config.enableMissedCallNotifications ?? false)
|
|
791
834
|
);
|
|
835
|
+
await AsyncStorage.setItem(
|
|
836
|
+
QUALITY_METRICS_STORAGE_KEY,
|
|
837
|
+
String(config.enableQualityMetrics ?? false)
|
|
838
|
+
);
|
|
839
|
+
await AsyncStorage.setItem(
|
|
840
|
+
SIGNALING_ENVIRONMENT_STORAGE_KEY,
|
|
841
|
+
config.environment ?? this._options.environment ?? 'production'
|
|
842
|
+
);
|
|
843
|
+
|
|
844
|
+
if (config.iceServers) {
|
|
845
|
+
await AsyncStorage.setItem(ICE_SERVERS_STORAGE_KEY, JSON.stringify(config.iceServers));
|
|
846
|
+
} else {
|
|
847
|
+
await AsyncStorage.removeItem(ICE_SERVERS_STORAGE_KEY);
|
|
848
|
+
}
|
|
792
849
|
|
|
793
850
|
if (config.pushNotificationDeviceToken) {
|
|
794
851
|
await AsyncStorage.setItem('@push_token', config.pushNotificationDeviceToken);
|
|
@@ -24,7 +24,15 @@ declare module '@telnyx/react-native-voice-sdk' {
|
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
/** A STUN/TURN server for WebRTC peer connections (core `TelnyxIceServer`). */
|
|
28
|
+
export interface TelnyxIceServer {
|
|
29
|
+
urls: string;
|
|
30
|
+
username?: string;
|
|
31
|
+
credential?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
27
34
|
export interface ClientOptions {
|
|
35
|
+
environment?: 'production' | 'development';
|
|
28
36
|
login?: string;
|
|
29
37
|
password?: string;
|
|
30
38
|
token?: string;
|
|
@@ -38,9 +46,13 @@ declare module '@telnyx/react-native-voice-sdk' {
|
|
|
38
46
|
enableMissedCallNotifications?: boolean;
|
|
39
47
|
useTrickleIce?: boolean;
|
|
40
48
|
enableCallReports?: boolean;
|
|
49
|
+
enableQualityMetrics?: boolean;
|
|
41
50
|
callReportInterval?: number;
|
|
42
51
|
callReportLogLevel?: string;
|
|
43
52
|
callReportMaxLogEntries?: number;
|
|
53
|
+
/** Custom ICE servers (STUN/TURN) for WebRTC peer connections */
|
|
54
|
+
iceServers?: TelnyxIceServer[];
|
|
55
|
+
sdkName?: string;
|
|
44
56
|
sdkVersion?: string;
|
|
45
57
|
}
|
|
46
58
|
|
|
@@ -55,6 +67,52 @@ declare module '@telnyx/react-native-voice-sdk' {
|
|
|
55
67
|
PURGE = 'purge',
|
|
56
68
|
}
|
|
57
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Quality rating derived from the MOS score (same bands as iOS and Android).
|
|
72
|
+
*/
|
|
73
|
+
export enum CallQualityLevel {
|
|
74
|
+
EXCELLENT = 'excellent',
|
|
75
|
+
GOOD = 'good',
|
|
76
|
+
FAIR = 'fair',
|
|
77
|
+
POOR = 'poor',
|
|
78
|
+
BAD = 'bad',
|
|
79
|
+
UNKNOWN = 'unknown',
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** A raw WebRTC stats report, copied as a plain object. */
|
|
83
|
+
export type QualityStatsRecord = Record<string, unknown>;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Snapshot of call quality metrics at a single sampling point. Field names
|
|
87
|
+
* and units match iOS `CallQualityMetrics`.
|
|
88
|
+
*/
|
|
89
|
+
export interface CallQualityMetrics {
|
|
90
|
+
/** The call identifier this metrics snapshot belongs to. */
|
|
91
|
+
callId: string;
|
|
92
|
+
/** ISO-8601 timestamp of when the metrics were collected. */
|
|
93
|
+
timestamp: string;
|
|
94
|
+
/** Jitter in seconds, or null when unavailable. */
|
|
95
|
+
jitter: number | null;
|
|
96
|
+
/** Round-trip time in seconds, or null when unavailable. */
|
|
97
|
+
rtt: number | null;
|
|
98
|
+
/** Mean Opinion Score (1.0–5.0), or null when it cannot be calculated. */
|
|
99
|
+
mos: number | null;
|
|
100
|
+
/** Quality rating derived from `mos`; UNKNOWN when `mos` is null. */
|
|
101
|
+
quality: CallQualityLevel;
|
|
102
|
+
/** Instantaneous inbound (remote) audio level, 0.0–1.0. */
|
|
103
|
+
inboundAudioLevel: number;
|
|
104
|
+
/** Instantaneous outbound (local) audio level, 0.0–1.0. */
|
|
105
|
+
outboundAudioLevel: number;
|
|
106
|
+
/** Raw `inbound-rtp` audio stats, or null when unavailable. */
|
|
107
|
+
inboundAudio: QualityStatsRecord | null;
|
|
108
|
+
/** Raw `outbound-rtp` audio stats, or null when unavailable. */
|
|
109
|
+
outboundAudio: QualityStatsRecord | null;
|
|
110
|
+
/** Raw `remote-inbound-rtp` audio stats, or null when unavailable. */
|
|
111
|
+
remoteInboundAudio: QualityStatsRecord | null;
|
|
112
|
+
/** Raw `remote-outbound-rtp` audio stats, or null when unavailable. */
|
|
113
|
+
remoteOutboundAudio: QualityStatsRecord | null;
|
|
114
|
+
}
|
|
115
|
+
|
|
58
116
|
export class Call extends EventEmitter {
|
|
59
117
|
callId: string;
|
|
60
118
|
state: CallState;
|
|
@@ -67,17 +125,24 @@ declare module '@telnyx/react-native-voice-sdk' {
|
|
|
67
125
|
/**
|
|
68
126
|
* Custom headers received from the WebRTC INVITE message.
|
|
69
127
|
* These headers are passed during call initiation and can contain application-specific information.
|
|
70
|
-
* Format
|
|
128
|
+
* Format: `[{"name": "X-Header-Name", "value": "Value"}]`; header names must start with `X-`.
|
|
71
129
|
*/
|
|
72
130
|
inviteCustomHeaders: { name: string; value: string }[] | null;
|
|
73
131
|
|
|
74
132
|
/**
|
|
75
133
|
* Custom headers received from the WebRTC ANSWER message.
|
|
76
134
|
* These headers are passed during call acceptance and can contain application-specific information.
|
|
77
|
-
* Format
|
|
135
|
+
* Format: `[{"name": "X-Header-Name", "value": "Value"}]`; header names must start with `X-`.
|
|
78
136
|
*/
|
|
79
137
|
answerCustomHeaders: { name: string; value: string }[] | null;
|
|
80
138
|
|
|
139
|
+
/**
|
|
140
|
+
* Callback invoked with each call quality metrics snapshot (every 200 ms by
|
|
141
|
+
* default) while collection is active. Snapshots are also emitted as the
|
|
142
|
+
* `telnyx.call.qualityMetrics` event.
|
|
143
|
+
*/
|
|
144
|
+
onQualityMetrics: ((metrics: CallQualityMetrics) => void) | null;
|
|
145
|
+
|
|
81
146
|
constructor(options: any);
|
|
82
147
|
|
|
83
148
|
answer(customHeaders?: { name: string; value: string }[]): Promise<void>;
|