2025-05-24 09:14:19 -05:00

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>