let isLooping = false; // Flag to manage loop state let isLoadingMusic = false; // Flag to manage loading state let currentPlaying = ''; // Store the filename of the currently playing music let trackList = []; // Store currently displayed track filenames let currentPage = 1; let totalPages = 0; let audio = new Audio(); window.onload = () => { // Attach click handlers for paging document.getElementById('prev-page').addEventListener('click', () => changePage(-1)); document.getElementById('next-page').addEventListener('click', () => changePage(1)); loadMusicList(); document.getElementById('search-bar').addEventListener('keyup', () => { currentPage = 1; // Reset to first page on new search loadMusicList(); }); document.getElementById('audio-player').style.display = 'none'; updatePageIndicator(); setupCustomAudioPlayer(); }; function changePage(direction) { currentPage += direction; loadMusicList(); } function updatePageIndicator(totalPages) { document.getElementById('page-indicator').textContent = `${currentPage}/${totalPages}`; } function debounce(func, delay) { let debounceTimer; return function() { const context = this; const args = arguments; clearTimeout(debounceTimer); debounceTimer = setTimeout(() => func.apply(context, args), delay); }; } function toggleLoop() { isLooping = !isLooping; document.getElementById('loop-toggle').textContent = `Loop: ${isLooping ? 'On' : 'Off'}`; const player = document.getElementById('audio-player'); player.loop = isLooping; } function updateNavigationVisibility(searchQuery, totalPages) { const navigation = document.getElementById('navigation'); if (searchQuery) { navigation.style.display = 'none'; // Hide navigation during search } else { navigation.style.display = 'flex'; // Show navigation when not searching document.getElementById('prev-page').disabled = currentPage <= 1; document.getElementById('next-page').disabled = currentPage >= totalPages; } } // Call loadMusicList when the search input changes document.getElementById('search-bar').addEventListener('keyup', debounce(() => { currentPage = 1; loadMusicList(); }, 500)); // Waits for 0.5s of inactivity after typing function loadMusicList() { const searchQuery = document.getElementById('search-bar').value.toLowerCase(); const params = new URLSearchParams({ page: currentPage }); if (searchQuery) { params.append('search', searchQuery); // Add search query to the request if it exists } // Disabling buttons and showing loading indicator before the request document.getElementById('prev-page').disabled = true; document.getElementById('next-page').disabled = true; const loaderContainer = document.getElementById('loader-container'); loaderContainer.innerHTML = ''; // Clears any existing loader elements if they are present const loaderElement = document.createElement('div'); loaderElement.classList.add('loader'); loaderContainer.appendChild(loaderElement); fetch(`/tracks?${params}`) .then(response => response.json()) .then(data => { const { tracks, total } = data; const musicList = document.getElementById('music-list'); musicList.innerHTML = ''; trackList = []; const totalPages = Math.ceil(total / 5); // Hide loading indicator loaderContainer.innerHTML = ''; // Re-enable buttons based on page state document.getElementById('prev-page').disabled = currentPage === 1; document.getElementById('next-page').disabled = currentPage === totalPages || searchQuery; tracks.forEach(track => { trackList.push(track.filename); const musicItem = createMusicItem(track); musicList.appendChild(musicItem); }); // Show/hide navigation based on whether there is a search query updatePageIndicator(totalPages); updateNavigationVisibility(searchQuery, totalPages); updatePlayingIndicator(); }); } function createMusicItem(track) { const musicItem = document.createElement('div'); musicItem.classList.add('music-item'); musicItem.setAttribute('data-filename', track.filename); const artworkImg = document.createElement('img'); artworkImg.src = track.artwork ? track.artwork : 'placeholder_art.png'; artworkImg.alt = 'Album Art'; artworkImg.classList.add('album-art'); const fileNameSpan = document.createElement('span'); fileNameSpan.textContent = track.filename; musicItem.append(artworkImg, fileNameSpan); // Bind the music item click to playMusic musicItem.addEventListener('click', () => playMusic(track.filename)); return musicItem; } function updatePlayingIndicator() { const musicItems = document.querySelectorAll('.music-item'); musicItems.forEach(item => { if (item.getAttribute('data-filename') === currentPlaying) { item.style.boxShadow = '0 0 10px rgba(255, 255, 255, 0.5)'; // Green box shadow } else { item.style.boxShadow = ''; // Remove box shadow from other items } }); } function setupCustomAudioPlayer() { // Play/Pause toggle document.getElementById('play-pause-btn').addEventListener('click', function() { if (audio.paused) { audio.play(); this.textContent = '❙❙'; // Update button text to "❙❙" } else { audio.pause(); this.textContent = '▶'; // Update button text to "▶" } }); // Update progress bar as the audio plays audio.addEventListener('timeupdate', function() { const progress = document.getElementById('progress-bar'); progress.value = (audio.currentTime / audio.duration) * 100; }); // Seek in the audio when the progress bar value changes document.getElementById('progress-bar').addEventListener('input', function() { const duration = audio.duration; audio.currentTime = (this.value * duration) / 100; }); // Mute toggle document.getElementById('mute-btn').addEventListener('click', function() { audio.muted = !audio.muted; this.textContent = audio.muted ? '🔊' : '🔇'; // Update button text based on mute state }); // Volume control document.getElementById('volume-control').addEventListener('input', function() { audio.volume = this.value / 100; }); // Initial volume (100%) audio.volume = 1.0; audio.addEventListener('timeupdate', function() { updateProgress(); }); // When audio metadata is loaded, update duration audio.addEventListener('loadedmetadata', function() { document.getElementById('duration').textContent = formatTime(audio.duration); }); } function updateProgress() { const progress = document.getElementById('progress-bar'); progress.value = (audio.currentTime / audio.duration) * 100; document.getElementById('current-time').textContent = formatTime(audio.currentTime); } function formatTime(seconds) { let minutes = Math.floor(seconds / 60); minutes = (minutes >= 10) ? minutes : "0" + minutes; seconds = Math.floor(seconds % 60); seconds = (seconds >= 10) ? seconds : "0" + seconds; return minutes + ":" + seconds; } function playMusic(fileName) { if (isLoadingMusic && fileName === currentPlaying) { console.log("This song is already loading."); return; } else if (!isLoadingMusic && fileName === currentPlaying) { console.log("This song is already playing."); return; } isLoadingMusic = true; currentPlaying = fileName; updatePlayingIndicator(); document.getElementById('audio-player').style.display = 'none'; // Hide custom player UI const loaderContainer = document.getElementById('loader-container'); loaderContainer.innerHTML = ''; const loaderElement = document.createElement('div'); loaderElement.classList.add('loader'); loaderContainer.appendChild(loaderElement); // Set the new source file for audio audio.src = `/music/${fileName}`; audio.load(); // Start loading the new source file audio.oncanplaythrough = () => { document.getElementById('audio-player').style.display = 'flex'; // Show custom player UI loaderContainer.innerHTML = ''; isLoadingMusic = false; document.getElementById('play-pause-btn').textContent = '❙❙'; // Update play/pause button audio.play(); // Start playback }; // Updated onended event handler within playMusic function audio.onended = () => { if (isLooping) { // Replay the current song audio.currentTime = 0; audio.play(); } else { const currentIndex = trackList.indexOf(currentPlaying); if (currentIndex !== -1 && currentIndex < trackList.length - 1) { playMusic(trackList[currentIndex + 1]); } } }; audio.onerror = () => { isLoadingMusic = false; alert(`Error loading the music: ${fileName}`); currentPlaying = ''; // Reset the current playing track }; }