2024-09-12 07:47:29 +00:00
|
|
|
let LocalHistoryId = 0;
|
2024-08-06 08:29:21 +00:00
|
|
|
|
2024-09-12 07:47:29 +00:00
|
|
|
let members = new Map();
|
2024-08-11 12:17:53 +00:00
|
|
|
|
2024-09-12 07:47:29 +00:00
|
|
|
let loadedMessages = new Map(); // messageSt objects
|
|
|
|
/*
|
|
|
|
container: EL, box: EL, offset: number (msgPres) */
|
|
|
|
let visibleMessages = new Map(); // HTMLElement objects
|
2024-08-11 12:17:53 +00:00
|
|
|
|
2024-09-12 07:47:29 +00:00
|
|
|
let anchoredMsg = -1;
|
|
|
|
let visibleMsgSegStart = -1;
|
|
|
|
let visibleMsgSegEnd = -2;
|
|
|
|
let offsetOfAnchor = 500;
|
|
|
|
let highestPoint = null;
|
|
|
|
let lowestPoint = null;
|
|
|
|
|
|
|
|
let lastMsgId = -1;
|
|
|
|
let myRoleHere = null; // Dung local state updates should be updated first
|
|
|
|
|
|
|
|
// Would start with true if opened `/chat/<>`
|
|
|
|
let bumpedAtBottom = false;
|
2024-08-11 12:17:53 +00:00
|
|
|
|
2024-09-12 07:47:29 +00:00
|
|
|
// Hidden variable. When deletion window popup is active
|
|
|
|
// Persists from popup activation until popup deactivation
|
|
|
|
let storeHiddenMsgIdForDeletionWin = -1;
|
|
|
|
|
|
|
|
let debugMode = false;
|
|
|
|
|
|
|
|
// Positive in production, negative for debug
|
|
|
|
let softZoneSz = debugMode ? -150 : 300;
|
|
|
|
let chatPadding = debugMode ? 300 : 5;
|
|
|
|
let msgGap = 5;
|
|
|
|
const msgErased = pres.chat.msgErased;
|
|
|
|
|
|
|
|
function genSentBase(){
|
|
|
|
return {
|
|
|
|
'chatUpdReq': {
|
|
|
|
'LocalHistoryId': LocalHistoryId,
|
|
|
|
'chatId': openedchat.id
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
2024-08-11 12:17:53 +00:00
|
|
|
|
2024-09-12 07:47:29 +00:00
|
|
|
function genSentBaseGMN(){
|
|
|
|
let Sent = genSentBase();
|
|
|
|
Sent.amount = debugMode ? 2 : 14;
|
|
|
|
return Sent;
|
|
|
|
}
|
2024-08-11 12:17:53 +00:00
|
|
|
|
2024-09-12 07:47:29 +00:00
|
|
|
function getChatWgSz(){
|
|
|
|
let chatWg = document.getElementById("chat-widget");
|
|
|
|
return [chatWg.offsetWidth, chatWg.offsetHeight];
|
|
|
|
}
|
2024-08-11 12:17:53 +00:00
|
|
|
|
2024-09-12 07:47:29 +00:00
|
|
|
function elSetOffsetInChat(el, offset){
|
|
|
|
el.style.bottom = String(offset) + "px";
|
|
|
|
}
|
2024-08-11 12:17:53 +00:00
|
|
|
|
2024-09-12 07:47:29 +00:00
|
|
|
function isMissingPrimaryMsgHeap(){
|
|
|
|
return lastMsgId >= 0 && anchoredMsg < 0;
|
|
|
|
}
|
2024-08-11 12:17:53 +00:00
|
|
|
|
2024-09-12 07:47:29 +00:00
|
|
|
function isMissingTopMsgHeap(){
|
|
|
|
let [W, H] = getChatWgSz();
|
|
|
|
return anchoredMsg >= 0 && (highestPoint < H + softZoneSz && visibleMsgSegStart > 0);
|
|
|
|
}
|
2024-08-11 12:17:53 +00:00
|
|
|
|
2024-09-12 07:47:29 +00:00
|
|
|
function isMissingBottomMsgHeap(){
|
|
|
|
return anchoredMsg >= 0 && (lowestPoint > - softZoneSz && visibleMsgSegEnd < lastMsgId);
|
|
|
|
}
|
2024-08-14 22:07:59 +00:00
|
|
|
|
2024-09-12 07:47:29 +00:00
|
|
|
function updateOffsetOfVisibleMsg(msgId, offset){
|
|
|
|
visibleMessages.get(msgId).container.style.bottom = String(offset) + "px";
|
|
|
|
}
|
2024-08-14 22:07:59 +00:00
|
|
|
|
2024-09-12 07:47:29 +00:00
|
|
|
function updateOffsetsUpToTop(){
|
|
|
|
let offset = offsetOfAnchor;
|
|
|
|
for (let curMsg = anchoredMsg; curMsg >= visibleMsgSegStart; curMsg--){
|
|
|
|
updateOffsetOfVisibleMsg(curMsg, offset);
|
|
|
|
let height = visibleMessages.get(curMsg).container.offsetHeight;
|
|
|
|
offset += height + msgGap;
|
|
|
|
}
|
|
|
|
return offset - msgGap;
|
|
|
|
}
|
2024-08-14 22:07:59 +00:00
|
|
|
|
2024-09-12 07:47:29 +00:00
|
|
|
function updateOffsetsDown(){
|
|
|
|
let offset = offsetOfAnchor;
|
|
|
|
for (let curMsg = anchoredMsg + 1; curMsg <= visibleMsgSegEnd; curMsg++){
|
|
|
|
let height = visibleMessages.get(curMsg).container.offsetHeight;
|
|
|
|
offset -= (height + msgGap);
|
|
|
|
updateOffsetOfVisibleMsg(curMsg, offset);
|
|
|
|
}
|
|
|
|
return offset;
|
|
|
|
}
|
2024-08-14 22:07:59 +00:00
|
|
|
|
2024-09-12 07:47:29 +00:00
|
|
|
function updateOffsetsSane(){
|
|
|
|
if (anchoredMsg < 0)
|
|
|
|
return;
|
|
|
|
highestPoint = updateOffsetsUpToTop();
|
|
|
|
lowestPoint = updateOffsetsDown();
|
|
|
|
}
|
2024-08-11 12:17:53 +00:00
|
|
|
|
2024-09-12 07:47:29 +00:00
|
|
|
function heightOfPreloadGhost(){
|
|
|
|
let [W, H] = getChatWgSz();
|
|
|
|
return Math.min(H * 0.9, Math.max(H * 0.69, 30));
|
|
|
|
}
|
2024-08-14 22:07:59 +00:00
|
|
|
|
2024-09-12 07:47:29 +00:00
|
|
|
function updateOffsets(){
|
|
|
|
let spinnerTop = document.getElementById("top-loading");
|
|
|
|
let spinnerBottom = document.getElementById("bottom-loading");
|
|
|
|
let SbH = spinnerBottom.offsetHeight;
|
|
|
|
if (anchoredMsg < 0){
|
|
|
|
hideHTMLElement(spinnerBottom);
|
|
|
|
elSetOffsetInChat(spinnerTop, chatPadding);
|
|
|
|
setElementVisibility(spinnerTop, isMissingPrimaryMsgHeap());
|
|
|
|
} else {
|
|
|
|
let [W, H] = getChatWgSz();
|
|
|
|
updateOffsetsSane();
|
|
|
|
let lowestLowestPoint = isMissingBottomMsgHeap() ? lowestPoint - heightOfPreloadGhost(): lowestPoint;
|
|
|
|
let highestHighestPoint = isMissingTopMsgHeap() ? highestPoint + heightOfPreloadGhost() : highestPoint;
|
|
|
|
if (lowestLowestPoint > chatPadding || (highestHighestPoint - lowestLowestPoint) <= H - chatPadding * 2 ||
|
|
|
|
(!isMissingBottomMsgHeap() && bumpedAtBottom)) {
|
|
|
|
|
|
|
|
offsetOfAnchor += (-lowestLowestPoint + chatPadding);
|
|
|
|
updateOffsetsSane();
|
|
|
|
} else if (highestHighestPoint < H - chatPadding) {
|
|
|
|
offsetOfAnchor += (-highestHighestPoint + (H - chatPadding));
|
|
|
|
updateOffsetsSane();
|
|
|
|
}
|
|
|
|
/* Messages weere updated (and only them). They were talking with ghosts.
|
|
|
|
Now we are trying to show spinners of ghosts */
|
|
|
|
elSetOffsetInChat(spinnerTop, highestPoint);
|
|
|
|
setElementVisibility(spinnerTop, isMissingTopMsgHeap());
|
|
|
|
elSetOffsetInChat(spinnerBottom, lowestPoint - SbH);
|
|
|
|
setElementVisibility(spinnerBottom, isMissingBottomMsgHeap());
|
|
|
|
/* Fix anchor */
|
|
|
|
let oldAnchor = anchoredMsg;
|
|
|
|
while (true){
|
|
|
|
let h = visibleMessages.get(anchoredMsg).container.offsetHeight;
|
|
|
|
if (!(offsetOfAnchor + h < chatPadding && visibleMsgSegStart < anchoredMsg))
|
|
|
|
break
|
|
|
|
offsetOfAnchor += (msgGap + h);
|
|
|
|
anchoredMsg--;
|
2024-08-11 12:17:53 +00:00
|
|
|
}
|
2024-09-12 07:47:29 +00:00
|
|
|
while (offsetOfAnchor > H - chatPadding && anchoredMsg < visibleMsgSegEnd){
|
|
|
|
anchoredMsg++;
|
|
|
|
let h = visibleMessages.get(anchoredMsg).container.offsetHeight;
|
|
|
|
offsetOfAnchor -= (msgGap + h);
|
|
|
|
}
|
|
|
|
if (oldAnchor !== anchoredMsg)
|
|
|
|
console.log("anchoredMsg: " + String(oldAnchor) + " -> " + String(anchoredMsg))
|
2024-08-11 12:17:53 +00:00
|
|
|
}
|
2024-08-14 22:07:59 +00:00
|
|
|
}
|
2024-08-11 12:17:53 +00:00
|
|
|
|
2024-09-12 07:47:29 +00:00
|
|
|
function shouldShowDeleteMesgBtn(messageSt){
|
|
|
|
return !messageSt.isSystem && messageSt.exists && (myRoleHere !== userChatRoleReadOnly) &&(
|
|
|
|
myRoleHere === userChatRoleAdmin || messageSt.senderUserId === userinfo.uid);
|
|
|
|
}
|
|
|
|
|
|
|
|
function getMsgTypeClassSenderBased(messageSt){
|
|
|
|
if (messageSt.isSystem)
|
|
|
|
return "message-box-system"
|
|
|
|
if (messageSt.senderUserId === userinfo.uid)
|
|
|
|
return "message-box-mine"
|
|
|
|
return "message-box-alien";
|
|
|
|
}
|
|
|
|
|
|
|
|
function getMsgFullTypeClassName(messageSt){
|
|
|
|
return getMsgTypeClassSenderBased(messageSt) + (messageSt.exists ? "" : " message-box-deleted");
|
2024-08-10 03:09:51 +00:00
|
|
|
}
|
2024-08-14 22:07:59 +00:00
|
|
|
|
2024-09-12 07:47:29 +00:00
|
|
|
/* Two things can be updated: messages existance and delete button visibility
|
|
|
|
* Supercontainer.container is persistent, Supercontainer.box can change it's class */
|
|
|
|
function updateMessageSupercontainer(supercontainer, messageSt){
|
|
|
|
let box = supercontainer.box;
|
|
|
|
if (messageSt.isSystem)
|
|
|
|
return;
|
|
|
|
setElementVisibility(box.querySelector(".message-box-button-delete"), shouldShowDeleteMesgBtn(messageSt), "inline");
|
|
|
|
box.className = getMsgFullTypeClassName(messageSt);
|
|
|
|
// Notice, that no check of previous state is performed. Double loading is a rare event, I can afford to be slow
|
|
|
|
if (!messageSt.exists)
|
|
|
|
box.querySelector(".message-box-msg").innerText = msgErased;
|
2024-08-10 03:09:51 +00:00
|
|
|
}
|
2024-08-14 22:07:59 +00:00
|
|
|
|
2024-09-12 07:47:29 +00:00
|
|
|
function decodeSystemMessage(text){
|
|
|
|
let [subject, verb, object] = text.split(',');
|
|
|
|
let subjectId = Number(subject);
|
|
|
|
let objectId = Number(object);
|
|
|
|
let subjectRef = members.has(subjectId) ? members.get(subjectId).nickname : "???";
|
|
|
|
let objectRef = members.has(objectId) ? members.get(objectId).nickname : "???";
|
|
|
|
if (verb === "kicked"){
|
|
|
|
return subjectRef + " " + pres.chat.syslog.kicked + " " + objectRef;
|
|
|
|
} else if (verb === "summoned"){
|
|
|
|
return subjectRef + " " + pres.chat.syslog.summoned + " " + objectRef;
|
|
|
|
} else if (verb === "left"){
|
|
|
|
return subjectRef + " " + pres.chat.syslog.left;
|
|
|
|
} else if (verb === "created"){
|
|
|
|
return subjectRef + " " + pres.chat.syslog.created;
|
2024-08-06 08:29:21 +00:00
|
|
|
}
|
2024-09-12 07:47:29 +00:00
|
|
|
return "... Bad log ...";
|
|
|
|
}
|
2024-08-14 22:07:59 +00:00
|
|
|
|
2024-09-12 07:47:29 +00:00
|
|
|
function convertMessageStToSupercontainer(messageSt){
|
|
|
|
let container = document.createElement("div");
|
|
|
|
container.className = "message-supercontainer";
|
|
|
|
|
|
|
|
let box = document.createElement("div");
|
|
|
|
container.appendChild(box);
|
|
|
|
box.className = getMsgFullTypeClassName(messageSt);
|
|
|
|
|
|
|
|
let ID = messageSt.id;
|
|
|
|
|
|
|
|
if (messageSt.isSystem){
|
|
|
|
|
|
|
|
} else {
|
|
|
|
let topPart = document.createElement("div");
|
|
|
|
box.appendChild(topPart);
|
|
|
|
topPart.className = "message-box-top";
|
|
|
|
|
|
|
|
if (!members.has(messageSt.senderUserId))
|
|
|
|
throw new Error("First - update members");
|
|
|
|
let senderMemberSt = members.get(messageSt.senderUserId);
|
|
|
|
let senderProfileURI = "/user/" + senderMemberSt.nickname;
|
|
|
|
|
|
|
|
let inTopPartSenderName = document.createElement("a");
|
|
|
|
topPart.appendChild(inTopPartSenderName);
|
|
|
|
inTopPartSenderName.className = "message-box-sender-name";
|
|
|
|
inTopPartSenderName.innerText = senderMemberSt.name;
|
|
|
|
inTopPartSenderName.href = senderProfileURI;
|
|
|
|
|
|
|
|
let inTopPartSenderNickname = document.createElement("a");
|
|
|
|
topPart.appendChild(inTopPartSenderNickname);
|
|
|
|
inTopPartSenderNickname.className = "message-box-sender-name message-box-sender-shortname"
|
|
|
|
inTopPartSenderNickname.innerText = senderMemberSt.nickname;
|
|
|
|
inTopPartSenderNickname.href = senderProfileURI;
|
|
|
|
|
|
|
|
let inTopPartButtonDelete = document.createElement("img");
|
|
|
|
topPart.appendChild(inTopPartButtonDelete);
|
|
|
|
inTopPartButtonDelete.className = "message-box-button message-box-button-delete";
|
|
|
|
inTopPartButtonDelete.src = "/assets/img/delete.svg";
|
|
|
|
inTopPartButtonDelete.onclick = (ev) => {
|
|
|
|
if (ev.button !== 0)
|
|
|
|
return;
|
|
|
|
let msgText = box.querySelector(".message-box-msg").innerText;
|
|
|
|
let previewText = senderMemberSt.nickname + ":\n" + msgText;
|
|
|
|
if (previewText.length > 1000)
|
|
|
|
previewText = previewText.substring(0, 1000 - 3);
|
|
|
|
document.getElementById("win-deletion-msg-preview").innerText = previewText;
|
|
|
|
storeHiddenMsgIdForDeletionWin = ID;
|
|
|
|
activatePopupWindowById("msg-deletion-win");
|
|
|
|
};
|
|
|
|
setElementVisibility(inTopPartButtonDelete, shouldShowDeleteMesgBtn(messageSt), "inline");
|
|
|
|
|
|
|
|
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)
|
|
|
|
return;
|
|
|
|
let URI = window.location.host + "/chat/" + openedchat.nickname + "/m/" + String(ID);
|
|
|
|
document.getElementById("message-input").innerText += (" " + URI + "");
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
let msgPart = document.createElement("p");
|
|
|
|
box.appendChild(msgPart);
|
|
|
|
msgPart.className = "message-box-msg";
|
|
|
|
if (messageSt.exists){
|
|
|
|
if (messageSt.isSystem)
|
|
|
|
msgPart.innerText = decodeSystemMessage(messageSt.text);
|
|
|
|
else
|
|
|
|
msgPart.innerText = messageSt.text;
|
|
|
|
} else
|
|
|
|
msgPart.innerText = msgErased;
|
|
|
|
|
|
|
|
return {'container': container, 'box': box};
|
|
|
|
}
|
2024-08-14 22:07:59 +00:00
|
|
|
|
2024-09-12 07:47:29 +00:00
|
|
|
function makeVisible(msgId){
|
|
|
|
let supercontainer = convertMessageStToSupercontainer(loadedMessages.get(msgId));
|
|
|
|
const chatWin = document.getElementById("chat-widget");
|
|
|
|
chatWin.appendChild(supercontainer.container);
|
|
|
|
visibleMessages.set(msgId, supercontainer);
|
|
|
|
}
|
|
|
|
|
|
|
|
function opaNewMessageSt(messageSt){
|
|
|
|
let msgId = messageSt.id;
|
|
|
|
if (loadedMessages.has(msgId)){
|
|
|
|
loadedMessages.set(msgId, messageSt);
|
|
|
|
if (visibleMessages.has(msgId)){
|
|
|
|
updateMessageSupercontainer(visibleMessages.get(msgId), messageSt);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
loadedMessages.set(msgId, messageSt);
|
|
|
|
if (anchoredMsg < 0){
|
|
|
|
anchoredMsg = msgId;
|
|
|
|
visibleMsgSegStart = msgId;
|
|
|
|
visibleMsgSegEnd = msgId;
|
|
|
|
makeVisible(msgId);
|
|
|
|
} else if (msgId + 1 === visibleMsgSegStart) {
|
|
|
|
visibleMsgSegStart--;
|
|
|
|
makeVisible(msgId);
|
|
|
|
while (loadedMessages.has(visibleMsgSegStart - 1)){
|
|
|
|
visibleMsgSegStart--;
|
|
|
|
makeVisible(visibleMsgSegStart);
|
|
|
|
}
|
|
|
|
} else if (msgId - 1 === visibleMsgSegEnd){
|
|
|
|
visibleMsgSegEnd++;
|
|
|
|
makeVisible(msgId);
|
|
|
|
while (loadedMessages.has(visibleMsgSegEnd + 1)){
|
|
|
|
visibleMsgSegEnd++;
|
|
|
|
makeVisible(visibleMsgSegEnd);
|
|
|
|
}
|
2024-08-14 22:07:59 +00:00
|
|
|
}
|
|
|
|
}
|
2024-09-12 07:47:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function canISendMessages(){
|
|
|
|
return myRoleHere === userChatRoleRegular || myRoleHere === userChatRoleAdmin;
|
|
|
|
}
|
|
|
|
|
|
|
|
function updateLocalStateFromChatUpdRespBlind(chatUpdResp){
|
|
|
|
LocalHistoryId = chatUpdResp.HistoryId;
|
|
|
|
for (let memberSt of chatUpdResp.members){
|
|
|
|
let id = memberSt.userId;
|
|
|
|
if (id === userinfo.uid && myRoleHere !== memberSt.roleHere) {
|
|
|
|
myRoleHere = memberSt.roleHere;
|
|
|
|
for (let [msgId, sc] of visibleMessages){
|
|
|
|
updateMessageSupercontainer(sc, loadedMessages.get(msgId));
|
|
|
|
}
|
|
|
|
setElementVisibility(document.getElementById("message-input"), canISendMessages());
|
2024-08-14 22:07:59 +00:00
|
|
|
}
|
2024-09-12 07:47:29 +00:00
|
|
|
}
|
|
|
|
for (let memberSt of chatUpdResp.members){
|
|
|
|
let id = memberSt.userId;
|
|
|
|
members.set(id, memberSt);
|
|
|
|
}
|
|
|
|
lastMsgId = chatUpdResp.lastMsgId;
|
|
|
|
for (let messageSt of chatUpdResp.messages){
|
|
|
|
opaNewMessageSt(messageSt);
|
|
|
|
}
|
|
|
|
updateOffsets();
|
|
|
|
}
|
|
|
|
|
|
|
|
function updateLocalStateFromRecvBlind(Recv){
|
|
|
|
updateLocalStateFromChatUpdRespBlind(Recv.chatUpdResp);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function requestMessageNeighbours(fromMsg, direction){
|
|
|
|
let Sent = genSentBaseGMN();
|
|
|
|
Sent.msgId = fromMsg;
|
|
|
|
Sent.direction = direction;
|
|
|
|
let Recv = await apiRequest("getMessageNeighbours", Sent);
|
|
|
|
updateLocalStateFromRecvBlind(Recv); // Blind to non-loaded whitespaces
|
|
|
|
}
|
|
|
|
|
|
|
|
function needToLoadWhitespace(){
|
|
|
|
return isMissingPrimaryMsgHeap() || isMissingTopMsgHeap() || isMissingBottomMsgHeap();
|
|
|
|
}
|
|
|
|
|
|
|
|
async function tryLoadWhitespaceSingle(){
|
|
|
|
if (isMissingPrimaryMsgHeap()){
|
|
|
|
await requestMessageNeighbours(-1, "backward");
|
|
|
|
} else if (isMissingTopMsgHeap()){
|
|
|
|
await requestMessageNeighbours(visibleMsgSegStart, "backward");
|
|
|
|
} else if (isMissingBottomMsgHeap()){
|
|
|
|
await requestMessageNeighbours(visibleMsgSegEnd, "forward");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function loadWhitespaceMultitry(){
|
|
|
|
if (needToLoadWhitespace()){
|
|
|
|
cancelMainloopTimeout();
|
|
|
|
do {
|
|
|
|
try {
|
|
|
|
await tryLoadWhitespaceSingle();
|
|
|
|
if (debugMode)
|
|
|
|
await sleep(900);
|
|
|
|
} catch (e) {
|
|
|
|
console.error(e);
|
|
|
|
await sleep(1500);
|
|
|
|
}
|
|
|
|
} while (needToLoadWhitespace());
|
|
|
|
setMainloopTimeout();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function updateLocalStateFromRecv(Recv){
|
|
|
|
updateLocalStateFromRecvBlind(Recv);
|
|
|
|
await loadWhitespaceMultitry();
|
|
|
|
}
|
|
|
|
|
|
|
|
async function safeApiRequestWithLocalStUpdate(type, Sent, errMsg){
|
|
|
|
try {
|
|
|
|
let Recv = await apiRequest(type, Sent)
|
|
|
|
await updateLocalStateFromRecv(Recv);
|
|
|
|
} catch(e) {
|
|
|
|
console.error(e);
|
|
|
|
alert(errMsg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function configureMsgDeletionPopupButtons(){
|
|
|
|
document.getElementById("msg-deletion-yes").onclick = function(ev){
|
|
|
|
if (ev.button !== 0)
|
|
|
|
return;
|
|
|
|
deactivateActivePopup();
|
|
|
|
let Sent = genSentBase();
|
|
|
|
Sent.id = storeHiddenMsgIdForDeletionWin;
|
|
|
|
safeApiRequestWithLocalStUpdate("deleteMessage", Sent, pres.chat['failed-delete-message']);
|
2024-08-14 22:07:59 +00:00
|
|
|
};
|
2024-09-12 07:47:29 +00:00
|
|
|
|
|
|
|
document.getElementById("msg-deletion-no").onclick = function (ev){
|
|
|
|
if (ev.button !== 0)
|
|
|
|
return;
|
|
|
|
deactivateActivePopup();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
__mainloopDelayMs = 1000;
|
|
|
|
async function UPDATE(){
|
|
|
|
let Recv = await apiRequest("chatPollEvents", genSentBase());
|
|
|
|
await updateLocalStateFromRecv(Recv);
|
|
|
|
}
|
|
|
|
__guestMainloopPollerAction = UPDATE;
|
|
|
|
|
|
|
|
window.onload = function (){
|
|
|
|
console.log("Page was loaded");
|
|
|
|
|
|
|
|
document.body.addEventListener("wheel", function (event) {
|
|
|
|
let offset = event.deltaY / 3;
|
|
|
|
if (offset < 0){
|
|
|
|
bumpedAtBottom = false;
|
|
|
|
} else if (offset > 0 && !isMissingBottomMsgHeap() && lowestPoint + offset > chatPadding){
|
|
|
|
bumpedAtBottom = true;
|
|
|
|
}
|
|
|
|
offsetOfAnchor += offset;
|
|
|
|
updateOffsets();
|
|
|
|
loadWhitespaceMultitry().then(dopDopYesYes);
|
|
|
|
});
|
|
|
|
|
|
|
|
document.getElementById("message-input").addEventListener("keyup", function (event) {
|
|
|
|
if (event.ctrlKey && event.key === 'Enter'){
|
|
|
|
let textarea = document.getElementById("message-input");
|
|
|
|
let text = String(textarea.innerText);
|
|
|
|
textarea.innerText = "";
|
|
|
|
let Sent = genSentBase();
|
|
|
|
Sent.content = {};
|
|
|
|
Sent.content.text = text;
|
|
|
|
safeApiRequestWithLocalStUpdate("sendMessage", Sent, pres.chat['failed-send-message']);
|
|
|
|
}
|
2024-08-14 22:07:59 +00:00
|
|
|
});
|
|
|
|
|
2024-09-12 07:47:29 +00:00
|
|
|
bumpedAtBottom = (openedchat.selectedMessageId < 0);
|
|
|
|
|
|
|
|
let chatWg = document.getElementById("chat-widget");
|
|
|
|
let chatWgDebugLinesFnc = function (){
|
|
|
|
let H = chatWg.offsetHeight;
|
|
|
|
elSetOffsetInChat(document.getElementById("debug-line-lowest"), -softZoneSz);
|
|
|
|
elSetOffsetInChat(document.getElementById("debug-line-highest"), H + softZoneSz);
|
|
|
|
elSetOffsetInChat(document.getElementById("debug-line-top-padding"), H - chatPadding);
|
|
|
|
elSetOffsetInChat(document.getElementById("debug-line-bottom-padding"), chatPadding)
|
|
|
|
};
|
|
|
|
if (debugMode){
|
|
|
|
window.addEventListener("resize", chatWgDebugLinesFnc);
|
|
|
|
chatWgDebugLinesFnc();
|
2024-08-14 22:07:59 +00:00
|
|
|
}
|
2024-09-12 07:47:29 +00:00
|
|
|
|
|
|
|
configureMsgDeletionPopupButtons();
|
|
|
|
|
|
|
|
updateLocalStateFromChatUpdRespBlind(initial_chatUpdResp);
|
|
|
|
|
|
|
|
setMainloopTimeout();
|
|
|
|
|
|
|
|
loadWhitespaceMultitry();
|
2024-08-14 22:07:59 +00:00
|
|
|
}
|