@zyratalk1/zyra-twilio-wrapper 1.2.0 → 1.2.1
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/.eslint.json +15 -0
- package/dist/index.d.mts +4 -24
- package/dist/index.d.ts +4 -24
- package/dist/index.js +113 -66
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +113 -66
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/types/interface.ts +1 -0
package/.eslint.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"env": {
|
|
3
|
+
"node": true,
|
|
4
|
+
"es2021": true
|
|
5
|
+
},
|
|
6
|
+
"extends": "eslint:recommended",
|
|
7
|
+
"parserOptions": {
|
|
8
|
+
"ecmaVersion": "latest",
|
|
9
|
+
"sourceType": "commonjs"
|
|
10
|
+
},
|
|
11
|
+
"rules": {
|
|
12
|
+
"semi": ["error", "always"],
|
|
13
|
+
"quotes": ["error", "double"]
|
|
14
|
+
}
|
|
15
|
+
}
|
package/dist/index.d.mts
CHANGED
|
@@ -4,6 +4,7 @@ interface Config {
|
|
|
4
4
|
waitUrl?: string;
|
|
5
5
|
sdkToken: string;
|
|
6
6
|
accessToken?: string;
|
|
7
|
+
enableAndroidVoiceRegister?: boolean;
|
|
7
8
|
requestTimeoutMs?: number;
|
|
8
9
|
retry?: {
|
|
9
10
|
maxRetries?: number;
|
|
@@ -287,14 +288,6 @@ interface NativeModule {
|
|
|
287
288
|
};
|
|
288
289
|
}
|
|
289
290
|
type SDKEventName = "onReady" | "onCallRinging" | "onCallConnected" | "onParticipantJoined" | "onParticipantLeft" | "onCallEnded" | "onCallStateChanged" | "onAuthStateChanged" | "onMissedCall" | "onError";
|
|
290
|
-
/**
|
|
291
|
-
* Options for {@link ReactNativeVoipSdk.makeCall}.
|
|
292
|
-
* - `parallel`: start a second Twilio `voice.connect` leg while another call is active (independent lifecycle).
|
|
293
|
-
* - Omitted / false: if a call is already active, add a conference participant via `addNewCallee` (existing behavior).
|
|
294
|
-
*/
|
|
295
|
-
interface MakeCallOptions {
|
|
296
|
-
parallel?: boolean;
|
|
297
|
-
}
|
|
298
291
|
|
|
299
292
|
type EventPayload = Record<string, unknown>;
|
|
300
293
|
type Listener = (payload: EventPayload) => void;
|
|
@@ -327,9 +320,6 @@ declare class ReactNativeVoipSdk {
|
|
|
327
320
|
private readonly configService;
|
|
328
321
|
private initialized;
|
|
329
322
|
protected activeCallId: string | null;
|
|
330
|
-
/** Tracks every in-flight call leg (parallel or single); kept in sync with native `onCallEnded`. */
|
|
331
|
-
protected activeCallIds: Set<string>;
|
|
332
|
-
private unsubscribeOnCallEnded;
|
|
333
323
|
protected internalConferenceName: string;
|
|
334
324
|
constructor(config: Config, nativeModule?: NativeModule);
|
|
335
325
|
on(eventName: SDKEventName | string, listener: (payload: Record<string, unknown>) => void): () => void;
|
|
@@ -345,23 +335,14 @@ declare class ReactNativeVoipSdk {
|
|
|
345
335
|
disconnectParticipant(participantId: string): Promise<void>;
|
|
346
336
|
init(): Promise<void>;
|
|
347
337
|
verifySDKToken(): Promise<boolean>;
|
|
348
|
-
|
|
349
|
-
* Start a call or add to a conference.
|
|
350
|
-
* Use `makeCall(to, { parallel: true })` (or `addCall(to)`) while a call is active to open a second
|
|
351
|
-
* independent leg; failures on that leg are isolated to its `callId` in `onError` / `onCallEnded`.
|
|
352
|
-
*/
|
|
353
|
-
makeCall(to: string, options?: MakeCallOptions): Promise<CallResponse<CallSession>>;
|
|
354
|
-
/** Start a parallel outbound call while another call is active (alias for `makeCall(to, { parallel: true })`). */
|
|
355
|
-
addCall(to: string): Promise<CallResponse<CallSession>>;
|
|
356
|
-
/** All active call legs (parallel-aware). */
|
|
357
|
-
getActiveCallIds(): string[];
|
|
338
|
+
makeCall(to: string): Promise<CallResponse<CallSession>>;
|
|
358
339
|
acceptCall(callId?: string): Promise<CallResponse<null>>;
|
|
359
340
|
rejectCall(callId: string): Promise<CallResponse<null>>;
|
|
360
341
|
hangup(callId?: string): Promise<CallResponse<null>>;
|
|
361
342
|
hold(callId: string): Promise<CallResponse<null>>;
|
|
362
343
|
resume(callId: string): Promise<CallResponse<null>>;
|
|
363
344
|
merge(callId: string): Promise<CallResponse<CallSession>>;
|
|
364
|
-
toggleMute(mute: boolean
|
|
345
|
+
toggleMute(mute: boolean): Promise<CallResponse<null>>;
|
|
365
346
|
makeCallIncoming(to: string, callSid: string): Promise<CallResponse<CallSession>>;
|
|
366
347
|
holdAndAddParticipant(callSid: string, number: string): Promise<CallResponse<unknown>>;
|
|
367
348
|
holdAndAddParticipantIncoming(callSid: string, number: string): Promise<CallResponse<unknown>>;
|
|
@@ -380,7 +361,6 @@ declare class ReactNativeVoipSdk {
|
|
|
380
361
|
isWebhookConfigured(): Promise<CallResponse<WebhookConfigResult>>;
|
|
381
362
|
welcomeMessageConfig(welcomeType: "audio" | "tts", welcomeMessage: string): Promise<CallResponse<WelcomeConfigResult>>;
|
|
382
363
|
destroy(): void;
|
|
383
|
-
private pickNextActiveCallId;
|
|
384
364
|
private ensureAuthenticated;
|
|
385
365
|
}
|
|
386
366
|
|
|
@@ -404,4 +384,4 @@ declare class ZyraTwilioWrapper extends ReactNativeVoipSdk {
|
|
|
404
384
|
destroy(): void;
|
|
405
385
|
}
|
|
406
386
|
|
|
407
|
-
export { type AuthPayload, type CallSession, type ConsumerAuth, type
|
|
387
|
+
export { type AuthPayload, type CallSession, type ConsumerAuth, type NativeModule, type Participant, ReactNativeVoipSdk, type SDKConfig, type SDKEventName, ZyraTwilioWrapper as default };
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ interface Config {
|
|
|
4
4
|
waitUrl?: string;
|
|
5
5
|
sdkToken: string;
|
|
6
6
|
accessToken?: string;
|
|
7
|
+
enableAndroidVoiceRegister?: boolean;
|
|
7
8
|
requestTimeoutMs?: number;
|
|
8
9
|
retry?: {
|
|
9
10
|
maxRetries?: number;
|
|
@@ -287,14 +288,6 @@ interface NativeModule {
|
|
|
287
288
|
};
|
|
288
289
|
}
|
|
289
290
|
type SDKEventName = "onReady" | "onCallRinging" | "onCallConnected" | "onParticipantJoined" | "onParticipantLeft" | "onCallEnded" | "onCallStateChanged" | "onAuthStateChanged" | "onMissedCall" | "onError";
|
|
290
|
-
/**
|
|
291
|
-
* Options for {@link ReactNativeVoipSdk.makeCall}.
|
|
292
|
-
* - `parallel`: start a second Twilio `voice.connect` leg while another call is active (independent lifecycle).
|
|
293
|
-
* - Omitted / false: if a call is already active, add a conference participant via `addNewCallee` (existing behavior).
|
|
294
|
-
*/
|
|
295
|
-
interface MakeCallOptions {
|
|
296
|
-
parallel?: boolean;
|
|
297
|
-
}
|
|
298
291
|
|
|
299
292
|
type EventPayload = Record<string, unknown>;
|
|
300
293
|
type Listener = (payload: EventPayload) => void;
|
|
@@ -327,9 +320,6 @@ declare class ReactNativeVoipSdk {
|
|
|
327
320
|
private readonly configService;
|
|
328
321
|
private initialized;
|
|
329
322
|
protected activeCallId: string | null;
|
|
330
|
-
/** Tracks every in-flight call leg (parallel or single); kept in sync with native `onCallEnded`. */
|
|
331
|
-
protected activeCallIds: Set<string>;
|
|
332
|
-
private unsubscribeOnCallEnded;
|
|
333
323
|
protected internalConferenceName: string;
|
|
334
324
|
constructor(config: Config, nativeModule?: NativeModule);
|
|
335
325
|
on(eventName: SDKEventName | string, listener: (payload: Record<string, unknown>) => void): () => void;
|
|
@@ -345,23 +335,14 @@ declare class ReactNativeVoipSdk {
|
|
|
345
335
|
disconnectParticipant(participantId: string): Promise<void>;
|
|
346
336
|
init(): Promise<void>;
|
|
347
337
|
verifySDKToken(): Promise<boolean>;
|
|
348
|
-
|
|
349
|
-
* Start a call or add to a conference.
|
|
350
|
-
* Use `makeCall(to, { parallel: true })` (or `addCall(to)`) while a call is active to open a second
|
|
351
|
-
* independent leg; failures on that leg are isolated to its `callId` in `onError` / `onCallEnded`.
|
|
352
|
-
*/
|
|
353
|
-
makeCall(to: string, options?: MakeCallOptions): Promise<CallResponse<CallSession>>;
|
|
354
|
-
/** Start a parallel outbound call while another call is active (alias for `makeCall(to, { parallel: true })`). */
|
|
355
|
-
addCall(to: string): Promise<CallResponse<CallSession>>;
|
|
356
|
-
/** All active call legs (parallel-aware). */
|
|
357
|
-
getActiveCallIds(): string[];
|
|
338
|
+
makeCall(to: string): Promise<CallResponse<CallSession>>;
|
|
358
339
|
acceptCall(callId?: string): Promise<CallResponse<null>>;
|
|
359
340
|
rejectCall(callId: string): Promise<CallResponse<null>>;
|
|
360
341
|
hangup(callId?: string): Promise<CallResponse<null>>;
|
|
361
342
|
hold(callId: string): Promise<CallResponse<null>>;
|
|
362
343
|
resume(callId: string): Promise<CallResponse<null>>;
|
|
363
344
|
merge(callId: string): Promise<CallResponse<CallSession>>;
|
|
364
|
-
toggleMute(mute: boolean
|
|
345
|
+
toggleMute(mute: boolean): Promise<CallResponse<null>>;
|
|
365
346
|
makeCallIncoming(to: string, callSid: string): Promise<CallResponse<CallSession>>;
|
|
366
347
|
holdAndAddParticipant(callSid: string, number: string): Promise<CallResponse<unknown>>;
|
|
367
348
|
holdAndAddParticipantIncoming(callSid: string, number: string): Promise<CallResponse<unknown>>;
|
|
@@ -380,7 +361,6 @@ declare class ReactNativeVoipSdk {
|
|
|
380
361
|
isWebhookConfigured(): Promise<CallResponse<WebhookConfigResult>>;
|
|
381
362
|
welcomeMessageConfig(welcomeType: "audio" | "tts", welcomeMessage: string): Promise<CallResponse<WelcomeConfigResult>>;
|
|
382
363
|
destroy(): void;
|
|
383
|
-
private pickNextActiveCallId;
|
|
384
364
|
private ensureAuthenticated;
|
|
385
365
|
}
|
|
386
366
|
|
|
@@ -404,4 +384,4 @@ declare class ZyraTwilioWrapper extends ReactNativeVoipSdk {
|
|
|
404
384
|
destroy(): void;
|
|
405
385
|
}
|
|
406
386
|
|
|
407
|
-
export { type AuthPayload, type CallSession, type ConsumerAuth, type
|
|
387
|
+
export { type AuthPayload, type CallSession, type ConsumerAuth, type NativeModule, type Participant, ReactNativeVoipSdk, type SDKConfig, type SDKEventName, ZyraTwilioWrapper as default };
|
package/dist/index.js
CHANGED
|
@@ -209,15 +209,14 @@ var TwilioVoiceAdapter = class {
|
|
|
209
209
|
error: "Twilio access token missing. Pass accessToken in constructor or authenticate({ accessToken })."
|
|
210
210
|
};
|
|
211
211
|
}
|
|
212
|
-
const conferenceName = `conf_${this.sdkConfig.consumerId}_${input.callId}`;
|
|
213
212
|
console.log("[VOIP SDK] voice.connect() params", {
|
|
214
213
|
To: input.number,
|
|
215
|
-
conferenceName
|
|
214
|
+
conferenceName: this.defaultConferenceName
|
|
216
215
|
});
|
|
217
216
|
const call = await this.voice.connect(token, {
|
|
218
217
|
params: {
|
|
219
218
|
To: input.number,
|
|
220
|
-
conferenceName
|
|
219
|
+
conferenceName: this.defaultConferenceName
|
|
221
220
|
}
|
|
222
221
|
});
|
|
223
222
|
const callSid = this.readCallSid(call);
|
|
@@ -226,7 +225,7 @@ var TwilioVoiceAdapter = class {
|
|
|
226
225
|
callSid,
|
|
227
226
|
call,
|
|
228
227
|
direction: "OUTBOUND",
|
|
229
|
-
conferenceName,
|
|
228
|
+
conferenceName: this.defaultConferenceName,
|
|
230
229
|
conferenceDetail: null
|
|
231
230
|
};
|
|
232
231
|
this.calls.set(input.callId, tracked);
|
|
@@ -268,10 +267,26 @@ var TwilioVoiceAdapter = class {
|
|
|
268
267
|
};
|
|
269
268
|
}
|
|
270
269
|
}
|
|
270
|
+
async waitForInvite(callId, timeoutMs = 8e3) {
|
|
271
|
+
const existing = this.callInvites.get(callId);
|
|
272
|
+
if (existing) return existing;
|
|
273
|
+
console.log("[VOIP DEBUG] waitForInvite polling\u2026", { callId, timeoutMs });
|
|
274
|
+
const start = Date.now();
|
|
275
|
+
while (Date.now() - start < timeoutMs) {
|
|
276
|
+
await new Promise((r) => setTimeout(r, 300));
|
|
277
|
+
const inv = this.callInvites.get(callId);
|
|
278
|
+
if (inv) {
|
|
279
|
+
console.log("[VOIP DEBUG] waitForInvite found invite", { callId, elapsed: Date.now() - start });
|
|
280
|
+
return inv;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
console.warn("[VOIP DEBUG] waitForInvite timed out", { callId });
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
271
286
|
async answerCall(input) {
|
|
272
287
|
console.log("[VOIP DEBUG] call accepted flow start", { callId: input.callId });
|
|
273
288
|
try {
|
|
274
|
-
const invite = this.
|
|
289
|
+
const invite = await this.waitForInvite(input.callId);
|
|
275
290
|
if (!invite) {
|
|
276
291
|
return { success: false, error: "Incoming call invite not found" };
|
|
277
292
|
}
|
|
@@ -1177,6 +1192,54 @@ async function setRoutingConfig(deps, input) {
|
|
|
1177
1192
|
}
|
|
1178
1193
|
}
|
|
1179
1194
|
|
|
1195
|
+
// src/twilioConfig.ts
|
|
1196
|
+
async function setTwilioVoiceConfig(deps) {
|
|
1197
|
+
try {
|
|
1198
|
+
const res = await deps.axiosInstance.post(
|
|
1199
|
+
`${deps.serverUrl}/voipSdk.setTwilioVoiceConfig`,
|
|
1200
|
+
{},
|
|
1201
|
+
{
|
|
1202
|
+
headers: {
|
|
1203
|
+
Authorization: `Bearer ${deps.sdkToken}`
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
);
|
|
1207
|
+
const result = res?.data?.result ?? res?.data;
|
|
1208
|
+
return createSuccessResult(
|
|
1209
|
+
result?.message || "Twilio voice config updated",
|
|
1210
|
+
result
|
|
1211
|
+
);
|
|
1212
|
+
} catch (error) {
|
|
1213
|
+
return createErrorResult(
|
|
1214
|
+
error instanceof Error ? error : "Failed to set Twilio voice config"
|
|
1215
|
+
);
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
async function getVoipProviderConfigStatus(deps) {
|
|
1219
|
+
try {
|
|
1220
|
+
const res = await deps.axiosInstance.post(
|
|
1221
|
+
`${deps.serverUrl}/voipSdk.getVoipProviderConfigStatus`,
|
|
1222
|
+
{},
|
|
1223
|
+
{
|
|
1224
|
+
headers: {
|
|
1225
|
+
Authorization: `Bearer ${deps.sdkToken}`
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
);
|
|
1229
|
+
const data = res?.data?.result ?? res?.data;
|
|
1230
|
+
const raw = data?.data?.isConfiguredVoipProvider;
|
|
1231
|
+
const isConfiguredVoipProvider = raw === true || raw === 1 || raw === "1";
|
|
1232
|
+
return createSuccessResult(
|
|
1233
|
+
"VoIP provider config status fetched",
|
|
1234
|
+
{ isConfiguredVoipProvider }
|
|
1235
|
+
);
|
|
1236
|
+
} catch (error) {
|
|
1237
|
+
return createErrorResult(
|
|
1238
|
+
error instanceof Error ? error : "Failed to fetch VoIP provider config status"
|
|
1239
|
+
);
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1180
1243
|
// src/webhook.ts
|
|
1181
1244
|
function validateWebhookUrl(webhookUrl) {
|
|
1182
1245
|
const trimmed = (webhookUrl ?? "").trim();
|
|
@@ -1348,6 +1411,12 @@ var ConfigService = class {
|
|
|
1348
1411
|
async welcomeMessageConfig(welcomeType, welcomeMessage) {
|
|
1349
1412
|
return welcomeMessageConfig(this.withDeps(), { welcomeType, welcomeMessage });
|
|
1350
1413
|
}
|
|
1414
|
+
async getVoipProviderConfigStatus() {
|
|
1415
|
+
return getVoipProviderConfigStatus(this.withDeps());
|
|
1416
|
+
}
|
|
1417
|
+
async setTwilioVoiceConfig() {
|
|
1418
|
+
return setTwilioVoiceConfig(this.withDeps());
|
|
1419
|
+
}
|
|
1351
1420
|
withDeps() {
|
|
1352
1421
|
return {
|
|
1353
1422
|
axiosInstance: this.axiosInstance,
|
|
@@ -1505,9 +1574,6 @@ var ReactNativeVoipSdk = class {
|
|
|
1505
1574
|
constructor(config, nativeModule) {
|
|
1506
1575
|
this.initialized = false;
|
|
1507
1576
|
this.activeCallId = null;
|
|
1508
|
-
/** Tracks every in-flight call leg (parallel or single); kept in sync with native `onCallEnded`. */
|
|
1509
|
-
this.activeCallIds = /* @__PURE__ */ new Set();
|
|
1510
|
-
this.unsubscribeOnCallEnded = null;
|
|
1511
1577
|
logVoipDebug("constructor() invoked", {
|
|
1512
1578
|
hasServerUrl: Boolean(config.serverUrl),
|
|
1513
1579
|
hasIdentity: Boolean(config.identity),
|
|
@@ -1521,7 +1587,8 @@ var ReactNativeVoipSdk = class {
|
|
|
1521
1587
|
identity: config.identity,
|
|
1522
1588
|
sdkToken: config.sdkToken,
|
|
1523
1589
|
accessToken: config.accessToken,
|
|
1524
|
-
waitUrl: config.waitUrl
|
|
1590
|
+
waitUrl: config.waitUrl,
|
|
1591
|
+
enableAndroidVoiceRegister: config.enableAndroidVoiceRegister
|
|
1525
1592
|
};
|
|
1526
1593
|
this.bridge = new BridgeClient(nativeModule);
|
|
1527
1594
|
this.retry = new RetryPolicy(config.retry);
|
|
@@ -1551,14 +1618,6 @@ var ReactNativeVoipSdk = class {
|
|
|
1551
1618
|
sdkToken: this.sdkConfig.sdkToken,
|
|
1552
1619
|
ensureAuthenticated: this.ensureAuthenticated.bind(this)
|
|
1553
1620
|
});
|
|
1554
|
-
this.unsubscribeOnCallEnded = this.bridge.on("onCallEnded", (payload) => {
|
|
1555
|
-
const callId = typeof payload.callId === "string" ? payload.callId : null;
|
|
1556
|
-
if (!callId) return;
|
|
1557
|
-
this.activeCallIds.delete(callId);
|
|
1558
|
-
if (this.activeCallId === callId) {
|
|
1559
|
-
this.activeCallId = this.pickNextActiveCallId();
|
|
1560
|
-
}
|
|
1561
|
-
});
|
|
1562
1621
|
}
|
|
1563
1622
|
on(eventName, listener) {
|
|
1564
1623
|
return this.bridge.on(eventName, listener);
|
|
@@ -1566,16 +1625,37 @@ var ReactNativeVoipSdk = class {
|
|
|
1566
1625
|
async initializeSDK(config) {
|
|
1567
1626
|
logVoipDebug("initializeSDK() called");
|
|
1568
1627
|
if (this.initialized) return;
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1628
|
+
try {
|
|
1629
|
+
const configStatus = await this.configService.getVoipProviderConfigStatus();
|
|
1630
|
+
if (!configStatus.success) {
|
|
1631
|
+
throw new Error("Failed to fetch VoIP provider config status");
|
|
1632
|
+
}
|
|
1633
|
+
const isConfigured = configStatus.data?.isConfiguredVoipProvider;
|
|
1634
|
+
logVoipDebug("VoIP config status checked", { isConfigured });
|
|
1635
|
+
if (!isConfigured) {
|
|
1636
|
+
logVoipDebug("VoIP not configured. Setting Twilio config");
|
|
1637
|
+
const setupRes = await this.configService.setTwilioVoiceConfig();
|
|
1638
|
+
if (!setupRes.success) {
|
|
1639
|
+
throw new Error("Failed to set Twilio Voice Config");
|
|
1640
|
+
}
|
|
1641
|
+
logVoipDebug("VoIP configuration completed");
|
|
1642
|
+
}
|
|
1643
|
+
const mergedConfig = { ...this.sdkConfig, ...config };
|
|
1644
|
+
const result = await this.bridge.nativeModule.initializeSDK(mergedConfig);
|
|
1645
|
+
if (!result.success) {
|
|
1646
|
+
logVoipDebug("initializeSDK() failed", {
|
|
1647
|
+
error: result.error ?? "Failed to initialize native VOIP SDK"
|
|
1648
|
+
});
|
|
1649
|
+
throw new Error(result.error ?? "Failed to initialize native VOIP SDK");
|
|
1650
|
+
}
|
|
1651
|
+
this.initialized = true;
|
|
1652
|
+
logVoipDebug("initializeSDK() success");
|
|
1653
|
+
} catch (error) {
|
|
1654
|
+
logVoipDebug("initializeSDK() config check failure", {
|
|
1655
|
+
message: error instanceof Error ? error.message : String(error)
|
|
1574
1656
|
});
|
|
1575
|
-
throw
|
|
1657
|
+
throw error;
|
|
1576
1658
|
}
|
|
1577
|
-
this.initialized = true;
|
|
1578
|
-
logVoipDebug("initializeSDK() success");
|
|
1579
1659
|
}
|
|
1580
1660
|
async authenticate(payload) {
|
|
1581
1661
|
logVoipDebug("authenticate() start", {
|
|
@@ -1593,7 +1673,6 @@ var ReactNativeVoipSdk = class {
|
|
|
1593
1673
|
logVoipDebug("startCall() invoked", { number });
|
|
1594
1674
|
this.ensureAuthenticated();
|
|
1595
1675
|
const session = await this.callEngine.startCall(number);
|
|
1596
|
-
this.activeCallIds.add(session.callId);
|
|
1597
1676
|
this.activeCallId = session.callId;
|
|
1598
1677
|
logVoipDebug("startCall() success", { callId: session.callId });
|
|
1599
1678
|
return session;
|
|
@@ -1606,9 +1685,8 @@ var ReactNativeVoipSdk = class {
|
|
|
1606
1685
|
logVoipDebug("endCall() invoked", { callId });
|
|
1607
1686
|
this.ensureAuthenticated();
|
|
1608
1687
|
await this.callEngine.endCall(callId);
|
|
1609
|
-
this.activeCallIds.delete(callId);
|
|
1610
1688
|
if (this.activeCallId === callId) {
|
|
1611
|
-
this.activeCallId =
|
|
1689
|
+
this.activeCallId = null;
|
|
1612
1690
|
}
|
|
1613
1691
|
logVoipDebug("endCall() success", { callId });
|
|
1614
1692
|
}
|
|
@@ -1644,17 +1722,8 @@ var ReactNativeVoipSdk = class {
|
|
|
1644
1722
|
return false;
|
|
1645
1723
|
}
|
|
1646
1724
|
}
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
* Use `makeCall(to, { parallel: true })` (or `addCall(to)`) while a call is active to open a second
|
|
1650
|
-
* independent leg; failures on that leg are isolated to its `callId` in `onError` / `onCallEnded`.
|
|
1651
|
-
*/
|
|
1652
|
-
async makeCall(to, options) {
|
|
1653
|
-
logVoipDebug("makeCall() start", {
|
|
1654
|
-
to,
|
|
1655
|
-
hasActiveCall: Boolean(this.activeCallId),
|
|
1656
|
-
parallel: Boolean(options?.parallel)
|
|
1657
|
-
});
|
|
1725
|
+
async makeCall(to) {
|
|
1726
|
+
logVoipDebug("makeCall() start", { to, hasActiveCall: Boolean(this.activeCallId) });
|
|
1658
1727
|
try {
|
|
1659
1728
|
const destination = to.trim();
|
|
1660
1729
|
if (!destination) {
|
|
@@ -1665,11 +1734,6 @@ var ReactNativeVoipSdk = class {
|
|
|
1665
1734
|
logVoipDebug("makeCall() new call started", { callId: data.callId });
|
|
1666
1735
|
return createSuccessResult("Call started", data);
|
|
1667
1736
|
}
|
|
1668
|
-
if (options?.parallel) {
|
|
1669
|
-
const data = await this.startCall(destination);
|
|
1670
|
-
logVoipDebug("makeCall() parallel call started", { callId: data.callId });
|
|
1671
|
-
return createSuccessResult("Parallel call started", data);
|
|
1672
|
-
}
|
|
1673
1737
|
if (!this.bridge.nativeModule.addNewCallee) {
|
|
1674
1738
|
return createErrorResult("addNewCallee not supported by native module");
|
|
1675
1739
|
}
|
|
@@ -1701,14 +1765,6 @@ var ReactNativeVoipSdk = class {
|
|
|
1701
1765
|
return createErrorResult(error instanceof Error ? error : "Failed to start call");
|
|
1702
1766
|
}
|
|
1703
1767
|
}
|
|
1704
|
-
/** Start a parallel outbound call while another call is active (alias for `makeCall(to, { parallel: true })`). */
|
|
1705
|
-
async addCall(to) {
|
|
1706
|
-
return this.makeCall(to, { parallel: true });
|
|
1707
|
-
}
|
|
1708
|
-
/** All active call legs (parallel-aware). */
|
|
1709
|
-
getActiveCallIds() {
|
|
1710
|
-
return [...this.activeCallIds];
|
|
1711
|
-
}
|
|
1712
1768
|
async acceptCall(callId) {
|
|
1713
1769
|
try {
|
|
1714
1770
|
const id = callId ?? this.activeCallId;
|
|
@@ -1767,10 +1823,10 @@ var ReactNativeVoipSdk = class {
|
|
|
1767
1823
|
return createErrorResult(error instanceof Error ? error : "Failed to merge call");
|
|
1768
1824
|
}
|
|
1769
1825
|
}
|
|
1770
|
-
async toggleMute(mute
|
|
1771
|
-
|
|
1772
|
-
logVoipDebug("toggleMute() invoked", { mute, callId: id, hasActiveCall: Boolean(this.activeCallId) });
|
|
1826
|
+
async toggleMute(mute) {
|
|
1827
|
+
logVoipDebug("toggleMute() invoked", { mute, hasActiveCall: Boolean(this.activeCallId) });
|
|
1773
1828
|
try {
|
|
1829
|
+
const id = this.activeCallId;
|
|
1774
1830
|
if (!id) return createErrorResult("No active call");
|
|
1775
1831
|
await this.callEngine.toggleMute(id, mute);
|
|
1776
1832
|
return createSuccessResult(`Mute ${mute}`, null);
|
|
@@ -1969,19 +2025,12 @@ var ReactNativeVoipSdk = class {
|
|
|
1969
2025
|
}
|
|
1970
2026
|
destroy() {
|
|
1971
2027
|
logVoipDebug("destroy() invoked");
|
|
1972
|
-
this.unsubscribeOnCallEnded?.();
|
|
1973
|
-
this.unsubscribeOnCallEnded = null;
|
|
1974
2028
|
this.authManager.destroy();
|
|
1975
2029
|
this.bridge.destroy();
|
|
1976
2030
|
this.initialized = false;
|
|
1977
2031
|
this.activeCallId = null;
|
|
1978
|
-
this.activeCallIds.clear();
|
|
1979
2032
|
logVoipDebug("destroy() completed");
|
|
1980
2033
|
}
|
|
1981
|
-
pickNextActiveCallId() {
|
|
1982
|
-
if (this.activeCallIds.size === 0) return null;
|
|
1983
|
-
return this.activeCallIds.values().next().value ?? null;
|
|
1984
|
-
}
|
|
1985
2034
|
ensureAuthenticated() {
|
|
1986
2035
|
if (this.authManager.getState() !== "AUTHENTICATED") {
|
|
1987
2036
|
throw new Error("SDK not authenticated.");
|
|
@@ -2011,10 +2060,8 @@ var ZyraTwilioWrapper = class extends ReactNativeVoipSdk {
|
|
|
2011
2060
|
this.onConnect?.(payload);
|
|
2012
2061
|
});
|
|
2013
2062
|
this.on("onCallEnded", () => {
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
this.onDisconnect?.();
|
|
2017
|
-
}
|
|
2063
|
+
this.activeCallSid = null;
|
|
2064
|
+
this.onDisconnect?.();
|
|
2018
2065
|
});
|
|
2019
2066
|
this.on("onMissedCall", () => {
|
|
2020
2067
|
this.activeCallSid = null;
|