From 23134e74f0ad29aaf69daba33b9337285fdbb84a Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Tue, 16 Aug 2016 23:11:42 +0200 Subject: [PATCH] Many fixes and other things - Fixed handling the case of no messages in conversation - Changed sending new messages to HTML instead of JSON - So the message format is at one place - Fixed new messages showing the conversation ID to the user at the top - Fixed unsent messages - Fixed unread indicator on own message - Fixed error hider timer - Fixed message receiving when not logged in --- .settings/org.eclipse.jdt.core.prefs | 1 + .settings/org.eclipse.jdt.ui.prefs | 2 + pages/js/receivemessage.js | 55 +++++++++++-------- pages/js/sendmessage.js | 4 +- pages/js/utils.js | 9 ++- src/io/github/norbipeti/chat/server/Main.java | 2 - .../data/LoaderCollectionSerializer.java | 2 - .../chat/server/db/domain/Message.java | 8 ++- .../norbipeti/chat/server/db/domain/User.java | 1 - .../norbipeti/chat/server/page/IndexPage.java | 14 ++--- .../server/page/ReceiveMessageAjaxPage.java | 55 +++++++++---------- 11 files changed, 83 insertions(+), 70 deletions(-) create mode 100644 .settings/org.eclipse.jdt.ui.prefs diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index cbd0dab..9e54ec2 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -104,3 +104,4 @@ org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning org.eclipse.jdt.core.compiler.source=1.8 +org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter diff --git a/.settings/org.eclipse.jdt.ui.prefs b/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 0000000..069fa88 --- /dev/null +++ b/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +formatter_settings_version=12 diff --git a/pages/js/receivemessage.js b/pages/js/receivemessage.js index 54b6f3e..27cace9 100644 --- a/pages/js/receivemessage.js +++ b/pages/js/receivemessage.js @@ -1,11 +1,15 @@ -function handlereceivedmessage(msgnode) { +function updatemsgtime(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(); + ctime.innerText = moment($(ctime).data("val"), "YYYY-MM-DDTHH:mm:ssZ").fromNow(); +} + +function handlereceivedmessage(msgnode) { + updatemsgtime(msgnode); msgnode.scrollIntoView(false); } @@ -16,12 +20,13 @@ var updateUnreadCount = function () { document.title = "(" + unreadCount + ") Chat"; else document.title = "Chat"; - var msgs = document.getElementById("channelmessages").children; + var msgs = document.getElementById("channelmessages").getElementsByClassName("chmessage"); for (var i = msgs.length - 1; i >= 0; i--) { if (i >= msgs.length - unreadCount) msgs[i].style.backgroundColor = "darkgray"; else msgs[i].style = ""; + updatemsgtime(msgs[i]); } }; @@ -35,27 +40,29 @@ var resetUnread = function resetUnread() { updateUnreadCount(); }; -(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 span = header.appendChild(document.createElement("span")); - span.className = "converttime"; - span.innerText = data.time; - var body = msgelement.appendChild(document.createElement("p")); - body.innerText = data.message; - handlereceivedmessage(msgelement); - addUnread(); - }, dataType: "json", complete: poll - }); - }, 100); -})(); - +var readTimer = null; $(document).ready(function () { - $('#msginput').on("focus", resetUnread); + $('#msginput').on("focus", function () { readTimer == null ? readTimer = setTimeout(function () { resetUnread(); }, 3000) : readTimer; }); $('#msginput').on("keydown", resetUnread); + $('#msginput').on("blur", function () { readTimer != null ? clearTimeout(readTimer) : readTimer; }); + + if (isLoggedIn()) + (function poll() { + setTimeout(function () { + $.ajax({ + url: "/receivemessage", success: function (data) { + var msgs = document.getElementById("channelmessages"); + msgs.innerHTML += data; + var msgelement = msgs.children[msgs.children.length - 1]; + handlereceivedmessage(msgelement); + if (justsentmsgread) + justsentmsgread = false; + else + addUnread(); + }, error: function (data) { + showError(data.responseText); + }, dataType: "text", complete: poll + }); + }, 100); + })(); }); diff --git a/pages/js/sendmessage.js b/pages/js/sendmessage.js index b5f4dc4..d311bdf 100644 --- a/pages/js/sendmessage.js +++ b/pages/js/sendmessage.js @@ -1,11 +1,11 @@ var sendmsg = function sendmsg(msginputta) { window.jsonobj = JSON.stringify({ "message": msginputta.value, "conversation": window.convid }); - console.log(window.jsonobj); $.ajax({ url: "/sendmessage", data: window.jsonobj, method: "POST", success: respfunc, error: respfunc }); }; +var justsentmsgread = false; var respfunc = function respfunc(result) { var msginput = document.getElementById("msginput"); if (result != "Success") { //on success result is string @@ -18,12 +18,14 @@ var respfunc = function respfunc(result) { showError(result.responseText); msginput.disabled = false; msginput.focus(); + resetUnread(); } } else { msginput.value = ""; msginput.disabled = false; msginput.focus(); + justsentmsgread = true; } }; diff --git a/pages/js/utils.js b/pages/js/utils.js index 8663fab..eb319fe 100644 --- a/pages/js/utils.js +++ b/pages/js/utils.js @@ -12,9 +12,16 @@ function getFormData($form) { return indexed_array; } +var errorcleartimer = null; function showError(message) { + if (errorcleartimer != null) + clearInterval(errorcleartimer); var errormsg = document.getElementById("errormsg"); errormsg.innerHTML = message; errormsg.style = "display: block"; - setTimeout(function () { errormsg.style.display = "none"; }, 2000); + errorcleartimer = setTimeout(function () { errormsg.style.display = "none"; }, 2000); +} + +function isLoggedIn() { + return document.getElementById("usercontent") != null; } diff --git a/src/io/github/norbipeti/chat/server/Main.java b/src/io/github/norbipeti/chat/server/Main.java index f11d617..558a56e 100644 --- a/src/io/github/norbipeti/chat/server/Main.java +++ b/src/io/github/norbipeti/chat/server/Main.java @@ -19,7 +19,6 @@ import io.github.norbipeti.chat.server.data.*; import io.github.norbipeti.chat.server.db.domain.*; import io.github.norbipeti.chat.server.io.DataType; import io.github.norbipeti.chat.server.page.*; -import io.vertx.core.Vertx; public class Main { public static Gson gson; @@ -31,7 +30,6 @@ public class Main { LogManager.getLogger().log(Level.INFO, "Loading files..."); DataManager.init(); 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()) diff --git a/src/io/github/norbipeti/chat/server/data/LoaderCollectionSerializer.java b/src/io/github/norbipeti/chat/server/data/LoaderCollectionSerializer.java index 9444742..673d82d 100644 --- a/src/io/github/norbipeti/chat/server/data/LoaderCollectionSerializer.java +++ b/src/io/github/norbipeti/chat/server/data/LoaderCollectionSerializer.java @@ -1,7 +1,6 @@ package io.github.norbipeti.chat.server.data; import java.io.IOException; -import java.util.Collection; import java.util.List; import com.google.gson.Gson; @@ -40,7 +39,6 @@ public class LoaderCollectionSerializer extends TypeAdapter> in.beginObject(); in.nextName(); List list; - LoaderCollection itemcol; list = new Gson().fromJson(in, new TypeToken>() { }.getType()); if (!in.nextName().equals("class")) 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 676c7d5..347f804 100644 --- a/src/io/github/norbipeti/chat/server/db/domain/Message.java +++ b/src/io/github/norbipeti/chat/server/db/domain/Message.java @@ -103,14 +103,20 @@ public class Message extends ManagedData { public Element getAsHTML(Element channelmessages) { Element msgelement = channelmessages.appendElement("div"); + msgelement.addClass("chmessage"); Element header = msgelement.appendElement("p"); header.text(getSender().get().getName() + " - "); - header.appendElement("span").addClass("converttime").text(formatDate()); + header.appendElement("span").addClass("converttime").attr("data-val", formatDate()); Element body = msgelement.appendElement("p"); body.text(getMessage()); return msgelement; } + /** + * + * @Deprecated Why send it as JSON then convert it to HTML? + */ + @Deprecated public JsonObject getAsJson() { JsonObject msgobj = new JsonObject(); msgobj.add("sender", Main.gson.toJsonTree(getSender().get())); 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 73688c1..7fcafe2 100644 --- a/src/io/github/norbipeti/chat/server/db/domain/User.java +++ b/src/io/github/norbipeti/chat/server/db/domain/User.java @@ -4,7 +4,6 @@ import java.io.IOException; import java.util.List; import javax.persistence.*; -import io.github.norbipeti.chat.server.data.DataManager; import io.github.norbipeti.chat.server.data.LoaderCollection; @Entity diff --git a/src/io/github/norbipeti/chat/server/page/IndexPage.java b/src/io/github/norbipeti/chat/server/page/IndexPage.java index 990edaf..ab80fd7 100644 --- a/src/io/github/norbipeti/chat/server/page/IndexPage.java +++ b/src/io/github/norbipeti/chat/server/page/IndexPage.java @@ -1,10 +1,6 @@ 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; import org.apache.logging.log4j.LogManager; import org.jsoup.nodes.Element; @@ -57,10 +53,12 @@ public class IndexPage extends Page { cide.attr("style", "display: none"); cide.attr("id", "convidp"); cide.text(Long.toString(conv.getId())); - LogManager.getLogger().log(Level.DEBUG, "Messages: " + conv.getMesssageChunks().size()); - MessageChunk chunk = conv.getMesssageChunks().get(conv.getMesssageChunks().size() - 1); - for (Message message : chunk.getMessages()) { - message.getAsHTML(channelmessages); + LogManager.getLogger().log(Level.DEBUG, "Messagechunks: " + conv.getMesssageChunks().size()); + if (conv.getMesssageChunks().size() > 0) { + MessageChunk chunk = conv.getMesssageChunks().get(conv.getMesssageChunks().size() - 1); + for (Message message : chunk.getMessages()) { + message.getAsHTML(channelmessages); + } } return doc; }, exchange); diff --git a/src/io/github/norbipeti/chat/server/page/ReceiveMessageAjaxPage.java b/src/io/github/norbipeti/chat/server/page/ReceiveMessageAjaxPage.java index 4d64b48..e44b858 100644 --- a/src/io/github/norbipeti/chat/server/page/ReceiveMessageAjaxPage.java +++ b/src/io/github/norbipeti/chat/server/page/ReceiveMessageAjaxPage.java @@ -1,17 +1,19 @@ package io.github.norbipeti.chat.server.page; import java.io.IOException; +import java.util.ArrayList; import java.util.HashMap; -import java.util.Map.Entry; +import java.util.Iterator; + +import javax.swing.text.html.HTMLDocument; import org.apache.logging.log4j.LogManager; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; -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; @@ -26,7 +28,7 @@ public class ReceiveMessageAjaxPage extends Page { } public static HashMap exmap = new HashMap<>(); - public static HashMap unsentmessages = new HashMap<>(); + public static HashMap> unsentmessages = new HashMap<>(); @Override public void handlePage(HttpExchange exchange) throws IOException { @@ -36,42 +38,35 @@ public class ReceiveMessageAjaxPage extends Page { return; } 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; - * LogManager.getLogger().log(Level.DEBUG, "Len: " + convos.size()); for (Conversation con : convos) { LogManager.getLogger().log(Level.DEBUG, con.getId()); if (con.getId() == conversation) { - * conv = con; break; } } if (conv == null) { IOHelper.SendResponse(400, "

400 Conversation not found

The conversation with the id " + conversation + " is not found.

", exchange); - * return; } MessageChunk chunk = ManagedData.create(MessageChunk.class); chunk.setConversation(conv); Message msg = new Message(); msg.setSender(user); msg.setMessage(message); - * msg.setTime(new Date()); msg.setMessageChunk(chunk); chunk.getMessages().add(msg); conv.getMesssageChunks().add(chunk); DataManager.save(conv); LogManager.getLogger().log(Level.DEBUG, - * "Added conversation's message count: " + conv.getMesssageChunks().size()); - */ - } public static void sendMessageBack(Message msg, Conversation conv) throws IOException { for (User user : conv.getUsers()) { // TODO: Load older messages when scrolling up - if (unsentmessages.size() > 10) - unsentmessages.clear(); - if (exmap.containsKey(user)) { // TODO: Save new messages if not listening - If message count is bigger than 10, remove (the user is probably offline) - unsentmessages.put(user, msg); - for (Entry entry : unsentmessages.) { //TODO: Only one key allowed, fix - JsonObject msgobj = entry.getValue().getAsJson(); // TODO: Only send messages if the user's current conversation matches + if (unsentmessages.containsKey(user) && unsentmessages.get(user).size() > 10) { + unsentmessages.get(user).clear(); + } + if (!unsentmessages.containsKey(user)) + unsentmessages.put(user, new ArrayList()); + unsentmessages.get(user).add(msg); + if (exmap.containsKey(user)) { + Iterator it = unsentmessages.get(user).iterator(); + String finalmsghtml = ""; + while (it.hasNext()) { + Message entry = it.next(); + Element msgobj = entry.getAsHTML(new Document("")); // TODO: Only send messages if the user's current conversation matches + finalmsghtml += msgobj.toString() + "\n"; try { - IOHelper.SendResponse(200, msgobj.toString(), exmap.get(user)); - } catch (IOException e) { // Remove users even if an error occurs (otherwise they may not be able to send a new message due to "headers already sent") + it.remove(); // Remove sent message + } catch (Exception e) { // Remove users even if an error occurs (otherwise they may not be able to send a new/ message due to "headers already sent") e.printStackTrace(); } } - JsonObject msgobj = msg.getAsJson(); // TODO: Only send messages if the user's current conversation matches - try { - IOHelper.SendResponse(200, msgobj.toString(), exmap.get(user)); - } catch (IOException e) { // Remove users even if an error occurs (otherwise they may not be able to send a new message due to "headers already sent") - e.printStackTrace(); - } + IOHelper.SendResponse(200, finalmsghtml, exmap.get(user)); exmap.remove(user); + if (unsentmessages.get(user).size() == 0) + unsentmessages.remove(user); } else { LogManager.getLogger().warn("User is not listening: " + user); - unsentmessages.put(user, msg); } } }