This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
+ published by the Free Software Foundation, version 3.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
font-family: monospace;
}
a {
- color: white;
+ color: #ddd;
}
#container {
height: 100%;
width: 100%;
position: fixed;
bottom: 0;
+ display: none;
}
#input {
width: 100%;
font-size: 85%;
text-align: right;
}
+ .status {
+ color: #dd8;
+ }
+ .local.self {
+ color: #d8d;
+ }
+ .self {
+ color: #8d8;
+ }
+ .me {
+ color: #bbd;
+ }
.servercount {
margin-right: -0.5em;
font-size: 70%;
padding-left: 5px;
padding-right: 5px;
}
+ #getnick {
+ padding-left: 3em;
+ display: none;
+ }
/* BEGIN expando input box trick kindly provided by http://www.alistapart.com/articles/expanding-text-areas-made-elegant/ */
.expandingArea {
position: relative;
border: 1px solid #888;
- background: #fff;
+ background: silver;
}
.expandingArea > textarea,
.expandingArea > pre {
/*]]>*/--></style>
<script type="text/javascript"><!--//--><![CDATA[//><!--
- var servers = ['chkno.net', 'rc2.chkno.net', 'echto.net', 'the-wes.com', 'vibrantlogic.com'];
+ var servers = ['chkno.net', 'rc2.chkno.net', 'reliablechat-chk.rhcloud.com:80', 'intense-basin-3395.herokuapp.com:80', 'echto.net', 'the-wes.com', 'vibrantlogic.com'];
var session = Math.random(); // For outgoing message IDs
var since = {}; // server -> time: For fetch?since=
var seen = {}; // seen_key -> message
- var history = []; // List of messages sorted by Time
+ var hist = []; // List of messages sorted by Time
// Messages have these fields:
// Time: The timestamp. Median of ServerTimes
// ID: Some unique string for deduping
// UI: The DOM node for this message in the UI
function rcnick() {
- var nick = localStorage.getItem("nick");
- if (nick) {
- return nick;
- }
- return 'anonymous';
+ return localStorage.getItem("nick");
}
function rcsetnick(new_nick) {
type = "status";
} else if (/^\* /.test(message.Text)) {
type = "me";
+ } else if (/^-!- /.test(message.Text)) {
+ type = "local";
} else {
type = "text";
}
function rcaddmessagetohistory(message) {
var message_i;
if (message.Time) {
- for (var i = history.length - 1; ; i--) {
- if (i < 0 || (history[i].Time && message.Time >= history[i].Time)) {
+ for (var i = hist.length - 1; ; i--) {
+ if (i < 0 || (hist[i].Time && message.Time >= hist[i].Time)) {
message_i = i+1;
- history.splice(message_i, 0, message);
+ hist.splice(message_i, 0, message);
break;
}
}
} else {
- history.push(message);
- message_i = history.length-1;
+ hist.push(message);
+ message_i = hist.length-1;
}
+ if (message_i + 1 < hist.length) {
+ rcaddmessagetoUI(message, hist[message_i + 1].UI);
+ } else {
+ rcaddmessagetoUI(message, null);
+ }
+ }
+ function rcaddmessagetoUI(message, before) {
if (!message.UI) {
rcmakemessageUI(message);
}
var h = document.getElementById("history");
- if (message_i + 1 < history.length) {
- h.insertBefore(message.UI, history[message_i + 1].UI);
+ if (before) {
+ h.insertBefore(message.UI, before);
} else {
h.appendChild(message.UI);
}
message.Time = new Date(times[middle-1].getTime() + difference/2);
}
- // This may have broken history's in-sorted-order invariant
- var hi = history.indexOf(message);
- if ((history[hi-1] && history[hi-1].Time > message.Time) ||
- (history[hi+1] && history[hi+1].Time < message.Time)) {
- history.splice(hi,1);
+ // This may have broken hist's in-sorted-order invariant
+ var hi = hist.indexOf(message);
+ if ((hist[hi-1] && hist[hi-1].Time > message.Time) ||
+ (hist[hi+1] && hist[hi+1].Time < message.Time)) {
+ hist.splice(hi,1);
rcaddmessagetohistory(message);
}
}
}
+ function rcstart() {
+ if (rcnick()) {
+ document.getElementById("client").style.display = 'block';
+ rcconnect();
+ } else {
+ document.getElementById("getnick").style.display = 'block';
+ }
+ }
+
function rcsend(d, message) {
message.ID = new Date().getTime() + "-" + session + "-" + Math.random();
seen[make_seen_key(message.ID, message.Text)] = message;
"?id=" + encodeURIComponent(message.ID) +
"&text=" + encodeURIComponent(message.Text);
for (var i in servers) {
- var uri = rcserverbase(servers[i]) + path;
- var img = document.createElement("img");
- img.setAttribute("src", uri);
- d.appendChild(img);
+ var xhr = new XMLHttpRequest();
+ xhr.open("POST", rcserverbase(servers[i]) + path);
+ xhr.send();
}
}
function rcinput(input) {
var message;
- var re = /^\/([a-z]+) (.*)/
+ var re = /^\/(\S+)(\s(.*))?/;
var match = re.exec(input);
- if (match && match[1] == 'me') {
- message = "* " + rcnick() + " " + match[2];
- } else if (match && match[1] == 'nick') {
- message = "*** " + rcnick() + " is now known as " + match[2];
- rcsetnick(match[2]);
+ if (match) {
+ var command = match[1];
+ var rest = match[3];
+ if (command == 'me') {
+ message = "* " + rcnick() + " " + rest;
+ } else if (command == 'nick') {
+ if (rcnick() == rest) {
+ rcaddmessagetoUI({'Text': '-!- Your nick is already ' + rcnick(), 'ServerTimes': {}});
+ return;
+ }
+ if (rest) {
+ message = "*** " + rcnick() + " is now known as " + rest;
+ rcsetnick(rest);
+ } else {
+ rcaddmessagetoUI({'Text': '-!- /nick requires an argument', 'ServerTimes': {}});
+ return;
+ }
+ } else {
+ rcaddmessagetoUI({'Text': '-!- No such command: ' + command, 'ServerTimes': {}});
+ return;
+ }
} else {
message = "<" + rcnick() + "> " + input;
}
function rckeydown(event) {
if (event.keyCode == 13) {
- rcinput(document.input.say.value);
+ if (document.input.say.value) {
+ rcinput(document.input.say.value);
+ }
document.input.say.value = "";
return false;
}
}
+ function rcsetinitialnick() {
+ if (document.getnickform.initial_nick.value) {
+ rcsetnick(document.getnickform.initial_nick.value);
+ document.getElementById("getnick").style.display = 'none';
+ document.getElementById("client").style.display = 'block';
+ rcconnect();
+ }
+ return false;
+ }
+
// From http://www.alistapart.com/articles/expanding-text-areas-made-elegant/
function makeExpandingArea(container) {
var area = container.querySelector('textarea');
</head>
-<body onload="rcconnect()">
+<body onload="rcstart()">
<div id="container">
<div class="banner">(You are using <a href="https://github.com/chkno/reliable-chat">Reliable Chat</a>)</div>
<div id="history"></div>
<div class="expandingArea" style="visibility: hidden">
<pre><span id="historypad"></span><br></pre>
</div>
+ <div id="getnick">
+ <h1>Set your nick</h1>
+ <form name="getnickform" onsubmit="return rcsetinitialnick();">
+ <input id="initial_nick" type="text"></input>
+ <input type="submit" value="ok"></input>
+ </form>
+ </div>
<div id="client">
<div id="input">
<form name="input" onsubmit="return false" autocomplete="off">