iu9-ca-web-chat/assets/js/chat.js

222 lines
6.9 KiB
JavaScript

// In real world, I would get this variables from server through nytl
let pres = {lang: ''}
let userinfo = {id: 2, nickname: 'pv', name: 'Pavlov Vladimir'};
let openedchat = {id: 100, name: "Some chat", nickname: 'chat'};
let initial_chatUpdResp = {
LocalHistoryId: 0,
lastMsgId: -1,
messages: [],
members: [
{id: 1, name: 'grisha', nickname: 'gri', role: 'admin'},
{id: 2, name: 'Pavlov Vladimir', nickname: 'pv', role: 'regular'},
{id: 3, name: 'Ivan', nickname: 'ivan', role: 'read-only'}
]
};
let loadedMessages = new Map(); // messageSt objects
let visibleMessages = new Map(); // HTMLElement objects
let anchoredMsg = -1;
let visibleMsgSegStart = -1;
let visibleMsgSegEnd = -2;
let offsetOfAnchor = 100;
// Would start with true if opened `/chat/<>`
let bumpedAtTheBottom = false;
let members = new Map();
for (let memberSt of initial_chatUpdResp.members){
members.set(memberSt.id, memberSt);
}
function updateOffsetOfVisibleMsg(msgId, offset){
visibleMessages.get(msgId).style.bottom = String(offset) + "px";
}
function updateOffsetsUpToTop(){
let offset = offsetOfAnchor;
for (let curMsg = anchoredMsg; curMsg >= visibleMsgSegStart; curMsg--){
updateOffsetOfVisibleMsg(curMsg, offset);
let height = visibleMessages.get(curMsg).offsetHeight;
offset += height + 5;
}
return offset;
}
function updateOffsetsDown(){
let offset = offsetOfAnchor;
for (let curMsg = anchoredMsg + 1; curMsg <= visibleMsgSegEnd; curMsg++){
let height = visibleMessages.get(curMsg).offsetHeight;
offset -= (height + 5);
updateOffsetOfVisibleMsg(curMsg, offset);
}
return offset;
}
function updateOffsetsSane(){
let highest_point = updateOffsetsUpToTop();
let lowest_point = updateOffsetsDown();
return [highest_point, lowest_point];
}
function updateOffsets(){
if (anchoredMsg < 0)
return;
let [highest_point, lowest_point] = updateOffsetsSane();
let winTop = document.getElementById("chat-widget").offsetHeight;
if (lowest_point > 5 || (highest_point - lowest_point) <= winTop){
bumpedAtTheBottom = true;
anchoredMsg = visibleMsgSegEnd;
offsetOfAnchor = 5;
updateOffsetsSane();
} else if (highest_point < winTop - 5){
console.log("Adancing by " + (winTop - 5 - highest_point))
offsetOfAnchor += (winTop - 5 - highest_point);
updateOffsetsSane();
}
}
function makeMessageBox(messageSt){
if (!messageSt.exists || messageSt.isSystem)
throw new Error("Not ready for this");
const parentDiv = document.getElementById("chat-widget");
let box = document.createElement("div");
parentDiv.appendChild(box);
box.className = "message-box";
let topPart = document.createElement("div");
box.appendChild(topPart);
topPart.className = "message-box-top";
let inTopPartSenderName = document.createElement("a");
topPart.appendChild(inTopPartSenderName);
inTopPartSenderName.className = "message-box-sender-name";
if (!members.has(messageSt.senderUserId))
throw new Error("MMMHMMMMGMHMMMM. First - update members. Then messages");
let memberSt = members.get(messageSt.senderUserId);
inTopPartSenderName.innerText = memberSt.name + " (" + memberSt.nickname + ")";
inTopPartSenderName.href = "/user/" + memberSt.nickname;
let ID = messageSt.id;
let inTopPartButtonDelete = document.createElement("img");
topPart.appendChild(inTopPartButtonDelete);
inTopPartButtonDelete.className = "message-box-button";
inTopPartButtonDelete.src = "/assets/img/delete.svg";
inTopPartButtonDelete.onclick = (ev) => {
if (ev.button === 0){
console.log("Tried to delete message " + ID);
}
};
let inTopPartButtonGetLink = document.createElement("img");
topPart.appendChild(inTopPartButtonGetLink);
inTopPartButtonGetLink.className = "message-box-button";
inTopPartButtonGetLink.src = "/assets/img/link.svg";
inTopPartButtonGetLink.onclick = (ev) => {
if (ev.button === 0){
console.log("Tried to get link on message " + ID);
}
};
let msgPart = document.createElement("p");
box.appendChild(msgPart);
msgPart.className = "message-box-msg";
msgPart.innerText = messageSt.text;
return box;
}
function makeVisible(msgId){
visibleMessages.set(msgId, makeMessageBox(loadedMessages.get(msgId)))
}
function opaNewMessage(messageSt){
let msgId = messageSt.id;
let text = messageSt.text;
const chatWin = document.getElementById("chat-widget");
if (loadedMessages.has(msgId)){
throw new Error("Not ready yet");
// loadedMessages.get(msgId).text = text;
// if (visibleMessages.has(msgId)){
// visibleMessages.get(msgId).textContent = text;
// updateOffsets();
// }
} else {
loadedMessages.set(msgId, messageSt);
if (anchoredMsg < 0){
anchoredMsg = msgId;
visibleMsgSegStart = msgId;
visibleMsgSegEnd = msgId;
makeVisible(msgId);
updateOffsets();
} else if (msgId + 1 === visibleMsgSegStart) {
visibleMsgSegStart--;
makeVisible(msgId);
while (loadedMessages.has(visibleMsgSegStart - 1)){
visibleMsgSegStart--;
makeVisible(visibleMsgSegStart);
}
updateOffsets();
} else if (msgId - 1 === visibleMsgSegEnd){
visibleMsgSegEnd++;
makeVisible(msgId);
while (loadedMessages.has(visibleMsgSegEnd + 1)){
visibleMsgSegEnd++;
makeVisible(visibleMsgSegEnd);
}
updateOffsets();
}
}
}
function test(id, uid){
opaNewMessage({
id: id, text: "Message number " + String(id), senderUserId: uid, exists: true, isSystem: false}
);
}
let mainloopTimeout = null;
let mainloopPoller = null;
function setMainloopTimeout(){
mainloopTimeout = setTimeout(mainloopPoller, 1000);
}
mainloopPoller = function(){
try {
console.log("Hello, World!");
} catch (error){}
setMainloopTimeout();
}
window.onload = function (){
console.log("Everything was loaded");
test(6, 1);
test(1, 2);
test(3, 3);
test(2, 1);
test(4, 2);
test(0, 3);
test(5, 2);
test(8, 1);
test(9, 2);
test(7, 3);
for (let i = 10; i < 30; i++){
test(i, 2);
}
document.body.addEventListener("wheel", (event) => {
event.preventDefault();
bumpedAtTheBottom = false;
console.log("Scroll of " + String(event.deltaY));
offsetOfAnchor += event.deltaY / 5;
updateOffsets();
});
mainloopPoller();
document.getElementById("message-input").addEventListener("keyup", (event) => {
if (event.ctrlKey && event.key === 'Enter'){
let textarea = document.getElementById("message-input");
console.log(textarea.value);
}
});
}