Add some web socket goodness.

This commit is contained in:
Jonathan Harker 2016-02-06 17:02:45 +13:00
parent 04d90b7c7a
commit 74b370f19b
4 changed files with 73 additions and 5 deletions

25
public/chat.js Normal file
View file

@ -0,0 +1,25 @@
function sendMessage()
{
var msg = document.getElementById("inputLine")
socket.send(msg.value);
msg.value = "";
return false;
}
function connect(room, name)
{
socket = new WebSocket("ws://127.0.0.1:8080/ws?room="+encodeURIComponent(room)+"&name="+encodeURIComponent(name));
socket.onmessage = function(message) {
var history = document.getElementById("history");
var previous = history.innerHTML.trim();
if (previous.length) previous = previous + "\n";
history.innerHTML = previous + message.data;
history.scrollTop = history.scrollHeight;
}
socket.onclose = function() {
console.log("socket closed - reconnecting...");
connect();
}
}

7
public/main.css Normal file
View file

@ -0,0 +1,7 @@
textarea, input {
width: 40em;
}
textarea {
resize: vertical;
}

View file

@ -19,10 +19,21 @@ import vibe.d;
final class Room { final class Room {
string[] messages; string[] messages;
ManualEvent messageEvent;
this() {
messageEvent = createManualEvent();
}
void addMessage(string nick, string message) { void addMessage(string nick, string message) {
messages ~= nick ~ ": " ~ message; messages ~= nick ~ ": " ~ message;
} }
void waitForMessage(size_t next_message) {
while (messages.length <= next_message) {
messageEvent.wait();
}
}
} }
final class WebChat { final class WebChat {
@ -51,6 +62,29 @@ final class WebChat {
redirect("room?room=" ~ room.urlEncode ~ "&nick=" ~ nick.urlEncode); redirect("room?room=" ~ room.urlEncode ~ "&nick=" ~ nick.urlEncode);
} }
// /ws?room=...&nick=...
void getWS(string room, string nick, scope WebSocket socket) {
auto r = getOrCreateRoom(room);
auto writer = runTask({
auto next_message = r.messages.length;
while (socket.connected) {
while (next_message < r.messages.length) {
socket.send(r.messages[next_message++]);
}
r.waitForMessage(next_message);
}
});
while (socket.waitForData) {
auto message = socket.receiveText();
if (message.length) {
r.addMessage(nick, message);
}
}
writer.join();
}
private Room getOrCreateRoom(string room) { private Room getOrCreateRoom(string room) {
if (auto pr = room in rooms) return *pr; if (auto pr = room in rooms) return *pr;
return rooms[room] = new Room; return rooms[room] = new Room;
@ -67,7 +101,7 @@ shared static this()
auto settings = new HTTPServerSettings; auto settings = new HTTPServerSettings;
settings.port = 8083; settings.port = 8083;
settings.bindAddresses = ["::1", "127.0.0.1"]; // settings.bindAddresses = ["::", "0.0.0.0"];
listenHTTP(settings, router); listenHTTP(settings, router);
logInfo("Please open http://127.0.0.1:%d/ in your browser.".format(settings.port)); logInfo("Please open http://127.0.0.1:%d/ in your browser.".format(settings.port));

View file

@ -1,17 +1,19 @@
doctype html doctype html
html html
head head
title #{room} - Webchat title #{room} - Webchat
style. style(type="text/css", src="main.css")
textarea, input { width: 100%; }
textarea { resize: vertical; }
body body
- import vibe.data.json;
script(src="chat.js")
script connect(#{Json(room)}, #{Json(nick)})
h1 Room '#{room}' h1 Room '#{room}'
textarea#history(rows=20, readonly=true) textarea#history(rows=20, readonly=true)
- foreach (m; messages) - foreach (m; messages)
|= m |= m
form(action="room", method="POST") form(action="room", method="POST", autocomplete="off", onsubmit="return sendMessage()")
input(type="hidden", name="room", value=room) input(type="hidden", name="room", value=room)
input(type="hidden", name="nick", value=nick) input(type="hidden", name="nick", value=nick)
input#inputLine(type="text", name="message", autofocus=true) input#inputLine(type="text", name="message", autofocus=true)