diff --git a/_includes/player.html b/_includes/player.html index 78c113d..bafa721 100644 --- a/_includes/player.html +++ b/_includes/player.html @@ -76,17 +76,33 @@ console.log("Usuário da live:", streamUser); const videoElement = document.querySelector('video'); const playerOffElement = document.querySelector('.player-off'); + const chatContainer = document.querySelector('.chat-container'); + const chatForm = document.querySelector('.chat-input-form'); + const usernameInput = document.querySelector('#username-input'); + const chatInputField = document.querySelector('.chat-enter'); + const url = `https://class.alice.ufsj.edu.br/dash/${streamUser}.mpd`; videoElement.src = url; + let chatAtivo = false; + fetch(url) .then(response => { if (response.ok) { console.log("Arquivo existe."); playerOffElement.style.display = "none"; + iniciarChat(); } else { console.log("Arquivo não encontrado."); videoElement.style.opacity = "0"; + + if (chatContainer) { + chatContainer.style.opacity = "0.3"; + chatContainer.style.pointerEvents = "none"; + } + + if (usernameInput) usernameInput.disabled = true; + if (chatInputField) chatInputField.disabled = true; } }); @@ -94,58 +110,70 @@ // Chat ao vivo // ===================== - const nomesAlice = [ - 'Alice', 'Chapeleiro Maluco', 'Coelho Branco', 'Rainha de Copas', - 'Gato de Cheshire', 'Lebre de Março', 'Lagarta', 'Dodo', - 'Tweedledee', 'Tweedledum', 'Rainha Vermelha', 'Rei de Copas' - ]; + function iniciarChat() { + chatAtivo = true; - function nomeAleatorio() { - return nomesAlice[Math.floor(Math.random() * nomesAlice.length)]; - } + const nomesAlice = [ + 'Alice', 'Chapeleiro Maluco', 'Coelho Branco', 'Rainha de Copas', + 'Gato de Cheshire', 'Lebre de Março', 'Lagarta', 'Dodo', + 'Tweedledee', 'Tweedledum', 'Rainha Vermelha', 'Rei de Copas' + ]; - let username = nomeAleatorio(); + function nomeAleatorio() { + return nomesAlice[Math.floor(Math.random() * nomesAlice.length)]; + } - function setCustomUsername() { - const customUsername = document.querySelector('#username-input').value.trim(); - username = customUsername || nomeAleatorio(); - } + let username = nomeAleatorio(); - const source = new EventSource(`php/chat/relay.php?user=${encodeURIComponent(streamUser)}`); + function setCustomUsername() { + const customUsername = usernameInput.value.trim(); + username = customUsername || nomeAleatorio(); + } - source.onmessage = function (event) { - const msg = JSON.parse(event.data); - addMessage(msg); - }; + const source = new EventSource(`php/chat/relay.php?user=${encodeURIComponent(streamUser)}`); - function sendMessage(event) { - event.preventDefault(); + let ultimaMensagem = ""; - const message = document.querySelector('.chat-enter').value; - const msgData = { - nome: username, - mensagem: message + source.onmessage = function (event) { + if (event.data !== ultimaMensagem) { + ultimaMensagem = event.data; + const msg = JSON.parse(event.data); + addMessage(msg); + } }; - fetch(`php/chat/send.php?user=${encodeURIComponent(streamUser)}`, { - method: 'POST', - headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, - body: 'mensagem=' + encodeURIComponent(JSON.stringify(msgData)) - }); + function sendMessage(event) { + event.preventDefault(); - document.querySelector('.chat-enter').value = ''; + const message = document.querySelector('.chat-enter').value; + if (!message.trim()) return; + + const msgData = { + nome: username, + mensagem: message.trim() + }; + + fetch(`php/chat/send.php?user=${encodeURIComponent(streamUser)}`, { + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + body: 'mensagem=' + encodeURIComponent(JSON.stringify(msgData)) + }) + .catch(err => console.error("Erro ao enviar mensagem:", err)); + + document.querySelector('.chat-enter').value = ''; + } + + function addMessage(msg) { + const chatLines = document.querySelector('.chat-lines'); + const newMessage = document.createElement('div'); + newMessage.classList.add('chat-line'); + newMessage.innerHTML = `
${msg.nome}: ${msg.mensagem}
`; + + chatLines.appendChild(newMessage); + chatLines.scrollTop = chatLines.scrollHeight; + } + + chatForm.addEventListener('submit', sendMessage); + usernameInput.addEventListener('change', setCustomUsername); } - - function addMessage(msg) { - const chatLines = document.querySelector('.chat-lines'); - const newMessage = document.createElement('div'); - newMessage.classList.add('chat-line'); - newMessage.innerHTML = `${msg.nome}: ${msg.mensagem}
`; - - chatLines.appendChild(newMessage); - chatLines.scrollTop = chatLines.scrollHeight; - } - - document.querySelector('.chat-input-form').addEventListener('submit', sendMessage); - document.querySelector('#username-input').addEventListener('change', setCustomUsername); diff --git a/assets/css/stylesheet.css b/assets/css/stylesheet.css index c900f53..e4396f1 100755 --- a/assets/css/stylesheet.css +++ b/assets/css/stylesheet.css @@ -578,7 +578,6 @@ h1, h2, h3, h4, h5, h6 { .player-off{ height: 80vh; - display: flex; align-items: center; justify-content: center; @@ -590,10 +589,9 @@ h1, h2, h3, h4, h5, h6 { .player-container { position: relative; - /* width: 100%; - height: 100%; */ - flex-grow: 10; + /* Em telas grandes, pode ser interessante adicionar margem para separar do chat */ + /* margin: 15px; */ } .player { @@ -608,14 +606,13 @@ h1, h2, h3, h4, h5, h6 { left: 0; width: 100%; height: 100%; - background-color: rgba(0, 0, 0, 0.6); /* Cor de fundo semitransparente */ + background-color: rgba(0, 0, 0, 0.6); /* Fundo semitransparente */ color: #fff; display: flex; align-items: center; justify-content: center; border-radius: 15px; - z-index: 10; /* Garante que a mensagem "Offline" apareça em cima do vídeo */ - + z-index: 10; /* Garante que a mensagem "Offline" fique acima do player */ } .player-info { @@ -623,7 +620,7 @@ h1, h2, h3, h4, h5, h6 { background-color: #0b1a33; } -/* Estilos específicos para o player, se necessário */ +/* Estilos específicos para o player */ video::-webkit-media-controls { background-color: hsl(0, 0%, 14%); } @@ -632,22 +629,24 @@ video::-webkit-media-controls-play-button { color: #fff; } +/* Container que engloba o player e o chat */ .live-container{ display: flex; - flex-direction: row; - + flex-direction: column; /* Padrão: empilha o player e o chat (telas pequenas) */ height: 70vh; + padding: 15px; width: 100%; } +/* Estilos do chat */ .chat { -display: flex; -flex-direction: column; -flex-grow: 1; -margin: 15px; -background-color: var(--background-color); -border-radius: 10px; -color: #fff; + display: flex; + flex-direction: column; + flex-grow: 1; + margin: 15px; + background-color: var(--background-color); + border-radius: 10px; + color: #fff; } .chat-container { @@ -682,6 +681,7 @@ color: #fff; .chat-line p { margin: 0; color: #fff; + overflow-wrap: break-word; } .username { @@ -714,6 +714,45 @@ color: #fff; background-color: #243b65; } +/* ===== Regras responsivas ===== */ + +/* Para telas grandes: layout em linha com chat à direita */ +@media (min-width: 768px) { + .live-container { + flex-direction: row; /* Player e chat lado a lado */ + align-items: stretch; /* Garante que ambos tenham a mesma altura */ + } + + .player-container { + flex-grow: 1; + margin: 15px; /* Opcional: ajuste de espaçamento */ + } + + .chat { + width: 400px; /* Largura fixa, semelhante à do chat da Twitch */ + height: 95%; /* Alinha a altura do chat à do contêiner (e do player) */ + margin: 15px; + } +} + +/* Para telas pequenas: layout em coluna com chat abaixo do player */ +@media (max-width: 767px) { + .live-container { + flex-direction: column; + height: auto; + } + + .player-container, .chat { + width: 100%; + margin: 15px 0; /* Espaçamento vertical */ + } + + .chat { + height: 500px; /* Altura ajustada para um tamanho adequado */ + } +} + + .page-aula{ font-family: var(--font-family); } @@ -780,4 +819,4 @@ color: #fff; } .content-aula a:hover { border-bottom-color: #007bff; /* Mostra a borda inferior ao passar o mouse */ -} \ No newline at end of file +} diff --git a/php/chat/relay.php b/php/chat/relay.php old mode 100644 new mode 100755 index 1613733..a1cafe7 --- a/php/chat/relay.php +++ b/php/chat/relay.php @@ -5,31 +5,38 @@ if (!isset($_GET['user'])) { } $user = preg_replace('/[^a-zA-Z0-9_-]/', '', $_GET['user']); + +// Verifica se a live está online (arquivo .mpd existe) +$mpdPath = "/var/www/html/stream/{$user}.mpd"; +if (!file_exists($mpdPath)) { + http_response_code(404); + exit("Live offline"); +} + header("Content-Type: text/event-stream"); header("Cache-Control: no-cache"); header("Connection: keep-alive"); $tmp_file = sys_get_temp_dir() . "/relay_chat_{$user}.txt"; +// Cria o arquivo se ainda não existir if (!file_exists($tmp_file)) { file_put_contents($tmp_file, ''); } -$last_modif = 0; +$lastMessage = ''; while (true) { clearstatcache(); - $current_modif = filemtime($tmp_file); + $currentMessage = trim(file_get_contents($tmp_file)); - if ($current_modif > $last_modif) { - $last_modif = $current_modif; - $data = file_get_contents($tmp_file); - echo "data: " . trim($data) . "\n\n"; + if ($currentMessage !== '' && $currentMessage !== $lastMessage) { + echo "data: " . $currentMessage . "\n\n"; ob_flush(); flush(); + $lastMessage = $currentMessage; } sleep(1); } ?> - diff --git a/php/chat/send.php b/php/chat/send.php old mode 100644 new mode 100755 index 7dda579..e37588b --- a/php/chat/send.php +++ b/php/chat/send.php @@ -1,11 +1,11 @@