Files
locutus/www/res/js/modules/locutus.js

215 lines
6.3 KiB
JavaScript

"use strict";
import * as USIMP from "./usimp.js";
export class App {
account;
defaultLocation;
main;
windows;
session;
constructor() {
if (localStorage.session === undefined) {
this.defaultLocation = '/welcome';
this.account = null;
} else {
let session = JSON.parse(localStorage.session);
this.defaultLocation = '/';
this.account = session.account;
}
this.main = document.getElementsByTagName("main")[0];
this.windows = document.getElementById("windows");
window.addEventListener("hashchange", event => {
this.handleUrl(event.newURL);
});
this.handleUrl(document.URL);
}
setHash(hash) {
let url = new URL(document.URL);
url.hash = hash;
location.href = url.toString();
}
handleUrl(url) {
this.handleHash(new URL(url).hash);
}
handleHash(hash) {
console.log(hash);
if (hash[0] === '#') hash = hash.substr(1);
let defaultCase = () => {
history.replaceState(null, null, `#${this.defaultLocation}`);
this.handleHash(this.defaultLocation);
}
switch (hash) {
case "/":
if (!this.session) {
return defaultCase();
}
this.hideWindows();
this.showMain();
this.removeAllWindows();
this.setupMain();
break;
case "/welcome":
this.hideMain();
this.showWindows();
this.removeAllWindows();
this.addWelcomeWindow();
break;
case "/login":
if (this.session) {
return defaultCase();
}
this.hideMain();
this.showWindows();
this.removeAllWindows();
this.addLoginWindow();
break;
default:
console.warn(`Invalid url hash #${hash}`);
return defaultCase();
}
//this.setHash(hash);
}
login(accountName, domainName, password) {
return USIMP.Domain.fromName(domainName).then(domain => {
let session = new USIMP.Session(domain);
session.authenticate(accountName, password)
.catch((event) => {
console.error(`Unable to reach domain server: ${event}`);
})
.then(() => {
this.session = session;
this.defaultLocation = "/";
this.setHash("/");
});
});
}
hideMain() {
this.main.style.visibility = "hidden";
}
showMain() {
this.main.style.visibility = "visible";
}
hideWindows() {
this.windows.style.visibility = "hidden";
}
showWindows() {
this.windows.style.visibility = "visible";
}
removeAllWindows() {
while (this.windows.lastChild) this.windows.removeChild(this.windows.lastChild);
}
addWelcomeWindow() {
let win = document.createElement("div");
win.classList.add("window-welcome");
win.innerHTML = `
<h1>Welcome to Locutus!</h1>
<a href="#/login" class="button">Login</a>`;
this.windows.appendChild(win);
}
addMessage(message) {
let msg = document.createElement("div");
msg.classList.add("message");
msg.innerText = message;
let chat = this.main.getElementsByClassName("chat-history")[0];
chat.appendChild(msg);
chat.scrollTop = chat.scrollHeight;
}
addLoginWindow() {
let win = document.createElement("div");
win.classList.add("window-login");
win.innerHTML = `
<h1>Login to USIMP Account</h1>
<form>
<input name="account" placeholder="Account name" type="text" required/>
<input name="domain" placeholder="Domain" type="text" pattern="([a-zA-Z0-9_-]+\\.)+[a-zA-Z]{2,}" required/>
<input name="password" placeholder="Password" type="password" required/>
<button type="submit">Login</button>
</form>`;
win.getElementsByTagName("form")[0].addEventListener("submit", async (evt) => {
evt.preventDefault();
let form = evt.target;
for (let e of form) e.disabled = true;
for (let d of form.getElementsByTagName("div")) {
form.removeChild(d);
}
function formError(msg) {
let div = document.createElement("div");
div.classList.add("error");
div.innerText = msg;
form.appendChild(div);
}
this.login(form.account.value, form.domain.value, form.password.value)
.catch(reason => {
document.getElementsByName("domain")[0].setAttribute("invalid", "invalid");
formError("Invalid USIMP domain");
console.error(reason);
})
.finally(() => {
for (let e of form) e.disabled = false;
});
});
this.windows.appendChild(win);
document.getElementsByName("domain")[0].addEventListener("input", (event) => {
event.target.removeAttribute("invalid");
});
document.getElementsByName("account")[0].focus();
}
setupMain() {
this.main.innerHTML = `
<div class="chat">
<div class="chat-history"></div>
<div class="chat-input-wrapper">
<input name="message" type="text"/>
</div>
</div>`;
let input = document.getElementsByName("message")[0];
input.addEventListener("keyup", (event) => {
if (event.key === "Enter" && input.value.length > 0) {
this.session.sendEvent("60nc0XXDIYUh6QzX4p0rMpCdzDmxghZLZk8dLuQh628", {
message: input.value,
});
this.addMessage(input.value);
input.value = "";
}
});
this.session.subscribe(response => {
this.addMessage(response.event.data.message);
});
}
}