forked from lavender/watch-party
Implement a viewer list
TODO: - instead of fixing a size make it max-height - when the chat is below the video it would probably be better to put the viewer list next to the chatuser-list
parent
903fd535ce
commit
98505de0f0
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<title>watch party :D</title>
|
<title>watch party :D</title>
|
||||||
<link rel="stylesheet" href="/styles.css?v=3" />
|
<link rel="stylesheet" href="/styles.css?v=4" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<title>watch party :D</title>
|
<title>watch party :D</title>
|
||||||
<link rel="stylesheet" href="/styles.css?v=3" />
|
<link rel="stylesheet" href="/styles.css?v=4" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -46,12 +46,13 @@
|
||||||
|
|
||||||
<div id="video-container"></div>
|
<div id="video-container"></div>
|
||||||
<div id="chatbox-container">
|
<div id="chatbox-container">
|
||||||
|
<div id="viewer-list"></div>
|
||||||
<div id="chatbox"></div>
|
<div id="chatbox"></div>
|
||||||
<form id="chatbox-send">
|
<form id="chatbox-send">
|
||||||
<input type="text" placeholder="Message..." />
|
<input type="text" placeholder="Message..." />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="module" src="/main.mjs?v=2"></script>
|
<script type="module" src="/main.mjs?v=3"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -181,3 +181,19 @@ export const logEventToChat = (event) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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.appendChild(document.createTextNode(viewer));
|
||||||
|
viewerElem.appendChild(content);
|
||||||
|
listContainer.appendChild(viewerElem);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { joinSession } from "./watch-session.mjs?v=3";
|
import { joinSession } from "./watch-session.mjs?v=4";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {HTMLInputElement} field
|
* @param {HTMLInputElement} field
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { setupVideo } from "./video.mjs?v=2";
|
import { setupVideo } from "./video.mjs?v=2";
|
||||||
import { setupChat, logEventToChat } from "./chat.mjs?v=2";
|
import { setupChat, logEventToChat, updateViewerList } from "./chat.mjs?v=3";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} sessionId
|
* @param {string} sessionId
|
||||||
|
@ -69,6 +69,9 @@ const setupIncomingEvents = (video, socket) => {
|
||||||
setDebounce();
|
setDebounce();
|
||||||
setVideoTime(event.data);
|
setVideoTime(event.data);
|
||||||
break;
|
break;
|
||||||
|
case "UpdateViewerList":
|
||||||
|
updateViewerList(event.data);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { setupJoinSessionForm } from "./lib/join-session.mjs?v=2";
|
import { setupJoinSessionForm } from "./lib/join-session.mjs?v=3";
|
||||||
|
|
||||||
const main = () => {
|
const main = () => {
|
||||||
setupJoinSessionForm();
|
setupJoinSessionForm();
|
||||||
|
|
|
@ -156,6 +156,16 @@ button.small-button {
|
||||||
overflow-y: scroll;
|
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 {
|
#chatbox-container {
|
||||||
background-color: #222;
|
background-color: #222;
|
||||||
}
|
}
|
||||||
|
@ -191,6 +201,6 @@ button.small-button {
|
||||||
}
|
}
|
||||||
|
|
||||||
#chatbox {
|
#chatbox {
|
||||||
height: calc(100vh - 5em) !important;
|
height: calc(100vh - 5em - 4em) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ pub enum WatchEventData {
|
||||||
UserJoin,
|
UserJoin,
|
||||||
UserLeave,
|
UserLeave,
|
||||||
ChatMessage(String),
|
ChatMessage(String),
|
||||||
|
UpdateViewerList(Vec<String>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
|
|
|
@ -65,6 +65,8 @@ pub async fn ws_subscribe(session_uuid: Uuid, nickname: String, ws: WebSocket) {
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
update_viewer_list(session_uuid).await;
|
||||||
|
|
||||||
while let Some(Ok(message)) = viewer_ws_rx.next().await {
|
while let Some(Ok(message)) = viewer_ws_rx.next().await {
|
||||||
let event: WatchEventData = match message
|
let event: WatchEventData = match message
|
||||||
.to_str()
|
.to_str()
|
||||||
|
@ -97,6 +99,7 @@ pub async fn ws_subscribe(session_uuid: Uuid, nickname: String, ws: WebSocket) {
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
CONNECTED_VIEWERS.write().await.remove(&viewer_id);
|
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) {
|
pub async fn ws_publish(session_uuid: Uuid, skip_viewer_id: Option<usize>, event: WatchEvent) {
|
||||||
|
@ -111,3 +114,21 @@ pub async fn ws_publish(session_uuid: Uuid, skip_viewer_id: Option<usize>, event
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn update_viewer_list(session_uuid: Uuid) {
|
||||||
|
let mut names = Vec::new();
|
||||||
|
for viewer in CONNECTED_VIEWERS.read().await.values() {
|
||||||
|
if viewer.session == session_uuid && viewer.nickname != None {
|
||||||
|
names.push(viewer.nickname.clone().unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ws_publish(
|
||||||
|
session_uuid,
|
||||||
|
None,
|
||||||
|
WatchEvent::new(
|
||||||
|
String::from("server"),
|
||||||
|
WatchEventData::UpdateViewerList(names),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue