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