in packages/calling-stateful-client/src/CallAgentDeclarativeCommon.ts [173:256]
protected getCommon<AgentType extends CallAgent | TeamsCallAgent, P extends keyof CallAgent>(
target: AgentType,
prop: P | 'incomingCalls'
): any {
switch (prop) {
case 'startCall': {
return this._context.withErrorTeedToState((...args: Parameters<AgentType['startCall']>): CallCommon => {
const call = this.startCall(target, args);
this.addCall(call);
return this.getOrCreateDeclarativeCall(call);
}, 'CallAgent.startCall');
}
case 'join': {
return this._context.withErrorTeedToState((...args: Parameters<AgentType['join']>): CallCommon => {
const call = this.joinCall(target, args);
this.addCall(call);
return this.getOrCreateDeclarativeCall(call);
}, 'CallAgent.join');
}
case 'calls': {
return Array.from(this._declarativeCalls.values());
}
case 'on': {
return (...args: Parameters<AgentType['on']>): void => {
// typescript is not smart enough to handle multiple overloads and pull the correct type here so force casting args
const event = args[0] as 'incomingCall' | 'callsUpdated' | 'connectionStateChanged';
const isCallsUpdated = event === 'callsUpdated';
if (isCallsUpdated) {
const listener = args[1] as unknown as CollectionUpdatedEvent<CallCommon>;
this._externalCallsUpdatedListeners.add(listener);
} else {
this.agentSubscribe(target, args);
}
};
}
case 'off': {
return (...args: Parameters<AgentType['off']>): void => {
// typescript is not smart enough to handle multiple overloads and pull the correct type here so force casting args
const event = args[0] as 'incomingCall' | 'callsUpdated' | 'connectionStateChanged';
const isCallsUpdated = event === 'callsUpdated';
if (isCallsUpdated) {
const listener = args[1] as unknown as CollectionUpdatedEvent<CallCommon>;
this._externalCallsUpdatedListeners.delete(listener);
} else {
this.agentUnsubscribe(target, args);
}
};
}
case 'dispose': {
/* @conditional-compile-remove(calling-beta-sdk) */
return (): void => {
target.dispose();
this.unsubscribe();
};
// Wrapping CallAgent.dispose in a callback type (): Promise<void> to accomodate the change of CallAgent.dispose
// in calling beta version 1.8.0-beta.1 from callback type (): Promise<void> to (): void
const callAgentDisposeAsyncCallbackWrapper = async (): Promise<void> => {
await target.dispose();
return Promise.resolve();
};
return (): Promise<void> => {
return callAgentDisposeAsyncCallbackWrapper().then(() => {
this.unsubscribe();
});
};
}
/**
* This attribute is a special case and doesn't exist on the CallAgent interface.
* We need this to be able to return a declarative incoming call object using the call agent.
* In a standard headless SDK usage, the right way to get an incoming call is to use the `incomingCall` event.
* However, using the declarative layer, the ideal usage would be to:
* 1. subscribe to the `onStateChange` event
* 2. Get the incoming call from the new state and it's ID
* 3. Use `callAgent.incomingCalls` and filter an incoming call ID to get a declarative incoming call object
*/
case 'incomingCalls': {
return Array.from(this._incomingCalls.values());
}
default:
return Reflect.get(target, prop);
}
}