diff options
-rw-r--r-- | index.html | 61 | ||||
-rw-r--r-- | main.css | 65 | ||||
-rw-r--r-- | main.js | 156 |
3 files changed, 199 insertions, 83 deletions
@@ -1,64 +1,19 @@ -<html> +<!DOCTYPE html> <head> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script src="main.js"></script> - <style> - .UI { - background-color: blue; - } - #chatwindow { - display: flex; - flex-flow: column; - overflow-y: scroll; - word-break: break-word; - scroll-snap-align: end; - flex-basis: 100vh; - flex-grow: 1; - } - #chatwindow > span:hover { - background-color: #DDD; - } - #chatwindow > span { - white-space: pre-line; - } - #navbar { - border-bottom: 2px solid black; - width: 100%; - display: inline-block; - flex-grow: 0; - } - #inputbox { - border-top: 2px solid black; - display: flex; - } - #inputbox > button { - padding: 0 5px 0 5px; - } - #input { - resize: none; - flex-grow: 1; - } - - * { - margin: 0; - padding: 0; - border: 0; - } - - body { - display: flex; - flex-direction: column; - max-height: 100vh; - } - </style> + <link rel="stylesheet" href="main.css"> </head> <body onload="onload()"> <span id="navbar"> <span>Localhost</span> <span id = "info" class="UI">Server Information: </span> + <span>username: <input id="username"></span> </span> - <div id="chatwindow"></div> - <span id="inputbox" onkeyup="inputkey(event)"> - <textarea id="input" autofocus rows="2"></textarea> + <span id="new_messages" class="new_messages">New Messages</span> + <div id="chatwindow" onscroll="onscrollchat()"></div> + <span id="inputbox"> + <textarea id="input" rows="2.5" onkeypress="inputkey(event)" onkeyup="clearnewlineinput()"></textarea> <button onclick="send()">Send</button> </span> </body> diff --git a/main.css b/main.css new file mode 100644 index 0000000..f67887f --- /dev/null +++ b/main.css @@ -0,0 +1,65 @@ +.UI { + background-color: blue; +} +#chatwindow { + display: flex; + flex-flow: column; + overflow-y: scroll; + word-break: break-word; + scroll-snap-align: end; + flex-basis: 100vh; + flex-grow: 1; +} +.message:hover { + background-color: #DDD; +} +.message { + white-space: pre; +} +#navbar { + border-bottom: 2px solid black; + width: 100%; + display: inline-block; + flex-grow: 0; +} +#inputbox { + border-top: 2px solid black; + display: flex; +} +#inputbox > button { + padding: 0 5px 0 5px; +} +#input { + resize: none; + flex-grow: 1; + font-size: 16px; +} + +* { + margin: 0; + padding: 0; + border: 0; +} + +body { + display: flex; + flex-direction: column; + max-height: 100vh; +} + +.date { + text-align: center; + font-weight: bold; + border-bottom: 1px solid black; +} + +.deleted { + color: #999; +} + +.new_messages { + display: none; + text-align: center; + background-color: red; + color: white; +}
\ No newline at end of file @@ -1,5 +1,7 @@ const messages = new Map(); const users = new Map(); +const host = window.location.protocol + "//" + window.location.host; +let sent = false; function xhttp_request(location) { @@ -12,7 +14,7 @@ function xhttp_request(location) { return_string = xhttp.responseText; } }; - xhttp.open("GET", "http://localhost/api/" + location, false); + xhttp.open("GET", `${host}/api/${location}`, false); xhttp.send(); return JSON.parse(return_string); @@ -20,7 +22,7 @@ function xhttp_request(location) { function xhttp_post(location, json) { var xhttp = new XMLHttpRequest(); - xhttp.open("POST", "http://localhost/api/" + location, false); + xhttp.open("POST", `${host}/api/${location}`, false); xhttp.setRequestHeader("Content-Type", "application/json") @@ -40,27 +42,51 @@ function xhttp_post(location, json) { function format_message(m) { var s; var sender = get_user_name(m.sender); + var sclass = ""; if (m.deleted) { - s = `<span>${m.id}|${sender}: deleted</span>` - // s = "<span>" + m.id + "|" + m.sender + ": /deleted/" + "</span>" - } else { - s = `<span>${m.id}|${sender}: ${m.message}</span>` - // s = "<span>" + m.id + "|" + m.sender + ": " + m.message + "</span>" + m.message = "*deleted*" + sclass = "deleted" } + s = `<span title="${m.id}" class="message ${sclass}" id="${m.id}">${format_date(m.date)}|${sender}: ${m.message}</span>` 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 message = JSON.stringify({"sender": 0, "message": input}) + 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 = '' + document.getElementById("input").value = "" + sent = true } function get_newest_cache_id() { @@ -71,14 +97,24 @@ function get_newest_cache_id() { } } - return last + if (last == -1) { + return undefined + } else { + return last + } } // Returns message list function get_newest_messages() { - let newest_id = xhttp_request("get_message_id_newest").Ok; + 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 = []; @@ -86,8 +122,8 @@ function get_newest_messages() { return } - if (newest_cache_id == -1) { - get_message(0) + if (newest_cache_id == undefined) { + get_message(newest_id - 25) return get_newest_messages() } @@ -134,18 +170,34 @@ function get_message_list(oldest, newest) { function get_message(id) { let cached = messages.get(id) if (cached != undefined) { - return to_dom(cached) + 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(msg); + let dom = to_dom(format_message(msg)); - chatwindow() + chatwindow(msg.id) +} - return dom +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 undefined + } } function get_user_name(id) { @@ -163,12 +215,14 @@ function get_user_name(id) { // Returns dom function to_dom(x) { - let dom = new DOMParser().parseFromString(format_message(x), "text/xml").firstChild; + // Pretty hacky if I do say so myself + let dom = new DOMParser().parseFromString(x, "text/html").firstChild.lastChild.firstChild; return dom } -function chatwindow() { +function chatwindow(hash) { let window = document.getElementById("chatwindow"); + let pre_scroll = window.scrollHeight - window.clientHeight; window.innerHTML = ""; let array = []; @@ -183,22 +237,62 @@ function chatwindow() { } ); + let old_date = new Date(0); + let latest_v; for (v of array) { - let dom = to_dom(v); + 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(`<span class="date">${date.getDate()}/${date.getMonth()}/${date.getFullYear()}</span>`)) + } + let dom = to_dom(format_message(v)) + - window.append(dom) + 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" } - window.scrollTop = window.scrollHeight + 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) { + if (key == "Enter" && !shift && comp == 0) { send() - } else if (key == "Enter" && !shift) { - this.value += "\n" + } +} + +function clearnewlineinput() { + let window = document.getElementById("input"); + + if (window.value == "\n" && sent == true) { + window.value = "" + sent = false } } @@ -206,8 +300,10 @@ function onload() { let server_info = xhttp_request(""); document.getElementById("info").innerHTML += server_info.version + ", " + server_info.name + ", users: " + server_info.users; - // Get all messages on startup - // get_newest_messages(); - - const interval = setInterval(get_newest_messages, 1000); -}
\ No newline at end of file + // 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" + } +} |