const messages = new Map();
const users = new Map();
const host = window.location.protocol + "//" + window.location.host;
let sent = false;
function xhttp_request(location) {
var xhttp = new XMLHttpRequest();
var return_string;
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
// Typical action to be performed when the document is ready:
return_string = xhttp.responseText;
}
};
xhttp.open("GET", `${host}/api/${location}`, false);
xhttp.send();
return JSON.parse(return_string);
}
function xhttp_post(location, json) {
var xhttp = new XMLHttpRequest();
xhttp.open("POST", `${host}/api/${location}`, false);
xhttp.setRequestHeader("Content-Type", "application/json")
var return_string;
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
return_string = xhttp.responseText;
}
};
xhttp.send(json);
return JSON.parse(return_string);
}
function format_message(m) {
var s;
var sender = get_user_name(m.sender);
var sclass = "";
if (m.deleted) {
m.message = "*deleted*"
sclass = "deleted"
}
s = `${format_date(m.date)}|${sender}: ${m.message}`
return s
}
function format_time(t) {
let as_str = `${t}`;
if (as_str.length < 2) {
return `0${t}`
} else {
return `${t}`
}
}
function format_date(d) {
let date = new Date(d * 1000);
let hours = format_time(date.getHours());
let minutes = format_time(date.getMinutes());
let seconds = format_time(date.getSeconds());
return `${hours}:${minutes}:${seconds}`;
}
function send() {
var input = document.getElementById("input").value;
let user_id = get_user_from_name();
if (user_id == undefined) {
alert("User not found")
return undefined
}
let message = JSON.stringify({"sender": user_id, "message": input})
var id = xhttp_post("send_message", message)
get_message(id.Ok);
document.getElementById("input").value = ""
sent = true
}
function get_newest_cache_id() {
let last = -1;
for (k of messages.keys()) {
if (k > last) {
last = k
}
}
if (last == -1) {
return undefined
} else {
return last
}
}
// Returns message list
function get_newest_messages() {
let newest_id = xhttp_request("get_message_id_newest");
let newest_cache_id = get_newest_cache_id();
if (newest_id.Err) {
return
} else {
newest_id = newest_id.Ok
}
let final_array = [];
if (newest_id == newest_cache_id) {
return
}
if (newest_cache_id == undefined) {
let id = newest_id;
if (id - 25 < 0) {
get_message(0)
} else {
get_message(newest_id - 25)
}
return get_newest_messages()
}
if (newest_id > newest_cache_id) {
let delta = newest_id - newest_cache_id ;
if (delta > 25) {
let oldest = newest_id - 25;
let newest = delta;
let list = get_message_list(oldest, newest);
for (x of list.values()) {
final_array.push(x)
}
newest_id = oldest;
if (oldest - 25 < 0) {
newest_cache_id = 0
} else {
newest_cache_id = oldest - 25
}
}
}
let list = get_message_list(newest_cache_id, newest_id)
for (x of list.values()) {
final_array.push(x)
}
// Insert all values into the message map
for (x of final_array.values()) {
messages.set(x.id, x)
}
chatwindow()
}
function get_message_list(oldest, newest) {
let req = xhttp_request(`get_message_list/${oldest}/${newest}`).Ok
return req
}
// Returns dom
function get_message(id) {
let cached = messages.get(id)
if (cached != undefined) {
return to_dom(format_message(cached))
}
// Get message
let msg = xhttp_request("get_message/" + id).Ok;
messages.set(msg.id, msg)
let dom = to_dom(format_message(msg));
chatwindow(msg.id)
}
function get_user_from_name() {
let v = document.getElementById("username").value;
let cached;
for (x of users.values()) {
if (x.username == v) {
return x.id
}
}
let user = xhttp_post("get_user_by_name", JSON.stringify(v));
if (user.Ok) {
return user.Ok.id
} else {
return create_user(v)
}
}
function create_user(username) {
let user = xhttp_post("create_user", JSON.stringify(username));
return user.Ok
}
function get_user_name(id) {
let cached = users.get(id)
if (cached != undefined) {
return cached.username
}
let user = xhttp_request("get_user/" + id).Ok;
users.set(user.id, user)
return user.username
}
// Returns dom
function to_dom(x) {
// Pretty hacky if I do say so myself
let dom = new DOMParser().parseFromString(x, "text/html").firstChild.lastChild.firstChild;
return dom
}
function chatwindow(hash) {
let window = document.getElementById("chatwindow");
let pre_scroll = window.scrollHeight - window.clientHeight;
window.innerHTML = "";
let array = [];
for (v of messages.values()) {
array.push(v);
}
array.sort(
function(a, b) {
return a.id - b.id
}
);
let old_date = new Date(0);
let latest_v;
for (v of array) {
latest_v = v;
let date = new Date(v.date * 1000);
if (date.getDate() > old_date.getDate() || date.getFullYear() > old_date.getFullYear() || date.getMonth() > date.getMonth()) {
old_date = date;
window.append(to_dom(`${date.getDate()}/${date.getMonth()}/${date.getFullYear()}`))
}
let dom = to_dom(format_message(v))
let node = window.appendChild(dom);
}
if (window.scrollTop == pre_scroll) {
if (latest_v != undefined && hash == undefined) {
document.getElementById(v.id).scrollIntoView();
}
} else {
document.getElementById("new_messages").style.display = "unset"
}
if (hash != undefined) {
document.getElementById(hash).scrollIntoView();
}
}
function onscrollchat() {
let window = document.getElementById("chatwindow");
let pre_scroll = window.scrollHeight - window.clientHeight;
if (window.scrollTop == pre_scroll) {
document.getElementById("new_messages").style.display = "";
}
}
function inputkey(event) {
let window = document.getElementById("input");
// If the cursor pos is at the end of the textarea
let comp = window.selectionEnd - window.value.length
let key = event.key
let shift = event.shiftKey;
if (key == "Enter" && !shift && comp == 0) {
send()
}
}
function clearnewlineinput() {
let window = document.getElementById("input");
if (window.value == "\n" && sent == true) {
window.value = ""
sent = false
}
}
function onload() {
let server_info = xhttp_request("");
document.getElementById("info").innerHTML += server_info.version + ", " + server_info.name + ", users: " + server_info.users;
// Get ready for websockets implementation in rocket_test 0.3
if (server_info.version[2] < 3 ) {
const interval = setInterval(get_newest_messages, 1000);
} else {
// Initiate websocket "polling"
}
}