diff --git a/webroot/index.html b/webroot/index.html
index 28714cfed..6c8cbd092 100644
--- a/webroot/index.html
+++ b/webroot/index.html
@@ -1,26 +1,20 @@
+
+
Live stream test
-
-
+
-
-
-
-
-
-
+
+
+
+
+
@@ -34,7 +28,7 @@

-
Random Username 123
+
+
diff --git a/webroot/js/app.js b/webroot/js/app.js
index 7b6bf8962..10e74fa23 100644
--- a/webroot/js/app.js
+++ b/webroot/js/app.js
@@ -12,6 +12,8 @@ function setupApp() {
data: {
streamStatus: "",
viewerCount: 0,
+ sessionMaxViewerCount: 0,
+ overallMaxViewerCount: 0,
},
});
@@ -22,28 +24,8 @@ function setupApp() {
}
})
- window.chatForm = new Vue({
- el: "#chatForm",
- data: {
- message: {
- author: "",//localStorage.author || "Viewer" + (Math.floor(Math.random() * 42) + 1),
- body: ""
- }
- },
- methods: {
- submitChatForm: function (e) {
- const message = new Message(this.message);
- message.id = uuidv4();
- localStorage.author = message.author;
- const messageJSON = JSON.stringify(message);
- window.ws.send(messageJSON);
- e.preventDefault();
-
- this.message.body = "";
- }
- }
- });
+ window.VIDEOJS_NO_DYNAMIC_STYLE = true;
var appMessagingMisc = new Messaging();
appMessagingMisc.init();
}
@@ -58,9 +40,9 @@ async function getStatus() {
? "Stream is online."
: "Stream is offline."
- app.viewerCount = status.viewerCount
- app.sessionMaxViewerCount = status.sessionMaxViewerCount
- app.overallMaxViewerCount = status.overallMaxViewerCount
+ app.viewerCount = status.viewerCount;
+ app.sessionMaxViewerCount = status.sessionMaxViewerCount;
+ app.overallMaxViewerCount = status.overallMaxViewerCount;
} catch (e) {
app.streamStatus = "Stream server is offline."
@@ -85,8 +67,8 @@ function setupWebsocket() {
})
if (existing.length === 0 || !existing) {
- this.messagesContainer.messages.push(message)
- scrollSmoothToBottom("messages-container")
+ this.messagesContainer.messages.push(message);
+ setTimeout(() => { jumpToBottom("#messages-container"); } , 50); // could be better. is there a sort of Vue "componentDidUpdate" we can do this on?
}
}
@@ -111,16 +93,3 @@ getStatus()
setupWebsocket()
// setInterval(getStatus, 5000)
-function scrollSmoothToBottom(id) {
- const div = document.getElementById(id);
- $('#' + id).animate({
- scrollTop: div.scrollHeight - div.clientHeight
- }, 500)
-}
-
-function uuidv4() {
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
- const r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
- return v.toString(16);
- });
-}
diff --git a/webroot/js/message.js b/webroot/js/message.js
index 5fc9d704c..9b31c0891 100644
--- a/webroot/js/message.js
+++ b/webroot/js/message.js
@@ -1,14 +1,13 @@
class Message {
constructor(model) {
- this.author = model.author
- this.body = model.body
- this.image = "https://robohash.org/" + model.author
- this.id = model.id
+ this.author = model.author;
+ this.body = model.body;
+ this.image = model.image || "https://robohash.org/" + model.author;
+ this.id = model.id;
}
addNewlines(str) {
return str.replace(/(?:\r\n|\r|\n)/g, '
');
-
}
formatText() {
var linked = autoLink(this.body, { embed: true });
@@ -21,7 +20,7 @@ class Message {
body: this.body(),
image: this.image(),
id: this.id
- }
+ };
}
}
@@ -38,54 +37,77 @@ class Messaging {
this.maxMessageLength = 500;
this.maxMessageBuffer = 20;
+ this.keyUsername = "owncast_username";
+ this.keyChatDisplayed = "owncast_chat";
+
+ this.tagAppContainer = document.querySelector("#app-container");
this.tagChatToggle = document.querySelector("#chat-toggle");
- this.tagUserInfoDisplay = document.querySelector("#user-info-display");
+ this.textUserInfoDisplay = document.querySelector("#user-info-display");
this.tagUserInfoChanger = document.querySelector("#user-info-change");
this.tagUsernameDisplay = document.querySelector("#username-display");
this.imgUsernameAvatar = document.querySelector("#username-avatar");
- this.tagMessageAuthor = document.querySelector("#self-message-author");
+ this.inputMessageAuthor = document.querySelector("#self-message-author");
this.tagMessageFormWarning = document.querySelector("#message-form-warning");
- this.tagAppContainer = document.querySelector("#app-container");
this.inputChangeUserName = document.querySelector("#username-change-input");
this.btnUpdateUserName = document.querySelector("#button-update-username");
this.btnCancelUpdateUsername = document.querySelector("#button-cancel-change");
+ this.btnSubmitMessage = document.querySelector("#button-submit-message");
- this.formMessageInput = document.querySelector("#inputBody");
-
+ this.formMessageInput = document.querySelector("#message-body-form");
}
init() {
this.tagChatToggle.addEventListener("click", this.handleChatToggle);
- this.tagUsernameDisplay.addEventListener("click", this.handleShowChangeNameForm);
+ this.textUserInfoDisplay.addEventListener("click", this.handleShowChangeNameForm);
this.btnUpdateUserName.addEventListener("click", this.handleUpdateUsername);
this.btnCancelUpdateUsername.addEventListener("click", this.handleHideChangeNameForm);
this.inputChangeUserName.addEventListener("keydown", this.handleUsernameKeydown);
this.formMessageInput.addEventListener("keydown", this.handleMessageInputKeydown);
+ this.btnSubmitMessage.addEventListener("click", this.handleSubmitChatButton);
+ this.initLocalStates();
+
+ }
+
+ initLocalStates() {
+ this.username = getLocalStorage(this.keyUsername) || "User" + (Math.floor(Math.random() * 42) + 1);
+ this.updateUsernameFields(this.username);
+
+ this.chatDisplayed = getLocalStorage(this.keyChatDisplayed) || false;
+ this.displayChat();
+ }
+ updateUsernameFields(username) {
+ this.tagUsernameDisplay.innerText = username;
+ this.inputChangeUserName.value = username;
+ this.inputMessageAuthor.value = username;
+ this.imgUsernameAvatar.src = this.avatarSource + username;
+ }
+ displayChat() {
+ this.tagAppContainer.className = this.chatDisplayed ? "flex" : "flex no-chat";
}
handleChatToggle = () => {
+ this.chatDisplayed = !this.chatDisplayed;
if (this.chatDisplayed) {
- this.tagAppContainer.className = "flex no-chat";
- this.chatDisplayed = false;
+ setLocalStorage(this.keyChatDisplayed, this.chatDisplayed);
} else {
- this.tagAppContainer.className = "flex";
- this.chatDisplayed = true;
+ clearLocalStorage(this.keyChatDisplayed);
}
+ this.displayChat();
}
handleShowChangeNameForm = () => {
- this.tagUserInfoDisplay.style.display = "none";
+ this.textUserInfoDisplay.style.display = "none";
this.tagUserInfoChanger.style.display = "flex";
}
handleHideChangeNameForm = () => {
- this.tagUserInfoDisplay.style.display = "flex";
+ this.textUserInfoDisplay.style.display = "flex";
this.tagUserInfoChanger.style.display = "none";
}
handleUpdateUsername = () => {
@@ -95,10 +117,8 @@ class Messaging {
if (newValue) {
this.userName = newValue;
- this.inputChangeUserName.value = newValue;
- this.tagMessageAuthor.innerText = newValue;
- this.tagUsernameDisplay.innerText = newValue;
- this.imgUsernameAvatar.src = this.avatarSource + newValue;
+ this.updateUsernameFields(newValue);
+ setLocalStorage(this.keyUsername, newValue);
}
this.handleHideChangeNameForm();
}
@@ -118,11 +138,9 @@ class Messaging {
if (event.keyCode === 13) { // enter
if (!this.prepNewLine) {
- // submit()
+ this.submitChat(value);
event.preventDefault();
- // clear out things.
- this.formMessageInput.value = "";
- this.tagMessageFormWarning.innerText = "";
+
return;
}
this.prepNewLine = false;
@@ -143,7 +161,30 @@ class Messaging {
this.tagMessageFormWarning.innerText = "";
}
}
+ handleSubmitChatButton = event => {
+ var value = this.formMessageInput.value.trim();
+ if (value) {
+ this.submitChat(value);
+ event.preventDefault();
+ return false;
+ }
+ event.preventDefault();
+ return false;
+ }
+ submitChat(content) {
+ if (!content) {
+ return;
+ }
+ var message = new Message({
+ body: content,
+ author: this.username,
+ id: uuidv4(),
+ });
+ const messageJSON = JSON.stringify(message);
+ window.ws.send(messageJSON);
-
-
+ // clear out things.
+ this.formMessageInput.value = "";
+ this.tagMessageFormWarning.innerText = "";
+ }
}
\ No newline at end of file
diff --git a/webroot/js/utils.js b/webroot/js/utils.js
new file mode 100644
index 000000000..9bf1a4e5c
--- /dev/null
+++ b/webroot/js/utils.js
@@ -0,0 +1,39 @@
+function getLocalStorage(key) {
+ try {
+ return localStorage.getItem(key);
+ } catch (e) {
+ }
+ return null;
+}
+
+function setLocalStorage(key, value) {
+ try {
+ if (value !== "" && value !== null) {
+ localStorage.setItem(key, value);
+ } else {
+ localStorage.removeItem(key);
+ }
+ return true;
+ } catch (e) {}
+ return false;
+}
+
+function clearLocalStorage(key) {
+ localStorage.removeItem(key);
+}
+
+function jumpToBottom(id) {
+ const div = document.querySelector(id);
+ div.scrollTo({
+ top: div.scrollHeight,// - div.clientHeight,
+ left: 0,
+ behavior: 'smooth'
+ });
+}
+
+function uuidv4() {
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
+ const r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
+ return v.toString(16);
+ });
+}
\ No newline at end of file
diff --git a/webroot/styles/layout.css b/webroot/styles/layout.css
index 5ecc164b1..4587e9d55 100644
--- a/webroot/styles/layout.css
+++ b/webroot/styles/layout.css
@@ -36,6 +36,7 @@ header {
z-index: 10;
flex-direction: row;
justify-content: space-between;
+ flex-wrap: nowrap;
}
header h1 {
@@ -46,6 +47,7 @@ header h1 {
color: #ddd;
padding: .5em;
white-space: nowrap;
+ width: 20em;
}
#chat-toggle {
@@ -53,7 +55,7 @@ header h1 {
background-color: #555;
text-align: center;
height: 100%;
- width: 3em;
+ min-width: 3em;
justify-content: center;
align-items: center;
}
@@ -67,6 +69,7 @@ header h1 {
flex-direction: row;
justify-content: flex-end;
align-items: center;
+ flex-wrap: nowrap;
}
#user-info-display {
@@ -76,6 +79,8 @@ header h1 {
align-items: center;
cursor: pointer;
padding: .5em 1em;
+ overflow: hidden;
+ width: 100%;
}
#username-avatar {
@@ -87,8 +92,10 @@ header h1 {
#username-display {
font-weight: bold;
font-size: .75em;
- color: #516FEB
-
+ color: #516FEB;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
}
#user-info-display:hover {
transition: opacity .2s;
@@ -148,10 +155,12 @@ header h1 {
flex-direction: column;
justify-content: flex-start;
align-items: center;
+ background-color: black;
}
#video-container video {
width: 100%;
display: block;
+ min-height: 100%
}
#stream-info {
@@ -196,6 +205,9 @@ header h1 {
align-items: flex-end;
margin-bottom: 0;
}
+#message-body-form {
+ font-size: 1em;
+}
#message-form-actions {
flex-direction: row;
justify-content: space-between;
@@ -282,8 +294,10 @@ header h1 {
overflow: hidden;
}
-
- #info {
+ #user-info {
+ width: 12em;
+ }
+ #stream-info {
display: none;
overflow: auto;
height: auto;