cleanup js

This commit is contained in:
lelo 2025-03-24 11:40:56 +01:00
parent 7d938c046a
commit 576f6f9bc1
2 changed files with 74 additions and 60 deletions

View File

@ -226,4 +226,7 @@ footer {
#reload-button svg.rotate {
animation: rotate-icon 0.5s linear;
transition: opacity 1s ease;
opacity: 0;
cursor: auto;
}

View File

@ -175,15 +175,21 @@ function attachEventListeners() {
});
});
// Cache common DOM elements
const nowPlayingInfo = document.getElementById('nowPlayingInfo');
const audioPlayer = document.getElementById('globalAudio');
const playerButton = document.querySelector('.player-button');
const audioPlayerContainer = document.getElementById('audioPlayerContainer');
const footer = document.querySelector('footer');
// Global variable to store the current fetch's AbortController.
let currentFetchController = null;
document.querySelectorAll('.play-file').forEach(link => {
link.addEventListener('click', async function (event) {
event.preventDefault();
const fileType = this.getAttribute('data-file-type');
const relUrl = this.getAttribute('data-url');
const nowPlayingInfo = document.getElementById('nowPlayingInfo');
const { fileType, url: relUrl, index } = this.dataset;
// Remove the class from all file items.
document.querySelectorAll('.file-item').forEach(item => {
@ -191,57 +197,63 @@ document.querySelectorAll('.play-file').forEach(link => {
});
if (fileType === 'music') {
const idx = this.getAttribute('data-index');
const audioPlayer = document.getElementById('globalAudio');
const playerButton = document.querySelector('.player-button');
// Update the current music index.
currentMusicIndex = index !== undefined ? parseInt(index) : -1;
// Update currentMusicIndex based on the clicked element.
currentMusicIndex = idx !== null ? parseInt(idx) : -1;
// Display the audio player container.
audioPlayerContainer.style.display = "block";
// Show the audio player container.
document.getElementById('audioPlayerContainer').style.display = "block"
// Add the class to the clicked file item's parent.
// Mark the clicked item as currently playing.
this.closest('.file-item').classList.add('currently-playing');
// Abort any previous fetch if it is still running.
// Abort any previous fetch if still running.
if (currentFetchController) {
currentFetchController.abort();
}
// Create a new AbortController for the current fetch.
currentFetchController = new AbortController();
// Pause the audio and clear its source.
audioPlayer.pause();
audioPlayer.src = ''; // Clear existing source.
// only show this if it takes longer. avoid flicker
let loaderTimeout = setTimeout(() => {
audioPlayer.src = '';
// Set a timeout to display a loader message if needed.
const loaderTimeout = setTimeout(() => {
playerButton.innerHTML = playIcon;
nowPlayingInfo.textContent = "Wird geladen...";
}, 500);
document.querySelector('footer').style.display = 'flex';
const mediaUrl = '/media/' + relUrl;
footer.style.display = 'flex';
const mediaUrl = `/media/${relUrl}`;
try {
// Pass the signal to the fetch so it can be aborted.
// Perform a HEAD request to verify media availability.
const response = await fetch(mediaUrl, { method: 'HEAD', signal: currentFetchController.signal });
clearTimeout(loaderTimeout); // done loading. stop timeout
clearTimeout(loaderTimeout);
if (response.status === 403) {
nowPlayingInfo.textContent = "Fehler: Zugriff verweigert.";
window.location.href = '/'; // Redirect if forbidden.
window.location.href = '/';
return;
} else if (!response.ok) {
nowPlayingInfo.textContent = `Fehler: Unerwarteter Status (${response.status}).`;
console.error('Unexpected response status:', response.status);
} else {
return;
}
// Set the media URL, load, and play the audio.
audioPlayer.src = mediaUrl;
audioPlayer.load();
audioPlayer.play();
await audioPlayer.play();
playerButton.innerHTML = pauseIcon;
// Process file path for display.
const pathParts = relUrl.split('/');
const folderName = pathParts[pathParts.length - 2];
const fileName = pathParts.pop();
const pathStr = pathParts.join('/');
// write into hardware player
// Update Media Session metadata if available.
if ('mediaSession' in navigator) {
navigator.mediaSession.metadata = new MediaMetadata({
title: currentMusicFiles[currentMusicIndex].title,
@ -250,24 +262,26 @@ document.querySelectorAll('.play-file').forEach(link => {
{ src: '/static/icons/logo-192x192.png', sizes: '192x192', type: 'image/png' }
]
});
};
nowPlayingInfo.innerHTML = pathStr.replace(/\//g, ' > ') + '<br><span style="font-size: larger; font-weight: bold;">' + fileName.replace('.mp3', '') + '</span>';
// Delay preloading to avoid blocking playback
}
nowPlayingInfo.innerHTML = pathStr.replace(/\//g, ' > ') +
'<br><span style="font-size: larger; font-weight: bold;">' +
fileName.replace('.mp3', '') + '</span>';
// Delay preloading to avoid blocking playback.
setTimeout(preload_audio, 1000);
};
} catch (error) {
// If the fetch was aborted, error.name will be 'AbortError'.
if (error.name === 'AbortError') {
console.log('Previous fetch aborted.');
} else {
console.error('Error fetching media:', error);
nowPlayingInfo.textContent = "Fehler: Netzwerkproblem oder ungültige URL.";
};
};
}
}
} else if (fileType === 'image') {
// Open the gallery modal for image files.
openGalleryModal(relUrl);
};
}
});
});
@ -341,23 +355,20 @@ function reloadDirectory() {
// Force reflow to reset the animation
void reloadBtnSVG.offsetWidth;
reloadBtnSVG.classList.add("rotate");
// Gradually fade out the button by reducing opacity over 500ms
setTimeout(() => {
reloadBtnSVG.classList.remove("rotate");
reloadBtn.style.transition = 'opacity 0.5s ease';
reloadBtn.style.opacity = '0';
isReloadButtonVisible = false; // Update the visibility status.
}, 500);
isReloadButtonVisible = false;
// Gradually fade back in after 10 seconds
setTimeout(() => {
reloadBtnSVG.classList.remove("rotate");
reloadBtn.style.transition = 'opacity 0.5s ease';
reloadBtn.style.opacity = '1';
isReloadButtonVisible = true; // Update the visibility status.
reloadBtn.style.pointer = 'cursor';
isReloadButtonVisible = true;
}, 10000);
}
if ('mediaSession' in navigator) {
// Handler for the play action