forked from lavender/watch-party
		
	implement a viewer list
This commit is contained in:
		
							parent
							
								
									951007df2a
								
							
						
					
					
						commit
						72c212a100
					
				
					 6 changed files with 72 additions and 10 deletions
				
			
		|  | @ -31,12 +31,7 @@ | |||
|         /> | ||||
| 
 | ||||
|         <label for="join-session-colour">Colour:</label> | ||||
|         <input | ||||
|           type="color" | ||||
|           id="join-session-colour" | ||||
|           value="#7ed0ff" | ||||
|           required | ||||
|         /> | ||||
|         <input type="color" id="join-session-colour" value="#7ed0ff" required /> | ||||
| 
 | ||||
|         <label for="join-session-id">Session ID:</label> | ||||
|         <input | ||||
|  | @ -55,6 +50,7 @@ | |||
| 
 | ||||
|     <div id="video-container"></div> | ||||
|     <div id="chatbox-container"> | ||||
|       <div id="viewer-list"></div> | ||||
|       <div id="chatbox"></div> | ||||
|       <form id="chatbox-send"> | ||||
|         <input type="text" placeholder="Message..." /> | ||||
|  |  | |||
|  | @ -267,3 +267,20 @@ const beep = () => { | |||
|   oscillator.start(context.currentTime); | ||||
|   oscillator.stop(context.currentTime + 0.22); | ||||
| }; | ||||
| 
 | ||||
| export const updateViewerList = (viewers) => { | ||||
|   const listContainer = document.querySelector("#viewer-list"); | ||||
| 
 | ||||
|   // empty out the current list
 | ||||
|   listContainer.innerHTML = ""; | ||||
| 
 | ||||
|   // display the updated list
 | ||||
|   for (const viewer of viewers) { | ||||
|     const viewerElem = document.createElement("div"); | ||||
|     const content = document.createElement("strong"); | ||||
|     content.textContent = viewer.nickname; | ||||
|     content.style = `color: #${viewer.colour}`; | ||||
|     viewerElem.appendChild(content); | ||||
|     listContainer.appendChild(viewerElem); | ||||
|   } | ||||
| }; | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| import { setupVideo } from "./video.mjs?v=8"; | ||||
| import { setupChat, logEventToChat } from "./chat.mjs?v=8"; | ||||
| import { setupChat, logEventToChat, updateViewerList } from "./chat.mjs?v=8"; | ||||
| 
 | ||||
| /** | ||||
|  * @param {string} sessionId | ||||
|  | @ -70,6 +70,9 @@ const setupIncomingEvents = (video, socket) => { | |||
|             setDebounce(); | ||||
|             setVideoTime(event.data); | ||||
|             break; | ||||
|           case "UpdateViewerList": | ||||
|             updateViewerList(event.data); | ||||
|             break; | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
|  |  | |||
|  | @ -161,6 +161,16 @@ button.small-button { | |||
|   overflow-y: scroll; | ||||
| } | ||||
| 
 | ||||
| #viewer-list { | ||||
|   padding: 0.5em 2em; | ||||
|   /* TODO: turn this into max-height instead of fixed height without breaking the chatbox height */ | ||||
|   height: 4em; | ||||
|   overflow-y: scroll; | ||||
|   color: rgb(126, 208, 255); | ||||
|   border-bottom: var(--fg); | ||||
|   border-bottom-style: solid; | ||||
| } | ||||
| 
 | ||||
| #chatbox-container { | ||||
|   background-color: #222; | ||||
| } | ||||
|  | @ -196,6 +206,6 @@ button.small-button { | |||
|   } | ||||
| 
 | ||||
|   #chatbox { | ||||
|     height: calc(100vh - 5em) !important; | ||||
|     height: calc(100vh - 5em - 4em) !important; | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -1,5 +1,13 @@ | |||
| use serde::{Deserialize, Serialize}; | ||||
| 
 | ||||
| #[derive(Clone, Serialize, Deserialize)] | ||||
| pub struct Viewer { | ||||
|     #[serde(default, skip_serializing_if = "Option::is_none")] | ||||
|     pub nickname: Option<String>, | ||||
|     #[serde(default, skip_serializing_if = "Option::is_none")] | ||||
|     pub colour: Option<String>, | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Serialize, Deserialize)] | ||||
| #[serde(tag = "op", content = "data")] | ||||
| pub enum WatchEventData { | ||||
|  | @ -17,6 +25,7 @@ pub enum WatchEventData { | |||
|     UserLeave, | ||||
|     ChatMessage(String), | ||||
|     Ping(String), | ||||
|     UpdateViewerList(Vec<Viewer>), | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Serialize, Deserialize)] | ||||
|  |  | |||
|  | @ -15,7 +15,7 @@ use uuid::Uuid; | |||
| use warp::ws::{Message, WebSocket}; | ||||
| 
 | ||||
| use crate::{ | ||||
|     events::{WatchEvent, WatchEventData}, | ||||
|     events::{Viewer, WatchEvent, WatchEventData}, | ||||
|     utils::truncate_str, | ||||
|     watch_session::{get_session, handle_watch_event_data}, | ||||
| }; | ||||
|  | @ -74,6 +74,8 @@ pub async fn ws_subscribe(session_uuid: Uuid, nickname: String, colour: String, | |||
|     ) | ||||
|     .await; | ||||
| 
 | ||||
|     update_viewer_list(session_uuid).await; | ||||
| 
 | ||||
|     while let Some(Ok(message)) = viewer_ws_rx.next().await { | ||||
|         let event: WatchEventData = match message | ||||
|             .to_str() | ||||
|  | @ -113,6 +115,7 @@ pub async fn ws_subscribe(session_uuid: Uuid, nickname: String, colour: String, | |||
|     .await; | ||||
| 
 | ||||
|     CONNECTED_VIEWERS.write().await.remove(&viewer_id); | ||||
|     update_viewer_list(session_uuid).await; | ||||
| } | ||||
| 
 | ||||
| pub async fn ws_publish(session_uuid: Uuid, skip_viewer_id: Option<usize>, event: WatchEvent) { | ||||
|  | @ -127,3 +130,27 @@ pub async fn ws_publish(session_uuid: Uuid, skip_viewer_id: Option<usize>, event | |||
|         }); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| async fn update_viewer_list(session_uuid: Uuid) { | ||||
|     let mut viewers = Vec::new(); | ||||
| 
 | ||||
|     for viewer in CONNECTED_VIEWERS.read().await.values() { | ||||
|         if viewer.session == session_uuid { | ||||
|             viewers.push(Viewer { | ||||
|                 nickname: viewer.nickname.clone(), | ||||
|                 colour: viewer.colour.clone(), | ||||
|             }) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     ws_publish( | ||||
|         session_uuid, | ||||
|         None, | ||||
|         WatchEvent::new( | ||||
|             String::from("server"), | ||||
|             String::from(""), | ||||
|             WatchEventData::UpdateViewerList(viewers), | ||||
|         ), | ||||
|     ) | ||||
|     .await; | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue