Messenger Library 2 Contact List Sample

We recently shipped version 2 of the Windows Live Messenger Library. In it, we added a number of features to make your life as a developer easier. We'll be showcasing a few of these in this blog post and its corresponding sample. Our sample itself is built using Script#, which is an awesome C# to JavaScript compiler that we've used to build the Messenger Library. Its output is human-readable JavaScript, so even if you're not familiar with Script# or don't want to use it, you can still try the sample and follow along. You can download the sample here.

In particular, we cover:

  • MessengerUtility.EmoticonEncode - Now you can easily encode various strings throughout your application with the corresponding Messenger emoticons. We use this method to show emoticons in contacts' display names and personal messages.
  • User.OnlineContacts and User.OfflineContacts - These collections keep track of who is online and who is offline. They also take care of sorting users based on their display names.

We'll cover these each in turn and then tie them together to produce a nice result.


MessengerUtility.EmoticonEncode

This method is simple enough: simply pass in the string that you'd like to encode and we'll hand back DOM objects that you can insert directly into your page. Any time we find a character sequence that represents a Messenger emoticon (like :-) or :-D) we'll replace them with an image tag pointing to a 16x16 PNG of the particular emoticon. This is a great way to light up your application and give your users an experience that is consistent with what they're accustomed to when using Messenger. As a security-minded developer, you'll also appreciate that we do the replacement in a way to prevent XSS vulnerabilities in your application. Whenever you're dealing with user content in your app, it's important not to use innerHTML -- this is why we hand back DOM objects that you can use directly.

Here is the Script# syntax:

MessengerUtility

.EmoticonEncode(personalMessage);

And JavaScript:

Microsoft.Live.Messenger.MessengerUtility.emoticonEncode(personalMessage); ****

User.OnlineContacts / OfflineContacts

In order to make your life easier, these two collections keep track of who is online and who is offline. As a user's contacts sign in and sign out, they'll be added and removed from each of these collections. We also do this in a way to ensure that the contacts are sorted based on the current locale of the user. This ensures that contacts will appear in an order that the user is used to when he or she uses other Messenger clients.

In order to use these, you'll need to understand a bit about the INotifyCollectionChanged interface that they both implement. If you're familiar with the .NET Framework, you may already know how this works. Essentially, an object that implements this interface needs to expose an event which notifies application code of collection changes. When the collection changes, you'll need to look at the event data to see how it changed. Typical event types include 'Reset', 'Add', and 'Remove' to indicate when the collection changes drastically, when a set of items are added, or when a set of items are removed respectively.

For your application, you'll want to register for the CollectionChanged event once you create your User object. This will ensure that the events get raised properly when the User.SignInCompleted event gets raised.

Here's the Script# code for this:

/// <summary>
/// Occurs when the associated collection changes.
/// </summary>
private void OnOnlineContactsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    switch (e.Action)
{
        case NotifyCollectionChangedAction.Add:
{
                int index = e.NewStartingIndex;
                foreach (Contact contact in e.NewItems)
{
                    this.AddContactItem(index, contact);
index++;
}
}
            break;
        case NotifyCollectionChangedAction.Remove:
{
                int index = e.OldStartingIndex;
                foreach (Contact contact in e.OldItems)
{
                    this.RemoveContactItem(index, contact);
index++;
}
}
            break;
        case NotifyCollectionChangedAction.Reset:
{
                this.DisposeItems();
                this.InitializeItems();
}
            break;
}
}

And here's the JavaScript:

function

onOnlineContactsChanged(sender, e) {

    /// <summary>
    /// Occurs when the associated collection changes.
    /// </summary>
    /// <param name="sender" type="Object">
    /// </param>
    /// <param name="e" type="Microsoft.Live.Core.NotifyCollectionChangedEventArgs">
    /// </param>switch (e.get_action()) {
    case Microsoft.Live.Core.NotifyCollectionChangedAction.add:
        var index = e.get_newStartingIndex();
        var enum = e.get_newItems().getEnumerator();
        while (enum.moveNext()) {
            var contact = enum.get_current();
            this._addContactItem$2(index, contact);
index++;
}
        break;
    case Microsoft.Live.Core.NotifyCollectionChangedAction.remove:
        var index = e.get_oldStartingIndex();
        var enum = e.get_oldItems().getEnumerator();
        while (enum.moveNext()) {
            var contact = enum.get_current();
            this._removeContactItem$2(index, contact);
index++;
}
        break;
    case Microsoft.Live.Core.NotifyCollectionChangedAction.reset:
        this._disposeItems$2();
        this._initializeItems$2();
        break;
}
}

As you can see, there's not much for you to take care of, but I think you'll appreciate the results:

If you take a look at the sample, you'll notice that we take care of one complexity related to Messenger contact lists: blocked contacts. Within Messenger, it's possible for a user to have someone on his or her contact list but also block that contact. This implies that the user can see the contact's presence but the contact can't see the user's. We handle this by simply monitoring the Contact.IsBlocked property and showing a special blocked icon for blocked contacts.

The sample also strives to separate UI from business logic, so you'll see we accomplish most visual effects directly in the corresponding CSS stylesheet. Feel free to dissect the sample and provide us feedback. Also let us know if there are other samples you'd like to see.

Thanks,
Steve