diff --git a/webroot/index.html b/webroot/index.html
index f6a563140..5f411e80d 100644
--- a/webroot/index.html
+++ b/webroot/index.html
@@ -79,7 +79,7 @@ GW TODO:
autoplay
playsinline
muted
- poster="/thumbnail.jpg"
+ poster="./img/logo.png"
>
diff --git a/webroot/js/app.js b/webroot/js/app.js
index d30963da4..a5110753f 100644
--- a/webroot/js/app.js
+++ b/webroot/js/app.js
@@ -4,7 +4,7 @@ async function setupApp() {
window.app = new Vue({
el: "#app-container",
data: {
- streamStatus: "Stream is offline.", // Default state.
+ streamStatus: MESSAGE_OFFLINE, // Default state.
viewerCount: 0,
sessionMaxViewerCount: 0,
overallMaxViewerCount: 0,
@@ -59,7 +59,7 @@ async function setupApp() {
app.extraUserContent = descriptionHTML;
return this;
} catch (error) {
- console.log("Error",error);
+ console.log("Error", error);
}
}
@@ -67,17 +67,13 @@ var websocketReconnectTimer;
function setupWebsocket() {
clearTimeout(websocketReconnectTimer);
- // Uncomment to point to somewhere other than goth.land
- const protocol = location.protocol == "https:" ? "wss" : "ws"
- // var ws = new WebSocket(protocol + "://" + location.host + "/entry")
-
- var ws = new WebSocket("wss://goth.land/entry")
+ var ws = new WebSocket(URL_WEBSOCKET);
ws.onmessage = (e) => {
- const model = JSON.parse(e.data)
+ const model = JSON.parse(e.data);
// Ignore non-chat messages (such as keepalive PINGs)
- if (model.type !== SocketMessageTypes.CHAT) { return; }
+ if (model.type !== SOCKET_MESSAGE_TYPES.CHAT) { return; }
const message = new Message(model);
diff --git a/webroot/js/message.js b/webroot/js/message.js
index fa4383d2b..ee5ef03f9 100644
--- a/webroot/js/message.js
+++ b/webroot/js/message.js
@@ -1,8 +1,3 @@
-const SocketMessageTypes = {
- CHAT: 'CHAT',
- PING: 'PING'
-}
-
class Message {
constructor(model) {
this.author = model.author;
@@ -39,10 +34,6 @@ class Messaging {
this.maxMessageLength = 500;
this.maxMessageBuffer = 20;
- this.keyUsername = 'owncast_username';
- this.keyUserAvatar = 'owncast_avatar';
- this.keyChatDisplayed = 'owncast_chat';
-
this.tagAppContainer = document.querySelector('#app-container');
this.tagChatToggle = document.querySelector('#chat-toggle');
this.tagUserInfoChanger = document.querySelector('#user-info-change');
@@ -89,16 +80,11 @@ class Messaging {
}
initLocalStates() {
- this.username = getLocalStorage(this.keyUsername) || generateUsername();
- console.log("=== initt state", getLocalStorage(this.keyUserAvatar))
- this.imgUsernameAvatar.src = getLocalStorage(this.keyUserAvatar) || generateAvatar(this.username);
-
-
- console.log("===",this.imgUsernameAvatar.src)
-
+ this.username = getLocalStorage(KEY_USERNAME) || generateUsername();
+ this.imgUsernameAvatar.src = getLocalStorage(KEY_AVATAR) || generateAvatar(this.username);
this.updateUsernameFields(this.username);
- this.chatDisplayed = getLocalStorage(this.keyChatDisplayed) || false;
+ this.chatDisplayed = getLocalStorage(KEY_CHAT_DISPLAYED) || false;
this.displayChat();
}
updateUsernameFields(username) {
@@ -134,9 +120,9 @@ class Messaging {
handleChatToggle() {
this.chatDisplayed = !this.chatDisplayed;
if (this.chatDisplayed) {
- setLocalStorage(this.keyChatDisplayed, this.chatDisplayed);
+ setLocalStorage(KEY_CHAT_DISPLAYED, this.chatDisplayed);
} else {
- clearLocalStorage(this.keyChatDisplayed);
+ clearLocalStorage(KEY_CHAT_DISPLAYED);
}
this.displayChat();
}
@@ -164,8 +150,8 @@ class Messaging {
this.username = newValue;
this.updateUsernameFields(newValue);
this.imgUsernameAvatar.src = generateAvatar(newValue);
- setLocalStorage(this.keyUsername, newValue);
- setLocalStorage(this.keyUserAvatar, this.imgUsernameAvatar.src);
+ setLocalStorage(KEY_USERNAME, newValue);
+ setLocalStorage(KEY_AVATAR, this.imgUsernameAvatar.src);
}
this.handleHideChangeNameForm();
}
diff --git a/webroot/js/player/player.js b/webroot/js/player/player.js
index 23323f362..209fd9c56 100644
--- a/webroot/js/player/player.js
+++ b/webroot/js/player/player.js
@@ -1,11 +1,8 @@
-// const streamURL = '/hls/stream.m3u8';
-const streamURL = 'https://goth.land/hls/stream.m3u8'; // Uncomment me to point to remote video
-
// style hackings
window.VIDEOJS_NO_DYNAMIC_STYLE = true;
// Create the player for the first time
-const player = videojs('video', null, function () {
+const player = videojs(VIDEO_ID, null, function () {
getStatus();
setInterval(getStatus, 5000);
setupPlayerEventHandlers();
@@ -18,17 +15,12 @@ player.ready(function () {
function resetPlayer(player) {
player.reset();
- player.src({ type: 'application/x-mpegURL', src: streamURL });
- if (app.isOnline) {
- player.poster('/thumbnail.jpg');
- } else {
- // Change this to some kind of offline image.
- player.poster('/img/logo.png');
- }
+ player.src({ type: 'application/x-mpegURL', src: URL_STREAM });
+ setVideoPoster(app.isOnline);
}
function setupPlayerEventHandlers() {
- const player = videojs('video');
+ const player = videojs(VIDEO_ID);
player.on('error', function (e) {
console.log("Player error: ", e);
@@ -68,8 +60,8 @@ function setupPlayerEventHandlers() {
function restartPlayer() {
try {
- console.log('restarting')
- const player = videojs('video');
+ console.log('restarting', player.src())
+ const player = videojs(VIDEO_ID);
player.pause();
player.src(player.src()); // Reload the same video
player.load();
@@ -78,4 +70,4 @@ function restartPlayer() {
console.log(e)
}
-}
\ No newline at end of file
+}
diff --git a/webroot/js/status.js b/webroot/js/status.js
index eb393b3a7..54d05c5a5 100644
--- a/webroot/js/status.js
+++ b/webroot/js/status.js
@@ -1,42 +1,45 @@
var playerRestartTimer;
-async function getStatus() {
- const url = "/status";
- try {
- const response = await fetch(url);
- const status = await response.json();
-
- clearTimeout(playerRestartTimer);
-
- if (!app.isOnline && status.online) {
- // The stream was offline, but now it's online. Force start of playback after an arbitrary
- // delay to make sure the stream has actual data ready to go.
- playerRestartTimer = setTimeout(function () {
- restartPlayer();
- }, 3000);
- }
-
- app.streamStatus = status.online
- ? "Stream is online."
- : "Stream is offline."
-
- const player = videojs('video');
- if (app.isOnline) {
- player.poster('/thumbnail.jpg');
- } else {
- // Change this to some kind of offline image.
- player.poster('/img/logo.png');
- }
-
- app.viewerCount = status.viewerCount;
- app.sessionMaxViewerCount = status.sessionMaxViewerCount;
- app.overallMaxViewerCount = status.overallMaxViewerCount;
- app.isOnline = status.online;
-
- } catch (e) {
- app.streamStatus = "Stream server is offline."
- app.viewerCount = 0
+function handleStatus(status) {
+ clearTimeout(playerRestartTimer);
+ if (!app.isOnline && status.online) {
+ // The stream was offline, but now it's online. Force start of playback after an arbitrary delay to make sure the stream has actual data ready to go.
+ playerRestartTimer = setTimeout(restartPlayer, 3000);
}
-}
\ No newline at end of file
+ app.streamStatus = status.online ? MESSAGE_ONLINE : MESSAGE_OFFLINE;
+
+ app.viewerCount = status.viewerCount;
+ app.sessionMaxViewerCount = status.sessionMaxViewerCount;
+ app.overallMaxViewerCount = status.overallMaxViewerCount;
+ app.isOnline = status.online;
+ setVideoPoster(app.isOnline);
+
+}
+
+function handleOffline() {
+ const player = videojs(VIDEO_ID);
+ player.poster(POSTER_DEFAULT);
+ app.streamStatus = MESSAGE_OFFLINE;
+ app.viewerCount = 0;
+}
+
+function getStatus() {
+ const options = {
+ // mode: 'no-cors',
+ }
+ fetch(URL_STATUS, options)
+ .then(response => {
+ if (!response.ok) {
+ throw new Error(`Network response was not ok ${response.ok}`);
+ }
+ return response.json();
+ })
+ .then(json => {
+ handleStatus(json);
+ })
+ .catch(error => {
+ handleOffline();
+ });
+}
diff --git a/webroot/js/utils.js b/webroot/js/utils.js
index eeec69656..f862dc137 100644
--- a/webroot/js/utils.js
+++ b/webroot/js/utils.js
@@ -1,3 +1,29 @@
+const MESSAGE_OFFLINE = 'Stream is offline.';
+const MESSAGE_ONLINE = 'Stream is online.';
+
+// const URL_PREFIX = '';
+const URL_PREFIX = 'https://goth.land';
+const URL_STATUS = `${URL_PREFIX}/status`;
+const URL_STREAM = `${URL_PREFIX}/hls/stream.m3u8`;
+
+const URL_WEBSOCKET = 'wss://goth.land/entry';
+// const URL_WEBSOCKET = `${location.protocol === 'https:' ? 'wss' : 'ws'}://${location.host}/entry`;
+
+const POSTER_DEFAULT = `${URL_PREFIX}/img/logo.png`;
+const POSTER_THUMB = `${URL_PREFIX}/thumbnail.jpg`;
+
+const SOCKET_MESSAGE_TYPES = {
+ CHAT: 'CHAT',
+ PING: 'PING'
+}
+
+const KEY_USERNAME = 'owncast_username';
+const KEY_AVATAR = 'owncast_avatar';
+const KEY_CHAT_DISPLAYED = 'owncast_chat';
+
+const VIDEO_ID = 'video';
+
+
function getLocalStorage(key) {
try {
return localStorage.getItem(key);
@@ -87,4 +113,10 @@ function generateAvatar(hash) {
function generateUsername() {
return `User ${(Math.floor(Math.random() * 42) + 1)}`;
-}
\ No newline at end of file
+}
+
+function setVideoPoster(online) {
+ const player = videojs(VIDEO_ID);
+ const poster = online ? POSTER_THUMB : POSTER_DEFAULT;
+ player.poster(poster);
+}