342 lines
15 KiB
HTML
342 lines
15 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en" dir="ltr" id="main_html" prefix="og: http://ogp.me/ns#">
|
|
<head>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" charset="utf-8" />
|
|
<title id="title">{{metadata['last_known_title']}}</title>
|
|
|
|
|
|
<meta property="og:title" content="{{metadata['last_known_title']}}">
|
|
<meta property="og:description" content="A place where we get together a stream while hanging out!">
|
|
<meta property="og:image" content="{{url_for('static', filename='website_images/poster.jpg')}}">
|
|
<meta property="og:url" content="http://184.83.153.182:5000/stream">
|
|
<meta property="og:type" content="video"> <!-- Can be 'article', 'video', etc. -->
|
|
<meta property="og:site_name" content="Treehouse Theatre">
|
|
|
|
<!-- Material Icons -->
|
|
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
|
|
<!-- Material Symbols - Outlined Set -->
|
|
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined" rel="stylesheet" />
|
|
<!-- Material Symbols - Rounded Set -->
|
|
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded" rel="stylesheet" />
|
|
<!-- Material Symbols - Sharp Set -->
|
|
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Sharp" rel="stylesheet" />
|
|
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/uikit.min.css') }}"/>
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/stream.css') }}"/>
|
|
<link id="dark-mode" rel="stylesheet" href="{{ url_for('static', filename='css/dark-mode.css') }}" disabled/>
|
|
|
|
|
|
<script src="{{ url_for('static', filename='js/uikit.min.js') }}"></script>
|
|
<script src="{{ url_for('static', filename='js/uikit-icons.min.js') }}"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
|
|
|
|
|
|
</head>
|
|
<body>
|
|
<div uk-sticky="sel-target: .uk-navbar-container; cls-active: uk-navbar-sticky;">
|
|
<nav id="navbar" class="uk-navbar-container">
|
|
<div class="uk-container uk-container-expand">
|
|
<div uk-navbar="dropbar: true">
|
|
<div class="uk-navbar-left">
|
|
<p style="margin-top: 20px;"><strong>{{metadata['last_known_title']}}</strong></p>
|
|
</div>
|
|
<div class="uk-navbar-right uk-margin-small">
|
|
<div>
|
|
<a onclick="toggleDarkMode()" class="uk-button uk-button-small"><span id="modeToggle" class="uk-flex material-symbols-outlined">dark_mode</span></a>
|
|
</div>
|
|
<a href="#" class="uk-button uk-button-small" uk-icon="icon: menu" uk-toggle> Menu</a>
|
|
<div uk-dropdown="pos: bottom-right">
|
|
<ul class="uk-nav uk-dropdown-nav">
|
|
<li><a href="/">Home</a></li>
|
|
<li><a href="/stream">Stream</a></li>
|
|
<li><a href="/events">Events</a></li>
|
|
<li><a href="/radios">Radio</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
</div>
|
|
<div style="margin-top: 30px;">
|
|
<div class="uk-container uk-container-xlarge">
|
|
<div class="testContainer">
|
|
<div id="video-container" class="video-container">
|
|
<div class="blurred-background"></div>
|
|
<video id="videoPlayer" class="uk-video" autoplay playsinline controls poster="{{ url_for('static', filename='website_images/poster.jpg') }}">Your browser does not support the video tag.</video>
|
|
</div>
|
|
<div id="chat-container" class="chat-container" hidden>
|
|
<div id="chat">
|
|
</div>
|
|
<div id="test" class="floating-square">
|
|
<div class="input-container">
|
|
<textarea id="messageInput" class="full-width-input" placeholder="Type your thoughts..." maxlength="255"></textarea>
|
|
</div>
|
|
<button id="sendButton" onclick="sendMessage()" class="send-button"><span class="material-symbols-outlined">
|
|
send
|
|
</span></button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="dock" uk-grid>
|
|
<div style="padding: 5px" class="uk-width-1-2">
|
|
<p id="viewer-count" class="uk-text-meta">{{metadata['viewer_count']+1}} Viewers</p>
|
|
</div>
|
|
<div style="padding: 5px" class="uk-width-1-2">
|
|
<button style="border-radius: 20px;" class="uk-button uk-button-small uk-align-right mybutton" id="popout-button" hidden>Chat</button>
|
|
<button onclick="toggleViewMode()" style="border-radius: 20px;" class="uk-button uk-button-small uk-align-right" id="view_mode" hidden>
|
|
Theatre
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js" integrity="sha512-q/dWJ3kcmjBLU4Qc47E4A9kTB4m3wuTY7vkFJDTZKjTs8jhyGQnaUrxa0Ytd0ssMZhbNua9hE+E7Qv1j+DyZwA==" crossorigin="anonymous"></script>
|
|
<script>
|
|
url = `${location.origin}`
|
|
console.log(url)
|
|
var socket = io.connect(url);
|
|
var thishost = location.hostname
|
|
var username;
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const videoContainer = document.getElementById('video-container');
|
|
const scrollableDiv = document.getElementById('chat-container');
|
|
|
|
function setScrollableDivHeight() {
|
|
scrollableDiv.style.height = `${videoContainer.clientHeight}px`;
|
|
}
|
|
|
|
// Set the initial height
|
|
setScrollableDivHeight();
|
|
|
|
// Update the height on window resize
|
|
window.addEventListener('resize', setScrollableDivHeight);
|
|
});
|
|
|
|
socket.on('titleChanged', function(data) {
|
|
document.getElementById('streamTitle').innerHTML = `<strong>${data}</strong>`
|
|
});
|
|
|
|
socket.on('updateViewerCount', function(data) {
|
|
document.getElementById('viewer-count').innerHTML = `${data} Viewers`
|
|
});
|
|
|
|
socket.on('userJoined', function(data) {
|
|
console.log(`JOIN: ${JSON.stringify(data)}`)
|
|
UIkit.notification({
|
|
message: `${data.user.displayName} has joined the chat!`,
|
|
status: 'secondary',
|
|
pos: 'bottom-center',
|
|
timeout: 5000
|
|
});
|
|
});
|
|
socket.on('userLeft', function(data) {
|
|
console.log(`LEFT: ${JSON.stringify(data)}`)
|
|
UIkit.notification({
|
|
message: `${data.user.displayName} has left the chat!`,
|
|
status: 'secondary',
|
|
pos: 'bottom-center',
|
|
timeout: 5000
|
|
});
|
|
});
|
|
socket.on('userNameChanged', function(data) {
|
|
console.log(`NAME_CHANGE: ${JSON.stringify(data)}`)
|
|
UIkit.notification({
|
|
message: `${data.user.previousNames.at(-1)} changed their name to ${data.newName}`,
|
|
status: 'secondary',
|
|
pos: 'bottom-center',
|
|
timeout: 5000
|
|
});
|
|
});
|
|
socket.on('newMessage', function() {
|
|
UIkit.notification({
|
|
message: `Chat has a new message!`,
|
|
status: 'secondary',
|
|
pos: 'bottom-center',
|
|
timeout: 5000
|
|
});
|
|
});
|
|
socket.on('joined', function(data) {
|
|
username = data.username
|
|
});
|
|
|
|
function sendMessage(){
|
|
let message = document.getElementById('messageInput')
|
|
|
|
let currentTime = new Date();
|
|
let timeString = currentTime.toLocaleTimeString();
|
|
let dateString = currentTime.toLocaleDateString();
|
|
let dateTimeString = `${dateString} ${timeString}`;
|
|
|
|
socket.emit('messageSend', {'message_content': message.value, 'channel_id': "stream", 'username': username, 'timestamp': currentTime})
|
|
message.value = '';
|
|
}
|
|
|
|
socket.on('messageReceive', function(data) {
|
|
console.log(data)
|
|
let message = data;
|
|
// instead of adding the message do I just reload the messages? what kind of infranstructure would that require.
|
|
addMessage(data)
|
|
});
|
|
|
|
|
|
async function joinStream(){
|
|
socket.emit('join');
|
|
}
|
|
joinStream()
|
|
|
|
document.getElementById('popout-button').addEventListener('click', function() {
|
|
// Define the URL of the Owncast chat
|
|
const chatUrl = `http://${thishost}:8086/embed/chat/readwrite`;
|
|
// Define the dimensions of the new window
|
|
const width = 600;
|
|
const height = 400;
|
|
// Calculate the position of the new window
|
|
const left = (window.screen.width - width) / 2;
|
|
const top = (window.screen.height - height) / 2;
|
|
// Open the chat in a new window
|
|
window.open(chatUrl, 'OwncastChat', `width=${width},height=${height},left=${left},top=${top}`);
|
|
});
|
|
|
|
// Get the video element
|
|
const video = document.getElementById('videoPlayer');
|
|
|
|
// Check if the browser supports HLS natively
|
|
if (Hls.isSupported()) {
|
|
var hls = new Hls();
|
|
hls.loadSource(`http://${thishost}:8086/hls/stream.m3u8`);
|
|
hls.attachMedia(video);
|
|
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
|
|
// If the browser natively supports HLS
|
|
console.log('maybe')
|
|
video.src = `http://${thishost}:8086/hls/stream.m3u8`;
|
|
} else {
|
|
// Fallback message for unsupported browsers
|
|
video.poster="fallback-image.jpg";
|
|
video.innerHTML = 'Your browser does not support HLS. Please use a modern browser.';
|
|
}
|
|
|
|
const mainVideo = document.getElementById('videoPlayer');
|
|
const blurredBackground = document.querySelector('.blurred-background');
|
|
|
|
// Create a canvas to draw the video frame
|
|
const canvas = document.createElement('canvas');
|
|
const ctx = canvas.getContext('2d');
|
|
|
|
// Set the canvas size to match the video
|
|
mainVideo.addEventListener('loadedmetadata', () => {
|
|
canvas.width = mainVideo.videoWidth;
|
|
canvas.height = mainVideo.videoHeight;
|
|
});
|
|
|
|
// Function to update the blurred background
|
|
function updateBlurredBackground() {
|
|
if (mainVideo.readyState === mainVideo.HAVE_ENOUGH_DATA) {
|
|
// Draw the current video frame onto the canvas
|
|
ctx.drawImage(mainVideo, 0, 0, canvas.width, canvas.height);
|
|
|
|
// Convert the canvas content to a Data URL
|
|
const dataUrl = canvas.toDataURL();
|
|
|
|
// Set the Data URL as the background image of the blurred background
|
|
blurredBackground.style.backgroundImage = `url(${dataUrl})`;
|
|
}
|
|
|
|
// Request the next frame update
|
|
requestAnimationFrame(updateBlurredBackground);
|
|
}
|
|
|
|
// Start updating the blurred background when the video plays
|
|
var background_blur = false
|
|
//mainVideo.addEventListener('play', () => {
|
|
// blurrBackground()
|
|
//});
|
|
|
|
function blurrBackground(){
|
|
if(background_blur){
|
|
updateBlurredBackground();
|
|
}
|
|
}
|
|
|
|
async function addMessage(data){
|
|
|
|
let message_card = document.createElement('div')
|
|
message_card.setAttribute('class', 'message-card')
|
|
|
|
let user_info = document.createElement('div')
|
|
user_info.setAttribute('class', 'user-info')
|
|
|
|
let image = document.createElement('img')
|
|
image.setAttribute('class', 'avatar')
|
|
image.setAttribute('src', "static/website_images/placeholder.webp")
|
|
|
|
let username = document.createElement('span')
|
|
username.setAttribute('class', 'username')
|
|
username.innerHTML = data.username
|
|
|
|
let timestamp = document.createElement('span')
|
|
timestamp.setAttribute('class', 'timestamp')
|
|
timestamp.innerHTML = data.timestamp
|
|
|
|
user_info.append(image)
|
|
user_info.append(username)
|
|
|
|
|
|
message_card.append(user_info)
|
|
message_card.append(timestamp)
|
|
|
|
let message = document.createElement('div')
|
|
message.setAttribute('class', 'message-content')
|
|
|
|
|
|
test = `${data.message_content}`
|
|
|
|
message.innerHTML = `${test}`
|
|
|
|
console.log(message.innerHTML.length)
|
|
|
|
message_card.append(message)
|
|
|
|
document.getElementById('chat').append(message_card)
|
|
document.getElementById('chat').scrollTop = document.getElementById('chat').scrollHeight;
|
|
}
|
|
|
|
|
|
var mode = false
|
|
async function toggleDarkMode() {
|
|
let darkMode = document.getElementById("dark-mode");
|
|
darkMode.disabled = !darkMode.disabled;
|
|
mode = !mode;
|
|
if(mode){
|
|
document.getElementById('modeToggle').innerHTML = "light_mode"
|
|
document.getElementById('main_html').classList.add('uk-light')
|
|
} else {
|
|
document.getElementById('modeToggle').innerHTML = "dark_mode"
|
|
document.getElementById('main_html').classList.remove('uk-light')
|
|
}
|
|
}
|
|
|
|
var detail_mode = true
|
|
async function toggleViewMode(){
|
|
detail_mode = !detail_mode
|
|
if (detail_mode){
|
|
console.log('Detail Mode Activate')
|
|
document.getElementById('popout-button').hidden = false
|
|
document.getElementById('viewer-count').hidden = false
|
|
background_blur = false
|
|
blurredBackground.style.backgroundImage = `none`;
|
|
} else {
|
|
console.log('Detail Mode Deactivate')
|
|
document.getElementById('popout-button').hidden = true
|
|
document.getElementById('viewer-count').hidden = true
|
|
background_blur = true
|
|
blurrBackground()
|
|
}
|
|
}
|
|
|
|
</script>
|
|
</html> |