forked from lavender/watch-party
		
	Implement frontend for chat
This commit is contained in:
		
							parent
							
								
									d48771e921
								
							
						
					
					
						commit
						d0be5f66cb
					
				
					 3 changed files with 133 additions and 6 deletions
				
			
		|  | @ -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 a new issue