generated from t/malachite
add: working chat ui
This commit is contained in:
parent
f53eb3d367
commit
b360c5e737
14 changed files with 319 additions and 53 deletions
153
app/public/messages.js
Normal file
153
app/public/messages.js
Normal file
|
@ -0,0 +1,153 @@
|
|||
const STATE = {
|
||||
id: 0,
|
||||
chat_id: "",
|
||||
observer: null,
|
||||
is_loading: false,
|
||||
stream_element: null,
|
||||
first_message_time: 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);
|
||||
}
|
||||
|
||||
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.first_message_time}?use_id=${STATE.id}`,
|
||||
)
|
||||
.then((res) => res.text())
|
||||
.then((res) => {
|
||||
setTimeout(() => {
|
||||
STATE.is_loading = false;
|
||||
}, 2000);
|
||||
|
||||
STATE.stream_element.innerHTML += res;
|
||||
STATE.first_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();
|
||||
read_receipt();
|
||||
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();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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 (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}`;
|
||||
});
|
||||
}
|
|
@ -746,3 +746,24 @@ menu.col {
|
|||
width: 25rem;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* messages */
|
||||
.message {
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.message:not(.mine) {
|
||||
flex-direction: row-reverse;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.message .inner {
|
||||
padding: var(--pad-2) var(--pad-3);
|
||||
background: var(--color-surface);
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
.message.mine .inner {
|
||||
background: var(--color-primary);
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue