Learn Skype Web SDK Day 19 : Receiving a New Conversation
[contemplate-1]
View Demo
Depending on the Skype for Web API application you’re building, you may need to deal with new incoming messages. Once you’ve signed in as a Skype for Business user your presence will show as Available to everyone else, and they may decide to IM you. It’s not obvious from the Skype for Business desktop client that a user has signed in over the web so people may just think that you have the full capabilities of the Skype for Business client.
Of course, you can just ignore possibility entirely, in which case anyone sending an IM will receive a timeout message. However a nicer user experience, even if you don’t intend on handling incoming messages is to code for it, and reject them – this will give a better experience to the person sending the message, rather than letting it just time out.
When a new conversation request is received by the Skype for Web API, it is added to the list of conversations managed by the conversationsManager
. By monitoring new conversations being added here you can then take actions when they appear.
You can register an event listener for new conversations being added with the event listener:
var client = new Skype.Web.Model.Application; //perform sign in client.conversationsManager.conversations.added(function (newConversation) { //do something with newConversation });
Obviously there is only one conversationsManager
and if you’re starting your own conversations as well then conversations will be being added and removed from this fairly regularly. There are two important things you should check for to know whether this is a incoming conversation you need to act on. You should check that you are able to accept the conversation, and that the conversation is in the right state to be accepted.
Checking to see whether you are able to accept the conversation is in fact checking the specific modality you are interested in, to see if it is supported. IM should always be support, but it’s good practice to make sure. You do this by checking the value of:
newConversation.chatService.accept.enabled()
Secondly, you should evaluate the state of the conversation. A conversation moves through various states during its lifetime and checking the current state will make sure you don’t try and accept or reject a conversation that isn’t ready for it. If the conversation state is Notified then it means that the conversation is waiting for an invitation decision to be made: i.e. it’s ready to be accepted or declined:
newConversation.chatService.state() == 'Notified'
Putting the two together gives you:
var client; //code to instantiate client and perform sign in client.conversationsManager.conversations.added(function (newConversation) { if (newConversation.chatService.accept.enabled() && newConversation.chatService.state() == 'Notified') { //accept or reject invite } });
Actually accepting or rejecting the conversation invitation is easy:
newConversation.chatService.accept();
or
newConversation.chatService.reject();
Of course, in a real-life scenario you might want to display a notification about the new conversation to the user, and let them make the decision to accept or reject. With the event listener shown above the newConversation
object has full information about who is calling (checking the participants() object for a list of participants so you can easily pull out the caller’s name and photo. You might also look at JavaScript libraries such as toast.js to provide a familiar toast popup.
The code sample below with respond to an incoming IM conversation, allowing it to be accepted or declined:
<div class="form-horizontal"> <div class="form-group"> <label for="username" class="col-sm-2 control-label">Username</label> <div class="col-sm-10"> <input type="email" class="form-control" id="username" placeholder="Email"> </div> </div> <div class="form-group"> <label for="password" class="col-sm-2 control-label">Password</label> <div class="col-sm-10"> <input type="password" class="form-control" id="password" placeholder="Password"> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button class="btn btn-default" id="btnLogIn">Log in</button> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button class="btn btn-default" id="btnLogOut">Log out</button> </div> </div> </div> <div> <span id="loginStatus"></span> </div> <hr/> <div id="divIncomingNotification" style="display: none;" > <span id="lblNewConversationMsg"></span> <div class="form-horizontal"> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button class="btn btn-default" id="btnAccept" >Accept</button> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button class="btn btn-default" id="btnDecline" >Decline</button> </div> </div> </div> </div> <!-- IncomingNotification --> <div id="divActiveConversationControls" style="display: none;"> <div class="form-horizontal"> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button class="btn btn-default" id="btnStopConversation">Stop</button> </div> </div> </div> Conversation State: <span id="lblConversationState"></span> <ul id='conversationText'></ul> <hr/> <div class="form-horizontal"> <div class="form-group"> <label for="message" class="col-sm-2 control-label">Send Message:</label> <div class="col-sm-10"> <input type="email" class="form-control" id="message" placeholder="Message to send"> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button class="btn btn-default" id="btnSendIM">Send IM</button> </div> </div> </div> </div> <!-- ActiveConversationControls --> <div id="footer"></div> <!-- This is not needed for the samples to run, but adds standard headers and footers to the samples, to display title, instructions, about etc. If you're taking this code and using it yourself, you can remove this.--> <script type="text/javascript" src="../../assets/layoutcodesample-min.js"></script> <script type="text/javascript"> <!-- These variables are only needed for laying out the code sample, they are not part of the sample code. --> var pageTitle = 'Receiving a Conversation'; var blogPostLocation = "http://thoughtstuff.co.uk"; var githubLocation = "http://github.com"; var client; $(function () { 'use strict'; Skype.initialize({ apiKey: 'SWX-BUILD-SDK', }, function (api) { client = new api.application(); // whenever client.state changes, display its value client.signInManager.state.changed(function (state) { $('#loginStatus').text("Login State: " + state); }); }, function (err) { alert('Error loading Skype Web SDK: ' + err); }); $('#btnLogIn').click(function () { // start signing in client.signInManager.signIn({ username: $('#username').val(), password: $('#password').val() }).then(function () { //log in worked! alert('Logged in!'); ListenForNewConversations(); }, function (error) { //Something went wrong. alert(error); }); }); $('#btnLogOut').click(function () { // start signing out client.signInManager.signOut() .then(function () { //log out worked! alert('Logged out!'); }, function (error) { //Something went wrong. alert(error); }); }); $('#btnStopConversation').click(function () { StopConversation(); }); $('#btnSendIM').click(function () { conversation.chatService.sendMessage($('#message').val()); }); $('#btnAccept').click(function () { AcceptConversation(); }); $('#btnDecline').click(function () { RejectConversation(); }) function ListenForNewConversations() { client.conversationsManager.conversations.added(function (newConversation) { if (newConversation.chatService.accept.enabled() && newConversation.chatService.state() == 'Notified') { conversation = newConversation; $('#lblNewConversationMsg').text('Incoming Conversation from ' + conversation.participants()[0].name()); $('#divIncomingNotification').show(); } }); } function AcceptConversation() { //register for the conversation state changing to connected. conversation.chatService.state.changed(function(newState){ $('#lblConversationState').text(newState); if (newState == 'Disconnected') { $('#divActiveConversationControls').hide(); } }); //register for new messages added to the historyService object conversation.historyService.activityItems.added(function (newMsg){ if (newMsg.type() == 'TextMessage') { var direction; if (newMsg.direction() == 'Incoming') direction = "<--"; else { direction = "-->"; } $("#conversationText").append('<li><b>' + direction + '</b>&nbsp; ' + newMsg.sender.displayName() + ' : ' + newMsg.text() + '</li>'); } }); //finally, accept the conversation conversation.chatService.accept(); //update the UI $('#divIncomingNotification').hide(); $('#divActiveConversationControls').show(); } function RejectConversation() { conversation.chatService.reject(); $('#divIncomingNotification').hide(); } function StopConversation() { if (conversation != null) //conversation.chatService.stop(); //client.conversationsManager.conversations.remove(conversation) conversation.leave(); } }); </script>
Demo Online
You can try this code out against your own Skype for Business environment by going to the demo page. From here you can also download the code from GitHub if you want to host it locally, or take it and use it in your next project.
[contemplate-2]