Implement frontend for chat
parent
d48771e921
commit
d0be5f66cb
|
@ -40,7 +40,12 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="video-container"></div>
|
<div id="video-container"></div>
|
||||||
<div id="chatbox-container"></div>
|
<div id="chatbox-container">
|
||||||
|
<div id="chatbox"></div>
|
||||||
|
<form id="chatbox-send">
|
||||||
|
<input type="text" placeholder="Message..." />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script src="/main.js"></script>
|
<script src="/main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
105
frontend/main.js
105
frontend/main.js
|
@ -46,6 +46,60 @@ const setDebounce = () => {
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const clearChat = () => {
|
||||||
|
document.querySelector("#chatbox").innerHTML = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const printToChat = (elem) => {
|
||||||
|
const chatbox = document.querySelector("#chatbox");
|
||||||
|
chatbox.appendChild(elem);
|
||||||
|
chatbox.scrollTop = chatbox.scrollHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleChatEvent = (event) => {
|
||||||
|
switch (event.op) {
|
||||||
|
case "UserJoin": {
|
||||||
|
// print something to the chat
|
||||||
|
const chatMessage = document.createElement("div");
|
||||||
|
chatMessage.classList.add("chat-message");
|
||||||
|
chatMessage.classList.add("user-join");
|
||||||
|
const userName = document.createElement("strong");
|
||||||
|
userName.textContent = event.data;
|
||||||
|
chatMessage.appendChild(userName);
|
||||||
|
chatMessage.appendChild(document.createTextNode(" joined"));
|
||||||
|
printToChat(chatMessage);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "UserLeave": {
|
||||||
|
const chatMessage = document.createElement("div");
|
||||||
|
chatMessage.classList.add("chat-message");
|
||||||
|
chatMessage.classList.add("user-leave");
|
||||||
|
const userName = document.createElement("strong");
|
||||||
|
userName.textContent = event.data;
|
||||||
|
chatMessage.appendChild(userName);
|
||||||
|
chatMessage.appendChild(document.createTextNode(" left"));
|
||||||
|
printToChat(chatMessage);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "ChatMessage": {
|
||||||
|
const chatMessage = document.createElement("div");
|
||||||
|
chatMessage.classList.add("chat-message");
|
||||||
|
const userName = document.createElement("strong");
|
||||||
|
userName.innerText = event.data.user;
|
||||||
|
chatMessage.appendChild(userName);
|
||||||
|
chatMessage.appendChild(document.createTextNode(" "));
|
||||||
|
const messageContent = document.createElement("span");
|
||||||
|
messageContent.classList.add("message-content");
|
||||||
|
messageContent.textContent = event.data.message;
|
||||||
|
chatMessage.appendChild(messageContent);
|
||||||
|
printToChat(chatMessage);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {WebSocket} socket
|
* @param {WebSocket} socket
|
||||||
* @param {HTMLVideoElement} video
|
* @param {HTMLVideoElement} video
|
||||||
|
@ -80,10 +134,12 @@ const setupSocketEvents = (socket, video) => {
|
||||||
case "SetTime":
|
case "SetTime":
|
||||||
setDebounce();
|
setDebounce();
|
||||||
setVideoTime(event.data);
|
setVideoTime(event.data);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
case "UserJoin":
|
||||||
// TODO: UserJoin, UserLeave, ChatMessage
|
case "UserLeave":
|
||||||
|
case "ChatMessage":
|
||||||
|
handleChatEvent(event);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} catch (_err) {
|
} catch (_err) {
|
||||||
}
|
}
|
||||||
|
@ -173,13 +229,48 @@ const setupVideo = async (sessionId, videoUrl, subtitles, currentTime, playing,
|
||||||
setupVideoEvents(sessionId, video, socket);
|
setupVideoEvents(sessionId, video, 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)`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const setupChatboxEvents = (socket) => {
|
||||||
|
// clear events by just reconstructing the form
|
||||||
|
const oldChatForm = document.querySelector("#chatbox-send");
|
||||||
|
const chatForm = oldChatForm.cloneNode(true);
|
||||||
|
oldChatForm.replaceWith(chatForm);
|
||||||
|
|
||||||
|
chatForm.addEventListener("submit", e => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const input = chatForm.querySelector("input");
|
||||||
|
const content = input.value;
|
||||||
|
input.value = "";
|
||||||
|
|
||||||
|
socket.send(JSON.stringify({
|
||||||
|
"op": "ChatMessage",
|
||||||
|
"data": {
|
||||||
|
"message": content,
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} sessionId
|
* @param {string} sessionId
|
||||||
* @param {WebSocket} socket
|
* @param {WebSocket} socket
|
||||||
*/
|
*/
|
||||||
const setupChat = async (sessionId, socket) => {
|
const setupChat = async (sessionId, socket) => {
|
||||||
document.querySelector("#chatbox-container").style["display"] = "initial";
|
document.querySelector("#chatbox-container").style["display"] = "block";
|
||||||
// TODO
|
setupChatboxEvents(socket);
|
||||||
|
fixChatSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -225,6 +316,10 @@ const main = () => {
|
||||||
if (window.location.hash.match(/#[0-9a-f\-]+/)) {
|
if (window.location.hash.match(/#[0-9a-f\-]+/)) {
|
||||||
document.querySelector("#join-session-id").value = window.location.hash.substring(1);
|
document.querySelector("#join-session-id").value = window.location.hash.substring(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window.addEventListener("resize", event => {
|
||||||
|
fixChatSize();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (document.readyState === "complete") {
|
if (document.readyState === "complete") {
|
||||||
|
|
|
@ -117,3 +117,30 @@ button.small-button {
|
||||||
#chatbox-container {
|
#chatbox-container {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.user-join {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-message > strong {
|
||||||
|
color: rgb(126, 208, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
#chatbox {
|
||||||
|
padding: 0.5em 2em;
|
||||||
|
min-height: 8em;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
#chatbox-container {
|
||||||
|
background-color: #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
#chatbox-send {
|
||||||
|
padding: 0 2em;
|
||||||
|
padding-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#chatbox-send > input {
|
||||||
|
font-size: 0.75em;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue