A whole bunch of code changes. Untested.
This commit is contained in:
parent
0296f38dd3
commit
576a2c975a
|
@ -0,0 +1,89 @@
|
||||||
|
// Functionality dealing with server-level things
|
||||||
|
|
||||||
|
var maxScrollback = 500;
|
||||||
|
var networks = {};
|
||||||
|
|
||||||
|
function networkConnect(network, baseURL, authtok) {
|
||||||
|
var eventSource;
|
||||||
|
var element = getTemplate("server-channels");
|
||||||
|
var channels = element.getElementByClassName("channels")[0];
|
||||||
|
var roomElement = element.getElementsByClassName("server")[0];
|
||||||
|
var rooms = {".": room};
|
||||||
|
newRoom(roomElement, element, network, maxScrollback);
|
||||||
|
|
||||||
|
function newRoom(name) {
|
||||||
|
var rElement = getTemplate("channel");
|
||||||
|
newRoom(rElement, element, name, maxScrollback);
|
||||||
|
channels.appendChild(rElement);
|
||||||
|
rooms[name] = rElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleEventSourceLine(line) {
|
||||||
|
var lhs = line.split(" :", 1)[0]
|
||||||
|
var parts = lhs.split(' ')
|
||||||
|
var timestamp = new Date(parts[0] * 1000);
|
||||||
|
var fullSender = parts[1];
|
||||||
|
var command = parts[2].toLowerCase();
|
||||||
|
var sender = parts[3];
|
||||||
|
var forum = parts[4];
|
||||||
|
var args = parts.slice(5);
|
||||||
|
var txt = line.substr(lhs.length + 2);
|
||||||
|
|
||||||
|
var room = rooms[forum];
|
||||||
|
if (! room) {
|
||||||
|
room = newRoom(forum);
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX: Handle differently based on command
|
||||||
|
room.addMessage(timestamp, command, sender, txt);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleEventSourceMessage(oEvent) {
|
||||||
|
msgs = oEvent.data.split("\n");
|
||||||
|
|
||||||
|
var first = Math.max(0, msgs.length - maxScrollback);
|
||||||
|
for (var i = first; i < msgs.length; i += 1) {
|
||||||
|
handleEventSourceLine(msgs[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleEventSourceError(oEvent) {
|
||||||
|
timestamp = new Date();
|
||||||
|
messageHandler(timestamp, null, "ERROR", null, null, [], null);
|
||||||
|
}
|
||||||
|
|
||||||
|
element.send = function(target, text) {
|
||||||
|
function handleError(oEvent) {
|
||||||
|
console.log("XXX: That didn't work out.", target, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
var form = new FormData();
|
||||||
|
form.append("type", "command");
|
||||||
|
form.append("auth", authtok);
|
||||||
|
form.append("network", network);
|
||||||
|
form.append("target", target);
|
||||||
|
form.append("text", text);
|
||||||
|
console.log(form);
|
||||||
|
|
||||||
|
var oReq = new XMLHttpRequest();
|
||||||
|
oReq.addEventListener("error", handleError);
|
||||||
|
oReq.open("POST", baseURL, true);
|
||||||
|
oReq.send(form);
|
||||||
|
}
|
||||||
|
|
||||||
|
element.close = function() {
|
||||||
|
eventSource.close();
|
||||||
|
element.parentNode.removeChild(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (networks[network]) {
|
||||||
|
networks[network].close();
|
||||||
|
}
|
||||||
|
networks[network] = element;
|
||||||
|
|
||||||
|
var pullURL = baseURL + "?network=" + encodeURIComponent(network) + "&auth=" + encodeURIComponent(authtok);
|
||||||
|
eventSource = new EventSource(pullURL);
|
||||||
|
eventSource.addEventListener("message", handleEventSourceMessage);
|
||||||
|
eventSource.addEventListener("error", handleEventSourceError);
|
||||||
|
}
|
|
@ -0,0 +1,113 @@
|
||||||
|
function djbhash(a) {
|
||||||
|
var r = 5381;
|
||||||
|
|
||||||
|
for (var i = 0; i < a.length; i += 1) {
|
||||||
|
r = (((r << 5) + r) + a.charCodeAt(i)) & 0xffff;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addText(p, text, kiboze) {
|
||||||
|
// Look for a URL
|
||||||
|
var txtElement = document.createElement("span");
|
||||||
|
txtElement.className = "text";
|
||||||
|
var rhs = text;
|
||||||
|
var match;
|
||||||
|
|
||||||
|
while ((match = urlRe.exec(rhs)) != null) {
|
||||||
|
var before = rhs.substr(0, match.index);
|
||||||
|
var a = document.createElement("a");
|
||||||
|
var href = match[0];
|
||||||
|
|
||||||
|
if (href.indexOf("hxx") == 0) {
|
||||||
|
href = "htt" + href.substr(3);
|
||||||
|
}
|
||||||
|
a.href = href
|
||||||
|
a.target = "_blank";
|
||||||
|
a.appendChild(document.createTextNode(match[0]));
|
||||||
|
txtElement.appendChild(document.createTextNode(before));
|
||||||
|
txtElement.appendChild(a);
|
||||||
|
rhs = rhs.substr(match.index + match[0].length);
|
||||||
|
}
|
||||||
|
txtElement.appendChild(document.createTextNode(rhs));
|
||||||
|
p.appendChild(txtElement);
|
||||||
|
|
||||||
|
if ((kiboze) || (-1 != text.search(kibozeRe))) {
|
||||||
|
var k = document.getElementById("kiboze");
|
||||||
|
var p2 = p.cloneNode(true);
|
||||||
|
|
||||||
|
if (k) {
|
||||||
|
k.insertBefore(p2, k.firstChild);
|
||||||
|
p2.onclick = function() { focus(p); }
|
||||||
|
|
||||||
|
// Setting title makes the tab flash sorta
|
||||||
|
document.title = document.title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var visibleRoom;
|
||||||
|
|
||||||
|
function newRoom(element, network, name, maxSize) {
|
||||||
|
var messages = getTemplate("messages");
|
||||||
|
if (! maxsize) {
|
||||||
|
maxSize = 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
element.addMessage = function(timestamp, command, source, content) {
|
||||||
|
var message = getTemplate("message");
|
||||||
|
|
||||||
|
var eTimestamp = message.getElementsByClassName("timestamp")[0];
|
||||||
|
var eSource = message.getElementsByClassName("source")[0];
|
||||||
|
var eContent = message.getElementsByClassName("content")[0];
|
||||||
|
|
||||||
|
message.nodeList.add(command);
|
||||||
|
if (source = ".") {
|
||||||
|
message.nodeList.add("self");
|
||||||
|
}
|
||||||
|
|
||||||
|
eTimestamp.textContent = timestamp.toLocaleTimeString();
|
||||||
|
eSource.textContent = source;
|
||||||
|
eSource.setAttribute("colornumber", djbhash(source) % 31);
|
||||||
|
eContent.textContent = content;
|
||||||
|
|
||||||
|
messages.appendChild(message);
|
||||||
|
|
||||||
|
while (messages.childNodes.length > maxSize) {
|
||||||
|
messages.removeChild(element.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (visibleRoom == element) {
|
||||||
|
message.scrollIntoView(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
element.hide = function() {
|
||||||
|
element.classList.remove("selected");
|
||||||
|
messages.classList.add("hidden");
|
||||||
|
}
|
||||||
|
|
||||||
|
element.show = function() {
|
||||||
|
if (visibleRoom) {
|
||||||
|
visibleRoom.hide()
|
||||||
|
}
|
||||||
|
element.classList.add("selected");
|
||||||
|
messages.classList.remove("hidden");
|
||||||
|
visibleRoom = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
element.send = function(text) {
|
||||||
|
network.send(name, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clicked() {
|
||||||
|
element.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
// start hidden
|
||||||
|
element.hide();
|
||||||
|
element.addEventListener("click", clicked);
|
||||||
|
element.getElementsByClassName("content-item")[0].textContent = name;
|
||||||
|
|
||||||
|
return element;
|
||||||
|
}
|
|
@ -1,67 +0,0 @@
|
||||||
// Functionality dealing with server-level things
|
|
||||||
|
|
||||||
var maxScrollback = 500;
|
|
||||||
|
|
||||||
function Server(network, baseURL, authtok, messageHandler) {
|
|
||||||
function init() {
|
|
||||||
var pullURL = baseURL + "?network=" + encodeURIComponent(network) + "&auth=" + encodeURIComponent(authtok);
|
|
||||||
this.eventSource = new EventSource(pullURL);
|
|
||||||
this.eventSource.addEventListener("message", handleEventSourceMessage);
|
|
||||||
this.eventSource.addEventListener("error", handleEventSourceError);
|
|
||||||
}
|
|
||||||
|
|
||||||
function close() {
|
|
||||||
this.eventSource.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleEventSourceLine(line) {
|
|
||||||
var lhs = line.split(" :", 1)[0]
|
|
||||||
var parts = lhs.split(' ')
|
|
||||||
var timestamp = new Date(parts[0] * 1000);
|
|
||||||
var fullSender = parts[1];
|
|
||||||
var command = parts[2];
|
|
||||||
var sender = parts[3];
|
|
||||||
var forum = parts[4];
|
|
||||||
var args = parts.slice(5);
|
|
||||||
var txt = line.substr(lhs.length + 2);
|
|
||||||
|
|
||||||
messageHandler(timestamp, fullSender, command, sender, forum, args, txt);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleEventSourceMessage(oEvent) {
|
|
||||||
msgs = oEvent.data.split("\n");
|
|
||||||
|
|
||||||
var first = Math.max(0, msgs.length - maxScrollback);
|
|
||||||
for (var i = first; i < msgs.length; i += 1) {
|
|
||||||
handleEventSourceLine(msgs[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleEventSourceError(oEvent) {
|
|
||||||
timestamp = new Date();
|
|
||||||
messageHandler(timestamp, null, "ERROR", null, null, [], null);
|
|
||||||
}
|
|
||||||
|
|
||||||
function send(target, text) {
|
|
||||||
function handleError(oEvent) {
|
|
||||||
console.log("XXX: That didn't work out.", target, text)
|
|
||||||
}
|
|
||||||
|
|
||||||
var form = new FormData();
|
|
||||||
form.append("type", "command");
|
|
||||||
form.append("auth", authtok);
|
|
||||||
form.append("network", network);
|
|
||||||
form.append("target", target);
|
|
||||||
form.append("text", text);
|
|
||||||
console.log(form);
|
|
||||||
|
|
||||||
var oReq = new XMLHttpRequest();
|
|
||||||
oReq.addEventListener("error", handleError);
|
|
||||||
oReq.open("POST", baseURL, true);
|
|
||||||
oReq.send(form);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.send = send;
|
|
||||||
|
|
||||||
init();
|
|
||||||
}
|
|
|
@ -6,7 +6,8 @@
|
||||||
<link rel="stylesheet" href="message_style.css">
|
<link rel="stylesheet" href="message_style.css">
|
||||||
<link rel="stylesheet" href="topbar.css">
|
<link rel="stylesheet" href="topbar.css">
|
||||||
|
|
||||||
<script src="server.js"></script>
|
<script src="network.js"></script>
|
||||||
|
<script src="room.js"></script>
|
||||||
<script src="wirc.js"></script>
|
<script src="wirc.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|
174
app/wirc.js
174
app/wirc.js
|
@ -4,27 +4,12 @@ var urlRe = /[a-z]+:\/\/[^ ]*/;
|
||||||
|
|
||||||
var nick = "Mme. M";
|
var nick = "Mme. M";
|
||||||
|
|
||||||
// XXX: get rid of this
|
|
||||||
var scrollbackLength = 500;
|
|
||||||
var current;
|
|
||||||
var target;
|
|
||||||
|
|
||||||
if (String.prototype.startsWith == null) {
|
if (String.prototype.startsWith == null) {
|
||||||
String.prototype.startsWith = function(needle) {
|
String.prototype.startsWith = function(needle) {
|
||||||
return this.lastIndexOf(needle, 0) == 0;
|
return this.lastIndexOf(needle, 0) == 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function djbhash(a) {
|
|
||||||
var r = 5381;
|
|
||||||
|
|
||||||
for (var i = 0; i < a.length; i += 1) {
|
|
||||||
r = (((r << 5) + r) + a.charCodeAt(i)) & 0xffff;
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function getTemplate(className) {
|
function getTemplate(className) {
|
||||||
return templates.getElementsByClassName(className)[0].cloneNode(true);
|
return templates.getElementsByClassName(className)[0].cloneNode(true);
|
||||||
}
|
}
|
||||||
|
@ -33,50 +18,6 @@ function isinView(oObject) {
|
||||||
return (oObject.offsetParent.clientHeight <= oObject.offsetTop);
|
return (oObject.offsetParent.clientHeight <= oObject.offsetTop);
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectForum(room) {
|
|
||||||
if (current) {
|
|
||||||
current.classList.remove("selected");
|
|
||||||
// XXX: do this with a class, too
|
|
||||||
current.messages.style.display = "none";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
current = room;
|
|
||||||
target = room.target;
|
|
||||||
room.classList.add("selected");
|
|
||||||
room.messages.style.display = "block";
|
|
||||||
|
|
||||||
if (room.messages.lastChild) {
|
|
||||||
room.messages.lastChild.scrollIntoView(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fora = {}
|
|
||||||
function getForumElement(forum) {
|
|
||||||
var fe = fora[forum];
|
|
||||||
|
|
||||||
if (! fe) {
|
|
||||||
var room = getTemplate("channel room");
|
|
||||||
var content = room.getElementsByClassName("content-item")[0];
|
|
||||||
|
|
||||||
content.textContent = forum;
|
|
||||||
rooms.appendChild(room);
|
|
||||||
|
|
||||||
fe = getTemplate("messages");
|
|
||||||
fe.room = room;
|
|
||||||
|
|
||||||
room.messages = fe;
|
|
||||||
room.target = forum;
|
|
||||||
// XXX: split out into non-anon function
|
|
||||||
room.addEventListener("click", function() {selectForum(room)});
|
|
||||||
|
|
||||||
fora[forum] = fe;
|
|
||||||
document.getElementById("messages-container").appendChild(fe);
|
|
||||||
}
|
|
||||||
|
|
||||||
return fe;
|
|
||||||
}
|
|
||||||
|
|
||||||
function addMessagePart(p, className, text) {
|
function addMessagePart(p, className, text) {
|
||||||
var e = document.createElement("span");
|
var e = document.createElement("span");
|
||||||
e.className = className;
|
e.className = className;
|
||||||
|
@ -85,45 +26,6 @@ function addMessagePart(p, className, text) {
|
||||||
p.appendChild(document.createTextNode(" "));
|
p.appendChild(document.createTextNode(" "));
|
||||||
}
|
}
|
||||||
|
|
||||||
function addText(p, text, kiboze) {
|
|
||||||
// Look for a URL
|
|
||||||
var txtElement = document.createElement("span");
|
|
||||||
txtElement.className = "text";
|
|
||||||
var rhs = text;
|
|
||||||
var match;
|
|
||||||
|
|
||||||
while ((match = urlRe.exec(rhs)) != null) {
|
|
||||||
var before = rhs.substr(0, match.index);
|
|
||||||
var a = document.createElement("a");
|
|
||||||
var href = match[0];
|
|
||||||
|
|
||||||
if (href.indexOf("hxx") == 0) {
|
|
||||||
href = "htt" + href.substr(3);
|
|
||||||
}
|
|
||||||
a.href = href
|
|
||||||
a.target = "_blank";
|
|
||||||
a.appendChild(document.createTextNode(match[0]));
|
|
||||||
txtElement.appendChild(document.createTextNode(before));
|
|
||||||
txtElement.appendChild(a);
|
|
||||||
rhs = rhs.substr(match.index + match[0].length);
|
|
||||||
}
|
|
||||||
txtElement.appendChild(document.createTextNode(rhs));
|
|
||||||
p.appendChild(txtElement);
|
|
||||||
|
|
||||||
if ((kiboze) || (-1 != text.search(kibozeRe))) {
|
|
||||||
var k = document.getElementById("kiboze");
|
|
||||||
var p2 = p.cloneNode(true);
|
|
||||||
|
|
||||||
if (k) {
|
|
||||||
k.insertBefore(p2, k.firstChild);
|
|
||||||
p2.onclick = function() { focus(p); }
|
|
||||||
|
|
||||||
// Setting title makes the tab flash sorta
|
|
||||||
document.title = document.title;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function focus(e) {
|
function focus(e) {
|
||||||
var pct = 1;
|
var pct = 1;
|
||||||
var timeout;
|
var timeout;
|
||||||
|
@ -142,49 +44,6 @@ function focus(e) {
|
||||||
}, 50)
|
}, 50)
|
||||||
}
|
}
|
||||||
|
|
||||||
function addMessage(timestamp, fullSender, command, sender, forum, args, msg) {
|
|
||||||
var forumElement = getForumElement(forum);
|
|
||||||
var msge = getTemplate("message");
|
|
||||||
|
|
||||||
msge.classList.add("update");
|
|
||||||
msge.classList.add("privmsg");
|
|
||||||
|
|
||||||
if (sender == ".") {
|
|
||||||
msge.classList.add("self");
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(timestamp, msg);
|
|
||||||
|
|
||||||
msge.getElementsByClassName("timestamp")[0].textContent = timestamp.toLocaleTimeString();
|
|
||||||
var sourcee = msge.getElementsByClassName("source")[0];
|
|
||||||
var contente = msge.getElementsByClassName("content")[0];
|
|
||||||
|
|
||||||
var senderhash = djbhash(sender) % 31;
|
|
||||||
sourcee.setAttribute("colornumber", senderhash)
|
|
||||||
|
|
||||||
|
|
||||||
sourcee.textContent = sender;
|
|
||||||
|
|
||||||
switch (command) {
|
|
||||||
case "PING":
|
|
||||||
case "PONG":
|
|
||||||
return;
|
|
||||||
case "PRIVMSG":
|
|
||||||
case "NOTICE":
|
|
||||||
addText(contente, msg);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
contente.textContent = command + " " + args + " " + msg;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
while (forumElement.childNodes.length > scrollbackLength) {
|
|
||||||
forumElement.removeChild(forumElement.firstChild)
|
|
||||||
}
|
|
||||||
|
|
||||||
forumElement.appendChild(msge);
|
|
||||||
msge.scrollIntoView(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleInput(oEvent) {
|
function handleInput(oEvent) {
|
||||||
var txt = oEvent.target.value;
|
var txt = oEvent.target.value;
|
||||||
if (txt.startsWith("/connect ")) {
|
if (txt.startsWith("/connect ")) {
|
||||||
|
@ -198,7 +57,7 @@ function handleInput(oEvent) {
|
||||||
storedConnections[network] = [url, authtok];
|
storedConnections[network] = [url, authtok];
|
||||||
chrome.storage.sync.set({"connections": storedConnections});
|
chrome.storage.sync.set({"connections": storedConnections});
|
||||||
} else {
|
} else {
|
||||||
server.send(target, txt);
|
visibleRoom.send(txt);
|
||||||
}
|
}
|
||||||
|
|
||||||
oEvent.target.value = "";
|
oEvent.target.value = "";
|
||||||
|
@ -206,42 +65,13 @@ function handleInput(oEvent) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var server;
|
|
||||||
var activeNetworks = {};
|
|
||||||
var storedConnections = {};
|
|
||||||
|
|
||||||
function connect(network, url, authtok) {
|
|
||||||
var newServer = new Server(network, url, authtok, addMessage);
|
|
||||||
var element;
|
|
||||||
|
|
||||||
if (activeNetworks[network]) {
|
|
||||||
activeNetworks[network].close();
|
|
||||||
element = activeNetworks[network].element;
|
|
||||||
} else {
|
|
||||||
newServer.element = getTemplate("server-channels");
|
|
||||||
rooms.appendChild(newServer.element);
|
|
||||||
}
|
|
||||||
|
|
||||||
newServer.room = newServer.element.getElementsByClassName("server room")[0];
|
|
||||||
newServer.content = newServer.element.getElementsByClassName("content-item")[0];
|
|
||||||
|
|
||||||
newServer.content.textContent = network;
|
|
||||||
|
|
||||||
activeNetworks[network] = newServer;
|
|
||||||
|
|
||||||
// XXX: this should be bound to the element
|
|
||||||
server = newServer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function restore(items) {
|
function restore(items) {
|
||||||
storedConnections = items["connections"];
|
storedConnections = items["connections"];
|
||||||
|
|
||||||
for (var network in storedConnections) {
|
for (var network in storedConnections) {
|
||||||
var conn = storedConnections[network];
|
var conn = storedConnections[network];
|
||||||
|
|
||||||
connect(network, conn[0], conn[1]);
|
networkConnect(network, conn[0], conn[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue