hannabox/web/script.js

331 lines
10 KiB
JavaScript

setInterval(getState, 4000);
setInterval(updateProgress, 500); // Update progress every second
// Get the <li> elements
var liElements = document.querySelectorAll('ul li');
var lastChange = 0;
var lastStateUpdateTime = Date.now();
var songStartTime = 0;
var currentSongLength = 0;
var isPlaying = false;
var userIsInteracting = false; // Flag to track user interaction with the slider
// Add click event listener to each <li> element
liElements.forEach(function(li) {
li.addEventListener('click', function() {
//var liText = this.innerText;
var id = this.dataset.id;
playSongById(id);
});
});
function simpleGetCall(endpoint) {
var xhr = new XMLHttpRequest();
xhr.open("GET", "/" + endpoint, true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
getState(); // Fetch the latest state right after the button action
}
};
xhr.send();
}
function postValue(endpoint,value) {
var xhr = new XMLHttpRequest();
xhr.open("POST", "/" + endpoint, true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
xhr.send("value="+encodeURIComponent(value));
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
getState(); // Fetch the latest state right after the button action
}
};
}
function getState() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
var state = JSON.parse(xhr.response);
isPlaying = state['playing'];
if (isPlaying) {
songStartTime = Date.now() - state['time'] * 1000;
currentSongLength = state['length'] * 1000;
}
lastStateUpdateTime = Date.now();
displayState(state);
}
}
xhr.open("GET","/state", true);
xhr.send();
}
function updateProgress() {
if (isPlaying && !userIsInteracting) { // Check if user is not interacting
var elapsedTime = Date.now() - songStartTime;
if (elapsedTime >= currentSongLength) {
elapsedTime = currentSongLength;
isPlaying = false; // Stop updating if the song has ended
}
var progressElement = document.getElementById('progressSlider');
progressElement.value = elapsedTime / 1000; // Convert to seconds
document.getElementById("progressLabel").innerHTML = Math.floor(elapsedTime / 1000);
}
}
function displayState(state) {
document.getElementById("state").innerHTML = state['title'];
document.getElementById("progressLabel").innerHTML = state['time'];
document.getElementById("voltage").innerHTML = state['voltage']+' mV';
document.getElementById("heap").innerHTML = state['heap']+' bytes free heap';
document.getElementById("uid").innerHTML = 'Last NFC ID: '+state['uid'];
/* ==== Autofill convenience fields ==== */
var fm = document.getElementById('fileManager');
if (state['filepath'] && fm.style.display == 'none') {
document.getElementById('moveFrom').value = state['filepath'];
document.getElementById('deleteFileName').value = state['filepath'];
document.getElementById('song').value = state['filepath'];
}
if (state['uid']) {
document.getElementById('rfid').value = state['uid'];
}
var elements = document.getElementsByClassName('play-button');
var btn = elements[0];
if (state['playing']) {
btn.classList.add('paused');
} else {
btn.classList.remove('paused');
}
if (Date.now()-lastChange>1200) {
var progress = document.getElementById('progressSlider');
progress.value = state['time'];
progress.max = state['length'];
var volume = document.getElementById('volumeSlider');
volume.value = state['volume'];
}
updateProgress();
}
function playSongById(id) {
var url = "/playbyid";
var params = "id="+id;
var http = new XMLHttpRequest();
http.open("GET", url+"?"+params, true);
http.onreadystatechange = function()
{
if(http.readyState == 4 && http.status == 200) {
getState();
}
}
http.send(null);
}
function playNamedSong(song) {
var xhr = new XMLHttpRequest();
xhr.open("POST", "/playnamed");
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
//application/x-www-form-urlencoded
var body = song;
xhr.send("title="+encodeURIComponent(body));
}
function editMapping() {
var rfid = document.getElementById('rfid').value;
var song = document.getElementById('song').value;
var xhr = new XMLHttpRequest();
xhr.open("POST", "/edit_mapping", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
xhr.send("rfid=" + encodeURIComponent(rfid) + "&song=" + encodeURIComponent(song));
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
alert("Mapping updated successfully!");
}
};
}
// Validate file before upload
function validateFile(file) {
var maxSize = 50 * 1024 * 1024; // 50MB limit
var allowedTypes = ['audio/mpeg', 'audio/wav', 'audio/flac', 'audio/mp4', 'audio/ogg'];
var allowedExtensions = ['.mp3', '.wav', '.flac', '.m4a', '.ogg'];
if (file.size > maxSize) {
return 'File too large. Maximum size is 50MB.';
}
var fileName = file.name.toLowerCase();
var hasValidExtension = allowedExtensions.some(ext => fileName.endsWith(ext));
if (!hasValidExtension) {
return 'Invalid file type. Only audio files (.mp3, .wav, .flac, .m4a, .ogg) are allowed.';
}
return null; // No error
}
// Handle form submission with AJAX to show upload status
document.getElementById('uploadForm').addEventListener('submit', function(event) {
event.preventDefault(); // Prevent the default form submit
var fileInput = document.getElementById('uploadFile');
var file = fileInput.files[0];
if (!file) {
alert('Please select a file to upload.');
return;
}
var validationError = validateFile(file);
if (validationError) {
alert(validationError);
return;
}
var form = event.target;
var formData = new FormData(form);
var uploadButton = document.getElementById('uploadButton');
var uploadStatus = document.getElementById('uploadStatus');
var uploadProgress = document.getElementById('uploadProgress');
var progressFill = document.getElementById('progressFill');
var progressText = document.getElementById('progressText');
// Disable upload button and show progress
uploadButton.disabled = true;
uploadButton.value = 'Uploading...';
uploadProgress.style.display = 'block';
uploadStatus.innerHTML = 'Preparing upload...';
var xhr = new XMLHttpRequest();
xhr.open('POST', '/upload', true);
xhr.upload.onloadstart = function() {
uploadStatus.innerHTML = 'Upload started...';
};
xhr.upload.onprogress = function(event) {
if (event.lengthComputable) {
var percentComplete = Math.round((event.loaded / event.total) * 100);
progressFill.style.width = percentComplete + '%';
progressText.innerHTML = percentComplete + '%';
uploadStatus.innerHTML = 'Uploading: ' + percentComplete + '% (' +
Math.round(event.loaded / 1024) + 'KB / ' +
Math.round(event.total / 1024) + 'KB)';
}
};
xhr.upload.onerror = function() {
uploadStatus.innerHTML = 'Upload failed due to network error.';
resetUploadForm();
};
xhr.upload.onabort = function() {
uploadStatus.innerHTML = 'Upload was cancelled.';
resetUploadForm();
};
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) { // Request is done
if (xhr.status >= 200 && xhr.status < 300) { // Success status code range
uploadStatus.innerHTML = 'Upload completed successfully!';
progressFill.style.width = '100%';
progressText.innerHTML = '100%';
setTimeout(function() {
alert('File uploaded successfully!');
location.reload(); // Reload to get updated playlist
}, 1000);
} else {
var errorMsg = xhr.responseText || 'Unknown error occurred';
uploadStatus.innerHTML = 'Upload failed: ' + errorMsg;
alert('Upload failed: ' + errorMsg);
resetUploadForm();
}
}
};
xhr.send(formData); // Send the form data using XMLHttpRequest
});
function resetUploadForm() {
var uploadButton = document.getElementById('uploadButton');
var uploadProgress = document.getElementById('uploadProgress');
var progressFill = document.getElementById('progressFill');
var progressText = document.getElementById('progressText');
uploadButton.disabled = false;
uploadButton.value = 'Upload';
uploadProgress.style.display = 'none';
progressFill.style.width = '0%';
progressText.innerHTML = '0%';
// Clear file input
document.getElementById('uploadFile').value = '';
}
/* ================= File Manager Functions ================= */
function toggleFileManager() {
var fm = document.getElementById('fileManager');
if (fm.style.display === 'none' || fm.style.display === '') {
fm.style.display = 'block';
} else {
fm.style.display = 'none';
}
}
function moveFile() {
var from = document.getElementById('moveFrom').value.trim();
var to = document.getElementById('moveTo').value.trim();
if (!from || !to) {
alert('Please provide both source and destination paths.');
return;
}
var xhr = new XMLHttpRequest();
xhr.open('GET', '/move_file?from=' + encodeURIComponent(from) + '&to=' + encodeURIComponent(to), true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
alert('File moved successfully.');
location.reload();
} else {
alert('Move failed: ' + (xhr.responseText || 'Unknown error'));
}
}
};
xhr.send();
}
function deleteFileOnServer() {
var filename = document.getElementById('deleteFileName').value.trim();
if (!filename) {
alert('Please provide filename to delete.');
return;
}
if (!confirm('Are you sure you want to delete ' + filename + '?')) {
return;
}
var xhr = new XMLHttpRequest();
xhr.open('GET', '/delete_file?filename=' + encodeURIComponent(filename), true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
alert('File deleted successfully.');
location.reload();
} else {
alert('Delete failed: ' + (xhr.responseText || 'Unknown error'));
}
}
};
xhr.send();
}