Add option to pop out the chat to a seperate window. #1

Closed
nyancrimew wants to merge 1 commits from nyancrimew/watch-party:chat-popout into main
4 changed files with 127 additions and 22 deletions

22
frontend/chat.html Normal file
View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>watch party chat <3</title>
<link rel="stylesheet" href="/styles.css?v=3" />
</head>
<body>
<noscript>
This site will <em>not</em> work without JavaScript, and there's not
really any way around that :(
</noscript>
<div id="chatbox-container" class="popped-out">
<div id="chatbox"></div>
<form id="chatbox-send">
<input type="text" placeholder="Message..." />
</form>
</div>
</body>
</html>

View File

@ -3,7 +3,7 @@
<head>
<meta charset="utf-8" />
<title>watch party :D</title>
<link rel="stylesheet" href="/styles.css?v=2" />
<link rel="stylesheet" href="/styles.css?v=3" />
</head>
<body>
@ -43,10 +43,11 @@
<div id="chatbox-container">
<div id="chatbox"></div>
<form id="chatbox-send">
<input type="text" placeholder="Message..." />
<input type="text" id="message-box" placeholder="Message..." />
<input type="button" id="pop-chat" value="Pop out chat" />
</form>
</div>
<script type="module" src="/main.mjs?v=1"></script>
<script type="module" src="/main.mjs?v=2"></script>
</body>
</html>

View File

@ -1,8 +1,14 @@
var win = window;
var poppedOut = false;
const setupChatboxEvents = (socket) => {
// clear events by just reconstructing the form
const oldChatForm = document.querySelector("#chatbox-send");
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();
@ -24,6 +30,13 @@ const setupChatboxEvents = (socket) => {
});
};
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");
@ -38,21 +51,72 @@ const fixChatSize = () => {
}
};
// 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) => {
document.querySelector("#chatbox-container").style["display"] = "block";
win.document.querySelector("#chatbox-container").style["display"] = "block";
setupChatboxEvents(socket);
fixChatSize();
window.addEventListener("resize", () => {
if (!poppedOut) {
fixChatSize();
});
window.addEventListener("resize", resizeCallback);
} else {
window.removeEventListener("resize", resizeCallback);
}
};
const printToChat = (elem) => {
const chatbox = document.querySelector("#chatbox");
const chatbox = win.document.querySelector("#chatbox");
chatbox.appendChild(elem);
chatbox.scrollTop = chatbox.scrollHeight;
};
@ -61,37 +125,35 @@ export const handleChatEvent = (event) => {
switch (event.op) {
case "UserJoin": {
// print something to the chat
const chatMessage = document.createElement("div");
const chatMessage = win.document.createElement("div");
chatMessage.classList.add("chat-message");
chatMessage.classList.add("user-join");
const userName = document.createElement("strong");
const userName = win.document.createElement("strong");
userName.textContent = event.data;
chatMessage.appendChild(userName);
chatMessage.appendChild(document.createTextNode(" joined"));
chatMessage.appendChild(win.document.createTextNode(" joined"));
printToChat(chatMessage);
break;
}
case "UserLeave": {
const chatMessage = document.createElement("div");
const chatMessage = win.document.createElement("div");
chatMessage.classList.add("chat-message");
chatMessage.classList.add("user-leave");
const userName = document.createElement("strong");
const userName = win.document.createElement("strong");
userName.textContent = event.data;
chatMessage.appendChild(userName);
chatMessage.appendChild(document.createTextNode(" left"));
chatMessage.appendChild(win.document.createTextNode(" left"));
printToChat(chatMessage);
break;
}
case "ChatMessage": {
const chatMessage = document.createElement("div");
const chatMessage = win.document.createElement("div");
chatMessage.classList.add("chat-message");
const userName = document.createElement("strong");
const userName = win.document.createElement("strong");
userName.innerText = event.data.user;
chatMessage.appendChild(userName);
chatMessage.appendChild(document.createTextNode(" "));
const messageContent = document.createElement("span");
chatMessage.appendChild(win.document.createTextNode(" "));
const messageContent = win.document.createElement("span");
messageContent.classList.add("message-content");
messageContent.textContent = event.data.message;
chatMessage.appendChild(messageContent);

View File

@ -23,6 +23,7 @@ html {
html,
body {
margin: 0;
height: 100%;
}
video {
@ -67,7 +68,8 @@ input[type="text"] {
overflow-y: scroll;
}
button {
button,
input[type="button"] {
background-color: var(--accent);
border: var(--accent);
border-radius: 6px;
@ -118,6 +120,15 @@ button.small-button {
display: none;
}
#chatbox-container.popped-out {
width: 100%;
height: 100%;
}
#chatbox-container.popped-out > #chatbox {
height: calc(100vh - 5em);
}
.user-join,
.user-leave {
font-style: italic;
@ -145,3 +156,12 @@ button.small-button {
#chatbox-send > input {
font-size: 0.75em;
}
#message-box {
display: inline-block;
}
#pop-chat {
width: auto;
float: right;
}