@telnyx/react-voice-commons-sdk 0.4.3 → 1.1.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 +23 -0
- package/README.md +28 -7
- package/android/src/main/java/com/telnyx/react_voice_commons/CallForegroundService.kt +16 -2
- package/android/src/main/java/com/telnyx/react_voice_commons/TelnyxFirebaseMessagingService.kt +16 -2
- package/android/src/main/java/com/telnyx/react_voice_commons/TelnyxNotificationHelper.kt +345 -24
- package/android/src/main/java/com/telnyx/react_voice_commons/VoicePnBridgeModule.kt +74 -1
- package/android/src/main/java/com/telnyx/react_voice_commons/VoicePnManager.kt +36 -1
- package/ios/CallKitBridge.m +20 -1
- package/ios/CallKitBridge.swift +935 -60
- package/ios/README.md +2 -2
- package/ios/VoicePnBridge.m +21 -1
- package/ios/VoicePnBridge.swift +62 -1
- package/lib/callkit/callkit-coordinator.d.ts +39 -3
- package/lib/callkit/callkit-coordinator.js +561 -148
- package/lib/callkit/callkit.d.ts +7 -0
- package/lib/callkit/callkit.js +83 -11
- package/lib/hooks/useAppStateHandler.js +6 -2
- package/lib/index.d.ts +1 -0
- package/lib/index.js +9 -0
- package/lib/internal/CallKitHandler.d.ts +3 -0
- package/lib/internal/CallKitHandler.js +52 -46
- package/lib/internal/calls/call-state-controller.d.ts +39 -1
- package/lib/internal/calls/call-state-controller.js +152 -64
- package/lib/internal/session/session-manager.d.ts +16 -1
- package/lib/internal/session/session-manager.js +229 -58
- package/lib/internal/voice-pn-bridge.d.ts +44 -0
- package/lib/internal/voice-pn-bridge.js +94 -0
- package/lib/models/call.js +35 -0
- package/lib/models/config.d.ts +18 -0
- package/lib/models/config.js +2 -0
- package/lib/telnyx-voice-app.js +85 -43
- package/lib/telnyx-voip-client.d.ts +48 -5
- package/lib/telnyx-voip-client.js +276 -22
- package/package.json +7 -5
- package/src/callkit/callkit-coordinator.ts +642 -160
- package/src/callkit/callkit.ts +110 -12
- package/src/hooks/useAppStateHandler.ts +7 -2
- package/src/index.ts +3 -0
- package/src/internal/CallKitHandler.tsx +60 -55
- package/src/internal/calls/call-state-controller.ts +173 -74
- package/src/internal/session/session-manager.ts +277 -61
- package/src/internal/voice-pn-bridge.ts +111 -0
- package/src/models/call.ts +34 -0
- package/src/models/config.ts +18 -0
- package/src/telnyx-voice-app.tsx +96 -45
- package/src/telnyx-voip-client.ts +260 -24
- package/src/types/telnyx-sdk.d.ts +12 -1
package/lib/callkit/callkit.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export declare enum CallEndReason {
|
|
|
7
7
|
}
|
|
8
8
|
export interface CallKitEvent {
|
|
9
9
|
callUUID: string;
|
|
10
|
+
isOnHold?: boolean;
|
|
10
11
|
[key: string]: any;
|
|
11
12
|
}
|
|
12
13
|
declare class CallKitManager {
|
|
@@ -33,7 +34,11 @@ declare class CallKitManager {
|
|
|
33
34
|
startOutgoingCall(callUUID: string, handle: string, displayName: string): Promise<boolean>;
|
|
34
35
|
reportIncomingCall(callUUID: string, handle: string, displayName: string): Promise<boolean>;
|
|
35
36
|
answerCall(callUUID: string): Promise<boolean>;
|
|
37
|
+
isCallRegistered(callUUID: string): Promise<boolean>;
|
|
36
38
|
endCall(callUUID: string): Promise<boolean>;
|
|
39
|
+
completeHeldCallAction(callUUID: string, success: boolean): Promise<boolean>;
|
|
40
|
+
setCallHeld(callUUID: string, isOnHold: boolean): Promise<boolean>;
|
|
41
|
+
swapCalls(activeCallUUID: string, heldCallUUID: string): Promise<boolean>;
|
|
37
42
|
reportCallConnected(callUUID: string): Promise<boolean>;
|
|
38
43
|
reportCallEnded(callUUID: string, reason?: CallEndReason): Promise<boolean>;
|
|
39
44
|
updateCall(callUUID: string, displayName: string, handle: string): Promise<boolean>;
|
|
@@ -41,7 +46,9 @@ declare class CallKitManager {
|
|
|
41
46
|
onStartCall(listener: (event: CallKitEvent) => void): () => void;
|
|
42
47
|
onAnswerCall(listener: (event: CallKitEvent) => void): () => void;
|
|
43
48
|
onEndCall(listener: (event: CallKitEvent) => void): () => void;
|
|
49
|
+
onHeldCall(listener: (event: CallKitEvent) => void): () => void;
|
|
44
50
|
onReceivePush(listener: (event: CallKitEvent) => void): () => void;
|
|
51
|
+
private addListener;
|
|
45
52
|
generateCallUUID(): string;
|
|
46
53
|
isAvailable(): boolean;
|
|
47
54
|
}
|
package/lib/callkit/callkit.js
CHANGED
|
@@ -68,6 +68,11 @@ class CallKitManager {
|
|
|
68
68
|
console.log('CallKit: Received end call action', normalizedEvent);
|
|
69
69
|
this.notifyListeners('endCall', normalizedEvent);
|
|
70
70
|
});
|
|
71
|
+
this.eventEmitter.addListener('CallKitDidPerformHeldCallAction', (event) => {
|
|
72
|
+
const normalizedEvent = this.normalizeEvent(event);
|
|
73
|
+
console.log('CallKit: Received held call action', normalizedEvent);
|
|
74
|
+
this.notifyListeners('heldCall', normalizedEvent);
|
|
75
|
+
});
|
|
71
76
|
this.eventEmitter.addListener('CallKitDidReceivePush', (event) => {
|
|
72
77
|
const normalizedEvent = this.normalizeEvent(event);
|
|
73
78
|
console.log('CallKit: Received push notification event', normalizedEvent);
|
|
@@ -75,9 +80,11 @@ class CallKitManager {
|
|
|
75
80
|
});
|
|
76
81
|
}
|
|
77
82
|
notifyListeners(eventType, event) {
|
|
78
|
-
const
|
|
79
|
-
if (
|
|
80
|
-
listener
|
|
83
|
+
const listeners = this.listeners.get(eventType);
|
|
84
|
+
if (listeners) {
|
|
85
|
+
for (const listener of listeners) {
|
|
86
|
+
listener(event);
|
|
87
|
+
}
|
|
81
88
|
}
|
|
82
89
|
}
|
|
83
90
|
// Public API methods
|
|
@@ -140,6 +147,21 @@ class CallKitManager {
|
|
|
140
147
|
return false;
|
|
141
148
|
}
|
|
142
149
|
}
|
|
150
|
+
async isCallRegistered(callUUID) {
|
|
151
|
+
if (!this.bridge || react_native_1.Platform.OS !== 'ios') {
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
try {
|
|
155
|
+
const result = await this.bridge.isCallRegistered(this.denormalizeUUID(callUUID));
|
|
156
|
+
return result.registered;
|
|
157
|
+
} catch (error) {
|
|
158
|
+
console.error('CallKit: Failed to check incoming call registration', {
|
|
159
|
+
callUUID,
|
|
160
|
+
error,
|
|
161
|
+
});
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
143
165
|
async endCall(callUUID) {
|
|
144
166
|
if (!this.bridge || react_native_1.Platform.OS !== 'ios') {
|
|
145
167
|
console.warn('CallKit: Not available on this platform');
|
|
@@ -157,6 +179,46 @@ class CallKitManager {
|
|
|
157
179
|
return false;
|
|
158
180
|
}
|
|
159
181
|
}
|
|
182
|
+
async completeHeldCallAction(callUUID, success) {
|
|
183
|
+
if (!this.bridge || react_native_1.Platform.OS !== 'ios') {
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
try {
|
|
187
|
+
const uppercaseUUID = this.denormalizeUUID(callUUID);
|
|
188
|
+
const result = await this.bridge.completeHeldCallAction(uppercaseUUID, success);
|
|
189
|
+
return result.success;
|
|
190
|
+
} catch (error) {
|
|
191
|
+
console.error('CallKit: Failed to complete held call action', error);
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
async setCallHeld(callUUID, isOnHold) {
|
|
196
|
+
if (!this.bridge || react_native_1.Platform.OS !== 'ios') {
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
try {
|
|
200
|
+
const result = await this.bridge.setCallHeld(this.denormalizeUUID(callUUID), isOnHold);
|
|
201
|
+
return result.success;
|
|
202
|
+
} catch (error) {
|
|
203
|
+
console.error('CallKit: Failed to change held state', { callUUID, isOnHold, error });
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
async swapCalls(activeCallUUID, heldCallUUID) {
|
|
208
|
+
if (!this.bridge || react_native_1.Platform.OS !== 'ios') {
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
try {
|
|
212
|
+
const result = await this.bridge.swapCalls(
|
|
213
|
+
this.denormalizeUUID(activeCallUUID),
|
|
214
|
+
this.denormalizeUUID(heldCallUUID)
|
|
215
|
+
);
|
|
216
|
+
return result.success;
|
|
217
|
+
} catch (error) {
|
|
218
|
+
console.error('CallKit: Failed to swap calls', error);
|
|
219
|
+
return false;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
160
222
|
async reportCallConnected(callUUID) {
|
|
161
223
|
if (!this.bridge || react_native_1.Platform.OS !== 'ios') {
|
|
162
224
|
return false;
|
|
@@ -220,20 +282,30 @@ class CallKitManager {
|
|
|
220
282
|
}
|
|
221
283
|
// Event listener management
|
|
222
284
|
onStartCall(listener) {
|
|
223
|
-
this.
|
|
224
|
-
return () => this.listeners.delete('startCall');
|
|
285
|
+
return this.addListener('startCall', listener);
|
|
225
286
|
}
|
|
226
287
|
onAnswerCall(listener) {
|
|
227
|
-
this.
|
|
228
|
-
return () => this.listeners.delete('answerCall');
|
|
288
|
+
return this.addListener('answerCall', listener);
|
|
229
289
|
}
|
|
230
290
|
onEndCall(listener) {
|
|
231
|
-
this.
|
|
232
|
-
|
|
291
|
+
return this.addListener('endCall', listener);
|
|
292
|
+
}
|
|
293
|
+
onHeldCall(listener) {
|
|
294
|
+
return this.addListener('heldCall', listener);
|
|
233
295
|
}
|
|
234
296
|
onReceivePush(listener) {
|
|
235
|
-
this.
|
|
236
|
-
|
|
297
|
+
return this.addListener('receivePush', listener);
|
|
298
|
+
}
|
|
299
|
+
addListener(eventType, listener) {
|
|
300
|
+
const listeners = this.listeners.get(eventType) ?? new Set();
|
|
301
|
+
listeners.add(listener);
|
|
302
|
+
this.listeners.set(eventType, listeners);
|
|
303
|
+
return () => {
|
|
304
|
+
listeners.delete(listener);
|
|
305
|
+
if (listeners.size === 0) {
|
|
306
|
+
this.listeners.delete(eventType);
|
|
307
|
+
}
|
|
308
|
+
};
|
|
237
309
|
}
|
|
238
310
|
// Utility methods
|
|
239
311
|
generateCallUUID() {
|
|
@@ -30,8 +30,12 @@ const useAppStateHandler = ({
|
|
|
30
30
|
if (appState.current.match(/active/) && nextAppState === 'background') {
|
|
31
31
|
log('AppStateHandler: App went to background, checking for active calls...');
|
|
32
32
|
const connectionState = voipClient.currentConnectionState;
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
const shouldHandleBackgroundConnection =
|
|
34
|
+
connectionState === connection_state_1.TelnyxConnectionState.CONNECTED ||
|
|
35
|
+
connectionState === connection_state_1.TelnyxConnectionState.CONNECTING ||
|
|
36
|
+
connectionState === connection_state_1.TelnyxConnectionState.RECONNECTING;
|
|
37
|
+
if (!shouldHandleBackgroundConnection) {
|
|
38
|
+
log('AppStateHandler: Not connected or connecting, skipping background handling');
|
|
35
39
|
appState.current = nextAppState;
|
|
36
40
|
return;
|
|
37
41
|
}
|
package/lib/index.d.ts
CHANGED
|
@@ -41,4 +41,5 @@ export {
|
|
|
41
41
|
export type { Config, CredentialConfig, TokenConfig } from './models/config';
|
|
42
42
|
export type { Call as TelnyxCall } from '@telnyx/react-native-voice-sdk';
|
|
43
43
|
export * from './callkit';
|
|
44
|
+
export { VoicePnBridge } from './internal/voice-pn-bridge';
|
|
44
45
|
export { useAppReadyNotifier } from './hooks/useAppReadyNotifier';
|
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', {
|
|
@@ -11,6 +11,9 @@ interface CallKitHandlerProps {
|
|
|
11
11
|
* Internal CallKit handler for iOS push notifications
|
|
12
12
|
* This component is automatically included in TelnyxVoiceApp
|
|
13
13
|
*
|
|
14
|
+
* The active instance removes only its own DeviceEventEmitter subscriptions on
|
|
15
|
+
* unmount via each listener's `.remove()` method.
|
|
16
|
+
*
|
|
14
17
|
* @internal - Users should not use this component directly
|
|
15
18
|
*/
|
|
16
19
|
export declare const CallKitHandler: React.FC<CallKitHandlerProps>;
|
|
@@ -9,19 +9,68 @@ exports.CallKitHandler = void 0;
|
|
|
9
9
|
const react_1 = require('react');
|
|
10
10
|
const react_native_1 = require('react-native');
|
|
11
11
|
const async_storage_1 = __importDefault(require('@react-native-async-storage/async-storage'));
|
|
12
|
-
|
|
13
|
-
// Global flag to ensure only one CallKitHandler is active
|
|
12
|
+
// Global flag to ensure only one CallKitHandler is active.
|
|
14
13
|
let isCallKitHandlerActive = false;
|
|
15
14
|
/**
|
|
16
15
|
* Internal CallKit handler for iOS push notifications
|
|
17
16
|
* This component is automatically included in TelnyxVoiceApp
|
|
18
17
|
*
|
|
18
|
+
* The active instance removes only its own DeviceEventEmitter subscriptions on
|
|
19
|
+
* unmount via each listener's `.remove()` method.
|
|
20
|
+
*
|
|
19
21
|
* @internal - Users should not use this component directly
|
|
20
22
|
*/
|
|
21
23
|
const CallKitHandler = ({ onLoginRequired, onNavigateToDialer, onNavigateBack }) => {
|
|
22
|
-
const { voipClient } = (0, TelnyxVoiceContext_1.useTelnyxVoice)();
|
|
23
24
|
// Store active calls by CallKit UUID for coordination
|
|
24
25
|
const activeCallsRef = (0, react_1.useRef)(new Map());
|
|
26
|
+
// DeviceEventEmitter listeners are registered once below, so read callbacks
|
|
27
|
+
// from refs that are updated during every render rather than stale closures.
|
|
28
|
+
const onLoginRequiredRef = (0, react_1.useRef)(onLoginRequired);
|
|
29
|
+
const onNavigateToDialerRef = (0, react_1.useRef)(onNavigateToDialer);
|
|
30
|
+
const onNavigateBackRef = (0, react_1.useRef)(onNavigateBack);
|
|
31
|
+
onLoginRequiredRef.current = onLoginRequired;
|
|
32
|
+
onNavigateToDialerRef.current = onNavigateToDialer;
|
|
33
|
+
onNavigateBackRef.current = onNavigateBack;
|
|
34
|
+
const handleIncomingCall = async (eventData) => {
|
|
35
|
+
console.log('CallKitHandler: Handling incoming call', {
|
|
36
|
+
callUUID: eventData.callUUID,
|
|
37
|
+
});
|
|
38
|
+
// Store the push notification payload
|
|
39
|
+
await async_storage_1.default.setItem(
|
|
40
|
+
'@push_notification_payload',
|
|
41
|
+
JSON.stringify(eventData.payload)
|
|
42
|
+
);
|
|
43
|
+
// Mark this call as being processed
|
|
44
|
+
activeCallsRef.current.set(eventData.callUUID, {
|
|
45
|
+
processing: true,
|
|
46
|
+
timestamp: Date.now(),
|
|
47
|
+
});
|
|
48
|
+
// Trigger login required callback if provided
|
|
49
|
+
if (onLoginRequiredRef.current) {
|
|
50
|
+
onLoginRequiredRef.current(eventData.payload);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
const handleAnswerCall = async (eventData) => {
|
|
54
|
+
console.log('CallKitHandler: User answered call via CallKit', {
|
|
55
|
+
callUUID: eventData.callUUID,
|
|
56
|
+
isTrackedCall: activeCallsRef.current.has(eventData.callUUID),
|
|
57
|
+
});
|
|
58
|
+
if (onNavigateToDialerRef.current) {
|
|
59
|
+
onNavigateToDialerRef.current();
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
const handleEndCall = async (eventData) => {
|
|
63
|
+
console.log('CallKitHandler: User ended call via CallKit', {
|
|
64
|
+
callUUID: eventData.callUUID,
|
|
65
|
+
isTrackedCall: activeCallsRef.current.has(eventData.callUUID),
|
|
66
|
+
});
|
|
67
|
+
// Clean up our local tracking info
|
|
68
|
+
activeCallsRef.current.delete(eventData.callUUID);
|
|
69
|
+
await async_storage_1.default.removeItem('@push_notification_payload');
|
|
70
|
+
if (onNavigateBackRef.current) {
|
|
71
|
+
onNavigateBackRef.current();
|
|
72
|
+
}
|
|
73
|
+
};
|
|
25
74
|
(0, react_1.useEffect)(() => {
|
|
26
75
|
if (react_native_1.Platform.OS !== 'ios') return;
|
|
27
76
|
if (isCallKitHandlerActive) {
|
|
@@ -30,8 +79,6 @@ const CallKitHandler = ({ onLoginRequired, onNavigateToDialer, onNavigateBack })
|
|
|
30
79
|
}
|
|
31
80
|
isCallKitHandlerActive = true;
|
|
32
81
|
console.log('CallKitHandler: Setting up DeviceEventEmitter listeners (singleton instance)...');
|
|
33
|
-
react_native_1.DeviceEventEmitter.removeAllListeners('incomingVoIPCall');
|
|
34
|
-
react_native_1.DeviceEventEmitter.removeAllListeners('callKitAction');
|
|
35
82
|
const incomingCallListener = react_native_1.DeviceEventEmitter.addListener(
|
|
36
83
|
'incomingVoIPCall',
|
|
37
84
|
async (eventData) => {
|
|
@@ -63,47 +110,6 @@ const CallKitHandler = ({ onLoginRequired, onNavigateToDialer, onNavigateBack })
|
|
|
63
110
|
isCallKitHandlerActive = false;
|
|
64
111
|
};
|
|
65
112
|
}, []);
|
|
66
|
-
const handleIncomingCall = async (eventData) => {
|
|
67
|
-
console.log('CallKitHandler: Handling incoming call', {
|
|
68
|
-
callUUID: eventData.callUUID,
|
|
69
|
-
hasClient: !!voipClient,
|
|
70
|
-
});
|
|
71
|
-
// Store the push notification payload
|
|
72
|
-
await async_storage_1.default.setItem(
|
|
73
|
-
'@push_notification_payload',
|
|
74
|
-
JSON.stringify(eventData.payload)
|
|
75
|
-
);
|
|
76
|
-
// Mark this call as being processed
|
|
77
|
-
activeCallsRef.current.set(eventData.callUUID, {
|
|
78
|
-
processing: true,
|
|
79
|
-
timestamp: Date.now(),
|
|
80
|
-
});
|
|
81
|
-
// Trigger login required callback if provided
|
|
82
|
-
if (onLoginRequired) {
|
|
83
|
-
onLoginRequired(eventData.payload);
|
|
84
|
-
}
|
|
85
|
-
};
|
|
86
|
-
const handleAnswerCall = async (eventData) => {
|
|
87
|
-
console.log('CallKitHandler: User answered call via CallKit', {
|
|
88
|
-
callUUID: eventData.callUUID,
|
|
89
|
-
isTrackedCall: activeCallsRef.current.has(eventData.callUUID),
|
|
90
|
-
});
|
|
91
|
-
if (onNavigateToDialer) {
|
|
92
|
-
onNavigateToDialer();
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
|
-
const handleEndCall = async (eventData) => {
|
|
96
|
-
console.log('CallKitHandler: User ended call via CallKit', {
|
|
97
|
-
callUUID: eventData.callUUID,
|
|
98
|
-
isTrackedCall: activeCallsRef.current.has(eventData.callUUID),
|
|
99
|
-
});
|
|
100
|
-
// Clean up our local tracking info
|
|
101
|
-
activeCallsRef.current.delete(eventData.callUUID);
|
|
102
|
-
await async_storage_1.default.removeItem('@push_notification_payload');
|
|
103
|
-
if (onNavigateBack) {
|
|
104
|
-
onNavigateBack();
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
113
|
// This component doesn't render anything, it just handles events
|
|
108
114
|
return null;
|
|
109
115
|
};
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { Observable } from 'rxjs';
|
|
2
2
|
import { Call } from '../../models/call';
|
|
3
3
|
import { SessionManager } from '../session/session-manager';
|
|
4
|
+
export type CustomHeader = {
|
|
5
|
+
name: string;
|
|
6
|
+
value: string;
|
|
7
|
+
};
|
|
8
|
+
export type CustomHeaders = Record<string, string> | CustomHeader[];
|
|
4
9
|
/**
|
|
5
10
|
* Central state machine for call management.
|
|
6
11
|
*
|
|
@@ -12,8 +17,10 @@ export declare class CallStateController {
|
|
|
12
17
|
private readonly _calls;
|
|
13
18
|
private readonly _callMap;
|
|
14
19
|
private _disposed;
|
|
20
|
+
private _listenerClient?;
|
|
15
21
|
private _isWaitingForInvite?;
|
|
16
22
|
private _onInviteAutoAccepted?;
|
|
23
|
+
private _activeCallId;
|
|
17
24
|
constructor(_sessionManager: SessionManager);
|
|
18
25
|
/**
|
|
19
26
|
* Observable stream of all current calls
|
|
@@ -45,11 +52,33 @@ export declare class CallStateController {
|
|
|
45
52
|
* @param callId The ID of the call to set to connecting state
|
|
46
53
|
*/
|
|
47
54
|
setCallConnecting(callId: string): void;
|
|
55
|
+
/**
|
|
56
|
+
* Explicitly set the active call for multi-call scenarios.
|
|
57
|
+
* When set, activeCall$ and currentActiveCall prefer this call over
|
|
58
|
+
* the first-match heuristic. The ID is cleared automatically when the
|
|
59
|
+
* call reaches a terminal state.
|
|
60
|
+
* @param callId The ID of the call to mark as active
|
|
61
|
+
*/
|
|
62
|
+
setActiveCall(callId: string): void;
|
|
63
|
+
/**
|
|
64
|
+
* Clear the explicitly-tracked active call ID, reverting to the
|
|
65
|
+
* first-match heuristic for active call selection.
|
|
66
|
+
*/
|
|
67
|
+
clearActiveCall(): void;
|
|
48
68
|
/**
|
|
49
69
|
* Find a call by its underlying Telnyx call ID
|
|
50
70
|
* @param telnyxCall The Telnyx call object to find
|
|
51
71
|
*/
|
|
52
72
|
findCallByTelnyxCall(telnyxCall: any): Call | null;
|
|
73
|
+
/**
|
|
74
|
+
* Select the active call, preferring the explicitly-tracked call ID
|
|
75
|
+
* over the first-match heuristic.
|
|
76
|
+
*/
|
|
77
|
+
private _selectActiveCall;
|
|
78
|
+
/**
|
|
79
|
+
* Check if a call is in a non-terminal (active or connecting) state.
|
|
80
|
+
*/
|
|
81
|
+
private _isNonTerminal;
|
|
53
82
|
/**
|
|
54
83
|
* Initialize client listeners when the Telnyx client becomes available
|
|
55
84
|
* This should be called by the session manager after client creation
|
|
@@ -62,8 +91,12 @@ export declare class CallStateController {
|
|
|
62
91
|
destination: string,
|
|
63
92
|
callerName?: string,
|
|
64
93
|
callerNumber?: string,
|
|
65
|
-
customHeaders?:
|
|
94
|
+
customHeaders?: CustomHeaders
|
|
66
95
|
): Promise<Call>;
|
|
96
|
+
/**
|
|
97
|
+
* Normalize public custom headers into the format expected by the underlying SDK.
|
|
98
|
+
*/
|
|
99
|
+
private _normalizeCustomHeaders;
|
|
67
100
|
/**
|
|
68
101
|
* Set callbacks for waiting for invite logic (used for push notifications)
|
|
69
102
|
*/
|
|
@@ -86,6 +119,11 @@ export declare class CallStateController {
|
|
|
86
119
|
* Set up event listeners for the Telnyx client
|
|
87
120
|
*/
|
|
88
121
|
private _setupClientListeners;
|
|
122
|
+
private _removeClientListeners;
|
|
123
|
+
private _handleTelnyxIncomingCall;
|
|
124
|
+
private _handleTelnyxReattachedCall;
|
|
125
|
+
private _handleTelnyxCallStateChanged;
|
|
126
|
+
private _handleTelnyxCallRemoved;
|
|
89
127
|
/**
|
|
90
128
|
* Handle incoming call or reattached call
|
|
91
129
|
*/
|