@telnyx/react-voice-commons-sdk 0.4.3 → 1.0.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/android/src/main/java/com/telnyx/react_voice_commons/TelnyxFirebaseMessagingService.kt +16 -2
- package/android/src/main/java/com/telnyx/react_voice_commons/VoicePnBridgeModule.kt +55 -1
- package/android/src/main/java/com/telnyx/react_voice_commons/VoicePnManager.kt +17 -1
- package/ios/CallKitBridge.swift +426 -0
- package/ios/VoicePnBridge.m +15 -1
- package/ios/VoicePnBridge.swift +47 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +9 -0
- package/lib/internal/calls/call-state-controller.d.ts +6 -0
- package/lib/internal/calls/call-state-controller.js +52 -36
- package/lib/internal/session/session-manager.d.ts +1 -0
- package/lib/internal/session/session-manager.js +19 -0
- package/lib/internal/voice-pn-bridge.d.ts +26 -0
- package/lib/internal/voice-pn-bridge.js +55 -0
- package/lib/models/config.d.ts +8 -0
- package/lib/telnyx-voip-client.d.ts +2 -0
- package/lib/telnyx-voip-client.js +42 -4
- package/package.json +2 -2
- package/src/index.ts +3 -0
- package/src/internal/calls/call-state-controller.ts +61 -45
- package/src/internal/session/session-manager.ts +21 -0
- package/src/internal/voice-pn-bridge.ts +64 -0
- package/src/models/config.ts +8 -0
- package/src/telnyx-voip-client.ts +48 -4
- package/src/types/telnyx-sdk.d.ts +10 -0
package/lib/index.js
CHANGED
|
@@ -38,6 +38,7 @@ var __exportStar =
|
|
|
38
38
|
};
|
|
39
39
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
40
40
|
exports.useAppReadyNotifier =
|
|
41
|
+
exports.VoicePnBridge =
|
|
41
42
|
exports.createTokenConfig =
|
|
42
43
|
exports.createCredentialConfig =
|
|
43
44
|
exports.validateTokenConfig =
|
|
@@ -215,6 +216,14 @@ Object.defineProperty(exports, 'createTokenConfig', {
|
|
|
215
216
|
});
|
|
216
217
|
// Export CallKit functionality
|
|
217
218
|
__exportStar(require('./callkit'), exports);
|
|
219
|
+
// Native push notification helpers
|
|
220
|
+
var voice_pn_bridge_1 = require('./internal/voice-pn-bridge');
|
|
221
|
+
Object.defineProperty(exports, 'VoicePnBridge', {
|
|
222
|
+
enumerable: true,
|
|
223
|
+
get: function () {
|
|
224
|
+
return voice_pn_bridge_1.VoicePnBridge;
|
|
225
|
+
},
|
|
226
|
+
});
|
|
218
227
|
// Export hooks
|
|
219
228
|
var useAppReadyNotifier_1 = require('./hooks/useAppReadyNotifier');
|
|
220
229
|
Object.defineProperty(exports, 'useAppReadyNotifier', {
|
|
@@ -12,6 +12,7 @@ export declare class CallStateController {
|
|
|
12
12
|
private readonly _calls;
|
|
13
13
|
private readonly _callMap;
|
|
14
14
|
private _disposed;
|
|
15
|
+
private _listenerClient?;
|
|
15
16
|
private _isWaitingForInvite?;
|
|
16
17
|
private _onInviteAutoAccepted?;
|
|
17
18
|
constructor(_sessionManager: SessionManager);
|
|
@@ -86,6 +87,11 @@ export declare class CallStateController {
|
|
|
86
87
|
* Set up event listeners for the Telnyx client
|
|
87
88
|
*/
|
|
88
89
|
private _setupClientListeners;
|
|
90
|
+
private _removeClientListeners;
|
|
91
|
+
private _handleTelnyxIncomingCall;
|
|
92
|
+
private _handleTelnyxReattachedCall;
|
|
93
|
+
private _handleTelnyxCallStateChanged;
|
|
94
|
+
private _handleTelnyxCallRemoved;
|
|
89
95
|
/**
|
|
90
96
|
* Handle incoming call or reattached call
|
|
91
97
|
*/
|
|
@@ -19,6 +19,33 @@ class CallStateController {
|
|
|
19
19
|
this._calls = new rxjs_1.BehaviorSubject([]);
|
|
20
20
|
this._callMap = new Map();
|
|
21
21
|
this._disposed = false;
|
|
22
|
+
this._handleTelnyxIncomingCall = (telnyxCall, msg) => {
|
|
23
|
+
console.log('CallStateController: Incoming call received:', telnyxCall.callId);
|
|
24
|
+
this._handleIncomingCall(telnyxCall, msg, false);
|
|
25
|
+
};
|
|
26
|
+
this._handleTelnyxReattachedCall = (telnyxCall, msg) => {
|
|
27
|
+
console.log('CallStateController: Reattached call received:', telnyxCall.callId);
|
|
28
|
+
this._handleIncomingCall(telnyxCall, msg, true);
|
|
29
|
+
};
|
|
30
|
+
this._handleTelnyxCallStateChanged = (telnyxCall, state) => {
|
|
31
|
+
console.log(
|
|
32
|
+
'CallStateController: Call state changed from TelnyxRTC:',
|
|
33
|
+
telnyxCall.callId,
|
|
34
|
+
state
|
|
35
|
+
);
|
|
36
|
+
// Find our wrapper call and update if needed
|
|
37
|
+
const call = this.findCallByTelnyxCall(telnyxCall);
|
|
38
|
+
if (call) {
|
|
39
|
+
console.log(
|
|
40
|
+
'CallStateController: Found wrapper call, state sync handled by Call subscription'
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
this._handleTelnyxCallRemoved = (callId) => {
|
|
45
|
+
console.log('CallStateController: Call removed from TelnyxRTC:', callId);
|
|
46
|
+
// The call cleanup is already handled by our call state subscription.
|
|
47
|
+
// This event is informational for logging/debugging.
|
|
48
|
+
};
|
|
22
49
|
console.log('CallStateController: Constructor called - instance created');
|
|
23
50
|
// Don't set up client listeners here - client doesn't exist yet
|
|
24
51
|
// Will be called when client is available
|
|
@@ -134,6 +161,9 @@ class CallStateController {
|
|
|
134
161
|
callerIdName: callerName,
|
|
135
162
|
callerIdNumber: callerNumber,
|
|
136
163
|
customHeaders,
|
|
164
|
+
peerConnectionOptions: {
|
|
165
|
+
useTrickleIce: this._sessionManager.useTrickleIce,
|
|
166
|
+
},
|
|
137
167
|
};
|
|
138
168
|
const telnyxCall = await this._sessionManager.telnyxClient.newCall(callOptions);
|
|
139
169
|
// Create our wrapper Call object
|
|
@@ -192,6 +222,7 @@ class CallStateController {
|
|
|
192
222
|
return;
|
|
193
223
|
}
|
|
194
224
|
this._disposed = true;
|
|
225
|
+
this._removeClientListeners();
|
|
195
226
|
// Dispose of all calls
|
|
196
227
|
this.currentCalls.forEach((call) => call.dispose());
|
|
197
228
|
this._callMap.clear();
|
|
@@ -203,30 +234,22 @@ class CallStateController {
|
|
|
203
234
|
*/
|
|
204
235
|
_setupClientListeners() {
|
|
205
236
|
console.log('CallStateController: Setting up client listeners...');
|
|
206
|
-
|
|
237
|
+
const telnyxClient = this._sessionManager.telnyxClient;
|
|
238
|
+
if (!telnyxClient) {
|
|
207
239
|
console.log('CallStateController: No telnyxClient available yet, skipping listener setup');
|
|
208
240
|
return;
|
|
209
241
|
}
|
|
242
|
+
this._removeClientListeners();
|
|
243
|
+
this._listenerClient = telnyxClient;
|
|
210
244
|
console.log('CallStateController: TelnyxClient found, setting up incoming call listener');
|
|
211
|
-
console.log(
|
|
212
|
-
'CallStateController: Client instance:',
|
|
213
|
-
this._sessionManager.telnyxClient.constructor.name
|
|
214
|
-
);
|
|
245
|
+
console.log('CallStateController: Client instance:', telnyxClient.constructor.name);
|
|
215
246
|
// Listen for incoming calls
|
|
216
|
-
|
|
217
|
-
console.log('CallStateController: Incoming call received:', telnyxCall.callId);
|
|
218
|
-
this._handleIncomingCall(telnyxCall, msg, false);
|
|
219
|
-
});
|
|
247
|
+
telnyxClient.on('telnyx.call.incoming', this._handleTelnyxIncomingCall);
|
|
220
248
|
// Listen for reattached calls (after network reconnection)
|
|
221
|
-
|
|
222
|
-
console.log('CallStateController: Reattached call received:', telnyxCall.callId);
|
|
223
|
-
this._handleIncomingCall(telnyxCall, msg, true);
|
|
224
|
-
});
|
|
249
|
+
telnyxClient.on('telnyx.call.reattached', this._handleTelnyxReattachedCall);
|
|
225
250
|
// Verify listeners are set up
|
|
226
|
-
const incomingListeners =
|
|
227
|
-
|
|
228
|
-
const reattachedListeners =
|
|
229
|
-
this._sessionManager.telnyxClient.listenerCount('telnyx.call.reattached');
|
|
251
|
+
const incomingListeners = telnyxClient.listenerCount('telnyx.call.incoming');
|
|
252
|
+
const reattachedListeners = telnyxClient.listenerCount('telnyx.call.reattached');
|
|
230
253
|
console.log(
|
|
231
254
|
'CallStateController: Listeners registered - incoming:',
|
|
232
255
|
incomingListeners,
|
|
@@ -234,28 +257,21 @@ class CallStateController {
|
|
|
234
257
|
reattachedListeners
|
|
235
258
|
);
|
|
236
259
|
// Listen for call state changes from the TelnyxRTC client (multi-call support)
|
|
237
|
-
|
|
238
|
-
console.log(
|
|
239
|
-
'CallStateController: Call state changed from TelnyxRTC:',
|
|
240
|
-
telnyxCall.callId,
|
|
241
|
-
state
|
|
242
|
-
);
|
|
243
|
-
// Find our wrapper call and update if needed
|
|
244
|
-
const call = this.findCallByTelnyxCall(telnyxCall);
|
|
245
|
-
if (call) {
|
|
246
|
-
console.log(
|
|
247
|
-
'CallStateController: Found wrapper call, state sync handled by Call subscription'
|
|
248
|
-
);
|
|
249
|
-
}
|
|
250
|
-
});
|
|
260
|
+
telnyxClient.on('telnyx.call.stateChanged', this._handleTelnyxCallStateChanged);
|
|
251
261
|
// Listen for call removal events from TelnyxRTC (multi-call support)
|
|
252
|
-
|
|
253
|
-
console.log('CallStateController: Call removed from TelnyxRTC:', callId);
|
|
254
|
-
// The call cleanup is already handled by our call state subscription
|
|
255
|
-
// This event is informational for logging/debugging
|
|
256
|
-
});
|
|
262
|
+
telnyxClient.on('telnyx.call.removed', this._handleTelnyxCallRemoved);
|
|
257
263
|
console.log('CallStateController: Client listeners set up successfully');
|
|
258
264
|
}
|
|
265
|
+
_removeClientListeners() {
|
|
266
|
+
if (!this._listenerClient) {
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
this._listenerClient.off('telnyx.call.incoming', this._handleTelnyxIncomingCall);
|
|
270
|
+
this._listenerClient.off('telnyx.call.reattached', this._handleTelnyxReattachedCall);
|
|
271
|
+
this._listenerClient.off('telnyx.call.stateChanged', this._handleTelnyxCallStateChanged);
|
|
272
|
+
this._listenerClient.off('telnyx.call.removed', this._handleTelnyxCallRemoved);
|
|
273
|
+
this._listenerClient = undefined;
|
|
274
|
+
}
|
|
259
275
|
/**
|
|
260
276
|
* Handle incoming call or reattached call
|
|
261
277
|
*/
|
|
@@ -59,6 +59,8 @@ const TelnyxSDK = __importStar(require('@telnyx/react-native-voice-sdk'));
|
|
|
59
59
|
const pkg = __importStar(require('../../../package.json'));
|
|
60
60
|
const connection_state_1 = require('../../models/connection-state');
|
|
61
61
|
const config_1 = require('../../models/config');
|
|
62
|
+
const USE_TRICKLE_ICE_STORAGE_KEY = '@use_trickle_ice';
|
|
63
|
+
const MISSED_CALL_NOTIFICATIONS_STORAGE_KEY = '@enable_missed_call_notifications';
|
|
62
64
|
/**
|
|
63
65
|
* Manages the connection lifecycle to the Telnyx platform.
|
|
64
66
|
*
|
|
@@ -110,6 +112,9 @@ class SessionManager {
|
|
|
110
112
|
get telnyxClient() {
|
|
111
113
|
return this._telnyxClient;
|
|
112
114
|
}
|
|
115
|
+
get useTrickleIce() {
|
|
116
|
+
return Boolean(this._currentConfig?.useTrickleIce);
|
|
117
|
+
}
|
|
113
118
|
/**
|
|
114
119
|
* Connect using credential authentication
|
|
115
120
|
*/
|
|
@@ -231,12 +236,20 @@ class SessionManager {
|
|
|
231
236
|
const storedPassword = await AsyncStorage.getItem('@telnyx_password');
|
|
232
237
|
const storedCredentialToken = await AsyncStorage.getItem('@credential_token');
|
|
233
238
|
const storedPushToken = await AsyncStorage.getItem('@push_token');
|
|
239
|
+
const storedUseTrickleIce = await AsyncStorage.getItem(USE_TRICKLE_ICE_STORAGE_KEY);
|
|
240
|
+
const storedMissedCallNotifications = await AsyncStorage.getItem(
|
|
241
|
+
MISSED_CALL_NOTIFICATIONS_STORAGE_KEY
|
|
242
|
+
);
|
|
243
|
+
const useTrickleIce = storedUseTrickleIce === 'true';
|
|
244
|
+
const enableMissedCallNotifications = storedMissedCallNotifications === 'true';
|
|
234
245
|
// Check if we have credential-based authentication data
|
|
235
246
|
if (storedUsername && storedPassword) {
|
|
236
247
|
console.log('SessionManager: RELEASE DEBUG - Found stored credentials, creating config');
|
|
237
248
|
const { createCredentialConfig } = require('../../models/config');
|
|
238
249
|
this._currentConfig = createCredentialConfig(storedUsername, storedPassword, {
|
|
239
250
|
pushNotificationDeviceToken: storedPushToken,
|
|
251
|
+
useTrickleIce,
|
|
252
|
+
enableMissedCallNotifications,
|
|
240
253
|
});
|
|
241
254
|
}
|
|
242
255
|
// Check if we have token-based authentication data
|
|
@@ -245,6 +258,8 @@ class SessionManager {
|
|
|
245
258
|
const { createTokenConfig } = require('../../models/config');
|
|
246
259
|
this._currentConfig = createTokenConfig(storedCredentialToken, {
|
|
247
260
|
pushNotificationDeviceToken: storedPushToken,
|
|
261
|
+
useTrickleIce,
|
|
262
|
+
enableMissedCallNotifications,
|
|
248
263
|
});
|
|
249
264
|
}
|
|
250
265
|
if (this._currentConfig) {
|
|
@@ -358,6 +373,8 @@ class SessionManager {
|
|
|
358
373
|
logLevel: this._currentConfig.debug ? 'debug' : 'warn',
|
|
359
374
|
debug: this._currentConfig.debug ?? false,
|
|
360
375
|
pushNotificationDeviceToken: this._currentConfig.pushNotificationDeviceToken,
|
|
376
|
+
enableMissedCallNotifications: this._currentConfig.enableMissedCallNotifications ?? false,
|
|
377
|
+
useTrickleIce: this._currentConfig.useTrickleIce,
|
|
361
378
|
enableCallReports: this._currentConfig.enableCallReports,
|
|
362
379
|
callReportInterval: this._currentConfig.callReportInterval,
|
|
363
380
|
callReportLogLevel: this._currentConfig.callReportLogLevel,
|
|
@@ -376,6 +393,8 @@ class SessionManager {
|
|
|
376
393
|
logLevel: this._currentConfig.debug ? 'debug' : 'warn',
|
|
377
394
|
debug: this._currentConfig.debug ?? false,
|
|
378
395
|
pushNotificationDeviceToken: this._currentConfig.pushNotificationDeviceToken,
|
|
396
|
+
enableMissedCallNotifications: this._currentConfig.enableMissedCallNotifications ?? false,
|
|
397
|
+
useTrickleIce: this._currentConfig.useTrickleIce,
|
|
379
398
|
enableCallReports: this._currentConfig.enableCallReports,
|
|
380
399
|
callReportInterval: this._currentConfig.callReportInterval,
|
|
381
400
|
callReportLogLevel: this._currentConfig.callReportLogLevel,
|
|
@@ -30,6 +30,10 @@ export interface VoicePnBridgeInterface {
|
|
|
30
30
|
clearPendingVoipPush(): Promise<boolean>;
|
|
31
31
|
getPendingVoipAction(): Promise<string | null>;
|
|
32
32
|
clearPendingVoipAction(): Promise<boolean>;
|
|
33
|
+
setMissedCallNotificationsEnabled(enabled: boolean): Promise<boolean>;
|
|
34
|
+
getMissedCallNotificationsEnabled(): Promise<boolean>;
|
|
35
|
+
setSpeakerEnabled(enabled: boolean): Promise<boolean>;
|
|
36
|
+
isSpeakerEnabled(): Promise<boolean>;
|
|
33
37
|
}
|
|
34
38
|
declare const NativeBridge: VoicePnBridgeInterface;
|
|
35
39
|
/**
|
|
@@ -107,6 +111,28 @@ export declare class VoicePnBridge {
|
|
|
107
111
|
* Clear pending VoIP action from native storage (iOS only)
|
|
108
112
|
*/
|
|
109
113
|
static clearPendingVoipAction(): Promise<boolean>;
|
|
114
|
+
/**
|
|
115
|
+
* Enable or disable local missed call notifications on iOS.
|
|
116
|
+
* Missed-call VoIP pushes are still handled through CallKit either way.
|
|
117
|
+
*/
|
|
118
|
+
static setMissedCallNotificationsEnabled(enabled: boolean): Promise<boolean>;
|
|
119
|
+
/**
|
|
120
|
+
* Returns true by default, matching the sample-app behavior for missed calls.
|
|
121
|
+
*/
|
|
122
|
+
static getMissedCallNotificationsEnabled(): Promise<boolean>;
|
|
123
|
+
/**
|
|
124
|
+
* Route call audio through the loudspeaker when enabled, or back to the
|
|
125
|
+
* platform default voice route when disabled.
|
|
126
|
+
*/
|
|
127
|
+
static setSpeakerEnabled(enabled: boolean): Promise<boolean>;
|
|
128
|
+
/**
|
|
129
|
+
* Returns whether the current audio route is using the loudspeaker.
|
|
130
|
+
*/
|
|
131
|
+
static isSpeakerEnabled(): Promise<boolean>;
|
|
132
|
+
/**
|
|
133
|
+
* Toggle between loudspeaker and the platform default voice route.
|
|
134
|
+
*/
|
|
135
|
+
static toggleSpeaker(): Promise<boolean>;
|
|
110
136
|
/**
|
|
111
137
|
* Android → React Native: Listen for immediate call action events from notification buttons
|
|
112
138
|
* Use this for active calls where immediate response is needed (e.g., ending ongoing calls)
|
|
@@ -184,6 +184,61 @@ class VoicePnBridge {
|
|
|
184
184
|
return false;
|
|
185
185
|
}
|
|
186
186
|
}
|
|
187
|
+
/**
|
|
188
|
+
* Enable or disable local missed call notifications on iOS.
|
|
189
|
+
* Missed-call VoIP pushes are still handled through CallKit either way.
|
|
190
|
+
*/
|
|
191
|
+
static async setMissedCallNotificationsEnabled(enabled) {
|
|
192
|
+
try {
|
|
193
|
+
return await NativeBridge.setMissedCallNotificationsEnabled(enabled);
|
|
194
|
+
} catch (error) {
|
|
195
|
+
console.error('VoicePnBridge: Error setting missed call notifications:', error);
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Returns true by default, matching the sample-app behavior for missed calls.
|
|
201
|
+
*/
|
|
202
|
+
static async getMissedCallNotificationsEnabled() {
|
|
203
|
+
try {
|
|
204
|
+
return await NativeBridge.getMissedCallNotificationsEnabled();
|
|
205
|
+
} catch (error) {
|
|
206
|
+
console.error('VoicePnBridge: Error getting missed call notifications setting:', error);
|
|
207
|
+
return true;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Route call audio through the loudspeaker when enabled, or back to the
|
|
212
|
+
* platform default voice route when disabled.
|
|
213
|
+
*/
|
|
214
|
+
static async setSpeakerEnabled(enabled) {
|
|
215
|
+
try {
|
|
216
|
+
return await NativeBridge.setSpeakerEnabled(enabled);
|
|
217
|
+
} catch (error) {
|
|
218
|
+
console.error('VoicePnBridge: Error setting speaker route:', error);
|
|
219
|
+
throw error;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Returns whether the current audio route is using the loudspeaker.
|
|
224
|
+
*/
|
|
225
|
+
static async isSpeakerEnabled() {
|
|
226
|
+
try {
|
|
227
|
+
return await NativeBridge.isSpeakerEnabled();
|
|
228
|
+
} catch (error) {
|
|
229
|
+
console.error('VoicePnBridge: Error getting speaker route:', error);
|
|
230
|
+
throw error;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Toggle between loudspeaker and the platform default voice route.
|
|
235
|
+
*/
|
|
236
|
+
static async toggleSpeaker() {
|
|
237
|
+
// This is intentionally read-then-write because route changes can also come from
|
|
238
|
+
// the OS, Bluetooth, wired accessories, or the active call session.
|
|
239
|
+
const enabled = await VoicePnBridge.isSpeakerEnabled();
|
|
240
|
+
return VoicePnBridge.setSpeakerEnabled(!enabled);
|
|
241
|
+
}
|
|
187
242
|
/**
|
|
188
243
|
* Android → React Native: Listen for immediate call action events from notification buttons
|
|
189
244
|
* Use this for active calls where immediate response is needed (e.g., ending ongoing calls)
|
package/lib/models/config.d.ts
CHANGED
|
@@ -7,6 +7,10 @@ export interface CredentialConfig {
|
|
|
7
7
|
sipPassword: string;
|
|
8
8
|
debug?: boolean;
|
|
9
9
|
pushNotificationDeviceToken?: string;
|
|
10
|
+
/** Enable native missed call push notifications. Default: false */
|
|
11
|
+
enableMissedCallNotifications?: boolean;
|
|
12
|
+
/** Enable Trickle ICE. Default: false */
|
|
13
|
+
useTrickleIce?: boolean;
|
|
10
14
|
/** Enable automatic call quality reporting. Default: true */
|
|
11
15
|
enableCallReports?: boolean;
|
|
12
16
|
/** Stats collection interval in seconds. Default: 5 */
|
|
@@ -24,6 +28,10 @@ export interface TokenConfig {
|
|
|
24
28
|
token: string;
|
|
25
29
|
debug?: boolean;
|
|
26
30
|
pushNotificationDeviceToken?: string;
|
|
31
|
+
/** Enable native missed call push notifications. Default: false */
|
|
32
|
+
enableMissedCallNotifications?: boolean;
|
|
33
|
+
/** Enable Trickle ICE. Default: false */
|
|
34
|
+
useTrickleIce?: boolean;
|
|
27
35
|
/** Enable automatic call quality reporting. Default: true */
|
|
28
36
|
enableCallReports?: boolean;
|
|
29
37
|
/** Stats collection interval in seconds. Default: 5 */
|
|
@@ -10,6 +10,8 @@ export interface TelnyxVoipClientOptions {
|
|
|
10
10
|
enableAppStateManagement?: boolean;
|
|
11
11
|
/** Enable debug logging */
|
|
12
12
|
debug?: boolean;
|
|
13
|
+
/** Enable Trickle ICE for calls created by this client */
|
|
14
|
+
useTrickleIce?: boolean;
|
|
13
15
|
}
|
|
14
16
|
/**
|
|
15
17
|
* The main public interface for the react-voice-commons module.
|
|
@@ -10,6 +10,8 @@ const config_1 = require('./models/config');
|
|
|
10
10
|
const session_manager_1 = require('./internal/session/session-manager');
|
|
11
11
|
const call_state_controller_1 = require('./internal/calls/call-state-controller');
|
|
12
12
|
const voice_pn_bridge_1 = require('./internal/voice-pn-bridge');
|
|
13
|
+
const USE_TRICKLE_ICE_STORAGE_KEY = '@use_trickle_ice';
|
|
14
|
+
const MISSED_CALL_NOTIFICATIONS_STORAGE_KEY = '@enable_missed_call_notifications';
|
|
13
15
|
/**
|
|
14
16
|
* The main public interface for the react-voice-commons module.
|
|
15
17
|
*
|
|
@@ -52,6 +54,7 @@ class TelnyxVoipClient {
|
|
|
52
54
|
this._options = {
|
|
53
55
|
enableAppStateManagement: true,
|
|
54
56
|
debug: false,
|
|
57
|
+
useTrickleIce: false,
|
|
55
58
|
...options,
|
|
56
59
|
};
|
|
57
60
|
// Initialize core components
|
|
@@ -185,9 +188,13 @@ class TelnyxVoipClient {
|
|
|
185
188
|
if (this._options.debug) {
|
|
186
189
|
console.log('TelnyxVoipClient: Logging in with credentials for user:', config.sipUser);
|
|
187
190
|
}
|
|
191
|
+
const loginConfig = {
|
|
192
|
+
...config,
|
|
193
|
+
useTrickleIce: config.useTrickleIce ?? this._options.useTrickleIce,
|
|
194
|
+
};
|
|
188
195
|
// Store credentials for future reconnection
|
|
189
|
-
await this._storeCredentials(
|
|
190
|
-
await this._sessionManager.connectWithCredential(
|
|
196
|
+
await this._storeCredentials(loginConfig);
|
|
197
|
+
await this._sessionManager.connectWithCredential(loginConfig);
|
|
191
198
|
}
|
|
192
199
|
/**
|
|
193
200
|
* Connects to the Telnyx platform using token authentication.
|
|
@@ -207,9 +214,13 @@ class TelnyxVoipClient {
|
|
|
207
214
|
if (this._options.debug) {
|
|
208
215
|
console.log('TelnyxVoipClient: Logging in with token');
|
|
209
216
|
}
|
|
217
|
+
const loginConfig = {
|
|
218
|
+
...config,
|
|
219
|
+
useTrickleIce: config.useTrickleIce ?? this._options.useTrickleIce,
|
|
220
|
+
};
|
|
210
221
|
// Store token for future reconnection
|
|
211
|
-
await this._storeToken(
|
|
212
|
-
await this._sessionManager.connectWithToken(
|
|
222
|
+
await this._storeToken(loginConfig);
|
|
223
|
+
await this._sessionManager.connectWithToken(loginConfig);
|
|
213
224
|
}
|
|
214
225
|
/**
|
|
215
226
|
* Disconnects from the Telnyx platform.
|
|
@@ -246,12 +257,21 @@ class TelnyxVoipClient {
|
|
|
246
257
|
const storedPassword = await AsyncStorage.getItem('@telnyx_password');
|
|
247
258
|
const storedCredentialToken = await AsyncStorage.getItem('@credential_token');
|
|
248
259
|
const storedPushToken = await AsyncStorage.getItem('@push_token');
|
|
260
|
+
const storedUseTrickleIce = await AsyncStorage.getItem(USE_TRICKLE_ICE_STORAGE_KEY);
|
|
261
|
+
const storedMissedCallNotifications = await AsyncStorage.getItem(
|
|
262
|
+
MISSED_CALL_NOTIFICATIONS_STORAGE_KEY
|
|
263
|
+
);
|
|
264
|
+
const useTrickleIce =
|
|
265
|
+
storedUseTrickleIce === null ? this._options.useTrickleIce : storedUseTrickleIce === 'true';
|
|
266
|
+
const enableMissedCallNotifications = storedMissedCallNotifications === 'true';
|
|
249
267
|
// Check if we have credential-based authentication data
|
|
250
268
|
if (storedUsername && storedPassword) {
|
|
251
269
|
// Create credential config from stored data
|
|
252
270
|
const { createCredentialConfig } = require('./models/config');
|
|
253
271
|
const config = createCredentialConfig(storedUsername, storedPassword, {
|
|
254
272
|
pushNotificationDeviceToken: storedPushToken,
|
|
273
|
+
useTrickleIce,
|
|
274
|
+
enableMissedCallNotifications,
|
|
255
275
|
});
|
|
256
276
|
if (this._options.debug) {
|
|
257
277
|
console.log(
|
|
@@ -268,6 +288,8 @@ class TelnyxVoipClient {
|
|
|
268
288
|
const { createTokenConfig } = require('./models/config');
|
|
269
289
|
const config = createTokenConfig(storedCredentialToken, {
|
|
270
290
|
pushNotificationDeviceToken: storedPushToken,
|
|
291
|
+
useTrickleIce,
|
|
292
|
+
enableMissedCallNotifications,
|
|
271
293
|
});
|
|
272
294
|
if (this._options.debug) {
|
|
273
295
|
console.log('TelnyxVoipClient: Reconnecting with stored token');
|
|
@@ -441,6 +463,14 @@ class TelnyxVoipClient {
|
|
|
441
463
|
const AsyncStorage = require('@react-native-async-storage/async-storage').default;
|
|
442
464
|
await AsyncStorage.setItem('@telnyx_username', config.sipUser);
|
|
443
465
|
await AsyncStorage.setItem('@telnyx_password', config.sipPassword);
|
|
466
|
+
await AsyncStorage.setItem(
|
|
467
|
+
USE_TRICKLE_ICE_STORAGE_KEY,
|
|
468
|
+
String(config.useTrickleIce ?? false)
|
|
469
|
+
);
|
|
470
|
+
await AsyncStorage.setItem(
|
|
471
|
+
MISSED_CALL_NOTIFICATIONS_STORAGE_KEY,
|
|
472
|
+
String(config.enableMissedCallNotifications ?? false)
|
|
473
|
+
);
|
|
444
474
|
if (config.pushNotificationDeviceToken) {
|
|
445
475
|
await AsyncStorage.setItem('@push_token', config.pushNotificationDeviceToken);
|
|
446
476
|
}
|
|
@@ -463,6 +493,14 @@ class TelnyxVoipClient {
|
|
|
463
493
|
try {
|
|
464
494
|
const AsyncStorage = require('@react-native-async-storage/async-storage').default;
|
|
465
495
|
await AsyncStorage.setItem('@credential_token', config.token);
|
|
496
|
+
await AsyncStorage.setItem(
|
|
497
|
+
USE_TRICKLE_ICE_STORAGE_KEY,
|
|
498
|
+
String(config.useTrickleIce ?? false)
|
|
499
|
+
);
|
|
500
|
+
await AsyncStorage.setItem(
|
|
501
|
+
MISSED_CALL_NOTIFICATIONS_STORAGE_KEY,
|
|
502
|
+
String(config.enableMissedCallNotifications ?? false)
|
|
503
|
+
);
|
|
466
504
|
if (config.pushNotificationDeviceToken) {
|
|
467
505
|
await AsyncStorage.setItem('@push_token', config.pushNotificationDeviceToken);
|
|
468
506
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@telnyx/react-voice-commons-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "A high-level, state-agnostic, drop-in module for the Telnyx React Native SDK that simplifies WebRTC voice calling integration",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"module": "lib/index.js",
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
},
|
|
87
87
|
"dependencies": {
|
|
88
88
|
"@react-native-community/eslint-config": "^3.2.0",
|
|
89
|
-
"@telnyx/react-native-voice-sdk": ">=0.
|
|
89
|
+
"@telnyx/react-native-voice-sdk": ">=1.0.0",
|
|
90
90
|
"eventemitter3": "^5.0.1",
|
|
91
91
|
"expo": "~53.0.22",
|
|
92
92
|
"react-native-url-polyfill": "^3.0.0",
|
package/src/index.ts
CHANGED
|
@@ -55,5 +55,8 @@ export type { Call as TelnyxCall } from '@telnyx/react-native-voice-sdk';
|
|
|
55
55
|
// Export CallKit functionality
|
|
56
56
|
export * from './callkit';
|
|
57
57
|
|
|
58
|
+
// Native push notification helpers
|
|
59
|
+
export { VoicePnBridge } from './internal/voice-pn-bridge';
|
|
60
|
+
|
|
58
61
|
// Export hooks
|
|
59
62
|
export { useAppReadyNotifier } from './hooks/useAppReadyNotifier';
|