93 lines
3.1 KiB
JavaScript
93 lines
3.1 KiB
JavaScript
(function () {
|
|
function messageExists(messageId) {
|
|
return Boolean(document.querySelector('[data-message-id="' + CSS.escape(messageId) + '"]'));
|
|
}
|
|
|
|
function isDiscussionMessageForm(element) {
|
|
return Boolean(element && element.matches && element.matches('form[action$="/discussion/messages"]'));
|
|
}
|
|
|
|
function requestElement(detail) {
|
|
return detail && detail.requestConfig && detail.requestConfig.elt;
|
|
}
|
|
|
|
function isSuccessfulDiscussionPost(detail) {
|
|
var status = detail && detail.xhr && detail.xhr.status;
|
|
return status >= 200 && status < 300;
|
|
}
|
|
|
|
function messageIdFromHTML(html) {
|
|
if (!html) return "";
|
|
var template = document.createElement("template");
|
|
template.innerHTML = html.trim();
|
|
var message = template.content.querySelector("[data-message-id]");
|
|
return message ? message.dataset.messageId : "";
|
|
}
|
|
|
|
function ensureMessageList(container) {
|
|
var messages = container.querySelector("#discussion-messages");
|
|
if (!messages) return null;
|
|
|
|
var list = messages.querySelector(".divide-y");
|
|
if (list) return list;
|
|
|
|
messages.innerHTML = "";
|
|
list = document.createElement("div");
|
|
list.className = "divide-y divide-slate-100";
|
|
messages.appendChild(list);
|
|
return list;
|
|
}
|
|
|
|
function appendMessage(container, event) {
|
|
if (!event || !event.messageId || !event.messageHtml || messageExists(event.messageId)) {
|
|
return;
|
|
}
|
|
var list = ensureMessageList(container);
|
|
if (!list) return;
|
|
|
|
var template = document.createElement("template");
|
|
template.innerHTML = event.messageHtml.trim();
|
|
list.appendChild(template.content);
|
|
}
|
|
|
|
function connectDiscussion(container) {
|
|
if (!container || container.dataset.discussionStreamConnected === "true") return;
|
|
|
|
var streamURL = container.dataset.discussionStreamUrl;
|
|
if (!streamURL || !window.EventSource) return;
|
|
|
|
container.dataset.discussionStreamConnected = "true";
|
|
var source = new EventSource(streamURL);
|
|
source.addEventListener("discussion-message", function (message) {
|
|
try {
|
|
appendMessage(container, JSON.parse(message.data));
|
|
} catch (_) {
|
|
return;
|
|
}
|
|
});
|
|
}
|
|
|
|
function connectDiscussionStreams() {
|
|
document.querySelectorAll("[data-discussion-stream-url]").forEach(connectDiscussion);
|
|
}
|
|
|
|
document.addEventListener("DOMContentLoaded", connectDiscussionStreams);
|
|
document.body.addEventListener("htmx:afterSwap", connectDiscussionStreams);
|
|
document.body.addEventListener("htmx:beforeSwap", function (event) {
|
|
if (!isDiscussionMessageForm(requestElement(event.detail))) return;
|
|
|
|
var messageId = messageIdFromHTML(event.detail.xhr && event.detail.xhr.responseText);
|
|
if (messageId && messageExists(messageId)) {
|
|
event.detail.shouldSwap = false;
|
|
event.preventDefault();
|
|
}
|
|
});
|
|
document.body.addEventListener("htmx:afterRequest", function (event) {
|
|
var form = requestElement(event.detail);
|
|
if (!isDiscussionMessageForm(form) || !isSuccessfulDiscussionPost(event.detail)) return;
|
|
|
|
form.reset();
|
|
var textarea = form.querySelector("#discussion-message-body");
|
|
if (textarea) textarea.value = "";
|
|
});
|
|
})();
|