aboutsummaryrefslogtreecommitdiff
path: root/webclient/client.html
diff options
context:
space:
mode:
Diffstat (limited to 'webclient/client.html')
-rw-r--r--webclient/client.html83
1 files changed, 68 insertions, 15 deletions
diff --git a/webclient/client.html b/webclient/client.html
index 28a91fd..512a2ed 100644
--- a/webclient/client.html
+++ b/webclient/client.html
@@ -4,12 +4,15 @@
<meta charset="utf-8">
<title>tomsg webclient</title>
<script>
-var PROTOCOL_VERSION=1;
+var PROTOCOL_VERSION=2;
+
+// Note: message id's are considered strings in this code. This is to not have to deal with full 64-bit integers.
var sock=null,negotiated_version=false,username=null;
+var messagecache=new Map(); // msgid => [user,message]
var roomlist=[":console"];
var currentroom=":console";
-var roomlogs=new Map([[":console",[]]]);
+var roomlogs=new Map([[":console",[]]]); // see drawRoomEntry for entry types
var commandlist=[
{cmd:"register",usage:"/register <username> <password>"},
@@ -93,11 +96,16 @@ function net_historyCollectionCallback(id,list,count,cb, item,err){
}
}
-function reconnect(){
+function resetState() {
if(sock)sock.close();
-
- net_callbacks={};
negotiated_version=false;
+ username=null;
+ messagecache.clear();
+ net_callbacks={};
+}
+
+function reconnect(){
+ resetState();
var url;
if(location.hostname!="")url="wss://"+location.hostname;
@@ -112,8 +120,10 @@ function reconnect(){
if(id=="_push"){
if(type=="message"){
var r=spl.word[2],u=spl.word[3],t=new Date(+spl.word[4]/1000);
- // Ignore msgid at word[5]
- addRoomEntry(r,"message",[u,t,spl.rest[6]]);
+ var msgid=spl.word[5],replyid=spl.word[6];
+ var text=spl.rest[7];
+ messagecache.set(msgid,[u,text]);
+ addRoomEntry(r,"message",[u,t,msgid,replyid,text]);
} else if(type=="invite"){
var r=spl.word[2],inviter=spl.word[3];
roomlist.push(r);
@@ -137,13 +147,14 @@ function reconnect(){
var obj;
if(type=="ok")fn(true);
else if(type=="error")fn(null,spl.rest[2]);
- else if(type=="number")fn(+spl.rest[2]);
+ else if(type=="number")fn(spl.rest[2]); // Note: no int parse!
else if(type=="name")fn(spl.rest[2]);
else if(type=="list")fn(spl.word.slice(3));
else if(type=="history"){
var count=+spl.word[2];
net_callbacks[id]=net_historyCollectionCallback.bind(this,id,[],count,fn);
- } else if(type=="history_message")fn([spl.word[4],+spl.word[5]/1000,spl.rest[7]]);
+ } else if(type=="history_message")fn([spl.word[4],+spl.word[5]/1000,spl.word[6],spl.word[7],spl.rest[8]]);
+ else if(type=="message")fn([spl.word[3],+spl.word[4]/1000,spl.word[5],spl.word[6],spl.rest[7]]);
else alert("Unknown server response message type '"+type+"'!");
} else {
alert("No callback for server message id '"+id+"'!");
@@ -206,6 +217,18 @@ function fetchRoomHistory(roomid){
});
}
+function getMessage(msgid,callback){
+ if(messagecache.has(msgid)){
+ callback(null,messagecache.get(msgid));
+ return;
+ }
+
+ net_send("get_message "+msgid,function(item,err){
+ if(err)callback(err,null);
+ else callback(null,item);
+ });
+}
+
function updateStatus(){
var str=null;
if(!sock||sock.readyState>=2){
@@ -284,21 +307,39 @@ function drawRoomEntry(type,args){
tr.appendChild(td2);
tbody.appendChild(tr);
switch(type){
- case "message":
+ case "message": // [username, timestamp_ms, msgid, replyid, text]
tr.classList.add("message");
node0.nodeValue=formatTime(new Date(args[1]));
node1.nodeValue="<"+args[0]+">";
- node2.nodeValue=args[2];
+ node2.nodeValue=args[4];
+ if(args[3]!="-1"){
+ var replyNode=document.createElement("span");
+ replyNode.classList.add("reply");
+ replyNode.classList.add("pending");
+ getMessage(args[3],function(err,item){
+ replyNode.classList.remove("pending");
+ var text;
+ if(err){
+ replyNode.classList.add("failed");
+ text="Failed to fetch original message!";
+ } else {
+ text="> <"+item[0]+"> "+item[4];
+ }
+ replyNode.appendChild(document.createTextNode(text));
+ });
+ td2.insertBefore(replyNode,node2);
+ td2.insertBefore(document.createElement("br"),node2);
+ }
break;
- case "error":
+ case "error": // [timestamp_ms, text]
tr.classList.add("error");
node0.nodeValue=formatTime(new Date(args[0]));
node1.nodeValue="--";
node2.nodeValue=args[1];
break;
- case "notice":
+ case "notice": // [timestamp_ms, text]
tr.classList.add("notice");
node0.nodeValue=formatTime(new Date(args[0]));
node1.nodeValue="--";
@@ -424,9 +465,10 @@ function sendMessage(roomid,text){
return;
}
var sentAs=username,msg=text.replace(/\n/g,"");
- net_send("send "+roomid+" "+msg,function(msgid,err){
+ net_send("send "+roomid+" -1 "+msg,function(msgid,err){
if(msgid!=null){
- addRoomEntry(roomid,"message",[sentAs,new Date().getTime(),msg]);
+ msgid=msgid.toString();
+ addRoomEntry(roomid,"message",[sentAs,new Date().getTime(),msgid,"-1",msg]);
return;
}
addRoomEntry(roomid,"error",[now(),"Unable to send message: "+err]);
@@ -564,6 +606,17 @@ table{
#roomlog > tr.notice{
color:#a8f;
}
+#roomlog > tr > td > span.reply{
+ color:#8f8;
+ font-style:italic;
+}
+#roomlog > tr > td > span.reply.pending:after{
+ content:"(...)";
+}
+#roomlog > tr > td > span.reply.failed{
+ color:#f22;
+ font-style:normal;
+}
#roombar_tr{
height:30px;