Bandyer-Chat-Widget

WEB BANDYER SDK

The BandyerSDK is a fast and effective way to offer a live videochat in your web application.

Consuming a library

You can consume the library from NPM:

npm install @bandyer/bandyer-chat-widget

or embed it directly in your HTML getting it from our CDN:

<script src="https://cdn.bandyer.com/sdk/js/chat/X.X.X/bandyer-widget.min.js" type="text/javascript" ></script>

Example embed in HTML page;

<html>
    <head></head>
    <body>
        <script src="https://cdn.bandyer.com/sdk/js/chat/2.8.0/bandyer-widget.min.js" type="text/javascript"></script>
    </body>
</html>

The script attaches in the window object the global variable BandyerSDK from where you can access the library.

Supported browsers

Browser min version Plugin requested
Chrome 72  
Firefox 66  
Safari 12  
Edge new 79  

Versions

The latest version is: 2.8.0 https://cdn.bandyer.com/sdk/js/chat/2.8.0/bandyer-widget.min.js

if you’re upgrading from v1.x.x you can find the migration guide here

For the complete list of versions changes visit: CHANGELOG

Screenshots

Drawing Drawing
Drawing Drawing
Drawing Drawing

BandyerSDK

Methods

Properties

Name Type Description
version string Return the current version of the widget

Configure

.configure(config)

const Client: Client = await BandyerSDK.configure({
    appId: 'client secret',
    region: 'eu or in',
    environment: 'sandbox or production'
});

This method allows the configuration of the BandyerSDK and it returns a Client object that can be used to connect and use the library. Be sure to keep a reference of this object somewhere in your code because it is impossible to retrieve it again due to security constraints.

The configuration of a new BandyerSDK instance is made by calling the BandyerSDK.configure() method. The available options are the following:

Parameters
Parameter Required Default Description
region yes   Region on witch your account belongs. Allowed parameters are eu, in, us or me
environment yes   Allowed values are: sandbox or production
appId yes   A valid appId associated to your account
hidden no false Configure the widget to start in hidden mode (not visible in the HTML)
layout no default layout Specify the custom layout (see more here)
recordingType no ‘none’ Wether the recording is disable (none) or starts automatically at the beginning of a call(automatic) or must be started manually(manual). Allowed values are: none, manual or automatic
isAdmin no false Specify wether the logged user is admin of the calls initiated from the widget. Admin users are able to start/stop the recording when is manual
callType no audio_video Specify the call type. Allowed values are: audio_only, audio_upgradable, audio_video
mode no embed Specify the widget call mode. Allowed values are: embed or window
language no ‘en’ Specify the language of the widget Allowed values are: en, it, es or pt
userDetailsProvider no default user provider Specify the data for each user (see more here)
userDetailsFormatter no default user formatter Specify how user data is formatted in the UI (see more here)
tools no All tools disabled Specify the tools to enable during the call (embed and window mode)(See more here)
virtualBackground no false It allows to publish the local webcam with blurred or the replaced background by default (embed and window mode). Allowed values are: blur or image
feedback no false Specify wether to show the view to leave a feedback at the end of the call
Errors
Name description
client_already_exists A client exists already, you need to destroy the existing client before creating a new one
invalid_config_error One or more parameters have an incorrect type. See the message to know which ones
browser_not_supported The current browser is not supported, please check the compatibility table

Call type options:

Mode options:

Hidden options

The widget remains not visible until it receives the following events:

  1. addChat event
  2. incoming call event

Tools option

By default, if no tools are provided (missing field), all the tools are disabled.

List of available tools

Name Mode Description
chat Window & Embed Specify wether to initialize the chat module or not
screen_sharing Window & Embed Enable the screen_sharing feature
file_upload Window & Embed Enable the capability to send file
whiteboard Window If true enable all the whiteboard tools. Can be an object of whiteboard tools
snapshot Window Enable the snapshot feature
live_edit Window Enable the live_edit feature
live_pointer Window Enable to send pointer-events to others participants (always active in reception)

The whiteboard(WB), snapshot(SN) and live_edit(LE) tools are strictly correlated, so use it accordingly as follows:

Combination Receive live_edit Collaborate Snapshot & Gallery Open whiteboard
SN+ LE + WB
SN
SN + WB (default LE active in reception)
WB (default LE active in reception)
NONE

Whiteboard tools

{
    "tools": {
        "whiteboard": {
            "wb_add_file": true,
            "wb_cursor": true,
            "wb_text": true,
            "wb_shape": true,
            "wb_pen": true,
            "wb_eraser": true
        }
    }
}

The whiteboard tools object is included in the tools parameter

Name Description
wb_add_file Allows to add files on the whiteboard
wb_cursor Allows to send the cursor events to the other participants
wb_text Allows to add text on the whiteboard
wb_shape Allows to add shape on the whiteboard
wb_pen Allows to using the pen on the whiteboard
wb_eraser Allows to erase a previous draw on the whiteboard

Custom layout

The widget has custom configurable layout to give the opportunity to match the look and feel you prefer. The layout option is composed by a list of other keys. The table above is the list of the available options:

Key Options Description
header background, color Specify the background and color of the header
headerButton background, color Specify the background and color of the header buttons
body background, color Specify the background and color of the body
launcher background Specify the background of the launcher
messageSent background, color Specify the background and color of the messages you sent
messageReceived background, color Specify the background and color messages you received
dial background, color Specify the background and color of the dial view
call background, color Specify the background and color of the call view
feedback body: {background, color}, buttons: {background, color} Specify the theme for the feedback view
fontFamily font Family Font family of the entire widget

Here an example:

BandyerSDK.configure({
    region: 'eu',
    appId: 'wAppId_fake123456',
    environment: 'sandbox',
    layout: {
        body: { background: '#0069B4', color: '#000' },
        dial: { background: '#003762', color: '#fff' },
        call: { background: '#003762', color: '#fff' },
        messageSent: { background: '#003762', color: '#fff' },
        launcher: { background: '#0069B4' },
        header: { background: '#003762', color: '#fff' },
        headerButton: { background: '#0069B4', color: '#fff' },
        feedback: { body: { background: '#0069B4', color: '#fff' }, buttons: { background: '#0069B4', color: '#fff' } },
        fontFamily: '"Segoe UI","Segoe",Tahoma,Helvetica,Arial,sans-serif'
    }
});

User details provider

Since Kaleyra Video solution treats users of a company referring to them only via anonymous identifiers, in order to display users details on sdk integrations (chat widget, Android and iOS SDks) and call links each platform expose a set of client api to customize the user information (display name and avatar).

In order to obtain user display name and image customization on the client call and chat UIs, has now been released a new convenient and centralized way to achieve the same result. We refer to this newly released API as Server side User Details Provider.

Server side User Details Provider

In order to enable this functionality you must specify a valid user_details_provider_url through the company update rest API.

The provider url, if defined, will be used as an endpoint to request the details of the users through a http post request whenever a client needs to display some user details.

As mentioned above, the best use case scenario for the Server side User Details Provider implementation is represented by those integrations that rely on a heterogeneous usage of client sdks (e.g. mobile sdks alongside chat widget implementation) and call links. Using the Server side User Details Provider will result in a more concise (and less error-prone too) way to display users information. Furthermore, it’s not will be necessary to implement the Client side user Details Provider APIs for the client SDKs.

Despite what has been mentioned, the Client side user Details Provider will be maintained for those integrations that cannot rely on webhook implementations.

More details about the REST integration of the Server side user Details Provider can be found here.

Client side user Details Provider

The BandyerSDK exposes the Client side user Details Provider API as a custom configurable function that allows customizing the users’ information, which later will be displayed in the UI. The userDetailsProvider is optional, but if defined must be a function.

This function takes an array of String (userId) as the only input parameter and must return a Promise that contains an Array of objects, one object for each userId provided as input.

Beware Client side user details Provider has a higher priority over the server side one, so be careful in implementing both the solutions.

Beware of Performance, the userDetailsProvider function is called and waited internally for up to 1200 ms, otherwise it uses the default provider logic. For this reason your logic will be applied only if it is faster than 1200 ms.

Every single object representing a user and must contain a userId key(otherwise the object will be ignored) and optionally other keys that can be used to define the logic used in your custom userDetailFormatter.

Here an example:

yourProviderFunction = function(usersIds) {
    const userObjPromises = [];
    usersIds.forEach(userId => {
        // Your logic here
        const user = yourAsyncFetchFunction(userId);
        // Example of yourAsyncFetchFunction promise return
        /* {
        userId: userId,
        firstName: myFirstName,
        lastName: myLastName,
        image: myImage
    }; */
        usersObjPromises.push(user);
    });
    return Promise.all(userObjPromises);
};

BandyerSDK.configure({
    region: 'eu',
    appId: 'wAppId_fake123456',
    environment: 'sandbox',
    userDetailsProvider: yourProviderFunction
});

N.B define a userDetailsProvider without the relative userDetailsFormatter is useless since the displayed result will be the server side information or the userId as it is the default logic of userDetailsFormatter.

Client side user details formatter

The local user details formatter API, if defined is a function that allows to use the information obtained from Client side user Details Provider in order to obtain a displayName to use in the different UIs

The userDetailsFormatter is optional, but if defined, it must be a function.

This function takes as input parameter an Object that represents one user and must return a String that represents how the user identity must be displayed in the UI.

If the return value is not a String or the logic fails, the displayed information will be the remote (if provided) or the userId.

Here an example:

yourFormatterFunction = function(user) {
    /*
    user = {
        userId: userId
        customParam1: the parameter provided in the providerFunction
        customParam2:  another parameter provided in the providerFunction
        displayName: optional parameter if you have defined a provider url for you company 
        }
     */
    return user.customParam1 + ' ' + user.customParam2;
};

BandyerSDK.configure({
    region: 'eu',
    appId: 'wAppId_fake123456',
    environment: 'sandbox',
    userDetailsFormatter: yourFormatterFunction
});

destroyClient

.destroyClient()

await BandyerSDK.destroyClient();

Allows to de-initialize the BandyerSDK, this operation destroys the client reference after which you are able to configure a new Client.

Client type

Methods

Properties

Name Type Description
channelsView channelView Retrieve the list of channel view
callView CallView Retrieve the current callView
region string Retrieve the region value forwarded in the configuration step
environment string Retrieve the environment value forwarded in the configuration step
appId string Retrieve the appId value forwarded in the configuration step
userId string Retrieve the userId value forwarded in the configuration step

Events

Name Description
client:access_token:expired The session expired, for some reason the update token process is failed, you need to re-connect the Client with a new access token
client:access_token:about_to_expire The session is about to expire, you need to provide a valid accesstoken through the updateAccessToken api
client:force_disconnect The user was disabled or deleted via REST api
channel:message:sent When a message was sent in a channel
channel:message:received When a message was received in a channel
channel:added When a channel was added using client api or rest
channel:removed When a channel was removed using client api or rest
call:incoming When there is an incoming call
call:status:changed Triggered when the call change the status. See call status
user:status:changed Triggered when a user change the status(online / offline)

Client life cycle

To connect the Client object you need a valid accessToken, you can obtain a valid access token via rest API

If you want to have a persisted user connected across the calls you need to obtain a valid accessToken token via rest API

In order to maintain the connected state you need to bind two events to the Client object(obtained with Configure):

//configuration step

// access token request

Client.on('client:access_token:is_about_to_expire', async data => {
    // data: {expiresAt: "2022-01-10T11:41:19.000Z"'}
    const accessToken = await yourAsyncFunction(); // async function that allow you to ask a new accessToken to the server
    // Provide the obtained accessToken to the sdk
    const { expiresAt } = await Client.updateAccessToken(accessToken); // return the new expiration date
});
Client.on('client:access_token:expired', async () => {
    // the session expired, for some reason the update token process is failed, you need to re-connect the Client with a new access token
    await Client.disconnect();
    // retrieve a new accessToken
    await Client.connect(userId, accessToken);
});

Client.on('client:force_disconnect', () => {
    // the user was disabled or deleted from a rest api
});
try {
    await Client.connect(userId, accessToken);
} catch (e) {
    console.error('Fail to connect the client', error);
}

Otherwise, you can use a classic call link obtained from the create call rest API

In that case the lifecycle is strictly related to the call, once the call finish the user is automatically disconnected.

try {
    const accessLink = 'https://sandbox.bandyer.com/eu/direct-rest-call-handler/adufj5769cnapmce';
    // remember that the link must match the region and the environment forwarded in the configuration phase
    await Client.joinCallUrl(accessLink);
} catch (e) {
    console.error('Fail to connect the client', error);
}

There is no need to manage and handle the access Token.

Following there are the two method for the connection

Connect

To connect the Client object you need a valid accessToken, you can obtain a valid access token via rest API

The access token must match the userId provided

.connect()

try {
    await Client.connect(userId, accessToken);
} catch (e) {
    console.error('Fail to connect the client', error)
}


Parameters
Parameter Required Default Description
userId yes   User that you want to authenticate
accessToken yes   Access token corresponding to the user provided
Errors
Name description
sdk_version_invalid If one or more parameter have an incorrect type, see the message to knows which ones
sdk_version_unsupported The browser is not supported, please check the compatibility table above
app_id_invalid The appId used in configuration step is invalid
access_token_expired The access token is expired, please retrieve a new one before retry the connection
access_token_invalid he access token is invalid, please check the token generation
access_token_invalid_signature The access token is compromised, please check the token generation
access_token_invalid_user The access token not belong to the userId forwarded in the connect method
user_not_found The user does not exists

BandyerSDK can optionally be connected using a call url link. The session that will be created using the call url link as access link will last only for the duration of the joined call.

All the sdk feature will be restricted on the call represented by the call link url.

In addition, the only chat accessibile will be the chat related to the current call specified by the call link url.

At the end of the call the BandyerSDK will be automatically disconnected and all persisted data will be cleared as well.

Note that if BandyerSDK is already connected via access token, connecting via access link with the same user or with another user is not allowed. The current access link session must be ended before connecting again.

.joinCallURL(url)

try {
    const call: CallView = await Client.joinCallURL(url);
} catch (e) {
    console.error('Fail to connect the client', error);
}
Parameters
Name Type Description
url string Valid url for the call
Errors
Name description
sdk_version_invalid If one or more parameter have an incorrect type, see the message to knows which ones
sdk_version_invalid If one or more parameter have an incorrect type, see the message to knows which ones
invalid_access_link The access link is not a valid url
invalid_access_link The access link is not valid, the room is inactive or the user does not belong to the URL
app_id_invalid The appId used in configuration step is invalid
user_not_found The user does not exists

Disconnect

.disconnect()

await Client.disconnect();

Update access token

Allow to refresh the session, you can obtain a valid access token via rest API

.updateAccessToken()

await updateAccessToken(accessToken);
Parameters
Parameter Required Default Description
accessToken yes   Access token corresponding to the user provided
Errors
Name description
access_token_expired The access token is expired, please retrieve a new one before retry the connection
access_token_invalid he access token is invalid, please check the token generation
access_token_invalid_signature The access token is compromised, please check the token generation
access_token_invalid_user The access token not belong to the userId forwarded in the connect method

Client: Chat API and types

If the Client was created with the chat module enabled it can perform some chat operation, also expose some real time events.

Events


// when a message was sent in a channel
Client.on('channel:message:sent', ({message: Message}) => {
  // your logic
})

// when a message was received in a channel
Client.on('channel:message:received', ({message: Message}) => {
  // your logic
})


// when a channel was added using api/ rest
Client.on('channel:added', ({channel: Channel}) => {
  // your logic
})

// when a channel was removed using api/ rest
Client.on('channel:removed', ({channelId: string, participants: string[] }) => {
  // your logic
})

Add channel

To create a chat channel another user of your platform, you need to call the .addChannel() method. The addChannel method expect a valid user alias (it must be a user already created). Once the method is called, the widget will return a channelView

.addChannel(userId)

const channelView: channelView = await Client.addChannel('usr_fr55ga3');
Parameters
Name Type Description
userId String User that you want to chat with
Errors
Name description
validation_error One of the arguments is invalid or the chat module is not initialized
authentication_error The Client is not authenticated
create_channel_oto An error has occurred during the creation phase, please refer to the message in the error

Remove channel

To remove a chat channel you need to call the .removeChannel() method. The removeChannel will remove the chat between the user authenticated and the user specified as input of the method. All the messages between them will be deleted permanently.

.removeChannel(userId)

await Client.removeChannel('usr_fr55ga3');
Parameters
Name Type Description
userId String Other participants of the chat that you want to remove
Errors
Name description
validation_error One of the arguments is invalid or the chat module is not initialized
authentication_error The Client is not authenticated
delete_channel An error has occurred during the remove phase, please refer to the message in the error

Get channel view

Allow to retrieve a specific channel view with a user

..getChannelView(userId)

Client.getChannelView(userId);
Parameters
Name Type Description
userId String Other participants of the chat that you want to remove
Errors
Name description
validation_error One of the arguments is invalid or the chat module is not initialized
channel_not_found The channel does not exists

Select channels view

Allow to show the main view of the Client, if you are in a call view or in a channel view this method allow to change the current view to the list of channels

.selectChannelsView()

Client.selectChannelsView();

Client: Call API and types

The client expose apis and events in order to manage a call lifecycle

Events

// triggered when a call is created (status equal to dialing)
Client.on('call:incoming', ({ call: Call }) => {
    // yuor logic
});

// triggered when the call change the status (connecting, connected, ended)
Client.on('call:status:changed', ({ call: Call, status }) => {
    // yuor logic, note if the status was ended, the call object can have a endReason
});

Create call

.createCall(users, options)

Create a call with arbitrary call options with the users specified in the array (Only one user at the moment)

This method return a callView that is a UI representation of the call, this object contains also the call(logical)

const callView: CallView = Client.createCall(['usr_fr55ga3'], { call_type: 'audio_video' });

Note: If the widget is in hidden mode, the createCall method mode will display the widget.

Parameters
Name Type Description
participants string[] List of users with whom you want to start a call (at most one at the moment)
options Object Call options
Options
Name Default Type Description
callType inherit from the config string Can be ‘audio_only’, ‘audio_upgradable’, ‘audio_video’
recording inherit from the config boolean Allow to define if the call start with recording
recordingType inherit from the config string Can be ‘manual’ or ‘automatic’
isAdmin inherit from the config boolean Allow the user to control the manual recording capabilities

N.B. if the call is {recording: true, recordingType: ‘manual’, isAdmin: false} create a call with the recording capability but no-one is able to start the recording. In order to do that create this type of call with isAdmin: true

Errors

Name description
validation_error One of the arguments is invalid
another_call_in_progress The user is already in call
current_user_not_available The connected user is in disconnection phase
current_user_busy The connect user is busy on another device
all_users_busy All the users are busy
no_plus_user Should be at least one plus user in the call
room_create_error A generic error has occurred please check the error message to know the cause
internal_server_error A server problem is occurred please retry or contact for support

Join call URL

.joinCallURL(url)

Join a call URL retrieved from the rest api integration Documentation can be found here

This method return a callView that is a UI representation of the call, this object contains also the call(logical)

const call: CallView = Client.joinCallUrl('https://sandbox.bandyer.com/region/direct-rest-call-handler/token');

Note: If the widget is in hidden mode, the joinCallURL method mode will display the widget.

Parameters
Name Type Description
url string Valid url for the call

Errors

Name description
validation_error One of the arguments is invalid
another_call_in_progress The user is already in call
current_user_not_available The connected user is in disconnection phase
current_user_busy The connect user is busy on another device
all_users_busy All the users are busy
invalid_url The given URL is invalid
invalid_token The call token is invalid or disabled
user_not_associated_to_link The user does not belong to the link
join_url_mtm At the moment the client does not support the many to many calls
no_plus_user Should be at least one plus user in the call
room_create_error A generic error has occurred please check the error message to know the cause
internal_server_error A server problem is occurred please retry or contact for support

Client : User API and events

The client expose apis and events to keep track of the other users status and life cycle

Events:

// triggered when a user in you company change you status(online, offline)
Client.on('user:status:changed', (data: { userId: string, status: string }) => {
    // yuor logic
});
Name description
invalid_call_status The call cannot be already in an ended status
user_not_in_dialing The other participants is in disconnection phase
dial_stop_error Generic dial stop error, please refer to the message in order to know the cause
dial_decline_error Generic dial stop error, please refer to the message in order to know the cause
internal_server_error A server problem is occurred please retry or contact for support

getOnlineUsers

.getOnlineUsers()

Allow to retrieve the current list of online users

const users: string[] = Client.getOnlineUsers();

Client : UI API

Show widget

.showWidget()

Allow to render the UI component when the Client was created with hidden:true

Client.showWidget();

Hide widget

.hideWidget()

Allow to remove the UI component when the Client was created with hidden:false

Client.hideWIdget();

Open widget

.openWidget()

Allow to expand the widget component

Client.openWidget();

Close widget

.closeWidget()

Allow to minimize the widget component

Client.closeWidget();

Toggle widget

.toggleWidget()

Allow expanding or minimize the widget component based on the status

Client.toggleWidget();

Channel view type

A channel view type is a UI representation of the logical Channel. On this object you can perform all the UI api’s

Methods

Property:

Name Type Description
textArea String Allow to get and set the textArea field on the channel UI
channel Channel Retrieve the logical channel

Select

.select()

This method allow to change the currentView to the channel one

// channelView received from an event or retrieved from the channelView() method

channelView.select();

Channel type

A channel is a logical representation of the chat On this object you can perform all the logical operation like retrieve messages, send message, get unreadMessages and participants

Methods

Property

Name Type Description
channelId String Retrieve the unique channelId, it can be use also in our rest apis
participants String[] Retrieve the userIds of the participants
unreadMessages number Retrieve the count of the unread messages
messages Message[] Array of messages in the channel

Events

Name Description
channel:message:added Notify when in the current channel a message (sent or received) was added
Channel.on('channel:message:added', (message: Message) => {
    // your logic
});

Fetch messages

.fetchMessages(messageToFetch, anchor, direction)

This method allow to retrieve the channel messages programmatically

// channelView received from an event or retrieved from the channelView() method

const messagesObejct: { messages: Message[], anchor: string } = channelView.fetchMessages(
    messageToFetch,
    anchor,
    direction
);
Parameters
Name Type Description
messageToFetch number Number of messages to fetch
anchor String[] Starting messageId from witch start to fetch
direction string Use ‘backwards’ to retrieve past messages , use ‘afterward’ otherwise
Errors
Name description
channel_not_exists When the request is performed after the channel was deleted
message_anchor_error Invalid anchor

Send message

.sendMessage(message)

This method allow to send a message programmatically

// channelView received from an event or retrieved from the channelView() method

const message: Message = channelView.sendMessage(text);
Parameters
Name Type Description
message string text message that you want to send
Errors
Name description
channel_not_exists When the request is performed after the channel was deleted
message_not_saved Error in storing the message, please retry

Message type

A message is a logical representation of a single message in a Channel

Property

Name Type Description
messageId String Retrieve the unique messageId
channel Channel Retrieve the logical channel
sender string UserId of the sender
text String Text of the message
creationDate String(ISO) ISO Date of the message creation

Call view type

A call view type is a UI representation of the logical Call. On this object you can perform all the UI operation

Methods

Properties

Name Type Description
call Call Allow to retrieve the logical call
tone Object Allow to manage the audios of the callView (ex ring)

Select method

.select()

This method allow to change the currentView to the call one

// callView received from an event or retrieved from the callView getter on the client object

callView.select();

Tone property

Name Type Description
ring {play: function, stop: function} Allow to play or stop the ring tone
// Example of how to use a ring tone

Client.on('call:incoming', ({ call }) => {
    Client.callView.tone.ring.stop(); // this avoid that the ring tone start
    // do what you want
    // ...
    Client.callView.tone.ring.play(); // if needed you can play the ring tone
});

Call type

A call is a logical representation of the room created On this object you can perform all the logical operation like answer, end, get status, participants, options etc

Methods

Properties

Name Type Description
roomId String RoomId of the call, can be used in out rest api to retrieve information
options Object Contains call information about his initialization and status
creationDate string(ISO) Creation date of the call
participants string[] Array of userId that participate to the call
direction string ‘incoming’ or ‘outgoing’
status string can be ‘dialing’, ‘connecting’ ‘connected’ or ‘ended’
recordingState String ‘started’ if the recording was started, ‘stopped’ otherwise
endReason string or null Filled if the call is in the end state, should be ‘declined’, ‘canceled’, ‘answered_of_another_device’, ‘hang_up’, ‘timeout’

Options object

Name Type Description
callType String Can be ‘audio_video’, ‘audio_upgradable’, ‘audio_only’
recordingType String Can be ‘none’, ‘automatic’ or ‘manual’
live String If the call trigger the incoming call event or hook

Events

Name Description
status:changed Triggered when a call change his status
recording:state:changed Triggered when the recordingState change

A call have some events that allow to retrieve real time information

// Triggered  when a call change his status
Call.on('status:changed', (status: string) => {
    // your logic
});

// Triggered  when the recording state was changed
Call.on('recording:state:changed', ({ recordingState: string }) => {
    // your logic
});

Answer

.answer()

This method allow to answer an incoming call in dialing state

// call received from an event or retrieved from the callView.call getter

await call.answer();
Errors
Name description
invalid_call_status In order to answer a call, this one should have an incoming direction an must be in dialing state
callee_not_available The other participants is in disconnection phase
dial_answer_error Generic error, please refer to the message in order to know the cause
internal_server_error A server problem is occurred please retry or contact for support

End

.end()

This method allow to end a call

It automatically performs the correct behaviour(decline, cancel or hangUp) based on the call status

// call received from an event or retrieved from the callView.call getter

await call.end();

Migration from v1.x.x to v2.x.x

Library changes

The library name has been changed from BandyerChat to BandyerSDK so now you can find the library once loaded from the CDN in window.BandyerSDk.

Initialize the BandyerSDK

The BandyerChat.create() function has been renamed to BandyerSDK.configure() to better represent its purpose.

The BandyerSDK.configure() function will now return a client which exposes all the apis previosuly exposed on the BandyerChat object.

The client object will also expose a new distinct client.connect() function that connects the SDK.

The BandyerChat.logout() function has been replaced by the client.disconnect() function exposed on the client object and by the BandyerSDK.destroyClient() that can be used to reconfigure the SDK.

Migrate BandyerChat.create to BandyerSDK.configure

console.log(BandyerChat.version());

const client = await BandyerChat.create({ userAlias, environment, appId, mode, layout });

// the SDK is connected
// put here your logic

await BandyerChat.logout();

becomes

console.log(BandyerSDK.version);

const client = BandyerSDK.configure({ region, environment, appId, mode, layout, tools });

// note that the client is not globally expose, if you want you can global store the object with window.bandyerClient =client

client.on('client:access_token:is_about_to_expire', async () => {
    const accessToken = await getAccessToken(userId); // your async function to obtain a valid accessToken
    await client.updateAccessToken(accessToken);
});

// the SDK is configured

// your async function to obtain a valid accessToken
const accessToken = await getAccessToken(userId);

// userAlias parameters is now called userId
await client.connect(userId, accessToken);

// the SDK is connected
// put here your logic

await client.disconnect(); // replacement of the old BandyerChat.logout() function

BandyerSDK.destroyClient(); // destroys the client allowing a new configuration

Configuration parameters changes

old value new value change
record recordingType Parameter key
tools tools Not specifying tools now means that the user will have none
language language The current default is en

Migrate Chat methods

const chatsList = await BandyerChat.getChats();

await BandyerChat.addChat(userId);

BandyerChat.selectChat(userId);

BandyerChat.composeMessage(userId, 'How are you?', false);

BandyerChat.composeMessage(userId, 'How are you?', true);

const unreadMessagesList = await BandyerChat.getUnreadMessages();

await BandyerChat.removeChat(userId);

becomes

const chatsList = Client.channelsView; // array of channelViews instead of getChats()

const channelView = await Client.addChannel(userId);

channelView.select();

channelView.textArea = 'How are you'; // same as composeMessage with send = false

const message = await channelView.channel.sendMessage('How are you'); // same as composeMessage with send = true

channelView.channel.unreadMessages; // get unreadMessages on singleChannels instead of getUnreadMessages()

await Client.removeChannel(userId);

Migrate Chat events

Client.on('chat_loaded', callback);
Client.on('message_received', callback);
Client.on('message_sent', callback);

becomes

// see the documentation in order to know the payload in the callback
Client.on('channel:added', callback);
Client.on('channel:removed', callback);
Client.on('channel:message:received', callback);
Client.on('channel:message:sent', callback);

Migrate Call methods

const call = await BandyerChat.createCall([userId], option);
// const call = await BandyerChat.joinCallUrl(url);
call.hangUp();

becomes

const callView = await client.createCall([userId], option);
// const callView = await Client.joinCallUrl(url);

callView.call.end(); //take care about the call object changes

Migrate Call events

Client.on('incoming_call', call => {
    /* call =  {
  		"event": "incoming_call",
  		"callAlias": "room_027b9312e9a5",
  		"callDirection": "outgoing",
  		"callParticipants": ["user1", "user2"],
  		"callOptions": {
    		"record": false,
			"creationDate": "2021-04-13T08:31:03.916Z",
		   "callType": "audio_video", 
    		"live": true
  		}
	}*/
});

Client.on('call_dial_answered', call => {
    // your logic
});

Client.on('call_dial_declined', call => {
    // your logic
});

Client.on('call_dial_stopped', call => {
    // your logic
});

Client.on('call_started', call => {
    // your logic
});

Client.on('call_ended', call => {
    // your logic
});

becomes

Client.on('call:incoming', (call: Call) => {
    // call is a calltype object (see documentation to know properties and methods)

    call.on('status:changed', (status: string) => {
        // status can be  'dialing', 'connecting' 'connected' or 'ended'
    });

    call.answer();
    //call.end();
});

Client.on('call:status:changed', (call: Call, status: string) => {
    // call is a calltype object (see documentation to know properties and methods)
    // status can be  'dialing', 'connecting' 'connected' or 'ended'
    // if the call status is ended the call object have and endReason getter
});

Migrate User methods

const user = await BandyerChat.getUser(userId);

console.log(user.status);

const users = await BandyerChat.getUsersStatusList();

users.forEach(user => {
    console.log(user.status);
});

becomes

const users = Client.getOnlineUsers();

users.forEach(user => {
    console.log('the user', user, 'is online');
});

// if a user is not in the list above the status is offline

Migrate User events

Client.on('user_connected', callback);

Client.on('user_disconnect', callback);

becomes

Client.on('user:status:changed', ({ userId, status }) => {
    console.log('the user', userId, 'went', status);
});

Migrate Widget methods

BandyerChat.showWidget();
BandyerChat.hideWidget();
BandyerChat.toggleWidget();
BandyerChat.closeWidget();
BandyerChat.openWidget();

becomes

Client.showWidget();
Client.hideWidget();
Client.toggleWidget();
Client.closeWidget();
Client.openWidget();