const messages = new Map(); const users = new Map(); let sent = false; const host = location.protocol + "//" + location.host; // const xhttp_worker = new Worker("xhttp.js"); function xhttp_request(location) { let f = fetch(`${host}/api/${location}`); return f.then((response) => response.json()); } function xhttp_post(location, json) { let f = fetch(`${host}/api/${location}`, { method: "POST", headers: {"Content-Type": "application/json"}, body: json }) return f.then((response) => response.json()); } async function format_message(m) { var s; var sender = await 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().then((user_id) => { 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).then((id) => { 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() { xhttp_request("get_message_id_newest").then(async (newest_id) => { 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 = await 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().then() }); } async function get_message_list(oldest, newest) { let data = await xhttp_request(`get_message_list/${oldest}/${newest}`).then(); let req = data.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 xhttp_request("get_message/" + id).then((data) => { if (data.Ok != undefined) { let msg = data.Ok; messages.set(msg.id, msg) chatwindow(msg.id) } }) } async function get_user_from_name() { let v = document.getElementById("username").value; for (x of users.values()) { if (x.username == v) { return x.id } } let user = await xhttp_post("get_user_by_name", JSON.stringify(v)); if (user.Ok) { users.set(user.id, user) return user.Ok.id } else { return await create_user(v) } } async function create_user(username) { let response = await xhttp_post("create_user", JSON.stringify(username)); if (response.Ok != undefined) { await get_user_name(response.Ok); return response.Ok } else { alert("Could not create user") return undefined } } async function get_user_name(id) { let cached = users.get(id) if (cached != undefined) { return cached.username } let data = await xhttp_request("get_user/" + id,); let user = data.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 } async function chatwindow(hash = undefined) { 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 data = await format_message(v).then() let dom = to_dom(data); 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() { xhttp_request("").then((server_info) => { 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" } }) }