Skip to content

Instantly share code, notes, and snippets.

@codeplanner
Last active December 24, 2015 14:49
Show Gist options
  • Save codeplanner/6815648 to your computer and use it in GitHub Desktop.
Save codeplanner/6815648 to your computer and use it in GitHub Desktop.
A simple chat where you can select one or more clients to recieve the message... The run the sample: 1 - Create a new project in Visual Studio (I used MVC4) 2 - Install XSockets from nuget 3 - Add the chat.cs file below 4 - Add the chat.html file below 5 - Go to project properties and set project to run under Visual Studio Development Server 6 -…
using System;
using System.Collections.Generic;
using System.Linq;
using XSockets.Core.Common.Socket.Event.Attributes;
using XSockets.Core.XSocket;
using XSockets.Core.XSocket.Helpers;
namespace SimpleChat
{
/// <summary>
/// A model for easier model bidning when sending messages
/// </summary>
public class ChatMessage
{
public string UserName { get; set; }
public string Time { get; set; }
public string Message { get; set; }
}
/// <summary>
/// The userinfo... Makes more sense to also have a name on the user
/// </summary>
public class User
{
public Guid Id { get; set; }
public string UserName { get; set; }
}
/// <summary>
/// A custom plugin (controller) in XSockets
/// This one for a simple chat where you can select who to target...
/// </summary>
public class Chat : XSocketController
{
/// <summary>
/// The user for this controller.
/// The NoEvent prevent the property from being changed from JavaScript directly
/// </summary>
[NoEvent]
public User User { get; set; }
/// <summary>
/// Ctor - listen for the disconnect event
/// </summary>
public Chat()
{
this.OnClientDisConnect += Chat_OnClientDisConnect;
}
void Chat_OnClientDisConnect(object sender, XSockets.Core.Common.Socket.Event.Arguments.OnClientDisConnectArgs e)
{
//Tell all clients that I leave
this.SendToAllExceptMe(this.User,"onClientDisconnected");
}
/// <summary>
/// Send a message to the clients having their ClientGuid in the clients list
/// </summary>
/// <param name="message"></param>
/// <param name="clients"></param>
public void OnChatMessage(string message, List<Guid> clients)
{
//Create a chatmessage
var chatMessage = new ChatMessage
{
UserName = this.User.UserName,
Message = message,
Time = DateTime.Now.ToLongTimeString()
};
//If you want to always send to the sender as well... uncomment this...
//if(!clients.Contains(this.ClientGuid))
// clients.Add(this.ClientGuid);
//send the message to the clients in the list provided
this.SendTo(p => clients.Contains(p.ClientGuid), chatMessage,"onChatMessage");
}
/// <summary>
/// Set the username for the client and notify others that I am online
/// </summary>
/// <param name="userName"></param>
public void SetUserName(string userName)
{
//Set the username
this.User = new User{ Id = this.ClientGuid, UserName = userName};
//Tell others that the user is online
this.SendToAllExceptMe(this.User, "onClientConnected");
//Send all other clients to me, but only clients that have set a username
this.Send(this.Find(p => p.User != null).Select(p => p.User),"onClientList");
}
}
}
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="Scripts/jquery-1.9.1.js"></script>
<script src="Scripts/XSockets.latest.js"></script>
<script src="Scripts/knockout-2.3.0.js"></script>
<style>
select { min-width: 150px;}
input { min-width: 150px;}
</style>
<script>
var ChatViewModel = {
me: ko.observable(''),
messages: ko.observableArray([]),
users: ko.observableArray([]),
userRemove: function (user) {
console.log('userremove ',user);
var match = ko.utils.arrayFirst(ChatViewModel.users(), function (u) {
return u.Id === user.Id;
});
if (match) {
ChatViewModel.users.remove(match);
}
}
};
var conn = null;
$(function () {
//Hide the chat when we start...
$('#chat').hide();
//Bind knockout
ko.applyBindings(ChatViewModel);
//Connect to our custom Chat Controller...
conn = new XSockets.WebSocket('ws://127.0.0.1:4502/Chat');
//When the open event is fired...
conn.on(XSockets.Events.open, function (clientInfo) {
console.log('Connected to Chat', clientInfo);
//Bind to our custom event... called chatMessage
conn.on('onChatMessage', function (data) {
//Prepend to chat...
ChatViewModel.messages.unshift(data);
});
//When we get the list of clients...
conn.on('onClientList', function (clients) {
ChatViewModel.users(clients);
});
//listen for new clients
conn.on('onClientConnected', function (client) {
ChatViewModel.users.push(client);
});
//listen for clients that leave
conn.on('onClientDisconnected', function (client) {
ChatViewModel.userRemove(client);
});
});
//UI Events
//When the user click join button... Open websocket
$('#btn-join').on('click', function () {
var userName = $('#input-username').val().trim();
if (userName.length === 0) {
alert("You have to provide a username");
return;
}
//Set the username
conn.publish('setUserName', { userName: userName });
ChatViewModel.me(userName);
//Show the chat
$('#join').hide();
$('#chat').show();
});
//Send a message to the client(s) selected
$('#btn-send').on('click', function () {
var message = $('#input-message').val().trim();
if (message.length === 0) {
alert("You have to provide a message");
return;
}
var clients = $('#select-clients').val();
if (clients === null) {
alert("You have not selected any client(s) to send to");
return;
}
//Send the message written and include the clients selected
conn.publish('onChatMessage', { message: message, clients: clients});
});
});
</script>
</head>
<body>
<div id="join">
<input id="input-username" placeholder="Write username here..." />
<button id="btn-join">Join Chat</button>
</div>
<div id="chat">
<h3 data-bind="text:me"></h3>
<div>
<h4>Select all clients in the multiselect-list that should get the message</h4>
<select multiple="multiple" id="select-clients" data-bind="foreach:users">
<option data-bind="value: Id, text: UserName"></option>
</select><br/>
<input id="input-message" placeholder="Message here..." value="Hello World"/>
<button id="btn-send">Send</button>
</div>
<h3>Messages</h3>
<table>
<thead>
<tr>
<td>Time</td>
<td>From</td>
<td>Message</td>
</tr>
</thead>
<tbody data-bind="foreach: messages">
<tr>
<td data-bind="text:Time"></td>
<td data-bind="text:UserName"></td>
<td data-bind="text:Message"></td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment