diff --git a/frontend/lib/chat.mjs b/frontend/lib/chat.mjs index 15ce7f3..ad9adac 100644 --- a/frontend/lib/chat.mjs +++ b/frontend/lib/chat.mjs @@ -4,7 +4,8 @@ import { setPlaying, } from "./watch-session.mjs?v=048af96"; import { emojify, findEmojis } from "./emojis.mjs?v=048af96"; -import { linkify } from "./links.mjs"; +import { linkify } from "./links.mjs?v=048af96"; +import { joinNewSession } from "./watch-session.mjs?v=048af96"; function setCaretPosition(elem, caretPos) { if (elem.createTextRange) { @@ -189,6 +190,10 @@ const setupChatboxEvents = (socket) => { ); handled = true; break; + case "/join": + joinNewSession(args); + handled = true; + break; case "/help": const helpMessageContent = document.createElement("span"); helpMessageContent.innerHTML = @@ -196,7 +201,8 @@ const setupChatboxEvents = (socket) => { " /help - display this help message
" + " /ping [message] - ping all viewers
" + " /sync - resyncs you with other viewers
" + - " /shrug - appends ¯\\_(ツ)_/¯ to your message"; + " /shrug - appends ¯\\_(ツ)_/¯ to your message
" + + " /join [session id] - joins another session"; printChatMessage( "command-message", @@ -294,7 +300,7 @@ const matpad = (n) => { * @param {string?} user * @param {Node?} content */ -const printChatMessage = (eventType, user, colour, content) => { +export const printChatMessage = (eventType, user, colour, content) => { const chatMessage = document.createElement("div"); chatMessage.classList.add("chat-message"); chatMessage.classList.add(eventType); diff --git a/frontend/lib/links.mjs b/frontend/lib/links.mjs index f69442c..998930e 100644 --- a/frontend/lib/links.mjs +++ b/frontend/lib/links.mjs @@ -1,3 +1,5 @@ +import { joinNewSession } from "./watch-session.mjs?v=048af96"; + export async function linkify( text, next = async (t) => [document.createTextNode(t)] @@ -29,9 +31,11 @@ export async function linkify( ) { nodes.push( Object.assign(document.createElement("a"), { - href: url.href, textContent: "Join Session", className: "chip join-chip", + onclick: () => { + joinNewSession(url.hash.substring(1)); + }, }) ); } else if ( diff --git a/frontend/lib/reconnecting-web-socket.mjs b/frontend/lib/reconnecting-web-socket.mjs index 563473d..6370c21 100644 --- a/frontend/lib/reconnecting-web-socket.mjs +++ b/frontend/lib/reconnecting-web-socket.mjs @@ -11,6 +11,7 @@ export default class ReconnectingWebSocket { this._lastConnect = 0; this._socket = null; this._unsent = []; + this._closing = false; this._connect(true); } _connect(first) { @@ -40,6 +41,7 @@ export default class ReconnectingWebSocket { }); } _reconnect() { + if (this._closing) return; if (this._reconnecting) return; this._eventTarget.dispatchEvent(new Event("reconnecting")); this._reconnecting = true; @@ -56,6 +58,10 @@ export default class ReconnectingWebSocket { this._unsent.push(message); } } + close() { + this._closing = true; + this._socket.close(); + } addEventListener(...a) { return this._eventTarget.addEventListener(...a); } diff --git a/frontend/lib/watch-session.mjs b/frontend/lib/watch-session.mjs index eb2304a..814f8fa 100644 --- a/frontend/lib/watch-session.mjs +++ b/frontend/lib/watch-session.mjs @@ -3,6 +3,7 @@ import { setupChat, logEventToChat, updateViewerList, + printChatMessage, } from "./chat.mjs?v=048af96"; import ReconnectingWebSocket from "./reconnecting-web-socket.mjs"; @@ -166,11 +167,41 @@ const setupOutgoingEvents = (video, socket) => { }); }; +let socket = null; +let video = null; + +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; + } + 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; + // try { // we are handling errors in the join form. const genericConnectionError = new Error( "There was an issue getting the session information." @@ -202,9 +233,9 @@ export const joinSession = async (nickname, sessionId, colour) => { throw genericConnectionError; } - const socket = createWebSocket(sessionId, nickname, colour); + socket = createWebSocket(sessionId, nickname, colour); socket.addEventListener("open", async () => { - const video = await setupVideo( + video = await setupVideo( video_url, subtitle_tracks, current_time_ms, diff --git a/frontend/styles.css b/frontend/styles.css index 64f524d..014d9f0 100644 --- a/frontend/styles.css +++ b/frontend/styles.css @@ -226,7 +226,8 @@ button.small-button { } .chat-message.set-time, -.chat-message.set-playing { +.chat-message.set-playing, +.chat-message.join-session { font-style: italic; text-align: right; font-size: 0.85em; @@ -237,7 +238,8 @@ button.small-button { } .chat-message.set-time > strong, -.chat-message.set-playing > strong { +.chat-message.set-playing > strong, +.chat-message.join-session > strong { color: unset !important; }