Pages Menu
TwitterRssFacebook

Posted by on May 25, 2015 in Skype for Business® (Lync®)

Learn Skype Web SDK Day 18 : Terminating a Conversation

Learn Skype Web SDK Day 18 : Terminating a Conversation

This is one post in a series of more than 30, devoted to helping you get up to speed quickly with the new Skype Web SDK. Each lesson comes with source code (in GitHub) and a working demo page so you can see what it does. Check out the full list of posts on the Skype Web SDK page.


View Demo

Be a good Skype for Web API citizan! When your user is done with a conversation, don’t just leave it open – close it! Open conversations are confusing to the other party, consume server resources and local resources and will slow down your application. Besides, it’s one of the easiest things you can do!

If you think back to starting a conversation, you’ll recall that having set up a conversation, we then used the chatService member, and invoked the start() method. You might have noticed that there is a also a stop() method, and assume that this is how you’d end the conversation.

However, there’s a really important distinction to be made here. Understanding this will really help you become a better Skype for Web API developer, especially as you progress to adding voice, video and desktop sharing.

A Skype for Business conversation is defined as two or more users being connected together so that they can communicate. However, within that, there are different ways in which they might be communicating. It might be Instant Messaging (IM), it might be voice, it might be desktop sharing. It might be a combination of those, or all three of them. These different methods of communication are called modalities. A conversation is a container for multiple modalities – a conversation might have one or more modalities, but a modality cannot exist without being in a conversation.

When we call stop() on the chatService, what we’re doing is ending the IM modality, but we’re not ending the conversation. The conversation is still there, just without the modality. Skype for Business is deliberately designed this way – so that you can start a conversation using IM, then add video halfway through, then add desktop sharing, then stop video, then start it again. Each time you don’t have to start a new conversation, it all happens within the same one.

If ending the IM modality whilst keeping the conversation open is what you want to do, then chatService.stop() is the right method for you. But if what you really want to do is end the conversation, there’s another method to use:

conversation.leave();

This will close all modalities in the conversation and correctly terminate the conversation with Skype for Business. If you’re monitoring the list of conversations handled by the conversationsManager then you’ll notice that the conversation gets removed from it’s list using this method (and doesn’t if you just stop the chatService). This is how you should fully terminate conversations.

Remember as well that after a period of inactivity Skype for Business will automatically close down a conversation. Your application should watch for this (check the conversation state: it will change to Disconnected) and respond appropriatly. Otherwise your user may think the conversation is still active and continue to send messages, which won’t go anywhere. Skype for Business won’t magically re-open the conversation if you send more messages.

<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 class="form-horizontal">
    <div class="form-group">
      <label for="contact" class="col-sm-2 control-label">Start Conversation with:</label>
      <div class="col-sm-10">
        <input type="email" class="form-control" id="contact" placeholder="Contact SIP Address">
      </div>
    </div>  

    <div class="form-group">
      <div class="col-sm-offset-2 col-sm-10">
        <button class="btn btn-default" id="btnStartConversation" disabled="disabled">Start</button>
      </div>
    </div>

     <div class="form-group">
      <div class="col-sm-offset-2 col-sm-10">
        <button class="btn btn-default" id="btnStopConversation" disabled="disabled">Stop</button>
      </div>
    </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" disabled="disabled">Send IM</button>
      </div>
    </div>
  </div>
  
  
  <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 = 'Terminating 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!');
            $('#btnStartConversation').prop('disabled', false);
            
          }, function (error) {
            //Something went wrong.
            alert(error);
          });
      });

    $('#btnLogOut').click(function () {
        // start signing out
        client.signInManager.signOut()
        .then(function () {
               //log out worked!
               alert('Logged out!');
               $('#btnStartConversation').prop('disabled', true);
               $('#btnSendIM').prop('disabled', true);
             }, function (error) {
                //Something went wrong.
                alert(error);
              });
      });

    $('#btnStartConversation').click(function () {
      StartConversation($('#contact').val());
    });

    $('#btnStopConversation').click(function () {
      StopConversation();
    })

        $('#btnSendIM').click(function () {
      conversation.chatService.sendMessage($('#message').val());
    });

  function StartConversation (contactSIP) {
  //first, get the person to start a conversation with. Assume one person.
  var person;
  GetContactFromName(contactSIP).then(function (results) {
    results.forEach(function (result) {
    person = result.result;          
  });

 //create the conversation object
 conversation = client.conversationsManager.createConversation();

 //add the person to the conversation by creating a conversation participant object
 var convParticipant = conversation.createParticipant(person);
 conversation.participants.add(convParticipant);

 //add the newly created conversation to the ConversationManager list
 client.conversationsManager.conversations.add(conversation);

//register for the conversation state changing to connected.
  conversation.chatService.state.changed(function(newState){
  $('#lblConversationState').text(newState);
  if (newState == 'Connected') {
    $('#btnSendIM').prop('disabled', false); //safe to send IMs now
    $('#btnStopConversation').prop('disabled', false); //OK to close conversation now
  }
  else if (newState == 'Disconnected') {
    $('#btnStopConversation').prop('disabled', true);
    $('#btnSendIM').prop('disabled', true);
  }
  });

//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>&amp;nbsp; ' + newMsg.sender.person.displayName() + ' : ' + newMsg.text() + '</li>');  
    }
  });
 
 conversation.chatService.start();
});

}

function StopConversation() {
if (conversation != null)
// dont use chatService.stop() to end a conversation, it wont. It only stops the 
//IM modality.
conversation.leave();
}

function GetContactFromName(contactSIP)
{
 var query = client.personsAndGroupsManager.createPersonSearchQuery();
 query.text(contactSIP);
 query.limit(1);
 return query.getMore();          
}

});

</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.

Disclaimer: This is sample code, intended to inform and educate. It is not production-ready and is lacking key components such as error handling. You use it entirely at your own risk. You should fully understand the effects, limitations and risks of the code before executing, and understand the implications of any set-up steps. By using these code examples you are using the Skype Web SDK, so you should read the Skype Software License Terms to which you are agreeing.

Good to Know

Written by Tom Morgan

Tom is a Microsoft Teams Platform developer and Microsoft MVP who has been blogging for over a decade. Find out more.
Buy the book: Building and Developing Apps & Bots for Microsoft Teams. Now available to purchase online with free updates.

Post a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.