@telnyx/react-voice-commons-sdk 0.1.2 → 0.1.3

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.
Files changed (58) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/TelnyxVoiceCommons.podspec +31 -31
  3. package/ios/CallKitBridge.m +43 -43
  4. package/ios/CallKitBridge.swift +874 -879
  5. package/ios/VoicePnBridge.m +30 -30
  6. package/ios/VoicePnBridge.swift +86 -86
  7. package/lib/callkit/callkit-coordinator.d.ts +110 -117
  8. package/lib/callkit/callkit-coordinator.js +664 -727
  9. package/lib/callkit/callkit.d.ts +41 -41
  10. package/lib/callkit/callkit.js +252 -242
  11. package/lib/callkit/index.js +15 -47
  12. package/lib/callkit/use-callkit.d.ts +19 -19
  13. package/lib/callkit/use-callkit.js +270 -310
  14. package/lib/context/TelnyxVoiceContext.d.ts +9 -9
  15. package/lib/context/TelnyxVoiceContext.js +10 -13
  16. package/lib/hooks/use-callkit-coordinator.d.ts +9 -17
  17. package/lib/hooks/use-callkit-coordinator.js +45 -50
  18. package/lib/hooks/useAppReadyNotifier.js +13 -15
  19. package/lib/hooks/useAppStateHandler.d.ts +6 -11
  20. package/lib/hooks/useAppStateHandler.js +95 -110
  21. package/lib/hooks/useNetworkStateHandler.d.ts +0 -0
  22. package/lib/hooks/useNetworkStateHandler.js +0 -0
  23. package/lib/index.d.ts +3 -21
  24. package/lib/index.js +50 -201
  25. package/lib/internal/CallKitHandler.d.ts +6 -6
  26. package/lib/internal/CallKitHandler.js +96 -104
  27. package/lib/internal/callkit-manager.d.ts +57 -57
  28. package/lib/internal/callkit-manager.js +299 -316
  29. package/lib/internal/calls/call-state-controller.d.ts +73 -86
  30. package/lib/internal/calls/call-state-controller.js +263 -307
  31. package/lib/internal/session/session-manager.d.ts +71 -75
  32. package/lib/internal/session/session-manager.js +360 -424
  33. package/lib/internal/user-defaults-helpers.js +49 -39
  34. package/lib/internal/voice-pn-bridge.d.ts +114 -12
  35. package/lib/internal/voice-pn-bridge.js +212 -5
  36. package/lib/models/call-state.d.ts +46 -44
  37. package/lib/models/call-state.js +70 -68
  38. package/lib/models/call.d.ts +161 -133
  39. package/lib/models/call.js +454 -382
  40. package/lib/models/config.d.ts +11 -18
  41. package/lib/models/config.js +37 -35
  42. package/lib/models/connection-state.d.ts +10 -10
  43. package/lib/models/connection-state.js +16 -16
  44. package/lib/telnyx-voice-app.d.ts +28 -28
  45. package/lib/telnyx-voice-app.js +463 -481
  46. package/lib/telnyx-voip-client.d.ts +167 -167
  47. package/lib/telnyx-voip-client.js +385 -390
  48. package/package.json +11 -4
  49. package/src/callkit/callkit-coordinator.ts +18 -34
  50. package/src/hooks/useNetworkStateHandler.ts +0 -0
  51. package/src/internal/calls/call-state-controller.ts +81 -58
  52. package/src/internal/session/session-manager.ts +42 -26
  53. package/src/internal/voice-pn-bridge.ts +250 -2
  54. package/src/models/call-state.ts +8 -1
  55. package/src/models/call.ts +119 -5
  56. package/src/telnyx-voice-app.tsx +87 -40
  57. package/src/telnyx-voip-client.ts +15 -3
  58. package/src/types/telnyx-sdk.d.ts +16 -2
@@ -1,319 +1,279 @@
1
- 'use strict';
2
- var __createBinding =
3
- (this && this.__createBinding) ||
4
- (Object.create
5
- ? function (o, m, k, k2) {
6
- if (k2 === undefined) k2 = k;
7
- var desc = Object.getOwnPropertyDescriptor(m, k);
8
- if (!desc || ('get' in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
- desc = {
10
- enumerable: true,
11
- get: function () {
12
- return m[k];
13
- },
14
- };
15
- }
16
- Object.defineProperty(o, k2, desc);
17
- }
18
- : function (o, m, k, k2) {
19
- if (k2 === undefined) k2 = k;
20
- o[k2] = m[k];
21
- });
22
- var __setModuleDefault =
23
- (this && this.__setModuleDefault) ||
24
- (Object.create
25
- ? function (o, v) {
26
- Object.defineProperty(o, 'default', { enumerable: true, value: v });
27
- }
28
- : function (o, v) {
29
- o['default'] = v;
30
- });
31
- var __importStar =
32
- (this && this.__importStar) ||
33
- (function () {
34
- var ownKeys = function (o) {
35
- ownKeys =
36
- Object.getOwnPropertyNames ||
37
- function (o) {
38
- var ar = [];
39
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
40
- return ar;
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
41
24
  };
42
- return ownKeys(o);
25
+ return ownKeys(o);
43
26
  };
44
27
  return function (mod) {
45
- if (mod && mod.__esModule) return mod;
46
- var result = {};
47
- if (mod != null)
48
- for (var k = ownKeys(mod), i = 0; i < k.length; i++)
49
- if (k[i] !== 'default') __createBinding(result, mod, k[i]);
50
- __setModuleDefault(result, mod);
51
- return result;
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
52
33
  };
53
- })();
54
- Object.defineProperty(exports, '__esModule', { value: true });
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
55
36
  exports.useCallKit = useCallKit;
56
- const react_1 = require('react');
57
- const callkit_1 = __importStar(require('./callkit'));
37
+ const react_1 = require("react");
38
+ const callkit_1 = __importStar(require("./callkit"));
58
39
  function useCallKit(options = {}) {
59
- const { onAnswerCall, onEndCall, onStartCall } = options;
60
- const [activeCalls, setActiveCalls] = (0, react_1.useState)([]);
61
- const [isAvailable, setIsAvailable] = (0, react_1.useState)(false);
62
- // Use refs to store stable callback references and current state
63
- const onAnswerCallRef = (0, react_1.useRef)(onAnswerCall);
64
- const onEndCallRef = (0, react_1.useRef)(onEndCall);
65
- const onStartCallRef = (0, react_1.useRef)(onStartCall);
66
- const activeCallsRef = (0, react_1.useRef)(activeCalls);
67
- // Update refs when callbacks change
68
- (0, react_1.useEffect)(() => {
69
- onAnswerCallRef.current = onAnswerCall;
70
- }, [onAnswerCall]);
71
- (0, react_1.useEffect)(() => {
72
- onEndCallRef.current = onEndCall;
73
- }, [onEndCall]);
74
- (0, react_1.useEffect)(() => {
75
- onStartCallRef.current = onStartCall;
76
- }, [onStartCall]);
77
- // Update active calls ref
78
- (0, react_1.useEffect)(() => {
79
- activeCallsRef.current = activeCalls;
80
- }, [activeCalls]);
81
- (0, react_1.useEffect)(() => {
82
- setIsAvailable(callkit_1.default.isAvailable());
83
- if (!callkit_1.default.isAvailable()) {
84
- console.log('CallKit: Not available on this platform');
85
- return;
86
- }
87
- // Load existing active calls only once
88
- const loadActiveCalls = async () => {
89
- const calls = await callkit_1.default.getActiveCalls();
90
- setActiveCalls(
91
- calls.map((call) => ({
92
- uuid: call.uuid,
93
- handle: call.handle || call.caller || 'Unknown',
94
- displayName: call.caller || call.displayName || 'Unknown Caller',
95
- isActive: true,
96
- direction: call.direction || 'incoming',
97
- }))
98
- );
99
- };
100
- loadActiveCalls();
101
- // Set up event listeners using stable refs
102
- const unsubscribeAnswer = callkit_1.default.onAnswerCall((event) => {
103
- console.log('useCallKit: Call answered via CallKit', event);
104
- onAnswerCallRef.current?.(event.callUUID);
105
- });
106
- const unsubscribeEnd = callkit_1.default.onEndCall((event) => {
107
- console.log('useCallKit: Call ended via CallKit', event);
108
- setActiveCalls((prev) => prev.filter((call) => call.uuid !== event.callUUID));
109
- onEndCallRef.current?.(event.callUUID);
110
- });
111
- const unsubscribeStart = callkit_1.default.onStartCall((event) => {
112
- console.log('useCallKit: Call started via CallKit', event);
113
- onStartCallRef.current?.(event.callUUID);
114
- });
115
- return () => {
116
- unsubscribeAnswer();
117
- unsubscribeEnd();
118
- unsubscribeStart();
119
- };
120
- }, []); // Empty dependency array - only run once
121
- // Start an outgoing call
122
- const startOutgoingCall = (0, react_1.useCallback)(async (call, handle, displayName) => {
123
- if (!callkit_1.default.isAvailable()) {
124
- console.warn('CallKit: Not available, cannot start outgoing call');
125
- return null;
126
- }
127
- const callUUID = callkit_1.default.generateCallUUID();
128
- const callHandle = handle || call.destinationNumber || 'Unknown';
129
- const callDisplayName = displayName || callHandle;
130
- console.log('useCallKit: Starting outgoing call', {
131
- callUUID,
132
- callHandle,
133
- callDisplayName,
134
- telnyxCallId: call.callId,
135
- });
136
- const success = await callkit_1.default.startOutgoingCall(
137
- callUUID,
138
- callHandle,
139
- callDisplayName
140
- );
141
- if (success) {
142
- const newCall = {
143
- uuid: callUUID,
144
- handle: callHandle,
145
- displayName: callDisplayName,
146
- isActive: false,
147
- direction: 'outgoing',
148
- };
149
- setActiveCalls((prev) => [...prev, newCall]);
150
- // Store mapping between CallKit UUID and Telnyx call for later reference
151
- call._callKitUUID = callUUID;
152
- return callUUID;
153
- }
154
- return null;
155
- }, []);
156
- // Report an incoming call
157
- const reportIncomingCall = (0, react_1.useCallback)(async (call, handle, displayName) => {
158
- if (!callkit_1.default.isAvailable()) {
159
- console.warn('CallKit: Not available, cannot report incoming call');
160
- return null;
161
- }
162
- const callUUID = callkit_1.default.generateCallUUID();
163
- const callHandle = handle || call.destinationNumber || call.callId || 'Unknown';
164
- const callDisplayName = displayName || callHandle;
165
- console.log('useCallKit: Reporting incoming call', {
166
- callUUID,
167
- callHandle,
168
- callDisplayName,
169
- telnyxCallId: call.callId,
170
- });
171
- const success = await callkit_1.default.reportIncomingCall(
172
- callUUID,
173
- callHandle,
174
- callDisplayName
175
- );
176
- if (success) {
177
- const newCall = {
178
- uuid: callUUID,
179
- handle: callHandle,
180
- displayName: callDisplayName,
181
- isActive: false,
182
- direction: 'incoming',
183
- };
184
- setActiveCalls((prev) => [...prev, newCall]);
185
- // Store mapping between CallKit UUID and Telnyx call for later reference
186
- call._callKitUUID = callUUID;
187
- return callUUID;
188
- }
189
- return null;
190
- }, []);
191
- // End a call
192
- const endCall = (0, react_1.useCallback)(
193
- async (callUUID, reason = callkit_1.CallEndReason.RemoteEnded) => {
194
- if (!callkit_1.default.isAvailable()) {
195
- return false;
196
- }
197
- console.log('useCallKit: Ending call', { callUUID, reason });
198
- try {
199
- // For incoming calls, we should use reportCallEnded (which dismisses the UI)
200
- // For outgoing calls, we should use endCall (which sends the end request)
201
- // Check if this is likely an incoming call by looking at our active calls
202
- const activeCall = activeCallsRef.current.find((call) => call.uuid === callUUID);
203
- const isIncomingCall = activeCall?.direction === 'incoming';
204
- if (isIncomingCall) {
205
- await callkit_1.default.reportCallEnded(callUUID, reason);
206
- } else {
207
- await callkit_1.default.endCall(callUUID);
40
+ const { onAnswerCall, onEndCall, onStartCall } = options;
41
+ const [activeCalls, setActiveCalls] = (0, react_1.useState)([]);
42
+ const [isAvailable, setIsAvailable] = (0, react_1.useState)(false);
43
+ // Use refs to store stable callback references and current state
44
+ const onAnswerCallRef = (0, react_1.useRef)(onAnswerCall);
45
+ const onEndCallRef = (0, react_1.useRef)(onEndCall);
46
+ const onStartCallRef = (0, react_1.useRef)(onStartCall);
47
+ const activeCallsRef = (0, react_1.useRef)(activeCalls);
48
+ // Update refs when callbacks change
49
+ (0, react_1.useEffect)(() => {
50
+ onAnswerCallRef.current = onAnswerCall;
51
+ }, [onAnswerCall]);
52
+ (0, react_1.useEffect)(() => {
53
+ onEndCallRef.current = onEndCall;
54
+ }, [onEndCall]);
55
+ (0, react_1.useEffect)(() => {
56
+ onStartCallRef.current = onStartCall;
57
+ }, [onStartCall]);
58
+ // Update active calls ref
59
+ (0, react_1.useEffect)(() => {
60
+ activeCallsRef.current = activeCalls;
61
+ }, [activeCalls]);
62
+ (0, react_1.useEffect)(() => {
63
+ setIsAvailable(callkit_1.default.isAvailable());
64
+ if (!callkit_1.default.isAvailable()) {
65
+ console.log('CallKit: Not available on this platform');
66
+ return;
208
67
  }
209
- // Update our local state
210
- setActiveCalls((prev) => prev.filter((call) => call.uuid !== callUUID));
211
- return true;
212
- } catch (error) {
213
- console.log('useCallKit: Error ending call (may already be ended):', error);
214
- // Still remove from our local state even if CallKit operation failed
215
- // This ensures our UI stays in sync
216
- setActiveCalls((prev) => prev.filter((call) => call.uuid !== callUUID));
217
- // Return true since the call is effectively ended from our perspective
218
- return true;
219
- }
220
- },
221
- []
222
- );
223
- // Report call connected
224
- const reportCallConnected = (0, react_1.useCallback)(async (callUUID) => {
225
- if (!callkit_1.default.isAvailable()) {
226
- return false;
227
- }
228
- console.log('useCallKit: Reporting call connected', { callUUID });
229
- const success = await callkit_1.default.reportCallConnected(callUUID);
230
- if (success) {
231
- // Update our local state to mark the call as active
232
- setActiveCalls((prev) =>
233
- prev.map((call) => (call.uuid === callUUID ? { ...call, isActive: true } : call))
234
- );
235
- }
236
- return success;
237
- }, []);
238
- // Update call information
239
- const updateCall = (0, react_1.useCallback)(async (callUUID, displayName, handle) => {
240
- if (!callkit_1.default.isAvailable()) {
241
- return false;
242
- }
243
- console.log('useCallKit: Updating call', { callUUID, displayName, handle });
244
- const success = await callkit_1.default.updateCall(callUUID, displayName, handle);
245
- if (success) {
246
- // Update our local state
247
- setActiveCalls((prev) =>
248
- prev.map((call) => (call.uuid === callUUID ? { ...call, displayName, handle } : call))
249
- );
250
- }
251
- return success;
252
- }, []);
253
- // Answer a call
254
- const answerCall = (0, react_1.useCallback)(async (callUUID) => {
255
- if (!callkit_1.default.isAvailable()) {
256
- return false;
257
- }
258
- console.log('useCallKit: Answering call', { callUUID });
259
- const success = await callkit_1.default.answerCall(callUUID);
260
- if (success) {
261
- // Update our local state to mark call as active
262
- setActiveCalls((prev) =>
263
- prev.map((call) => (call.uuid === callUUID ? { ...call, isActive: true } : call))
264
- );
265
- }
266
- return success;
267
- }, []);
268
- // Get CallKit UUID for a Telnyx call
269
- const getCallKitUUID = (0, react_1.useCallback)((call) => {
270
- return call._callKitUUID || null;
271
- }, []);
272
- // Set up automatic CallKit integration for a Telnyx call
273
- const integrateCall = (0, react_1.useCallback)(
274
- async (call, direction) => {
275
- if (!callkit_1.default.isAvailable()) {
276
- return null;
277
- }
278
- let callUUID = null;
279
- if (direction === 'incoming') {
280
- callUUID = await reportIncomingCall(call);
281
- } else {
282
- callUUID = await startOutgoingCall(call);
283
- }
284
- if (callUUID) {
285
- // Set up automatic state reporting
286
- const handleStateChange = async (call, state) => {
287
- if (state === 'active') {
288
- await reportCallConnected(callUUID);
289
- } else if (state === 'ended' || state === 'failed') {
290
- const reason =
291
- state === 'failed'
292
- ? callkit_1.CallEndReason.Failed
293
- : callkit_1.CallEndReason.RemoteEnded;
294
- await endCall(callUUID, reason);
295
- }
68
+ // Load existing active calls only once
69
+ const loadActiveCalls = async () => {
70
+ const calls = await callkit_1.default.getActiveCalls();
71
+ setActiveCalls(calls.map((call) => ({
72
+ uuid: call.uuid,
73
+ handle: call.handle || call.caller || 'Unknown',
74
+ displayName: call.caller || call.displayName || 'Unknown Caller',
75
+ isActive: true,
76
+ direction: call.direction || 'incoming',
77
+ })));
78
+ };
79
+ loadActiveCalls();
80
+ // Set up event listeners using stable refs
81
+ const unsubscribeAnswer = callkit_1.default.onAnswerCall((event) => {
82
+ console.log('useCallKit: Call answered via CallKit', event);
83
+ onAnswerCallRef.current?.(event.callUUID);
84
+ });
85
+ const unsubscribeEnd = callkit_1.default.onEndCall((event) => {
86
+ console.log('useCallKit: Call ended via CallKit', event);
87
+ setActiveCalls((prev) => prev.filter((call) => call.uuid !== event.callUUID));
88
+ onEndCallRef.current?.(event.callUUID);
89
+ });
90
+ const unsubscribeStart = callkit_1.default.onStartCall((event) => {
91
+ console.log('useCallKit: Call started via CallKit', event);
92
+ onStartCallRef.current?.(event.callUUID);
93
+ });
94
+ return () => {
95
+ unsubscribeAnswer();
96
+ unsubscribeEnd();
97
+ unsubscribeStart();
296
98
  };
297
- call.on('telnyx.call.state', handleStateChange);
298
- }
299
- return callUUID;
300
- },
301
- [reportIncomingCall, startOutgoingCall, reportCallConnected, endCall]
302
- );
303
- return {
304
- // State
305
- isAvailable,
306
- activeCalls,
307
- // Methods
308
- startOutgoingCall,
309
- reportIncomingCall,
310
- answerCall,
311
- endCall,
312
- reportCallConnected,
313
- updateCall,
314
- getCallKitUUID,
315
- integrateCall,
316
- // Utility
317
- generateCallUUID: callkit_1.default.generateCallUUID,
318
- };
99
+ }, []); // Empty dependency array - only run once
100
+ // Start an outgoing call
101
+ const startOutgoingCall = (0, react_1.useCallback)(async (call, handle, displayName) => {
102
+ if (!callkit_1.default.isAvailable()) {
103
+ console.warn('CallKit: Not available, cannot start outgoing call');
104
+ return null;
105
+ }
106
+ const callUUID = callkit_1.default.generateCallUUID();
107
+ const callHandle = handle || call.destinationNumber || 'Unknown';
108
+ const callDisplayName = displayName || callHandle;
109
+ console.log('useCallKit: Starting outgoing call', {
110
+ callUUID,
111
+ callHandle,
112
+ callDisplayName,
113
+ telnyxCallId: call.callId,
114
+ });
115
+ const success = await callkit_1.default.startOutgoingCall(callUUID, callHandle, callDisplayName);
116
+ if (success) {
117
+ const newCall = {
118
+ uuid: callUUID,
119
+ handle: callHandle,
120
+ displayName: callDisplayName,
121
+ isActive: false,
122
+ direction: 'outgoing',
123
+ };
124
+ setActiveCalls((prev) => [...prev, newCall]);
125
+ // Store mapping between CallKit UUID and Telnyx call for later reference
126
+ call._callKitUUID = callUUID;
127
+ return callUUID;
128
+ }
129
+ return null;
130
+ }, []);
131
+ // Report an incoming call
132
+ const reportIncomingCall = (0, react_1.useCallback)(async (call, handle, displayName) => {
133
+ if (!callkit_1.default.isAvailable()) {
134
+ console.warn('CallKit: Not available, cannot report incoming call');
135
+ return null;
136
+ }
137
+ const callUUID = callkit_1.default.generateCallUUID();
138
+ const callHandle = handle || call.destinationNumber || call.callId || 'Unknown';
139
+ const callDisplayName = displayName || callHandle;
140
+ console.log('useCallKit: Reporting incoming call', {
141
+ callUUID,
142
+ callHandle,
143
+ callDisplayName,
144
+ telnyxCallId: call.callId,
145
+ });
146
+ const success = await callkit_1.default.reportIncomingCall(callUUID, callHandle, callDisplayName);
147
+ if (success) {
148
+ const newCall = {
149
+ uuid: callUUID,
150
+ handle: callHandle,
151
+ displayName: callDisplayName,
152
+ isActive: false,
153
+ direction: 'incoming',
154
+ };
155
+ setActiveCalls((prev) => [...prev, newCall]);
156
+ // Store mapping between CallKit UUID and Telnyx call for later reference
157
+ call._callKitUUID = callUUID;
158
+ return callUUID;
159
+ }
160
+ return null;
161
+ }, []);
162
+ // End a call
163
+ const endCall = (0, react_1.useCallback)(async (callUUID, reason = callkit_1.CallEndReason.RemoteEnded) => {
164
+ if (!callkit_1.default.isAvailable()) {
165
+ return false;
166
+ }
167
+ console.log('useCallKit: Ending call', { callUUID, reason });
168
+ try {
169
+ // For incoming calls, we should use reportCallEnded (which dismisses the UI)
170
+ // For outgoing calls, we should use endCall (which sends the end request)
171
+ // Check if this is likely an incoming call by looking at our active calls
172
+ const activeCall = activeCallsRef.current.find((call) => call.uuid === callUUID);
173
+ const isIncomingCall = activeCall?.direction === 'incoming';
174
+ if (isIncomingCall) {
175
+ await callkit_1.default.reportCallEnded(callUUID, reason);
176
+ }
177
+ else {
178
+ await callkit_1.default.endCall(callUUID);
179
+ }
180
+ // Update our local state
181
+ setActiveCalls((prev) => prev.filter((call) => call.uuid !== callUUID));
182
+ return true;
183
+ }
184
+ catch (error) {
185
+ console.log('useCallKit: Error ending call (may already be ended):', error);
186
+ // Still remove from our local state even if CallKit operation failed
187
+ // This ensures our UI stays in sync
188
+ setActiveCalls((prev) => prev.filter((call) => call.uuid !== callUUID));
189
+ // Return true since the call is effectively ended from our perspective
190
+ return true;
191
+ }
192
+ }, []);
193
+ // Report call connected
194
+ const reportCallConnected = (0, react_1.useCallback)(async (callUUID) => {
195
+ if (!callkit_1.default.isAvailable()) {
196
+ return false;
197
+ }
198
+ console.log('useCallKit: Reporting call connected', { callUUID });
199
+ const success = await callkit_1.default.reportCallConnected(callUUID);
200
+ if (success) {
201
+ // Update our local state to mark the call as active
202
+ setActiveCalls((prev) => prev.map((call) => (call.uuid === callUUID ? { ...call, isActive: true } : call)));
203
+ }
204
+ return success;
205
+ }, []);
206
+ // Update call information
207
+ const updateCall = (0, react_1.useCallback)(async (callUUID, displayName, handle) => {
208
+ if (!callkit_1.default.isAvailable()) {
209
+ return false;
210
+ }
211
+ console.log('useCallKit: Updating call', { callUUID, displayName, handle });
212
+ const success = await callkit_1.default.updateCall(callUUID, displayName, handle);
213
+ if (success) {
214
+ // Update our local state
215
+ setActiveCalls((prev) => prev.map((call) => (call.uuid === callUUID ? { ...call, displayName, handle } : call)));
216
+ }
217
+ return success;
218
+ }, []);
219
+ // Answer a call
220
+ const answerCall = (0, react_1.useCallback)(async (callUUID) => {
221
+ if (!callkit_1.default.isAvailable()) {
222
+ return false;
223
+ }
224
+ console.log('useCallKit: Answering call', { callUUID });
225
+ const success = await callkit_1.default.answerCall(callUUID);
226
+ if (success) {
227
+ // Update our local state to mark call as active
228
+ setActiveCalls((prev) => prev.map((call) => (call.uuid === callUUID ? { ...call, isActive: true } : call)));
229
+ }
230
+ return success;
231
+ }, []);
232
+ // Get CallKit UUID for a Telnyx call
233
+ const getCallKitUUID = (0, react_1.useCallback)((call) => {
234
+ return call._callKitUUID || null;
235
+ }, []);
236
+ // Set up automatic CallKit integration for a Telnyx call
237
+ const integrateCall = (0, react_1.useCallback)(async (call, direction) => {
238
+ if (!callkit_1.default.isAvailable()) {
239
+ return null;
240
+ }
241
+ let callUUID = null;
242
+ if (direction === 'incoming') {
243
+ callUUID = await reportIncomingCall(call);
244
+ }
245
+ else {
246
+ callUUID = await startOutgoingCall(call);
247
+ }
248
+ if (callUUID) {
249
+ // Set up automatic state reporting
250
+ const handleStateChange = async (call, state) => {
251
+ if (state === 'active') {
252
+ await reportCallConnected(callUUID);
253
+ }
254
+ else if (state === 'ended' || state === 'failed') {
255
+ const reason = state === 'failed' ? callkit_1.CallEndReason.Failed : callkit_1.CallEndReason.RemoteEnded;
256
+ await endCall(callUUID, reason);
257
+ }
258
+ };
259
+ call.on('telnyx.call.state', handleStateChange);
260
+ }
261
+ return callUUID;
262
+ }, [reportIncomingCall, startOutgoingCall, reportCallConnected, endCall]);
263
+ return {
264
+ // State
265
+ isAvailable,
266
+ activeCalls,
267
+ // Methods
268
+ startOutgoingCall,
269
+ reportIncomingCall,
270
+ answerCall,
271
+ endCall,
272
+ reportCallConnected,
273
+ updateCall,
274
+ getCallKitUUID,
275
+ integrateCall,
276
+ // Utility
277
+ generateCallUUID: callkit_1.default.generateCallUUID,
278
+ };
319
279
  }
@@ -2,17 +2,17 @@ import React from 'react';
2
2
  import { TelnyxVoipClient } from '../telnyx-voip-client';
3
3
  import { TelnyxConnectionState } from '../models/connection-state';
4
4
  interface TelnyxVoiceContextValue {
5
- voipClient: TelnyxVoipClient;
6
- connectionState?: TelnyxConnectionState;
7
- setConnectionState?: (state: TelnyxConnectionState) => void;
8
- connect?: (payload: any) => Promise<any>;
9
- client?: any;
10
- setClient?: (client: any) => void;
11
- enableAutoReconnect?: (enabled: boolean) => void;
5
+ voipClient: TelnyxVoipClient;
6
+ connectionState?: TelnyxConnectionState;
7
+ setConnectionState?: (state: TelnyxConnectionState) => void;
8
+ connect?: (payload: any) => Promise<any>;
9
+ client?: any;
10
+ setClient?: (client: any) => void;
11
+ enableAutoReconnect?: (enabled: boolean) => void;
12
12
  }
13
13
  export declare const TelnyxVoiceProvider: React.FC<{
14
- voipClient: TelnyxVoipClient;
15
- children: React.ReactNode;
14
+ voipClient: TelnyxVoipClient;
15
+ children: React.ReactNode;
16
16
  }>;
17
17
  export declare const useTelnyxVoice: () => TelnyxVoiceContextValue;
18
18
  export {};
@@ -1,21 +1,18 @@
1
- 'use strict';
2
- Object.defineProperty(exports, '__esModule', { value: true });
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useTelnyxVoice = exports.TelnyxVoiceProvider = void 0;
4
- const jsx_runtime_1 = require('react/jsx-runtime');
5
- const react_1 = require('react');
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
6
  const TelnyxVoiceContext = (0, react_1.createContext)(null);
7
7
  const TelnyxVoiceProvider = ({ voipClient, children }) => {
8
- return (0, jsx_runtime_1.jsx)(TelnyxVoiceContext.Provider, {
9
- value: { voipClient },
10
- children: children,
11
- });
8
+ return ((0, jsx_runtime_1.jsx)(TelnyxVoiceContext.Provider, { value: { voipClient }, children: children }));
12
9
  };
13
10
  exports.TelnyxVoiceProvider = TelnyxVoiceProvider;
14
11
  const useTelnyxVoice = () => {
15
- const context = (0, react_1.useContext)(TelnyxVoiceContext);
16
- if (!context) {
17
- throw new Error('useTelnyxVoice must be used within a TelnyxVoiceProvider');
18
- }
19
- return context;
12
+ const context = (0, react_1.useContext)(TelnyxVoiceContext);
13
+ if (!context) {
14
+ throw new Error('useTelnyxVoice must be used within a TelnyxVoiceProvider');
15
+ }
16
+ return context;
20
17
  };
21
18
  exports.useTelnyxVoice = useTelnyxVoice;