Add connect form, add /join command

This commit is contained in:
Simon Ser 2020-06-05 23:35:33 +02:00
parent cbf64e56a0
commit f66c7c52f3
No known key found for this signature in database
GPG key ID: 0FDE7BE0E88F5E48
3 changed files with 195 additions and 60 deletions

View file

@ -1,19 +1,23 @@
var server = { var server = {
name: "chat.freenode.net", name: "chat.freenode.net",
url: "ws://localhost:8080", username: null,
username: "soju-test-user/chat.freenode.net", realname: null,
realname: "soju-test-user", nick: null,
nick: "soju-test-user", pass: null,
pass: "soju-test-user",
}; };
var ws = null;
var buffers = {}; var buffers = {};
var activeBuffer = null; var activeBuffer = null;
var serverBuffer = null;
var bufferListElt = document.querySelector("#buffer-list"); var bufferListElt = document.querySelector("#buffer-list");
var bufferElt = document.querySelector("#buffer"); var bufferElt = document.querySelector("#buffer");
var composerElt = document.querySelector("#composer"); var composerElt = document.querySelector("#composer");
var composerInputElt = document.querySelector("#composer input"); var composerInputElt = document.querySelector("#composer input");
var connectElt = document.querySelector("#connect");
var connectFormElt = document.querySelector("#connect form");
function djb2(s) { function djb2(s) {
var hash = 5381; var hash = 5381;
@ -160,78 +164,156 @@ function switchBuffer(buf) {
} }
} }
var serverBuffer = createBuffer(server.name); function showConnectForm() {
serverBuffer.readOnly = true; setConnectFormDisabled(false);
switchBuffer(serverBuffer); connectElt.style.display = "block";
}
var ws = new WebSocket(server.url); function connect() {
try {
ws.onopen = function() { ws = new WebSocket(server.url);
console.log("Connection opened"); } catch (err) {
console.error(err);
if (server.pass) { showConnectForm();
ws.send(formatMessage({ command: "PASS", params: [server.pass] })); return;
} }
ws.send(formatMessage({ command: "NICK", params: [server.nick] }));
ws.send(formatMessage({
command: "USER",
params: [server.username, "0", "*", server.realname],
}));
};
ws.onmessage = function(event) { ws.onopen = function() {
var msg = parseMessage(event.data); console.log("Connection opened");
console.log(msg);
switch (msg.command) { // TODO: wait for RPL_WELCOME
case "NOTICE": connectElt.style.display = "none";
case "PRIVMSG":
var target = msg.params[0]; if (server.pass) {
if (target == server.nick) { ws.send(formatMessage({ command: "PASS", params: [server.pass] }));
target = msg.prefix.name;
} }
var buf; ws.send(formatMessage({ command: "NICK", params: [server.nick] }));
if (target == "*") { ws.send(formatMessage({
buf = serverBuffer; command: "USER",
} else { params: [server.username, "0", "*", server.realname],
buf = createBuffer(target); }));
} };
buf.addMessage(msg);
break; ws.onmessage = function(event) {
case "JOIN": var msg = parseMessage(event.data);
var channel = msg.params[0]; console.log(msg);
if (msg.prefix.name == server.nick) {
createBuffer(channel); switch (msg.command) {
} else { case "NOTICE":
case "PRIVMSG":
var target = msg.params[0];
if (target == server.nick) {
target = msg.prefix.name;
}
var buf;
if (target == "*") {
buf = serverBuffer;
} else {
buf = createBuffer(target);
}
buf.addMessage(msg);
break;
case "JOIN":
var channel = msg.params[0];
if (msg.prefix.name == server.nick) {
createBuffer(channel);
} else {
createBuffer(channel).addMessage(msg);
}
break;
case "PART":
var channel = msg.params[0];
createBuffer(channel).addMessage(msg); createBuffer(channel).addMessage(msg);
break;
default:
serverBuffer.addMessage(msg);
} }
break; };
case "PART":
var channel = msg.params[0]; ws.onclose = function() {
createBuffer(channel).addMessage(msg); console.log("Connection closed");
showConnectForm();
};
ws.onerror = function() {
console.error("Connection error");
};
serverBuffer = createBuffer(server.name);
serverBuffer.readOnly = true;
switchBuffer(serverBuffer);
}
function sendMessage(msg) {
ws.send(formatMessage(msg));
}
function executeCommand(s) {
var parts = s.split(" ");
var cmd = parts[0].toLowerCase().slice(1);
var args = parts.slice(1);
switch (cmd) {
case "join":
var channel = args[0];
var msg = { command: "JOIN", params: [channel] };
sendMessage(msg);
break; break;
default: default:
serverBuffer.addMessage(msg); console.error("Unknwon command '" + cmd + "'");
} }
}; }
ws.onclose = function() {
console.log("Connection closed");
};
composerElt.onsubmit = function(event) { composerElt.onsubmit = function(event) {
event.preventDefault(); event.preventDefault();
var text = composerInputElt.value;
composerInputElt.value = "";
if (!text) {
return;
}
if (text.startsWith("//")) {
text = text.slice(1);
} else if (text.startsWith("/")) {
executeCommand(text);
return;
}
if (!activeBuffer || activeBuffer.readOnly) { if (!activeBuffer || activeBuffer.readOnly) {
return; return;
} }
var target = activeBuffer.name; var target = activeBuffer.name;
var text = composerInputElt.value;
if (!text) {
return;
}
var msg = { command: "PRIVMSG", params: [target, text] }; var msg = { command: "PRIVMSG", params: [target, text] };
ws.send(formatMessage(msg)); sendMessage(msg);
msg.prefix = { name: server.nick }; msg.prefix = { name: server.nick };
activeBuffer.addMessage(msg); activeBuffer.addMessage(msg);
composerInputElt.value = ""; };
function setConnectFormDisabled(disabled) {
connectElt.querySelectorAll("input, button").forEach(function(elt) {
elt.disabled = disabled;
});
}
connectFormElt.onsubmit = function(event) {
event.preventDefault();
setConnectFormDisabled(true);
server.url = connectFormElt.elements.url.value;
server.nick = connectFormElt.elements.nick.value;
server.pass = connectFormElt.elements.password.value;
server.username = connectFormElt.elements.username.value || server.nick;
server.realname = connectFormElt.elements.realname.value || server.nick;
connect();
};
window.onkeydown = function(event) {
if (activeBuffer && activeBuffer.readOnly && event.key == "/" && document.activeElement != composerInputElt) {
// Allow typing commands even in read-only buffers
composerElt.classList.remove("read-only");
composerInputElt.focus();
composerInputElt.value = "";
}
}; };

View file

@ -12,7 +12,8 @@ body {
font-family: monospace; font-family: monospace;
} }
#sidebar, #buffer { #sidebar, #buffer, #connect {
width: 100%;
height: 100%; height: 100%;
overflow: auto; overflow: auto;
} }
@ -49,6 +50,22 @@ body {
display: none; display: none;
} }
#connect {
position: absolute;
top: 0;
left: 0;
height: 100%;
background: white;
}
#connect form {
margin: 0 auto;
max-width: 300px;
}
#connect input {
box-sizing: border-box;
width: 100%;
}
a { a {
color: green; color: green;
} }

View file

@ -22,6 +22,42 @@
<input type="text" placeholder="Type a message"> <input type="text" placeholder="Type a message">
</form> </form>
<section id="connect">
<form>
<h2>Connect to IRC</h2>
<label for="connect-url">URL:</label><br/>
<input type="url" name="url" id="connect-url" value="ws://localhost:8080"/>
<br/><br/>
<label for="connect-nick">Nickname:</label><br/>
<input type="username" name="nick" id="connect-nick" autofocus required/>
<br/><br/>
<label for="connect-password">Password:</label><br/>
<input type="password" name="password" id="connect-password"/>
<br/><br/>
<details>
<summary>More options</summary>
<br/>
<label for="connect-username">Username:</label><br/>
<input type="username" name="username" id="connect-username" placeholder="Same as nickname"/>
<br/><br/>
<label for="connect-realname">Real name:</label><br/>
<input type="text" name="realname" id="connect-realname" placeholder="Same as nickname"/>
<br/>
</details>
<br/>
<button>Connect</button>
</form>
</section>
<script src="assets/irc.js"></script> <script src="assets/irc.js"></script>
<script src="assets/client.js"></script> <script src="assets/client.js"></script>
</body> </body>