Fixed long-polling and made some improvements in messages

This commit is contained in:
Norbi Peti 2016-08-15 12:37:51 +02:00
parent e12c0fee36
commit 01a1ce097c
12 changed files with 133 additions and 51 deletions

View file

@ -8,17 +8,7 @@ $(document).ready(function () {
var nodes = cmsgs.children; var nodes = cmsgs.children;
for (var x = 0; x < nodes.length; x++) { for (var x = 0; x < nodes.length; x++) {
var item = nodes[x]; var item = nodes[x];
console.log(item); handlereceivedmessage(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");
} }
cmsgs.lastElementChild.scrollIntoView(false);
} }
}); });

View file

@ -1,7 +1,30 @@
(function poll() { var handlereceivedmessage = function handlereceivedmessage(msgnode) {
setTimeout(function() { var spans = msgnode.getElementsByTagName("span");
$.ajax({ url: "/receivemessage", success: function(data) { var ctime = null;
for (var i = 0; i < spans.length; i++)
}, dataType: "json", complete: poll }); if (spans[i].className.split(' ').indexOf("converttime") > -1)
}, 100); 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);
})();

View file

@ -7,8 +7,8 @@ var sendmsg = function sendmsg(msginputta) {
}; };
var respfunc = function respfunc(result) { var respfunc = function respfunc(result) {
var msginput = document.getElementById("msginput");
if (result != "Success") { //on success result is string if (result != "Success") { //on success result is string
var msginput = document.getElementById("msginput");
if (result.responseText.indexOf("JSONERROR") != -1) { if (result.responseText.indexOf("JSONERROR") != -1) {
console.log("Got JSON error. Retrying..."); console.log("Got JSON error. Retrying...");
console.log(result.responseText); console.log(result.responseText);
@ -19,8 +19,10 @@ var respfunc = function respfunc(result) {
msginput.disabled = false; msginput.disabled = false;
} }
} }
else else {
location.reload(true); //TODO: Don't referesh on message send msginput.value = "";
msginput.disabled = false;
}
}; };
var sendmsgonenter = function sendmsgonenter(e) { var sendmsgonenter = function sendmsgonenter(e) {

View file

@ -14,7 +14,7 @@ function getFormData($form) {
function showError(message) { function showError(message) {
var errormsg = document.getElementById("errormsg"); var errormsg = document.getElementById("errormsg");
errormsg.innerHTML = result.responseText; errormsg.innerHTML = message;
errormsg.style = "display: block"; errormsg.style = "display: block";
setTimeout(function(){errormsg.style.display="none";}, 2000); setTimeout(function () { errormsg.style.display = "none"; }, 2000);
} }

View file

@ -30,7 +30,8 @@ public class Main {
// https://docs.oracle.com/javase/8/docs/api/ // https://docs.oracle.com/javase/8/docs/api/
LogManager.getLogger().log(Level.INFO, "Loading files..."); LogManager.getLogger().log(Level.INFO, "Loading files...");
DataManager.init(); DataManager.init();
final GsonBuilder gsonBuilder = new GsonBuilder(); final GsonBuilder saveGsonBuilder = new GsonBuilder();
final GsonBuilder exchangeGsonBuilder = new GsonBuilder();
Reflections rf = new Reflections(new ConfigurationBuilder() Reflections rf = new Reflections(new ConfigurationBuilder()
.setUrls(ClasspathHelper.forClassLoader(ManagedData.class.getClassLoader())) .setUrls(ClasspathHelper.forClassLoader(ManagedData.class.getClassLoader()))
.addClassLoader(ManagedData.class.getClassLoader()).addScanners(new SubTypesScanner()) .addClassLoader(ManagedData.class.getClassLoader()).addScanners(new SubTypesScanner())
@ -39,11 +40,11 @@ public class Main {
for (Class<? extends ManagedData> data : datas) { for (Class<? extends ManagedData> data : datas) {
if (Modifier.isAbstract(data.getModifiers())) if (Modifier.isAbstract(data.getModifiers()))
continue; continue;
gsonBuilder.registerTypeAdapter(new DataType(LoaderCollection.class, data), saveGsonBuilder.registerTypeAdapter(new DataType(LoaderCollection.class, data),
new LoaderCollectionSerializer()); 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 = * 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: " + * provider.save(user); // user2 = provider.save(user2); user.getContacts().add(user2); user2.getContacts().add(user); LogManager.getLogger().log(Level.DEBUG, "1st's contact: " +

View file

@ -18,7 +18,6 @@ import io.github.norbipeti.chat.server.db.domain.SavedData;
* </p> * </p>
* *
* @author Norbi * @author Norbi
*
* @param <T> * @param <T>
*/ */
public class LoaderCollection<T extends SavedData> extends Loader implements List<T> { public class LoaderCollection<T extends SavedData> extends Loader implements List<T> {
@ -41,7 +40,7 @@ public class LoaderCollection<T extends SavedData> extends Loader implements Lis
public LoaderCollection(LoaderCollection<T> parentofsub, int fromIndex, int toIndex) { public LoaderCollection(LoaderCollection<T> parentofsub, int fromIndex, int toIndex) {
this.cl = parentofsub.cl; this.cl = parentofsub.cl;
idlist = parentofsub.idlist.subList(fromIndex, toIndex); idlist = parentofsub.idlist.subList(fromIndex, toIndex); // TODO: Test
} }
public LoaderCollection(Class<T> cl, int capacity) { public LoaderCollection(Class<T> cl, int capacity) {
@ -132,8 +131,7 @@ public class LoaderCollection<T extends SavedData> extends Loader implements Lis
/** /**
* Remove an object from this collection * Remove an object from this collection
* *
* @param o * @param o Either the object of type T or the ID
* Either the object of type T or the ID
*/ */
@Override @Override
public boolean remove(Object o) { public boolean remove(Object o) {
@ -228,4 +226,19 @@ public class LoaderCollection<T extends SavedData> extends Loader implements Lis
sb.append("]"); sb.append("]");
return sb.toString(); return sb.toString();
} }
@SuppressWarnings("unchecked")
public Object clone() {
Object cloned = null;
if (idlist instanceof ArrayList<?>)
cloned = ((ArrayList<Long>) idlist).clone();
if (cloned == null)
return cloned;
else {
LoaderCollection<T> lc = new LoaderCollection<T>(cl, this.size());
if (cloned instanceof List<?>)
lc.idlist = (List<Long>) cloned;
return lc;
}
}
} }

View file

@ -1,6 +1,7 @@
package io.github.norbipeti.chat.server.data; package io.github.norbipeti.chat.server.data;
import java.io.IOException; import java.io.IOException;
import java.util.Collection;
import java.util.List; import java.util.List;
import com.google.gson.Gson; import com.google.gson.Gson;
@ -14,9 +15,7 @@ import io.github.norbipeti.chat.server.db.domain.ManagedData;
// @SuppressWarnings("rawtypes") // @SuppressWarnings("rawtypes")
public class LoaderCollectionSerializer extends TypeAdapter<LoaderCollection<?>> { public class LoaderCollectionSerializer extends TypeAdapter<LoaderCollection<?>> {
// private static final Type returnType = getReturnType();
// http://stackoverflow.com/a/17300227
@Override @Override
public void write(JsonWriter out, LoaderCollection<?> value) throws IOException { public void write(JsonWriter out, LoaderCollection<?> value) throws IOException {
if (value == null) { if (value == null) {
@ -40,9 +39,13 @@ public class LoaderCollectionSerializer extends TypeAdapter<LoaderCollection<?>>
} }
in.beginObject(); in.beginObject();
in.nextName(); in.nextName();
List<Long> list = new Gson().fromJson(in, new TypeToken<List<Long>>() { List<Long> list;
LoaderCollection<? extends ManagedData> itemcol;
list = new Gson().fromJson(in, new TypeToken<List<Long>>() {
}.getType()); }.getType());
if (!in.nextName().equals("class")) { if (!in.nextName().equals("class"))
{
new Exception("Error: Next isn't \"class\"").printStackTrace(); new Exception("Error: Next isn't \"class\"").printStackTrace();
return null; return null;
} }

View file

@ -1,9 +1,17 @@
package io.github.norbipeti.chat.server.db.domain; package io.github.norbipeti.chat.server.db.domain;
import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.TimeZone;
import javax.persistence.*; 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; import io.github.norbipeti.chat.server.data.LoaderRef;
@Entity @Entity
@ -92,4 +100,28 @@ public class Message extends ManagedData {
@Override @Override
protected void init() { 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";
}
} }

View file

@ -95,10 +95,6 @@ public class User extends SavedData {
private User() { private User() {
} }
public static LoaderCollection<User> getUsers() {
return DataManager.getAll(User.class);
}
@Override @Override
public long getId() { public long getId() {
return id; return id;

View file

@ -2,6 +2,7 @@ package io.github.norbipeti.chat.server.page;
import java.io.IOException; import java.io.IOException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.TimeZone; import java.util.TimeZone;
import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Level;
@ -49,6 +50,7 @@ public class IndexPage extends Page {
convs.add(c); // TODO: Handle no conversation open convs.add(c); // TODO: Handle no conversation open
} }
user.getConversations().add(convs.get(0)); user.getConversations().add(convs.get(0));
convs.get(0).getUsers().add(user);
} }
Conversation conv = user.getConversations().get(0); Conversation conv = user.getConversations().get(0);
Element cide = channelmessages.appendElement("p"); Element cide = channelmessages.appendElement("p");
@ -56,17 +58,13 @@ public class IndexPage extends Page {
cide.attr("id", "convidp"); cide.attr("id", "convidp");
cide.text(Long.toString(conv.getId())); cide.text(Long.toString(conv.getId()));
LogManager.getLogger().log(Level.DEBUG, "Messages: " + conv.getMesssageChunks().size()); LogManager.getLogger().log(Level.DEBUG, "Messages: " + conv.getMesssageChunks().size());
for (MessageChunk chunk : conv.getMesssageChunks()) { // TODO: Reverse @SuppressWarnings("unchecked")
LoaderCollection<MessageChunk> chunks = (LoaderCollection<MessageChunk>) conv.getMesssageChunks()
.clone();
Collections.reverse(chunks);
for (MessageChunk chunk : chunks) {
for (Message message : chunk.getMessages()) { for (Message message : chunk.getMessages()) {
Element msgelement = channelmessages.appendElement("div"); message.getAsHTML(channelmessages);
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());
} }
} }
return doc; return doc;

View file

@ -1,9 +1,18 @@
package io.github.norbipeti.chat.server.page; package io.github.norbipeti.chat.server.page;
import java.io.IOException; 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.google.gson.JsonObject;
import com.sun.net.httpserver.HttpExchange; 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.db.domain.User;
import io.github.norbipeti.chat.server.io.IOHelper; import io.github.norbipeti.chat.server.io.IOHelper;
@ -15,6 +24,8 @@ public class ReceiveMessageAjaxPage extends Page {
return "receivemessage"; return "receivemessage";
} }
public static HashMap<User, HttpExchange> exmap = new HashMap<>();
@Override @Override
public void handlePage(HttpExchange exchange) throws IOException { public void handlePage(HttpExchange exchange) throws IOException {
User user = IOHelper.GetLoggedInUser(exchange); User user = IOHelper.GetLoggedInUser(exchange);
@ -22,7 +33,7 @@ public class ReceiveMessageAjaxPage extends Page {
IOHelper.SendResponse(403, "<p>Please log in to receive messages</p>", exchange); IOHelper.SendResponse(403, "<p>Please log in to receive messages</p>", exchange);
return; 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, * String message = obj.get("message").getAsString().trim(); int conversation = obj.get("conversation").getAsInt(); if (message.trim().length() == 0) { IOHelper.SendResponse(400,
* "<h1>400 Bad request</h1><p>The message cannot be empty.</p>", exchange); return; } LoaderCollection<Conversation> convos = user.getConversations(); Conversation conv = null; * "<h1>400 Bad request</h1><p>The message cannot be empty.</p>", exchange); return; } LoaderCollection<Conversation> convos = user.getConversations(); Conversation conv = null;
@ -33,7 +44,18 @@ public class ReceiveMessageAjaxPage extends Page {
* "Added conversation's message count: " + conv.getMesssageChunks().size()); * "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);
}
}
} }

View file

@ -71,6 +71,8 @@ public class SendMessageAjaxPage extends Page {
LogManager.getLogger().log(Level.DEBUG, LogManager.getLogger().log(Level.DEBUG,
"Added conversation's message count: " + conv.getMesssageChunks().size()); "Added conversation's message count: " + conv.getMesssageChunks().size());
ReceiveMessageAjaxPage.sendMessageBack(msg, conv);
IOHelper.SendResponse(200, "Success", exchange); IOHelper.SendResponse(200, "Success", exchange);
} }