From a09af4b1fa0ea2067d05c03788e1552ab28711c6 Mon Sep 17 00:00:00 2001 From: "Valeriano A.R" Date: Wed, 27 May 2015 01:23:31 +0200 Subject: [PATCH] Chat: Basic send and receive messages. --- Scrummer/Code/Controls/ChatControl.cs | 48 +++++++++ Scrummer/Code/Controls/ChatHandler.cs | 141 ++++++++++++++++++++++++++ Scrummer/Scripts/10. Chat.js | 75 ++++++++++++++ Scrummer/Scrummer.csproj | 4 + Scrummer/Styles/10. Chat.css | 4 + 5 files changed, 272 insertions(+) create mode 100644 Scrummer/Code/Controls/ChatControl.cs create mode 100644 Scrummer/Code/Controls/ChatHandler.cs create mode 100644 Scrummer/Scripts/10. Chat.js create mode 100644 Scrummer/Styles/10. Chat.css diff --git a/Scrummer/Code/Controls/ChatControl.cs b/Scrummer/Code/Controls/ChatControl.cs new file mode 100644 index 0000000..7b13adc --- /dev/null +++ b/Scrummer/Code/Controls/ChatControl.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.UI; +using System.Web.UI.HtmlControls; +using System.Web.UI.WebControls; + +namespace Scrummer.Code.Controls +{ + public class ChatControl : Control + { + private int _idBoard = 0; + + public int IDBoard + { + get { return _idBoard; } + set { _idBoard = value; } + } + + public ChatControl() + { + Init += ChatControl_Init; + } + + void ChatControl_Init(object sender, EventArgs e) + { + var divChat = new Panel { ID = "divChat", CssClass = "divChat" }; + Controls.Add(divChat); + + var hidIDMessage = new HiddenField { ID = "hidIDMessage", Value = "0" }; + Controls.Add(hidIDMessage); + + var txtText = new TextBox { ID = "txtText", CssClass = "chatTextBox" }; + Controls.Add(txtText); + + var btnSend = new Button { ID = "btnSend", Text = "Send", CssClass = "chatButton" }; + Controls.Add(btnSend); + btnSend.Attributes.Add("onclick", String.Format("SendChat('{0}',{1}); return false;", txtText.ClientID, _idBoard)); + + + LiteralControl litScript = new LiteralControl(); + litScript.Text = String.Format("", + divChat.ClientID, _idBoard, hidIDMessage.ClientID); + Controls.Add(litScript); + } + } +} \ No newline at end of file diff --git a/Scrummer/Code/Controls/ChatHandler.cs b/Scrummer/Code/Controls/ChatHandler.cs new file mode 100644 index 0000000..dd07d0e --- /dev/null +++ b/Scrummer/Code/Controls/ChatHandler.cs @@ -0,0 +1,141 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Web; +using Scrummer.Code.JSON; + +namespace Scrummer.Code +{ + public class Message + { + public int IDMessage { get; set; } + public string UserName { get; set; } + public string Text { get; set; } + }; + + public class MessageBoard + { + private List _messages = new List(); + private int lastIDMessage = 0; + + public List Messages_GetList(int idMessage) + { + List listMessages = new List(); + for (int i = 0, n = _messages.Count; i < n; i++) + { + Message msg = _messages[i]; + if (msg.IDMessage > idMessage) + { + listMessages.Insert(0, msg); + } + else + { + break; + } + } + return listMessages; + } + + public void Message_Add(string userName, string text) + { + lastIDMessage++; + Message msg = new Message(); + msg.IDMessage = lastIDMessage; + msg.UserName = userName; + msg.Text = text; + _messages.Insert(0, msg); + } + } + + public class ChatHandler : IHttpHandler + { + private static object _monitor = new object(); + private static Dictionary _chatBoards = new Dictionary(); + + public bool IsReusable + { + get { throw new NotImplementedException(); } + } + + public void ProcessRequest(HttpContext context) + { + if (context.Request.RequestType == "GET") + { + ProcessRevicer(context); + } + if (context.Request.RequestType == "POST") + { + ProcessSender(context); + } + } + + private void ProcessRevicer(HttpContext context) + { + int idBoard = Convert.ToInt32(context.Request.Params["idBoard"]); + int idMessage = Convert.ToInt32(context.Request.Params["idMessage"]); + MessageBoard messageBoard; + bool mustWait = true; + do + { + if (_chatBoards.ContainsKey(idBoard)) + { + messageBoard = _chatBoards[idBoard]; + List listMessages = messageBoard.Messages_GetList(idMessage); + if (listMessages.Count > 0) + { + mustWait = false; + ResponseObject(context, listMessages); + } + } + if (mustWait) + { + lock (_monitor) { Monitor.Wait(_monitor, 10000); } + } + } while (mustWait); + } + + private void ProcessSender(HttpContext context) + { + string strIDBoard = GetRequestParm(context, "idBoard"); + int idBoard = Convert.ToInt32(string.IsNullOrEmpty(strIDBoard) ? "0" : strIDBoard); + string userName = Convert.ToString(GetRequestParm(context, "userName")); + string text = Convert.ToString(GetRequestParm(context, "text")); + + lock (_chatBoards) + { + MessageBoard messageBoard; + if (_chatBoards.ContainsKey(idBoard)) + { + messageBoard = _chatBoards[idBoard]; + } + else + { + messageBoard = new MessageBoard(); + _chatBoards[idBoard] = messageBoard; + } + messageBoard.Message_Add(userName, text); + lock (_monitor) { Monitor.PulseAll(_monitor); } + } + } + + private string GetRequestParm(HttpContext context, string parm) + { + foreach (string key in context.Request.Params.AllKeys) + { + if (string.IsNullOrEmpty(key) == false && key.EndsWith(parm)) + { + return context.Request.Params[key]; + } + } + return string.Empty; + } + + private void ResponseObject(HttpContext context, object obj) + { + var jsonWritter = new JSONWriter(true); + context.Response.ContentType = "text/json"; + context.Response.Write(jsonWritter.Write(obj)); + } + } +} \ No newline at end of file diff --git a/Scrummer/Scripts/10. Chat.js b/Scrummer/Scripts/10. Chat.js new file mode 100644 index 0000000..038a627 --- /dev/null +++ b/Scrummer/Scripts/10. Chat.js @@ -0,0 +1,75 @@ +function RunChat(divContainer, idBoard, hidIDMessage) { + divContainer = GetElement(divContainer); + hidIDMessage = GetElement(hidIDMessage); + + var CreateMessageDOM = function (message) { + var divMessageRow = document.createElement("DIV"); + divMessageRow.className = "messageRow"; + + var divMessage = document.createElement("DIV"); + divMessage.className = "message"; + divMessageRow.appendChild(divMessage); + + var divUser = document.createElement("DIV"); + divUser.className = "user"; + divUser.innerHTML = escapeHTML(message.UserName); + divMessage.appendChild(divUser); + + var text = message.Text; + + var divText = document.createElement("DIV"); + divText.className = "text"; + divText.innerHTML = escapeHTML(text); + divMessage.appendChild(divText); + + return divMessageRow; + }; + + var RequestChatData = function () { + var requestUrl = "ChatHandler?idBoard=" + idBoard + "&idMessage=" + hidIDMessage.value; + var ReciveChatData = function (responseText) { + + recvMsgs = JSON.parse(responseText); + if (recvMsgs) { + var idMessage = parseInt(hidIDMessage.value); + for (var i = 0, n = recvMsgs.length; i < n; i++) { + var msg = recvMsgs[i]; + if (idMessage < msg.IDMessage) { + hidIDMessage.value = msg.IDMessage; + idMessage = msg.IDMessage; + var elemMessage = CreateMessageDOM(msg); + divContainer.appendChild(elemMessage); + } + } + divContainer.scrollTop = divContainer.scrollHeight; + } + + // Reset pool + window.setTimeout(function () { + RequestChatData(); + }, 20); + }; + var ErrorChatData = function () { + + // Retry + window.setTimeout(function () { + RequestChatData(); + }, 5000); + }; + + // Pool data + SendRequest(requestUrl, ReciveChatData, ErrorChatData); + }; + RequestChatData(); +} + +function SendChat(txtText, idBoard) { + txtText = GetElement(txtText); + var data = { + "text": txtText.value, + "idBoard": idBoard, + "userName": "VAR" + }; + txtText.value = ""; + SendData("ChatHandler", data, null, null); +} \ No newline at end of file diff --git a/Scrummer/Scrummer.csproj b/Scrummer/Scrummer.csproj index eab6730..26b1a1d 100644 --- a/Scrummer/Scrummer.csproj +++ b/Scrummer/Scrummer.csproj @@ -70,11 +70,15 @@ + + + + diff --git a/Scrummer/Styles/10. Chat.css b/Scrummer/Styles/10. Chat.css new file mode 100644 index 0000000..004b1c0 --- /dev/null +++ b/Scrummer/Styles/10. Chat.css @@ -0,0 +1,4 @@ +.divChat { + overflow: auto; + height: 300px; +}