From 01a1ce097c3a21c09405acfeb6c6e0a961fdcd14 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Mon, 15 Aug 2016 12:37:51 +0200 Subject: [PATCH] Fixed long-polling and made some improvements in messages --- pages/js/index.js | 12 +----- pages/js/receivemessage.js | 37 +++++++++++++++---- pages/js/sendmessage.js | 8 ++-- pages/js/utils.js | 4 +- src/io/github/norbipeti/chat/server/Main.java | 9 +++-- .../chat/server/data/LoaderCollection.java | 21 +++++++++-- .../data/LoaderCollectionSerializer.java | 11 ++++-- .../chat/server/db/domain/Message.java | 32 ++++++++++++++++ .../norbipeti/chat/server/db/domain/User.java | 4 -- .../norbipeti/chat/server/page/IndexPage.java | 18 ++++----- .../server/page/ReceiveMessageAjaxPage.java | 26 ++++++++++++- .../chat/server/page/SendMessageAjaxPage.java | 2 + 12 files changed, 133 insertions(+), 51 deletions(-) diff --git a/pages/js/index.js b/pages/js/index.js index 0a1d36a..26bd47c 100644 --- a/pages/js/index.js +++ b/pages/js/index.js @@ -8,17 +8,7 @@ $(document).ready(function () { var nodes = cmsgs.children; for (var x = 0; x < nodes.length; x++) { var item = nodes[x]; - console.log(item); - var spans = item.getElementsByTagName("span"); - var ctime = null; - for (var i = 0; i < spans.length; i++) - if (spans[i].className.split(' ').indexOf("converttime") > -1) - ctime = spans[i]; - if (ctime != null) - console.log(ctime.innerText); - if (ctime != null) - ctime.innerText = moment(ctime.innerText, "YYYY-MM-DDTHH:mm:ssZ").fromNow(); //.format("lll"); + handlereceivedmessage(item); } - cmsgs.lastElementChild.scrollIntoView(false); } }); diff --git a/pages/js/receivemessage.js b/pages/js/receivemessage.js index 39b6e3c..78dd80b 100644 --- a/pages/js/receivemessage.js +++ b/pages/js/receivemessage.js @@ -1,7 +1,30 @@ -(function poll() { - setTimeout(function() { - $.ajax({ url: "/receivemessage", success: function(data) { - - }, dataType: "json", complete: poll }); - }, 100); -})(); +var handlereceivedmessage = function handlereceivedmessage(msgnode) { + var spans = msgnode.getElementsByTagName("span"); + var ctime = null; + for (var i = 0; i < spans.length; i++) + if (spans[i].className.split(' ').indexOf("converttime") > -1) + ctime = spans[i]; + if (ctime != null) + ctime.innerText = moment(ctime.innerText, "YYYY-MM-DDTHH:mm:ssZ").fromNow(); + msgnode.scrollIntoView(false); +} + + (function poll() { + setTimeout(function () { + $.ajax({ + url: "/receivemessage", success: function (data) { + console.log(data); + var msgelement = document.getElementById("channelmessages").appendChild(document.createElement("div")); + var header = msgelement.appendChild(document.createElement("p"); + header.innerText = data.sender.name + " - "; + var isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); + isoFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + header.appendElement("span").addClass("converttime") + .value = isoFormat.format(data.time) + "+00:00"; + var body = msgelement.appendChild(document.createElement("p")); + body.innerText = data.message; + handlereceivedmessage(msgnode); + }, dataType: "json", complete: poll + }); + }, 100); + })(); \ No newline at end of file diff --git a/pages/js/sendmessage.js b/pages/js/sendmessage.js index 67d55d9..ce20cf9 100644 --- a/pages/js/sendmessage.js +++ b/pages/js/sendmessage.js @@ -7,8 +7,8 @@ var sendmsg = function sendmsg(msginputta) { }; var respfunc = function respfunc(result) { + var msginput = document.getElementById("msginput"); if (result != "Success") { //on success result is string - var msginput = document.getElementById("msginput"); if (result.responseText.indexOf("JSONERROR") != -1) { console.log("Got JSON error. Retrying..."); console.log(result.responseText); @@ -19,8 +19,10 @@ var respfunc = function respfunc(result) { msginput.disabled = false; } } - else - location.reload(true); //TODO: Don't referesh on message send + else { + msginput.value = ""; + msginput.disabled = false; + } }; var sendmsgonenter = function sendmsgonenter(e) { diff --git a/pages/js/utils.js b/pages/js/utils.js index 761362c..01c0ade 100644 --- a/pages/js/utils.js +++ b/pages/js/utils.js @@ -14,7 +14,7 @@ function getFormData($form) { function showError(message) { var errormsg = document.getElementById("errormsg"); - errormsg.innerHTML = result.responseText; + errormsg.innerHTML = message; errormsg.style = "display: block"; - setTimeout(function(){errormsg.style.display="none";}, 2000); + setTimeout(function () { errormsg.style.display = "none"; }, 2000); } \ No newline at end of file diff --git a/src/io/github/norbipeti/chat/server/Main.java b/src/io/github/norbipeti/chat/server/Main.java index ff2cb51..f11d617 100644 --- a/src/io/github/norbipeti/chat/server/Main.java +++ b/src/io/github/norbipeti/chat/server/Main.java @@ -30,7 +30,8 @@ public class Main { // https://docs.oracle.com/javase/8/docs/api/ LogManager.getLogger().log(Level.INFO, "Loading files..."); DataManager.init(); - final GsonBuilder gsonBuilder = new GsonBuilder(); + final GsonBuilder saveGsonBuilder = new GsonBuilder(); + final GsonBuilder exchangeGsonBuilder = new GsonBuilder(); Reflections rf = new Reflections(new ConfigurationBuilder() .setUrls(ClasspathHelper.forClassLoader(ManagedData.class.getClassLoader())) .addClassLoader(ManagedData.class.getClassLoader()).addScanners(new SubTypesScanner()) @@ -39,11 +40,11 @@ public class Main { for (Class data : datas) { if (Modifier.isAbstract(data.getModifiers())) continue; - gsonBuilder.registerTypeAdapter(new DataType(LoaderCollection.class, data), + saveGsonBuilder.registerTypeAdapter(new DataType(LoaderCollection.class, data), new LoaderCollectionSerializer()); - gsonBuilder.registerTypeAdapter(new DataType(LoaderRef.class, data), new LoaderRefSerializer()); + saveGsonBuilder.registerTypeAdapter(new DataType(LoaderRef.class, data), new LoaderRefSerializer()); } - gson = gsonBuilder.create(); + gson = saveGsonBuilder.create(); /* * User user = new User(); user.setName("asd"); user.setEmail("test@test.com"); User user2 = new User(); user2.setName("Teszt"); user2.setEmail("test2@test.com"); // user = * provider.save(user); // user2 = provider.save(user2); user.getContacts().add(user2); user2.getContacts().add(user); LogManager.getLogger().log(Level.DEBUG, "1st's contact: " + diff --git a/src/io/github/norbipeti/chat/server/data/LoaderCollection.java b/src/io/github/norbipeti/chat/server/data/LoaderCollection.java index c43b032..a86476d 100644 --- a/src/io/github/norbipeti/chat/server/data/LoaderCollection.java +++ b/src/io/github/norbipeti/chat/server/data/LoaderCollection.java @@ -18,7 +18,6 @@ import io.github.norbipeti.chat.server.db.domain.SavedData; *

* * @author Norbi - * * @param */ public class LoaderCollection extends Loader implements List { @@ -41,7 +40,7 @@ public class LoaderCollection extends Loader implements Lis public LoaderCollection(LoaderCollection parentofsub, int fromIndex, int toIndex) { this.cl = parentofsub.cl; - idlist = parentofsub.idlist.subList(fromIndex, toIndex); + idlist = parentofsub.idlist.subList(fromIndex, toIndex); // TODO: Test } public LoaderCollection(Class cl, int capacity) { @@ -132,8 +131,7 @@ public class LoaderCollection extends Loader implements Lis /** * Remove an object from this collection * - * @param o - * Either the object of type T or the ID + * @param o Either the object of type T or the ID */ @Override public boolean remove(Object o) { @@ -228,4 +226,19 @@ public class LoaderCollection extends Loader implements Lis sb.append("]"); return sb.toString(); } + + @SuppressWarnings("unchecked") + public Object clone() { + Object cloned = null; + if (idlist instanceof ArrayList) + cloned = ((ArrayList) idlist).clone(); + if (cloned == null) + return cloned; + else { + LoaderCollection lc = new LoaderCollection(cl, this.size()); + if (cloned instanceof List) + lc.idlist = (List) cloned; + return lc; + } + } } diff --git a/src/io/github/norbipeti/chat/server/data/LoaderCollectionSerializer.java b/src/io/github/norbipeti/chat/server/data/LoaderCollectionSerializer.java index ce2c861..9444742 100644 --- a/src/io/github/norbipeti/chat/server/data/LoaderCollectionSerializer.java +++ b/src/io/github/norbipeti/chat/server/data/LoaderCollectionSerializer.java @@ -1,6 +1,7 @@ package io.github.norbipeti.chat.server.data; import java.io.IOException; +import java.util.Collection; import java.util.List; import com.google.gson.Gson; @@ -14,9 +15,7 @@ import io.github.norbipeti.chat.server.db.domain.ManagedData; // @SuppressWarnings("rawtypes") public class LoaderCollectionSerializer extends TypeAdapter> { - // private static final Type returnType = getReturnType(); - // http://stackoverflow.com/a/17300227 @Override public void write(JsonWriter out, LoaderCollection value) throws IOException { if (value == null) { @@ -40,9 +39,13 @@ public class LoaderCollectionSerializer extends TypeAdapter> } in.beginObject(); in.nextName(); - List list = new Gson().fromJson(in, new TypeToken>() { + List list; + LoaderCollection itemcol; + list = new Gson().fromJson(in, new TypeToken>() { }.getType()); - if (!in.nextName().equals("class")) { + if (!in.nextName().equals("class")) + + { new Exception("Error: Next isn't \"class\"").printStackTrace(); return null; } diff --git a/src/io/github/norbipeti/chat/server/db/domain/Message.java b/src/io/github/norbipeti/chat/server/db/domain/Message.java index f004e34..676c7d5 100644 --- a/src/io/github/norbipeti/chat/server/db/domain/Message.java +++ b/src/io/github/norbipeti/chat/server/db/domain/Message.java @@ -1,9 +1,17 @@ package io.github.norbipeti.chat.server.db.domain; +import java.text.SimpleDateFormat; import java.util.Date; +import java.util.TimeZone; import javax.persistence.*; +import org.jsoup.nodes.Element; + +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; + +import io.github.norbipeti.chat.server.Main; import io.github.norbipeti.chat.server.data.LoaderRef; @Entity @@ -92,4 +100,28 @@ public class Message extends ManagedData { @Override protected void init() { } + + public Element getAsHTML(Element channelmessages) { + Element msgelement = channelmessages.appendElement("div"); + Element header = msgelement.appendElement("p"); + header.text(getSender().get().getName() + " - "); + header.appendElement("span").addClass("converttime").text(formatDate()); + Element body = msgelement.appendElement("p"); + body.text(getMessage()); + return msgelement; + } + + public JsonObject getAsJson() { + JsonObject msgobj = new JsonObject(); + msgobj.add("sender", Main.gson.toJsonTree(getSender().get())); + msgobj.add("message", new JsonPrimitive(getMessage())); + msgobj.add("time", new JsonPrimitive(formatDate())); + return msgobj; + } + + private String formatDate() { + SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); + isoFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + return isoFormat.format(getTime()) + "+00:00"; + } } diff --git a/src/io/github/norbipeti/chat/server/db/domain/User.java b/src/io/github/norbipeti/chat/server/db/domain/User.java index 05b9e60..73688c1 100644 --- a/src/io/github/norbipeti/chat/server/db/domain/User.java +++ b/src/io/github/norbipeti/chat/server/db/domain/User.java @@ -95,10 +95,6 @@ public class User extends SavedData { private User() { } - public static LoaderCollection getUsers() { - return DataManager.getAll(User.class); - } - @Override public long getId() { return id; diff --git a/src/io/github/norbipeti/chat/server/page/IndexPage.java b/src/io/github/norbipeti/chat/server/page/IndexPage.java index 1937cd5..27a9e29 100644 --- a/src/io/github/norbipeti/chat/server/page/IndexPage.java +++ b/src/io/github/norbipeti/chat/server/page/IndexPage.java @@ -2,6 +2,7 @@ package io.github.norbipeti.chat.server.page; import java.io.IOException; import java.text.SimpleDateFormat; +import java.util.Collections; import java.util.TimeZone; import org.apache.logging.log4j.Level; @@ -49,6 +50,7 @@ public class IndexPage extends Page { convs.add(c); // TODO: Handle no conversation open } user.getConversations().add(convs.get(0)); + convs.get(0).getUsers().add(user); } Conversation conv = user.getConversations().get(0); Element cide = channelmessages.appendElement("p"); @@ -56,17 +58,13 @@ public class IndexPage extends Page { cide.attr("id", "convidp"); cide.text(Long.toString(conv.getId())); LogManager.getLogger().log(Level.DEBUG, "Messages: " + conv.getMesssageChunks().size()); - for (MessageChunk chunk : conv.getMesssageChunks()) { // TODO: Reverse + @SuppressWarnings("unchecked") + LoaderCollection chunks = (LoaderCollection) conv.getMesssageChunks() + .clone(); + Collections.reverse(chunks); + for (MessageChunk chunk : chunks) { for (Message message : chunk.getMessages()) { - Element msgelement = channelmessages.appendElement("div"); - Element header = msgelement.appendElement("p"); - header.text(message.getSender().get().getName() + " - "); - SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); - isoFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - header.appendElement("span").addClass("converttime") - .text(isoFormat.format(message.getTime()) + "+00:00"); - Element body = msgelement.appendElement("p"); - body.text(message.getMessage()); + message.getAsHTML(channelmessages); } } return doc; diff --git a/src/io/github/norbipeti/chat/server/page/ReceiveMessageAjaxPage.java b/src/io/github/norbipeti/chat/server/page/ReceiveMessageAjaxPage.java index 1621354..9aa4b67 100644 --- a/src/io/github/norbipeti/chat/server/page/ReceiveMessageAjaxPage.java +++ b/src/io/github/norbipeti/chat/server/page/ReceiveMessageAjaxPage.java @@ -1,9 +1,18 @@ package io.github.norbipeti.chat.server.page; import java.io.IOException; +import java.util.HashMap; + +import org.apache.logging.log4j.LogManager; + +import com.google.gson.Gson; import com.google.gson.JsonObject; import com.sun.net.httpserver.HttpExchange; +import io.github.norbipeti.chat.server.Main; +import io.github.norbipeti.chat.server.data.LoaderRef; +import io.github.norbipeti.chat.server.db.domain.Conversation; +import io.github.norbipeti.chat.server.db.domain.Message; import io.github.norbipeti.chat.server.db.domain.User; import io.github.norbipeti.chat.server.io.IOHelper; @@ -15,6 +24,8 @@ public class ReceiveMessageAjaxPage extends Page { return "receivemessage"; } + public static HashMap exmap = new HashMap<>(); + @Override public void handlePage(HttpExchange exchange) throws IOException { User user = IOHelper.GetLoggedInUser(exchange); @@ -22,7 +33,7 @@ public class ReceiveMessageAjaxPage extends Page { IOHelper.SendResponse(403, "

Please log in to receive messages

", exchange); return; } - JsonObject obj = new JsonObject(); // TODO + exmap.put(user, exchange); /* * String message = obj.get("message").getAsString().trim(); int conversation = obj.get("conversation").getAsInt(); if (message.trim().length() == 0) { IOHelper.SendResponse(400, * "

400 Bad request

The message cannot be empty.

", exchange); return; } LoaderCollection convos = user.getConversations(); Conversation conv = null; @@ -33,7 +44,18 @@ public class ReceiveMessageAjaxPage extends Page { * "Added conversation's message count: " + conv.getMesssageChunks().size()); */ - IOHelper.SendResponse(200, "Success", exchange); } + public static void sendMessageBack(Message msg, Conversation conv) throws IOException { + for (User user : conv.getUsers()) { + LogManager.getLogger().debug("User: " + user); + if (exmap.containsKey(user)) { + LogManager.getLogger().debug("Exmap contains user"); + JsonObject msgobj = msg.getAsJson(); + IOHelper.SendResponse(200, msgobj.toString(), exmap.get(user)); + exmap.remove(user); + } else + LogManager.getLogger().warn("User is not listening: " + user); + } + } } diff --git a/src/io/github/norbipeti/chat/server/page/SendMessageAjaxPage.java b/src/io/github/norbipeti/chat/server/page/SendMessageAjaxPage.java index c30e74e..73e3018 100644 --- a/src/io/github/norbipeti/chat/server/page/SendMessageAjaxPage.java +++ b/src/io/github/norbipeti/chat/server/page/SendMessageAjaxPage.java @@ -71,6 +71,8 @@ public class SendMessageAjaxPage extends Page { LogManager.getLogger().log(Level.DEBUG, "Added conversation's message count: " + conv.getMesssageChunks().size()); + ReceiveMessageAjaxPage.sendMessageBack(msg, conv); + IOHelper.SendResponse(200, "Success", exchange); }