generate channel info dynamically (no more HTML hardcoding)

This commit is contained in:
Lephenixnoir 2023-06-17 15:11:34 +02:00
parent 5124fd7f2a
commit 0cd00577f1
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
2 changed files with 98 additions and 34 deletions

View File

@ -9,25 +9,14 @@
<body>
<div id="v5shoutbox">
<div class="status"></div>
<div class="channel-buttons">
<button data-channel="#annonces">#annonces</button>
<button data-channel="#hs">#hs</button>
<button data-channel="#projets">#projets</button>
</div>
<div class="channels">
<pre class="channel-annonces">[[[#annonces]]]
</pre>
<pre class="channel-hs">[[[#hs]]]
</pre>
<pre class="channel-projets">[[[#projets]]]
</pre>
</div>
<div class="channel-buttons"></div>
<div class="channels"></div>
<div class="form">
<div class="login-form">
<form class="login-form">
<input type="text" class="login" placeholder="Utilisateur" />
<input type="password" class="password" placeholder="Mot de passe" />
<button class="connect">Connect!</button>
</div>
<input type="submit" class="connect" value="Connect!" />
</form>
<form class="shoutbox-form">
<input type="text" name="message" class="message" />
</form>

View File

@ -101,6 +101,7 @@ let irc = new function() {
this.onStateChanged = function() {};
this.onAuthenticated = function() {};
this.onNewMessage = function(channel, date, author, message) {};
this.onChannelInfo = function(channel, type, value) {};
function log(...args) {
irc.onLog(...args);
@ -284,7 +285,17 @@ let irc = new function() {
}
}
if(msg.command == "PRIVMSG")
if(msg.command === "JOIN" && msg.tags.get("account") === conn.username) {
irc.onChannelInfo(msg.args[0], "joined", undefined);
}
if(msg.command === 332) {
irc.onChannelInfo(msg.args[1], "header", msg.args[2]);
}
if(msg.command === 353 && msg.args[1] === "=") {
irc.onChannelInfo(msg.args[2], "clients", msg.args[3]);
}
if(msg.command === "PRIVMSG")
processPRIVMSG(msg);
}
@ -325,6 +336,10 @@ let irc = new function() {
/* Shoutbox entry point and DOM manipulation. */
let shoutbox = new function() {
const serverUrl = "wss://irc.planet-casio.com:443";
const postUrl = undefined;
const availableChannels = ["#annonces", "#projets", "#hs"];
this.init = function(root) {
/* Channel views */
this.eChannels = root.querySelector(".channels");
@ -341,8 +356,9 @@ let shoutbox = new function() {
this.eShoutboxForm = root.querySelector(".shoutbox-form");
this.eMessage = root.querySelector(".message");
this.eConnect.addEventListener("click", function() {
shoutbox.connect();
this.eLoginForm.addEventListener("submit", function(e) {
e.preventDefault();
shoutbox.connect(serverUrl, postUrl);
});
this.eShoutboxForm.addEventListener("submit", function(e) {
e.preventDefault();
@ -355,7 +371,6 @@ let shoutbox = new function() {
});
this.refreshView();
this.selectChannel("#annonces");
}
/*** IRC callbacks ***/
@ -383,25 +398,86 @@ let shoutbox = new function() {
irc.onStateChanged = this.refreshView.bind(this);
irc.onNewMessage = function(channel, date, author, message) {
shoutbox.addNewMessage(channel, date, author, message);
}
irc.onChannelInfo = function(channel, type, value) {
if(type === "joined")
this.createChannel(channel);
else if(type === "header")
this.setChannelHeader(channel, value);
else if(type === "clients")
this.setChannelClients(channel, value.split(" ").filter(s => s));
}.bind(this);
/*** DOM manipulation ***/
this.getChannelView = function(channel) {
return Array.from(this.eChannels.children)
.find(e => e.dataset.channel === channel);
}
this.createChannel = function(channel) {
if(!availableChannels.includes(channel))
return;
let view = document.createElement("div");
view.classList.add("channel");
view.dataset.channel = channel;
view.style.display = "none";
this.eChannels.appendChild(view);
let header = document.createElement("header");
header.textContent = channel;
view.appendChild(header);
/* TODO: Better display for channels */
let messages = document.createElement("pre");
view.appendChild(messages);
let button = document.createElement("button");
button.appendChild(document.createTextNode(channel));
button.dataset.channel = channel;
this.eChannelButtons.appendChild(button);
button.addEventListener("click", () => {
shoutbox.selectChannel(button.dataset.channel);
});
if(irc.currentChannel() === undefined)
shoutbox.selectChannel(channel);
}
this.setChannelHeader = function(channel, value) {
const view = this.getChannelView(channel);
if(view === undefined)
return;
const header = view.querySelector("header");
header.textContent = channel + ": " + value;
}
this.setChannelClients = function(channel, clients) {
}
this.addNewMessage = function(channel, date, author, message) {
const view = this.getChannelView(channel);
if(view === undefined)
return;
/* Remove the shoutbox bridge's "[s]" suffix */
if(author.endsWith("[s]"))
author = author.substr(0, author.length - 3);
if(channel.startsWith("#"))
channel = channel.substr(1);
const eChan = this.eChannels.querySelector(".channel-" + channel);
if(eChan === null)
return;
/* TODO: Better text element x) */
eChan.innerHTML += "[" + date.toLocaleTimeString() + "] [" + author + "] "
+ message + "\n";
const pre = view.querySelector("pre");
pre.innerHTML += "[" + date.toLocaleTimeString() + "] [" + author + "] "
+ message + "\n";
}.bind(this);
/*** User interactions ***/
this.connect = function() {
this.connect = function(serverUrl, postUrl) {
if(irc.isConnected())
return this.log("Already connected!");
if(this.eLogin.value === "" || this.ePassword.value === "")
@ -409,15 +485,14 @@ let shoutbox = new function() {
if(this.eLogin.value.includes(" "))
return this.log("Login should not contain a space!");
irc.connect("wss://irc.planet-casio.com:443", undefined,
this.eLogin.value, this.ePassword.value);
irc.connect(serverUrl, postUrl, this.eLogin.value, this.ePassword.value);
}
this.selectChannel = function(name) {
irc.selectChannel(name);
const cls = "channel-" + name.substr(1);
Array.from(this.eChannels.children).forEach(e => {
e.style.display = e.classList.contains(cls) ? "block" : "none";
if(e.dataset.channel !== undefined)
e.style.display = (e.dataset.channel === name) ? "block" : "none";
});
}