var previousTextLength; var config_data; var unread_words = 0; async function loadSentences(alertIfNew = false, increaseUnread = true) { fetch("./data/sentences.txt", {headers: {"Cache-Control": "no-cache, no-store"}}) .then((response) => { return response.text().then((text) => { document.querySelector(".sentences").innerHTML = text; if (text.length > previousTextLength) { if (increaseUnread) { document.getElementsByTagName("title")[0].innerText = "(" + ++unread_words + ") " + (config_data.title ? config_data.title : "One Word Each") ; } if (alertIfNew) { var newtxt = text.substring(previousTextLength, text.length); //var parser = new DOMParser(); //var xmltxt = parser.parseFromString(newtxt, "text/xml"); //var newword = xmltxt.getElementsByTagName("span")[0].innerHTML.trim(); var htmltxt = document.createElement("html"); htmltxt.innerHTML = newtxt; var newword = htmltxt.getElementsByTagName("span")[0].innerHTML.trim(); if (Notification.permission == 'granted') { displayNotification(newword); } else { alert("Neues Wort: " + newword); } } } previousTextLength = text.length; // color var spans = document.querySelector(".sentences").getElementsByTagName("span"); if (spans.length >= config_data.users.length) { var histurnspan = spans[spans.length - config_data.users.length]; //console.log(histurnspan.getAttribute("style")); document.getElementById("wordinput").setAttribute("style", histurnspan.getAttribute("style")); } else { console.error('Not enough spans available for users.'); } initializeLoginArea(); }); }); } async function loadConfig() { fetch("./data/config.json", {headers: {"Cache-Control": "no-cache, no-store"}}).then((response) => { return response.text().then((text) => { config_data = JSON.parse(text); setInterval(loadSentences, 5000, ((typeof config_data.notifications !== "undefined") ? config_data.notifications : true)); }); }).catch(() => { config_data = Object(); // leave empty }); } function getUsernameFromCookie() { // Split the document.cookie string into individual cookie key-value pairs var cookies = document.cookie.split(';').map(cookie => cookie.trim()); // Loop through the cookies to find the 'owe_user' cookie for (var i = 0; i < cookies.length; i++) { var cookie = cookies[i]; if (cookie.startsWith('owe_user=')) { // Extract the username from the 'owe_user' cookie return decodeURIComponent(cookie.substring('owe_user='.length)); } } // Return null if the 'owe_user' cookie is not set return null; } function deleteUsernameCookie() { // Set the 'owe_user' cookie to expire by setting its expiration date to a time in the past document.cookie = 'owe_user=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=.;'; } function onReloadClicked() { loadSentences(); document.querySelector("#but-reload").style.visibility = "hidden"; setTimeout(function(){ document.querySelector("#but-reload").style.visibility = "initial"; }, 100); } async function sendWord() { try { var data = new FormData(); var wordInput = document.getElementById("wordinput"); data.append('submitted', encodeURI(wordInput.value)); // Use await to get the next player asynchronously var nextPlayer = await getNextPlayer(); data.append('user', nextPlayer); const Http = new XMLHttpRequest(); Http.open('POST', '.'); Http.onreadystatechange = (e) => { wordInput.value = ""; loadSentences(false, false); resetUnread(); }; // Set the 'owe_user' cookie with the value obtained from getNextPlayer document.cookie = `owe_user=${encodeURIComponent(nextPlayer)}; path=.`; Http.send(data); } catch (error) { console.error("Error in sendWord:", error); } } function displayNotification(word) { if (Notification.permission == 'granted') { navigator.serviceWorker.getRegistration().then(function(reg) { reg.showNotification("Neuer Beitrag auf " + (config_data.title ? config_data.title : "OWE"), { body: word, icon: (config_data.logo? config_data.logo.image_path : "OWE_Logo.png"), requireInteraction: true }); }); } } function toggleArchives() { archives = document.getElementsByClassName("archive_links")[0]; if (archives.style.display == "none") { archives.style.display = "flex"; if (config_data.archive) { document.getElementById("archive_image").src = config_data.archive.logo_path_open } return; } archives.style.display = "none"; if (config_data.archive) { document.getElementById("archive_image").src = config_data.archive.logo_path_closed } } function resetUnread() { unread_words = 0; document.getElementsByTagName("title")[0].innerText = (config_data.title ? config_data.title : "One Word Each"); } function getNextPlayer() { var sentencesDiv = document.querySelector(".sentences"); var spans = sentencesDiv.getElementsByTagName("span"); if (spans.length > 0) { var lastSpan = spans[spans.length - 1]; var lastPlayer = lastSpan.dataset.user; var idxNext = (config_data.users.indexOf(lastPlayer) + 1) % config_data.users.length; return config_data.users[idxNext]; } else { // If there are no spans, determine the next user from the archive file var archiveFileUrl = getArchiveFileUrl(); // Replace with the actual function that returns the archive file URL return getLastUserFromArchive(archiveFileUrl) .then(lastUser => { if (lastUser) { // Calculate the next user's index based on the list of users var idxNext = (config_data.users.indexOf(lastUser) + 1) % config_data.users.length; return config_data.users[idxNext]; } else { // Handle the case when the archive file is empty or contains no spans console.error("Archive file is empty or contains no spans."); return null; } }) .catch(error => { console.error("Error fetching archive file:", error); return null; }); } } function getLastUserFromArchive(archiveFileUrl) { // Fetch the last span from the archive file and extract the username return getLastSpanFromArchive(archiveFileUrl) .then(lastArchiveSpan => { if (lastArchiveSpan) { return lastArchiveSpan.dataset.user; } else { // Handle the case when the archive file is empty or contains no spans console.error("Archive file is empty or contains no spans."); return null; } }) .catch(error => { console.error("Error fetching archive file:", error); return null; }); } function getLastSpanFromArchive(archiveFileUrl) { // Make an asynchronous request to fetch the content of the archive file return fetch(archiveFileUrl) .then(response => response.text()) .then(htmlContent => { // Parse the HTML content to get the last span var parser = new DOMParser(); var doc = parser.parseFromString(htmlContent, 'text/html'); var archiveSpans = doc.querySelectorAll("span"); if (archiveSpans.length > 0) { return archiveSpans[archiveSpans.length - 1]; } else { // Return null if the archive file is empty or contains no spans return null; } }); } // bullshit implementation: function getArchiveFileUrl() { return "./data/sentences-archive-25-nov-23-26-jan-24.txt"; } async function getTimeSinceLast() { var sentencesDiv = document.querySelector(".sentences"); var spans = sentencesDiv.getElementsByTagName("span"); if (spans.length > 0) { var lastSpan = spans[spans.length - 1]; var lastTime = lastSpan.dataset.time; return Date.now() / 1e3 - lastTime; // in seconds } else { // If there are no spans, determine the last time from the archive file var archiveFileUrl = getArchiveFileUrl(); // Replace with the actual function that returns the archive file URL return getLastTimeFromArchive(archiveFileUrl); } } async function getLastTimeFromArchive(archiveFileUrl) { try { // Fetch the last span from the archive file var lastSpan = await getLastSpanFromArchive(archiveFileUrl); if (lastSpan) { var lastTime = lastSpan.dataset.time; return Date.now() / 1e3 - lastTime; // in seconds } else { // Handle the case when the archive file is empty or contains no spans console.error("Archive file is empty or contains no spans."); return null; } } catch (error) { console.error("Error fetching archive file:", error); return null; } } function logoutUser() { deleteUsernameCookie(); initializeLoginArea(); // Reload everything in the login area } async function initializeLoginArea() { var loginArea = document.getElementById('login_area'); var sendButton = document.getElementById('sendbut'); sendButton.style.display = "unset" var wordInput = document.getElementById('wordinput'); wordInput.disabled = false; // Use async/await to wait for the result of getNextPlayer try { var loggedInPlayer = getUsernameFromCookie(); var nextPlayer = await getNextPlayer(); var relative_time = await getTimeSinceLast(); // Clear the login area loginArea.innerHTML = ""; if (loggedInPlayer != null) { loginArea.innerHTML += "Du bist angemeldet als " + loggedInPlayer + "." loginArea.innerHTML += "
\n"; if (loggedInPlayer != nextPlayer) { sendButton.style.display = "none"; wordInput.disabled = true; } } loginArea.innerHTML += nextPlayer + " ist dran!
\n"; var days = Math.floor(relative_time / (3600 * 24)); var hours = Math.floor(relative_time / 3600) % 24; var minutes = Math.floor(relative_time / 60) % 60; loginArea.innerHTML += "Schon seit " + days + " Tagen, " + hours + " Stunden und " + minutes + " Minuten!"; } catch (error) { // Handle any errors that may occur in the getNextPlayer function console.error("Error in initializeLoginArea:", error); } } window.onfocus = resetUnread; //setTimeout(loadSentences, 500); loadConfig(); loadSentences(); var input = document.getElementById("wordinput"); input.focus(); // Execute a function when the user releases a key on the keyboard input.addEventListener("keyup", function(event) { // Number 13 is the "Enter" key on the keyboard if (event.keyCode === 13) { // Cancel the default action, if needed event.preventDefault(); // Trigger the button element with a click document.getElementById("sendbut").click(); } }); var isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); if (!isMobile) { archives = document.getElementsByClassName("archive_links")[0]; sentences = document.getElementsByClassName("sentences")[0]; scrollbox = document.getElementsByClassName("scrollbox")[0]; scrollbox.style.flexDirection = "row"; sentences.style.fontSize = "x-large"; archives.style.order = "1"; document.getElementById("sidebar_button").style.display = "inline"; } if ('serviceWorker' in navigator) { navigator.serviceWorker.register('./service-worker.js') .then(function(registration) { console.log('Registration successful, scope is:', registration.scope); }) .catch(function(error) { console.log('Service worker registration failed, error:', error); }); } navigator.serviceWorker.register('./service-worker.js', { scope: './' }); navigator.serviceWorker.register('./service-worker.js', { scope: '.' }); Notification.requestPermission(function(status) { console.log('Notification permission status:', status); });