watch-party/frontend/lib/chat.mjs

165 lines
4.9 KiB
JavaScript

var win = window;
var poppedOut = false;
const setupChatboxEvents = (socket) => {
// clear events by just reconstructing the form
const oldChatForm = win.document.querySelector("#chatbox-send");
const chatForm = oldChatForm.cloneNode(true);
oldChatForm.replaceWith(chatForm);
if (!poppedOut) {
setupPopoutEvent(socket);
}
chatForm.addEventListener("submit", (e) => {
e.preventDefault();
const input = chatForm.querySelector("input");
const content = input.value;
if (content.trim().length) {
input.value = "";
socket.send(
JSON.stringify({
op: "ChatMessage",
data: {
message: content,
},
})
);
}
});
};
const setupPopoutEvent = (socket) => {
const button = document.querySelector("#pop-chat");
button.addEventListener("click", () => {
openPopout(socket);
});
};
const fixChatSize = () => {
const video = document.querySelector("video");
const chatbox = document.querySelector("#chatbox");
const chatboxContainer = document.querySelector("#chatbox-container");
if (video && chatbox && chatboxContainer) {
const delta = chatboxContainer.clientHeight - chatbox.clientHeight;
chatbox.style["height"] = `calc(${
window.innerHeight - video.clientHeight
}px - ${delta}px - 1em)`;
}
};
// TODO: transfer chat history to popout and back?
const openPopout = async (socket) => {
win.document.querySelector("#chatbox-container").style["display"] = "none";
const popout = window.open("/chat.html", "popout", "width=800,height=1000");
win = popout;
poppedOut = true;
// I am aware of the fact that this is incredibly cursed,
// but apparently this is the only way to wait for a child window to load....
// I love browsers :)
function defer(callback) {
var channel = new MessageChannel();
channel.port1.onmessage = function (e) {
callback();
};
channel.port2.postMessage(null);
}
win.addEventListener("unload", () => {
defer(() => {
if (popout.document.readyState === "complete") {
setupChat(socket);
// pop the chat back into the parent window on close
win.addEventListener("unload", () => {
popBackChat(socket);
});
} else {
win.document.addEventListener("DOMContentLoaded", () => {
setupChat(socket);
// pop the chat back into the parent window on close
win.addEventListener("unload", () => {
popBackChat(socket);
});
});
}
});
});
};
const popBackChat = async (socket) => {
win = window;
poppedOut = false;
setupChat(socket);
};
const resizeCallback = () => {
fixChatSize();
};
/**
* @param {WebSocket} socket
*/
export const setupChat = async (socket) => {
win.document.querySelector("#chatbox-container").style["display"] = "block";
setupChatboxEvents(socket);
if (!poppedOut) {
fixChatSize();
window.addEventListener("resize", resizeCallback);
} else {
window.removeEventListener("resize", resizeCallback);
}
};
const printToChat = (elem) => {
const chatbox = win.document.querySelector("#chatbox");
chatbox.appendChild(elem);
chatbox.scrollTop = chatbox.scrollHeight;
};
export const handleChatEvent = (event) => {
switch (event.op) {
case "UserJoin": {
// print something to the chat
const chatMessage = win.document.createElement("div");
chatMessage.classList.add("chat-message");
chatMessage.classList.add("user-join");
const userName = win.document.createElement("strong");
userName.textContent = event.data;
chatMessage.appendChild(userName);
chatMessage.appendChild(win.document.createTextNode(" joined"));
printToChat(chatMessage);
break;
}
case "UserLeave": {
const chatMessage = win.document.createElement("div");
chatMessage.classList.add("chat-message");
chatMessage.classList.add("user-leave");
const userName = win.document.createElement("strong");
userName.textContent = event.data;
chatMessage.appendChild(userName);
chatMessage.appendChild(win.document.createTextNode(" left"));
printToChat(chatMessage);
break;
}
case "ChatMessage": {
const chatMessage = win.document.createElement("div");
chatMessage.classList.add("chat-message");
const userName = win.document.createElement("strong");
userName.innerText = event.data.user;
chatMessage.appendChild(userName);
chatMessage.appendChild(win.document.createTextNode(" "));
const messageContent = win.document.createElement("span");
messageContent.classList.add("message-content");
messageContent.textContent = event.data.message;
chatMessage.appendChild(messageContent);
printToChat(chatMessage);
break;
}
}
};