diff --git a/frontend/lib/chat.mjs b/frontend/lib/chat.mjs index 37f8bff..5fce4da 100644 --- a/frontend/lib/chat.mjs +++ b/frontend/lib/chat.mjs @@ -5,7 +5,8 @@ import { } from "./watch-session.mjs?v=048af96"; import { emojify, findEmojis } from "./emojis.mjs?v=048af96"; import { linkify } from "./links.mjs?v=048af96"; -import { joinNewSession } from "./watch-session.mjs?v=048af96"; +import { joinSession } from "./watch-session.mjs?v=048af96"; +import { state } from "./state.mjs"; function setCaretPosition(elem, caretPos) { if (elem.createTextRange) { @@ -191,7 +192,8 @@ const setupChatboxEvents = (socket) => { handled = true; break; case "/join": - joinNewSession(args); + state().sessionId = args; + joinSession(); handled = true; break; case "/help": diff --git a/frontend/lib/join-session.mjs b/frontend/lib/join-session.mjs index 6995c63..87c5b22 100644 --- a/frontend/lib/join-session.mjs +++ b/frontend/lib/join-session.mjs @@ -1,4 +1,5 @@ import { joinSession } from "./watch-session.mjs?v=048af96"; +import { state } from "./state.mjs"; /** * @param {HTMLInputElement} field @@ -80,11 +81,10 @@ export const setupJoinSessionForm = () => { saveNickname(nickname); saveColour(colour); try { - await joinSession( - nickname.value, - sessionId.value, - colour.value.replace(/^#/, "") - ); + state().nickname = nickname.value; + state().sessionId = sessionId.value; + state().colour = colour.value.replace(/^#/, ""); + await joinSession(); } catch (e) { alert(e.message); button.disabled = false; diff --git a/frontend/lib/links.mjs b/frontend/lib/links.mjs index 998930e..4b64424 100644 --- a/frontend/lib/links.mjs +++ b/frontend/lib/links.mjs @@ -1,4 +1,5 @@ -import { joinNewSession } from "./watch-session.mjs?v=048af96"; +import { joinSession } from "./watch-session.mjs?v=048af96"; +import { state } from "./state.mjs"; export async function linkify( text, @@ -34,7 +35,8 @@ export async function linkify( textContent: "Join Session", className: "chip join-chip", onclick: () => { - joinNewSession(url.hash.substring(1)); + state().sessionId = url.hash.substring(1); + joinSession(); }, }) ); diff --git a/frontend/lib/state.mjs b/frontend/lib/state.mjs new file mode 100644 index 0000000..a119fe9 --- /dev/null +++ b/frontend/lib/state.mjs @@ -0,0 +1,7 @@ +let instance = null; +export const state = () => { + if (!instance) { + instance = {}; + } + return instance; +}; diff --git a/frontend/lib/video.mjs b/frontend/lib/video.mjs index 88bc434..9964f78 100644 --- a/frontend/lib/video.mjs +++ b/frontend/lib/video.mjs @@ -51,7 +51,12 @@ const saveCaptionsTrack = (track) => { * @param {{name: string, url: string}[]} subtitles */ const createVideoElement = (videoUrl, subtitles) => { + const oldVideo = document.getElementById("video"); + if (oldVideo) { + oldVideo.remove(); + } const video = document.createElement("video"); + video.id = "video"; video.controls = true; video.autoplay = false; video.volume = loadVolume(); diff --git a/frontend/lib/watch-session.mjs b/frontend/lib/watch-session.mjs index 814f8fa..2f45af8 100644 --- a/frontend/lib/watch-session.mjs +++ b/frontend/lib/watch-session.mjs @@ -6,17 +6,18 @@ import { printChatMessage, } from "./chat.mjs?v=048af96"; import ReconnectingWebSocket from "./reconnecting-web-socket.mjs"; +import { state } from "./state.mjs"; /** * @param {string} sessionId * @param {string} nickname * @returns {ReconnectingWebSocket} */ -const createWebSocket = (sessionId, nickname, colour) => { +const createWebSocket = () => { const wsUrl = new URL( - `/sess/${sessionId}/subscribe` + - `?nickname=${encodeURIComponent(nickname)}` + - `&colour=${encodeURIComponent(colour)}`, + `/sess/${state().sessionId}/subscribe` + + `?nickname=${encodeURIComponent(state().nickname)}` + + `&colour=${encodeURIComponent(state().colour)}`, window.location.href ); wsUrl.protocol = "ws" + window.location.protocol.slice(4); @@ -167,49 +168,29 @@ const setupOutgoingEvents = (video, socket) => { }); }; -let socket = null; -let video = null; +export const joinSession = async () => { + if (state().activeSession) { + if (state().activeSession === state().sessionId) { + // we are already in this session, dont rejoin + return; + } + // we are joining a new session from an existing session + const messageContent = document.createElement("span"); + messageContent.appendChild(document.createTextNode("joining new session ")); + messageContent.appendChild(document.createTextNode(state().sessionId)); -export const joinNewSession = async (sessionId) => { - const messageContent = document.createElement("span"); - messageContent.appendChild(document.createTextNode("joining new session ")); - messageContent.appendChild(document.createTextNode(sessionId)); - - printChatMessage("join-session", "watch-party", "#fffff", messageContent); - - // clean up previous session - // TODO: this most likely isnt properly working yet when using the /join command to join a new session - if (socket != null) { - socket.close(); - socket = null; + printChatMessage("join-session", "watch-party", "#fffff", messageContent); } - if (video != null) { - video.remove(); - video = null; - } - - joinSession(window.nickname, sessionId, sColour); -}; - -/** - * @param {string} nickname - * @param {string} sessionId - * @param {string} colour - */ -export const joinSession = async (nickname, sessionId, colour) => { - // TODO: we are getting to a point with our features where some kind of - // state store for the various info that is needed in a lot of places would probably make sense - window.nickname = nickname; - window.colour = colour; + state().activeSession = state().sessionId; // try { // we are handling errors in the join form. const genericConnectionError = new Error( "There was an issue getting the session information." ); - window.location.hash = sessionId; + window.location.hash = state().sessionId; let response, video_url, subtitle_tracks, current_time_ms, is_playing; try { - response = await fetch(`/sess/${sessionId}`); + response = await fetch(`/sess/${state().sessionId}`); } catch (e) { console.error(e); throw genericConnectionError; @@ -233,9 +214,14 @@ export const joinSession = async (nickname, sessionId, colour) => { throw genericConnectionError; } - socket = createWebSocket(sessionId, nickname, colour); + if (state().socket) { + state().socket.close(); + state().socket = null; + } + const socket = createWebSocket(); + state().socket = socket; socket.addEventListener("open", async () => { - video = await setupVideo( + const video = await setupVideo( video_url, subtitle_tracks, current_time_ms,