Skip to content

[FEATURE/BUG] Using option "closeProtection" as TRUE when registering Twilio Device, doesn't trigger a warning dialog for incoming calls only for active calls #299

@jhonland

Description

@jhonland

Is your feature request related to a problem? Please describe.
When using the closeProtection option when registering the Twilio Device, the behavior is to prevent the user from dropping the active call. This behavior is backed up by the documentation here Twilio Documentation For DeviceOptions. Ideally, this should also be activated for incoming calls.

Motivations for proposed change
Consider the following scenario:
A user who registers a new Device to listen for incoming calls to provide support for customers opens multiple browser tabs, initializing an instance of Twilio Device per opened tab that listens for incoming calls.
Then an incoming call is received but before the user accepts the call, the user closes by mistake one of the tabs where the Device has an incoming call pending.
At the time of writing, Twilio rejects any incoming calls and disconnects the active call as part of the Device's destroy cycle.
references: code extract

    ...
    const calls = this._calls.slice(0);
    calls.forEach((call: Call) => call.reject());

    this.disconnectAll();
    this._stopRegistrationTimer();
    ...

which is bound to the unload and pagehide events
references: code extract

    if (typeof window !== 'undefined' && window.addEventListener) {
      window.addEventListener('unload', this._boundDestroy);
      window.addEventListener('pagehide', this._boundDestroy);
    }

NOTE: This could probably be considered bad UX but users are users and it's hard to explain that you should only initialize a call support system (registering a Device to listen for calls) on one Tab only 🫠.

Describe the solution you'd like
Going through the Twilio Voice SDK source code, on file twilio-voice.js/blob/master/lib/twilio/device.ts#L886 the code indicates to not show the browser's confirmation dialog only if there is an active call:

private _confirmClose(event: any): string {
    if (!this._activeCall) { return ''; }
    ...

Propose solutions:

  • [SOLUTION 1]: Change the behavior of closeProtection flag to show the confirmation dialog also for incoming calls.
  • [SOLUTION 2]: Add an additional flag, something like closeProtectionIncomingCalls to also apply the behavior for incoming calls.
  • [SOLUTION 3]: Update the closeProtection flag that currently only accepts boolean | string to accept an object with extra parameters to also opt-in for incoming calls.

Example of solution:
NOTE: Currently there is no way to determine if the device has at least 1 incoming call that hasn't been accepted yet, for that METHOD_THAT_CALCS_IF_THERE_IS_AN_INCOMING_CALL assumes that that method exists

private _confirmClose(event: any): string {
    const closeProtection: boolean | string = this._options.closeProtection || false;
    const confirmationMsg: string = typeof closeProtection !== 'string'
      ? 'A call is currently in-progress. Leaving or reloading this page will end the call.'
      : closeProtection;

    if (this._activeCall || this.[METHOD_THAT_CALCS_IF_THERE_IS_AN_INCOMING_CALL]) {
        (event || window.event).returnValue = confirmationMsg;
        return confirmationMsg;
    }
    
    (event || window.event).returnValue = '';
    return '';
}

Example of implementation to know if there is an incoming call (METHOD_THAT_CALCS_IF_THERE_IS_AN_INCOMING_CALL) method:

function deviceHasIncomingCallsPending(): boolean {
    return this._calls.some((call) => call.status() === Call.State.Pending)
}

Describe alternatives you've considered
Implement the same solutions as proposed above from outside the SDK by listening directly to the beforeunload event.

Additional context
Do you need a new Dev? let's schedule an interview 😉.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions