Développons un Twitter-like avec ASP.NET MVC5 et SignalR 2 (2)

Dans l’épisode précédent (qui date un peu, convenons-en), nous avions une première version de notre simili-Twitter développé avec SignalR 2. Pour le moment, notre application est un simple flux de messages qui viennent s’afficher en temps réel dans le navigateur. Nous allons lui ajouter quelques fonctionnalités. D’abord la gestion des mentions, pour afficher plus clairement à l’utilisateur ses interactions avec les autres utilisateurs. Les messages qui lui sont destinés seront également affichés dans son flux de messages principal, mais mis en valeur. Ensuite, nous ajouterons quelques améliorations ergonomiques.

Evolution du Hub SignalR

Nous allons d’abord faire légèrement évoluer notre Hub. Jusqu’ici, il avait la tête suivante :

using Microsoft.AspNet.SignalR;

using System.Collections.Generic;

namespace SignalRChat
{
  public class TwignalRHub : Hub
  {
    public void SendToHub(string name, string message)
    {
      Clients.All.sendToClients(name, message);
    }
  }
}

Fonctionnellement, le destinataire d’un message est simplement celui dont le pseudo préfixé de “@” est contenu dans le message.

Donc le message suivant sera considéré comme étant destiné à @pit et @rik :

“@pit Tu as vu le dernier expoit de @rik ?”

Nous voulons donc maintenant détecter la liste des destinataires d’un message, s’il y en a. Nous allons également en profiter pour envoyer l’identifiant du message. Cela nous servira plus tard.

La nouvelle version de notre Hub est la suivante :

using Microsoft.AspNet.SignalR;
using System.Collections.Generic;
using System.Linq;

namespace SignalRChat
{
    public class TwignalRHub : Hub
    {
        static int nbMessages;
        public void SendToHub(string name, string message)
        {
            var filteredMessage = message.Replace(',', ' ').Replace('.', ' ').Replace('!', ' ').Replace('?', ' ');
            var destinataires = filteredMessage.Split(' ').Where(w => w.StartsWith("@")).ToArray();

            nbMessages++;
            Clients.All.sendToClients(name, message, nbMessages, destinataires);
        }
    }
}

Dans la méthode SendToHub, nous avons simplement filtré notre message de quelques caractères spéciaux, puis sélectionné les mots commençant par “@”.

Nous incrémentons également une variable privée statique nbMessages. Ceci nous servira à des fins de débuggage. En effet, il est important de NE RIEN STOCKER dans la classe Hub : celle-ci est désinstanciée en cas d’inutilisation. A la prochaine connexion d’un client, une nouvelle instance de notre Hub sera créée, et notre nbMessages retombera à 0.

Modification du client

Il nous reste maintenant à modifier le client. Premièrement, nous allons ajouter un nouveau div dont l’id est mentions à notre container :

<div class="container">
    <input type="text" id="message" />
    <input type="submit" id="sendmessage" value="Send" />
    <input type="hidden" id="displayname" />
    <br />
    <br />
    <div style="width: 45%; float: left; border: solid 1px #dad7d7; margin-right: 20px; padding: 5px; " id="discussion" onclick="vider('#h3Messages', 'Fil de discussion', '#nbMessages')">
        <input type="hidden" id="nbMessages" value="0" />
        <h3 id="h3Messages">Fil de discussion</h3>
    </div>
    <div style="width: 45%; float: left; border: solid 1px #dad7d7; margin-right: 20px; padding: 5px; " id="mentions" onclick="vider('#h3Mentions', 'Mentions', '#nbMentions')">
        <input type="hidden" id="nbMentions" value="0" />
        <h3 id="h3Mentions">Mentions</h3>
    </div>
</div>

Nous en profitons pour également ajouter deux champs hidden “nbMessages” et “nbMentions”. Ils nous serviront à afficher des compteurs.

Il faut maintenant modifier la méthode chat.client.sendToClients :

chat.client.sendToClients = function (name, message, messageId, to) {
                
                // Add the message to the page.
                var nbMessages = parseInt($('#nbMessages').val())
                var nbMentions = parseInt($('#nbMentions').val())

                var borderColor
                var displayNameWithAt = "@@" + $('#displayname').val()

                if ($.inArray(displayNameWithAt, to) > -1) {
                    borderColor = '#FF0000'

                    nbMentions = nbMentions + 1
                    $('#nbMentions').val(nbMentions)
                    $('#h3Mentions').text('Mentions (' + nbMentions + ')')

                    $('#h3Mentions').after('<div style="border: solid 1px #dad7d7; margin-top:5px; padding:5px"><strong>' + htmlEncode(messageId) + ' - ' + htmlEncode(name)
                    + '</strong>> ' + htmlEncode(message)
                    + ' | <a onclick="repondre(' + messageId + ')">Répondre</a><input type="hidden" id=from' + messageId + ' value="' + name + '" /></div>');
                }
                else {
                    borderColor = '#dad7d7'
                }

                $('#h3Messages').after('<div style="border: solid 1px ' + borderColor + '; margin-top:5px; padding:5px"><strong>' + htmlEncode(messageId) + ' - ' + htmlEncode(name)
                    + '</strong>> ' + htmlEncode(message)
                    + ' | <a onclick="repondre(' + messageId + ')">Répondre</a><input type="hidden" id=from' + messageId + ' value="' + name + '" /></div>');

                nbMessages = nbMessages + 1
                $('#nbMessages').val(nbMessages)
                $('#h3Messages').text('Fil de discussion (' + nbMessages + ')')
            }

L’idée ici est à la réception du message de vérifier si l’utiisateur courant est dans la liste des destinataires, contenue dans le paramètre to. Si c’est effectivement le cas, nous incrémentons le compteur nbMentions situé dans le champ caché vu un peu plus haut. Et nous ajoutons le message à la liste des mentions. Mais nous ajoutons également un bouton Répondre, qui permet de… répondre à l’auteur du message en appelant la méthode repondre() dont le code est le suivant :

        function repondre(idMessage) {
            var from = $('#from' + idMessage).val()
            $('#message').val('@@' + from + ' ')
            $('#message').focus();
        }

L’application est disponible sur AppHarbor. Et le code est sur GitHub.

Nous avons donc vu dans cet exemple comment faire évoluer simple (mais pas très propre) notre application. Il nous reste encore pas mal de choses à faire. D’abord ajouter la possibilité d’envoyer des messages privés à un utilisateur connecté. Nous voudrons également afficher la liste des utilisateurs actuellement connectés au Hub. Nous allons également revoir l’authentification, pour le moment légèrement rudimentaire.

Mais notre ambition est sans limite. Pour le moment, la partie cliente est loin d’être un modèle du genre. Nous allons implémenter une belle interface grâce à Bootstrap, et travailler plus proprement avec Angularjs.

Tags: asp.net, mvc, SignalR 2,

Un commentaire. Laisser un commentaire

[…] SignalR présenté précédemment par Nicholas Suter que vous retrouverez à ces liens : Article 1 Article 2 Article […]

Répondre

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *