222 lines
6.9 KiB
JavaScript
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);
|
|
}
|
|
});
|
|
}
|