The BandyerSDK is a fast and effective way to offer a live videochat in your web application.
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.
Browser | min version | Plugin requested |
---|---|---|
Chrome | 72 | |
Firefox | 66 | |
Safari | 12 | |
Edge new | 79 |
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
Name | Type | Description |
---|---|---|
version | string | Return the current version of the widget |
.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:
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 |
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 |
audio_only
: the call is only audio and the participants can’t use the webcamaudio_upgradable
: the call begins with only audio but the participants are allowed to enable the video later during the callaudio_video
: the call begins with audio and video enabledembed
: the call is shown in the widget viewwindow
: the call is shown in a separated popup windowThe widget remains not visible until it receives the following events:
By default, if no tools are provided (missing field), all the tools are disabled.
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 | ❌ | ❌ | ❌ | ❌ |
{
"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 |
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'
}
});
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.
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.
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.
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()
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.
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 |
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) |
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
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)
}
Parameter | Required | Default | Description |
---|---|---|---|
userId | yes | User that you want to authenticate | |
accessToken | yes | Access token corresponding to the user provided |
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);
}
Name | Type | Description |
---|---|---|
url | string | Valid url for the call |
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()
await Client.disconnect();
Allow to refresh the session, you can obtain a valid access token via rest API
.updateAccessToken()
await updateAccessToken(accessToken);
Parameter | Required | Default | Description |
---|---|---|---|
accessToken | yes | Access token corresponding to the user provided |
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 |
If the Client was created with the chat module enabled it can perform some chat operation, also expose some real time 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
})
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');
Name | Type | Description |
---|---|---|
userId | String | User that you want to chat with |
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 |
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');
Name | Type | Description |
---|---|---|
userId | String | Other participants of the chat that you want to remove |
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 |
Allow to retrieve a specific channel view with a user
..getChannelView(userId)
Client.getChannelView(userId);
Name | Type | Description |
---|---|---|
userId | String | Other participants of the chat that you want to remove |
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 |
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();
The client expose apis and events in order to manage a call lifecycle
// 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
});
.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.
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 |
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
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 |
.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.
Name | Type | Description |
---|---|---|
url | string | Valid url for the call |
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 |
The client expose apis and events to keep track of the other users status and life cycle
// 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()
Allow to retrieve the current list of online users
const users: string[] = Client.getOnlineUsers();
.showWidget()
Allow to render the UI component when the Client was created with hidden:true
Client.showWidget();
.hideWidget()
Allow to remove the UI component when the Client was created with hidden:false
Client.hideWIdget();
.openWidget()
Allow to expand the widget component
Client.openWidget();
.closeWidget()
Allow to minimize the widget component
Client.closeWidget();
.toggleWidget()
Allow expanding or minimize the widget component based on the status
Client.toggleWidget();
A channel view type is a UI representation of the logical Channel. On this object you can perform all the UI api’s
Name | Type | Description |
---|---|---|
textArea | String | Allow to get and set the textArea field on the channel UI |
channel | Channel | Retrieve the logical channel |
.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();
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
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 |
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
});
.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
);
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 |
Name | description |
---|---|
channel_not_exists | When the request is performed after the channel was deleted |
message_anchor_error | Invalid anchor |
.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);
Name | Type | Description |
---|---|---|
message | string | text message that you want to send |
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 |
A message is a logical representation of a single message in a Channel
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 |
A call view type is a UI representation of the logical Call. On this object you can perform all the UI operation
Name | Type | Description |
---|---|---|
call | Call | Allow to retrieve the logical call |
tone | Object | Allow to manage the audios of the callView (ex ring) |
.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();
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
});
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
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’ |
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 |
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()
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();
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()
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();
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
.
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.
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
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 |
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);
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);
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
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
});
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
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);
});
BandyerChat.showWidget();
BandyerChat.hideWidget();
BandyerChat.toggleWidget();
BandyerChat.closeWidget();
BandyerChat.openWidget();
becomes
Client.showWidget();
Client.hideWidget();
Client.toggleWidget();
Client.closeWidget();
Client.openWidget();