@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/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
- if (!this._sessionManager.telnyxClient) {
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
- this._sessionManager.telnyxClient.on('telnyx.call.incoming', (telnyxCall, msg) => {
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
- this._sessionManager.telnyxClient.on('telnyx.call.reattached', (telnyxCall, msg) => {
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
- this._sessionManager.telnyxClient.listenerCount('telnyx.call.incoming');
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
- this._sessionManager.telnyxClient.on('telnyx.call.stateChanged', (telnyxCall, state) => {
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
- this._sessionManager.telnyxClient.on('telnyx.call.removed', (callId) => {
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
  */
@@ -42,6 +42,7 @@ export declare class SessionManager {
42
42
  * Get the underlying Telnyx client instance
43
43
  */
44
44
  get telnyxClient(): TelnyxSDK.TelnyxRTC | undefined;
45
+ get useTrickleIce(): boolean;
45
46
  /**
46
47
  * Connect using credential authentication
47
48
  */
@@ -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)
@@ -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(config);
190
- await this._sessionManager.connectWithCredential(config);
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(config);
212
- await this._sessionManager.connectWithToken(config);
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.4.3",
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.4.5",
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';