diff options
-rw-r--r-- | TODO | 1 | ||||
-rw-r--r-- | src/index.html | 2 | ||||
-rw-r--r-- | src/main.css | 25 | ||||
-rw-r--r-- | src/main.ts | 123 |
4 files changed, 126 insertions, 25 deletions
@@ -1 +0,0 @@ -Reply to messages diff --git a/src/index.html b/src/index.html index 38bbbc8..ffcbea9 100644 --- a/src/index.html +++ b/src/index.html @@ -14,7 +14,7 @@ <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> + <textarea id="input" rows="2.5" onkeydown="inputkey(event)" onkeyup="clearnewlineinput()"></textarea> <button onclick="send()">Send</button> </span> </body> diff --git a/src/main.css b/src/main.css index b244020..fc7d02b 100644 --- a/src/main.css +++ b/src/main.css @@ -1,5 +1,5 @@ .UI { - background-color: blue; + background-color: lightblue; } #chatwindow { display: flex; @@ -105,7 +105,7 @@ body { } .username { margin-left: 0.3em; - margin-right: 0.4em; + margin-right: 0.7em; } .deleted { @@ -117,4 +117,25 @@ body { text-align: center; background-color: red; color: white; +} + +.reply { + font-size: 14px; + margin-left: 2em; + color: #666; + display: flex; +} +.reply:hover { + cursor: pointer; +} +.reply_icon { + font-size: 0.7em; + margin: auto; +} + +.highlight { + background-color: lightcoral; +} +.reply_highlight { + background-color: lightblue; }
\ No newline at end of file diff --git a/src/main.ts b/src/main.ts index e33391e..bc300c2 100644 --- a/src/main.ts +++ b/src/main.ts @@ -7,11 +7,12 @@ interface Message { id: number, sender: number, message: string, - reply_to: number, + reply_to: number | undefined, date: number, deleted: boolean, } +let initial = true; const messages = new Map<number, Message>(); const users = new Map<number, User>(); @@ -47,12 +48,12 @@ async function format_message(m: Message): Promise<string> { let s = `<span id="${m.id}" class="message ${sclass}"> <p class="messagedate">${format_date(m.date)}</p> - <p class="username">${sender}:</p> + <p class="username">${sender}</p> <p class="messagetext">${m.message}</p> <span class="message_buttons_anchor"> <span class="message_buttons"> <button title="information" onclick="message_info(${m.id})"><i class="fa fa-info" aria-hidden="true"></i></button> - <button title="reply"><i class="fa fa-reply" aria-hidden="true"></i></button> + <button title="reply" onclick="reply(${m.id})"><i class="fa fa-reply" aria-hidden="true"></i></button> <button title="delete" onclick="delete_message(${m.id})"><i class="fa fa-trash-o" aria-hidden="true"></i></button> </span> </span></span>` @@ -60,6 +61,24 @@ async function format_message(m: Message): Promise<string> { return s } +async function format_reply(m: Message): Promise<string> { + var sender = await get_user_name(m.sender); + var sclass = ""; + + if (m.deleted) { + m.message = "*deleted*" + sclass = "deleted" + } + + let s = `<span class="reply ${sclass}" onclick="chatwindow(${m.id}, true)"> + <span class="reply_icon"><i class="fa fa-level-down fa-rotate-270" aria-hidden="true"></i></span> + <p class="username">${sender}</p> + <p class="messagetext">${m.message}</p> + </span>` + + return s +} + function format_time(t: number) { let as_str = `${t}`; if (as_str.length < 2) { @@ -73,8 +92,8 @@ function format_date(d: number) { 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}`; + // let seconds = format_time(date.getSeconds()); + return `${hours}:${minutes}`; } function delete_message(id: number) { @@ -100,28 +119,40 @@ function message_info(id: number): void { let msg = messages.get(id); if (msg != undefined) { - let final = `id: ${msg.id}\nsender: ${msg.sender}\nmessage: ${msg.message}\ndate: ${msg.date}\nreply_to: ${msg.reply_to}\ndelted: ${msg.deleted}`; + let final = `id: ${msg.id}\nsender: ${msg.sender}\nmessage: ${msg.message}\ndate: ${msg.date}\nreply_to: ${msg.reply_to}\ndeleted: ${msg.deleted}`; alert(final) } } -function send() { +function send(id: undefined|number) { var input = getelementbyid("input"); + let button = getelementbyid("inputbox").lastElementChild get_user_from_name().then((user_id) => { if (user_id == undefined) { alert("User not found") return undefined } + + let reply_to: number|null = null; + if (id != undefined) { + reply_to = id + } - let message = JSON.stringify({"sender": user_id, "message": input.value}) + let message = JSON.stringify({"sender": user_id, "message": input.value, "reply_to": reply_to}) xhttp_send("POST", "send_message", message).then((id) => { if (id.Ok != undefined) { - get_message(id.Ok); - + get_message(id.Ok).then(() => { + chatwindow(id.Ok) + }); + input.value = ""; sent = true + button.innerHTML = "Send" + button.onclick = function() { + send(undefined) + } } else { alert(id.Err) sent = true @@ -130,6 +161,21 @@ function send() { }); } +function reply(id: number) { + var input = getelementbyid("input"); + let button = getelementbyid("inputbox").lastElementChild + let element = getelementbyid(id.toString()); + + // Set button to reply + input.focus() + button.innerHTML = "Reply"; + element.classList.add("reply_highlight"); + + button.onclick = function() { + send(id) + } +} + function get_newest_cache_id() { let last = -1; for (let k of messages.keys()) { @@ -147,6 +193,7 @@ function get_newest_cache_id() { function get_newest_messages() { xhttp_request("get_message_id_newest").then(async (newest_id) => { + let new_messages: HTMLSpanElement = getelementbyid("new_messages") let newest_cache_id = get_newest_cache_id(); if (newest_id.Err) { @@ -166,8 +213,10 @@ function get_newest_messages() { let id = newest_id; if (id - 25 < 0) { get_message(0) + chatwindow() } else { get_message(newest_id - 25) + chatwindow() } return get_newest_messages() } @@ -203,7 +252,13 @@ function get_newest_messages() { messages.set(x.id, x) } - chatwindow().then() + if (initial) { + chatwindow(newest_id).then() + initial = false + } else { + new_messages.style.display = "unset" + chatwindow().then() + } }); } @@ -213,19 +268,19 @@ async function get_message_list(oldest, newest): Promise<Message[]> { return req } -function get_message(id: number): void { +async function get_message(id: number): Promise<Message|undefined> { let cached = messages.get(id) if (cached != undefined) { - chatwindow(id) + return cached } // Get message - xhttp_request("get_message/" + id).then((data) => { + return await xhttp_request("get_message/" + id).then((data) => { if (data.Ok != undefined) { let msg = data.Ok; messages.set(msg.id, msg) - chatwindow(msg.id) + return get_message(id) } }) } @@ -293,9 +348,8 @@ function to_dom(x: string): Node { throw new Error("Could not convert to dom") } -async function chatwindow(hash: any = undefined) { +async function chatwindow(hash: any = undefined, hl = false) { let window: HTMLDivElement = getelementbyid("chatwindow"); - let new_messages: HTMLSpanElement = getelementbyid("new_messages") let pre_scroll = window.scrollHeight - window.clientHeight; window.innerHTML = ""; @@ -321,6 +375,14 @@ async function chatwindow(hash: any = undefined) { window.append(to_dom(`<span class="date">${date.getDate()}/${date.getMonth()}/${date.getFullYear()}</span>`)) } + if (v.reply_to != undefined) { + let r = await get_message(v.reply_to); + if (r != undefined) { + let reply = await format_reply(r).then(); + window.append(to_dom(reply)) + } + } + let data = await format_message(v).then() let dom: Node = to_dom(data); @@ -334,16 +396,23 @@ async function chatwindow(hash: any = undefined) { if (window.scrollTop == pre_scroll) { if (latest_v != undefined && hash == undefined) { getelementbyid(latest_v.id).scrollIntoView(); + // highlight(latest_v.id); } - } else { - new_messages.style.display = "unset" } if (hash != undefined) { getelementbyid(hash.toString()).scrollIntoView(); + if (hl) { + highlight(hash); + } } } +function highlight(id: number) { + let element: HTMLSpanElement = getelementbyid(id.toString()); + element.classList.add("highlight"); +} + function onscrollchat() { let window: HTMLDivElement = getelementbyid("chatwindow"); let new_messages: HTMLSpanElement = getelementbyid("new_messages") @@ -356,14 +425,26 @@ function onscrollchat() { function inputkey(event: KeyboardEvent) { let window: HTMLTextAreaElement = getelementbyid("input"); + let button = getelementbyid("inputbox").lastElementChild // 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() + + // @ts-ignore + if (key == "Enter" && !shift && comp == 0 && key != "Convert") { + button.onclick() + } + // @ts-ignore + if (key == "Escape" && !shift && key != "Convert") { + button.innerHTML = "Send" + button.onclick = function() { + send(undefined) + } + + chatwindow() } } |