183 lines
6.4 KiB
JavaScript
183 lines
6.4 KiB
JavaScript
let offset;
|
|
let timelineElement = document.getElementById("messages");
|
|
let moreButton = document.getElementById("more-button");
|
|
|
|
function escapeHTML(content) {
|
|
return content.replaceAll("&", "&").replaceAll("<", ">").replaceAll(">", "<");
|
|
}
|
|
|
|
function getMessageHTML(messageJSON, canRespond) {
|
|
let el = document.createElement("div");
|
|
el.classList.add("message-container");
|
|
el.dataset.messageId = messageJSON.id;
|
|
el.innerHTML = `<blockquote class="message">
|
|
<div><b>${messageJSON.from || "Anonymous"}</b> writes: <small>${timeSince(messageJSON.timestamp)}</small></div>
|
|
<pre class="not-code">${escapeHTML(messageJSON.content)}</pre>
|
|
</blockquote>
|
|
${messageJSON.response ? `<small>${timeSince(messageJSON.response_timestamp)}</small><pre class="not-code no-margin">\n${escapeHTML(messageJSON.response)}</pre>` : ""}
|
|
${
|
|
canRespond ? `
|
|
<div class="msg-error"></div>
|
|
${messageJSON.response ? "" : '<div><textarea placeholder="Your response..." maxlength="10000"></textarea></div>'}
|
|
<div class="center">
|
|
${messageJSON.response ? "" : `<button class="reply-button" onclick="replyTo(${messageJSON.id})">Reply</button>`}
|
|
<button onclick="deleteMessage(${messageJSON.id})">Delete</button>
|
|
</div>
|
|
` : `<i>No response</i>`
|
|
}`;
|
|
|
|
return el
|
|
}
|
|
|
|
function timeSince(date) {
|
|
let months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
let dateObject = new Date(date * 1000);
|
|
let dateString = `${months[dateObject.getMonth()]} ${dateObject.getDate()}, ${dateObject.getFullYear()}, ${String(dateObject.getHours()).padStart(2, "0")}:${String(dateObject.getMinutes()).padStart(2, "0")}:${String(dateObject.getSeconds()).padStart(2, "0")}`;
|
|
let seconds = Math.floor((+(new Date()) / 1000 - date + 1));
|
|
let unit = "second";
|
|
let amount = seconds > 0 ? seconds : 0;
|
|
const timeAmounts = [
|
|
{ name: "minute", amount: 60 },
|
|
{ name: "hour", amount: 3600 },
|
|
{ name: "day", amount: 86400 },
|
|
{ name: "month", amount: 2592000 },
|
|
{ name: "year", amount: 31536000 }
|
|
];
|
|
|
|
for (const info of timeAmounts) {
|
|
let interval = seconds / info.amount;
|
|
if (interval >= 1) {
|
|
unit = info.name;
|
|
amount = Math.floor(interval);
|
|
}
|
|
}
|
|
return `<span data-timestamp="${date}" title="${dateString}">${Math.floor(amount)} ${unit}${Math.floor(amount) == 1 ? "" : "s"} ago</span>`;
|
|
}
|
|
|
|
function replyTo(messageID) {
|
|
let msgContainer = document.querySelector(`.message-container[data-message-id="${messageID}"]`);
|
|
let self = msgContainer.querySelector(".reply-button")
|
|
let err = msgContainer.querySelector(`.msg-error`);
|
|
|
|
self.setAttribute("disabled", "");
|
|
|
|
fetch("/api/messages/", {
|
|
method: "POST",
|
|
body: JSON.stringify({
|
|
id: messageID,
|
|
content: msgContainer.querySelector("textarea").value
|
|
})
|
|
})
|
|
.then((response) => (response.json()))
|
|
.then((json) => {
|
|
if (json.success) {
|
|
let response = document.createElement("div");
|
|
response.innerHTML = `<small>${timeSince(json.timestamp)}</small><pre class="not-code no-margin">${escapeHTML(json.content)}</pre>`;
|
|
err.innerHTML = "";
|
|
|
|
msgContainer.querySelector("textarea").replaceWith(response);
|
|
self.remove();
|
|
} else {
|
|
err.innerHTML = "Something went wrong!";
|
|
self.removeAttribute("disabled");
|
|
}
|
|
})
|
|
.catch((err) => {
|
|
err.innerHTML = `Something went wrong: ${err}`;
|
|
self.removeAttribute("disabled");
|
|
});
|
|
}
|
|
|
|
function deleteMessage(messageID) {
|
|
//
|
|
}
|
|
|
|
function _updateURL_replaceElement(element, to) {
|
|
let newElement = document.createElement(to);
|
|
newElement.dataset.url = element.dataset.url;
|
|
newElement.dataset.id = element.dataset.id;
|
|
newElement.innerHTML = element.innerHTML;
|
|
newElement.setAttribute("href", element.getAttribute("href"));
|
|
|
|
if (to == "a") {
|
|
newElement.classList.add("not-bold");
|
|
}
|
|
|
|
element.replaceWith(newElement);
|
|
}
|
|
|
|
function updateURL(switchID) {
|
|
let switchElement = document.getElementById("switch").querySelector(`[data-id="${switchID}"]`);
|
|
|
|
for (const el of document.getElementById("switch").querySelectorAll("b")) {
|
|
_updateURL_replaceElement(el, "a");
|
|
}
|
|
|
|
_updateURL_replaceElement(switchElement, "b");
|
|
url = switchElement.dataset.url;
|
|
fetchMessages(true);
|
|
}
|
|
|
|
function fetchMessages(fetchFromStart=false) {
|
|
document.getElementById("refresh").setAttribute("disabled", "");
|
|
let err, append;
|
|
|
|
if (fetchFromStart) {
|
|
timelineElement.innerHTML = "<i class='delete-if-more-messages'>Loading...</i>"
|
|
moreButton.hidden = true;
|
|
} else {
|
|
err = document.querySelector(".delete-if-more-messages");
|
|
append = !!err;
|
|
err = err || document.createElement("i");
|
|
err.classList.add("delete-if-more-messages")
|
|
}
|
|
|
|
fetch(url + (fetchFromStart === true ? "" : `${url.includes("?") ? "&" : "?"}offset=${offset}`))
|
|
.then((response) => (response.json()))
|
|
.then((json) => {
|
|
if (json.success) {
|
|
let frag = document.createDocumentFragment();
|
|
|
|
if (fetchFromStart && json.messages.length == 0) {
|
|
out = "<i>No messages</i>";
|
|
} else {
|
|
for (const message of json.messages) {
|
|
frag.append(getMessageHTML(message, json.canRespond));
|
|
offset = message.id;
|
|
}
|
|
}
|
|
|
|
moreButton.hidden = !json.more;
|
|
timelineElement.append(frag);
|
|
|
|
for (el of document.getElementsByClassName("delete-if-more-messages")) {
|
|
el.remove();
|
|
}
|
|
} else {
|
|
err = document.querySelector(".delete-if-more-messages");
|
|
append = !!err;
|
|
err = err || document.createElement("i");
|
|
err.classList.add("delete-if-more-messages")
|
|
err.innerText = "Something went wrong!";
|
|
append && timelineElement.append(err);
|
|
}
|
|
document.getElementById("refresh").removeAttribute("disabled");
|
|
})
|
|
.catch((error) => {
|
|
err = document.querySelector(".delete-if-more-messages");
|
|
append = !!err;
|
|
err = err || document.createElement("i");
|
|
err.classList.add("delete-if-more-messages")
|
|
err.innerText = `Couldn't fetch timeline: ${error}`;
|
|
append && timelineElement.append(err);
|
|
document.getElementById("refresh").removeAttribute("disabled");
|
|
});
|
|
}
|
|
|
|
fetchMessages(true);
|
|
|
|
setInterval(function () {
|
|
for (const timestamp of document.querySelectorAll("[data-timestamp]")) {
|
|
timestamp.innerHTML = timeSince(Number(timestamp.dataset.timestamp));
|
|
}
|
|
}, 5000);
|