Learn Skype Web SDK Day 16 : Doing More with History Service
[contemplate-1]
View Demo
If you’ve registered a listener on new activityItems
being added then you probably won’t need anything else, but the historyService
object also has a unreadActivityItemCount
property and a markAllAsRead()
method which you can use to poll for unread messages.
You can also use the historyService
to provide rock-solid delivery notification and feedback for a great user experience when sending messages. When you send a message, it goes into the activityItems
collection immediately (with the direction of Outgoing). There is a status property you can monitor for the outcome of delivery of that message. Initially the status will change to Pending
. Once the message has been delivered it will change to Suceeded
, if it can’t be sent it will change to Failed
. There is also a changed()
event you can listen on.
We can add this event when evaluating new items being added to the historyService
object:
conversation.historyService.activityItems.added(function (newMsg){ if (newMsg.type() == 'TextMessage') { var direction; if (newMsg.direction() == 'Incoming') direction = "<--"; else { direction = "-->"; newMsg.status.changed(function (newStatus) { //do something with newStatus }); } }
In this code snippet we’re first checking that the new entry in the historyService is a TextMessage
. After that we evaluate the direction the message is moving in and populate a variable with an arror signifying the direction. In a real project you would use this variable to make a decision about how to display the message, such as a different coloured bubble, or different alignment etc.
For outgoing messages (in the example, messages which are not Incoming we also register for the changed event of the status of the message. We can use this to provide feedback to the user about what’s happening with their message.
<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> <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> Send Message Status: <span id="lblMsgSendStatus"></span> <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 = 'Doing More with History Service'; 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()); }); $('#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 } }); //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 = "-->"; newMsg.status.changed(function (newStatus) { $('#lblMsgSendStatus').text(newStatus); }); } $("#conversationText").append('<li><b>' + direction + '</b>&nbsp; ' + newMsg.sender.displayName() + ' : ' + newMsg.text() + '</li>'); } else { alert(newMsg.type()); } }); conversation.chatService.start(); }); } 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.
[contemplate-2]