const STATE = { id: 0, chat_id: "", observer: null, is_loading: false, stream_element: null, last_message_time: 0, last_read_receipt_load: 0, }; function create_streamer(chat_id, hook_element) { STATE.chat_id = chat_id; STATE.stream_element = hook_element.parentElement; STATE.observer = new IntersectionObserver( () => { load_messages(); }, { root: STATE.stream_element, rootMargin: "0px", scrollMargin: "0px", threshold: 1.0, }, ); STATE.observer.observe(hook_element); read_receipt(); } function load_messages() { if (STATE.is_loading) { return; } STATE.is_loading = true; STATE.id += 1; fetch( `/chats/_templates/chat/${STATE.chat_id}/messages/before/${STATE.last_message_time}?use_id=${STATE.id}`, ) .then((res) => res.text()) .then((res) => { setTimeout(() => { STATE.is_loading = false; }, 2000); STATE.stream_element.innerHTML += res; STATE.last_message_time = Number.parseInt( document .getElementById(`msgs_data_${STATE.id}`) .getAttribute("data-first-message-time"), ); // STATE.stream_element.scrollTo(0, STATE.stream_element.scrollHeight); if (document.getElementById(`msgs_quit_${STATE.id}`)) { STATE.observer.disconnect(); console.log("quit"); } else { STATE.observer.unobserve( STATE.stream_element.querySelector( "[ui_ident=data_marker]", ), ); const element = document.createElement("div"); element.setAttribute("ui_ident", "data_marker"); STATE.stream_element.append(element); STATE.observer.observe(element); } }); } function render_message(id) { STATE.is_loading = true; fetch(`/chats/_templates/message/${id}`) .then((res) => res.text()) .then((res) => { STATE.is_loading = false; STATE.stream_element.innerHTML = `${res}${STATE.stream_element.innerHTML}`; mark_message_read(); STATE.stream_element.scrollTo(0, STATE.stream_element.scrollHeight); }); } function sock_con() { const socket = new WebSocket( `//${window.location.origin.split("//")[1]}/api/v1/chats/${STATE.chat_id}/_connect`, ); socket.addEventListener("message", async (event) => { if (event.data === "Ping") { return socket.send("Pong"); } const msg = JSON.parse(event.data); if (msg.method === "MessageCreate") { render_message(msg.body); } else if (msg.method === "MessageDelete") { if (document.getElementById(`message_${msg.body}`)) { document.getElementById(`message_${msg.body}`).remove(); } } else if (msg.method === "ReadReceipt") { setTimeout(() => { read_receipt(); }, 1500); } }); } function create_message(e) { e.preventDefault(); const body = new FormData(); body.append( "body", JSON.stringify({ content: e.target.content.value, }), ); fetch(`/api/v1/messages/${STATE.chat_id}`, { method: "POST", body }) .then((res) => res.json()) .then((res) => { if (res.ok) { e.target.reset(); } else { show_message(res.message, res.ok); } }); } function mark_message_read() { fetch(`/api/v1/chats/${STATE.chat_id}/read_message`, { method: "POST", }) .then((res) => res.json()) .then((res) => { if (!res.ok) { show_message(res.message, res.ok); } }); } function read_receipt() { if (new Date().getTime() - STATE.last_read_receipt_load < 150) { console.log("too soon"); return; } STATE.last_read_receipt_load = new Date().getTime(); if (document.getElementById("delivered_read_status")) { document.getElementById("delivered_read_status").remove(); } fetch(`/chats/_templates/chat/${STATE.chat_id}/read_receipt`) .then((res) => res.text()) .then((res) => { STATE.stream_element.innerHTML = `${res}${STATE.stream_element.innerHTML}`; }); } function delete_message(id) { if (!confirm("Are you sure you want to do this?")) { return; } fetch(`/api/v1/messages/${id}`, { method: "DELETE", }) .then((res) => res.json()) .then((res) => { if (!res.ok) { show_message(res.message, res.ok); } }); }