feat: połączenie przycisków zapętlania w jeden przycisk z cyklem Wyłączone -> Kolejka -> Utwór (styl YT Music/Spotify)

This commit is contained in:
mmacierzanka committed 2026-07-04 16:41:17 +02:00
1 parent 2a399364d8
commit ab6f16b57d
4 files changed
+86 -59

No files matched your search

+38 -45
View File
@@ -31,7 +31,6 @@ const playPauseIcon = document.getElementById('play-pause-icon');
const btnSkip = document.getElementById('btn-skip');
const btnStop = document.getElementById('btn-stop');
const btnLoop = document.getElementById('btn-loop');
const btnLoopPlaylist = document.getElementById('btn-loop-playlist');
const vinylRecord = document.getElementById('vinyl-record');
const musicWave = document.getElementById('music-wave');
const volumeSlider = document.getElementById('volume-slider');
@@ -142,9 +141,6 @@ function bindEvents() {
btnSkip.addEventListener('click', skipTrack);
btnStop.addEventListener('click', stopPlayback);
btnLoop.addEventListener('click', toggleLoop);
if (btnLoopPlaylist) {
btnLoopPlaylist.addEventListener('click', toggleLoopPlaylist);
}
// Volume slider
volumeSlider.addEventListener('input', (e) => {
@@ -375,28 +371,39 @@ function updateUI(status) {
updateVolumeIcon(status.volume);
}
// 5. Loop State
if (status.loop_single) {
loopBadge.style.display = 'flex';
btnLoop.classList.add('active');
btnLoop.style.background = 'var(--primary)';
btnLoop.style.color = 'var(--bg-card)';
} else {
loopBadge.style.display = 'none';
btnLoop.classList.remove('active');
btnLoop.style.background = '';
btnLoop.style.color = '';
}
// 5. Loop State (Combined toggle: Off -> Playlist -> Single)
let loopMode = 'off';
if (status.loop_single) loopMode = 'single';
else if (status.loop_playlist) loopMode = 'playlist';
if (btnLoopPlaylist) {
if (status.loop_playlist) {
btnLoopPlaylist.classList.add('active');
btnLoopPlaylist.style.background = 'var(--primary)';
btnLoopPlaylist.style.color = 'var(--bg-card)';
if (btnLoop.dataset.loopMode !== loopMode) {
btnLoop.dataset.loopMode = loopMode;
if (loopMode === 'single') {
btnLoop.innerHTML = '<i data-lucide="repeat-1"></i>';
btnLoop.classList.add('active');
btnLoop.style.background = 'var(--primary)';
btnLoop.style.color = 'var(--bg-card)';
btnLoop.title = "Zapętlenie: jeden utwór (kliknij, aby wyłączyć)";
loopBadge.style.display = 'flex';
loopBadge.innerHTML = '<i data-lucide="repeat-1"></i> Zapętlenie utworu';
} else if (loopMode === 'playlist') {
btnLoop.innerHTML = '<i data-lucide="repeat"></i>';
btnLoop.classList.add('active');
btnLoop.style.background = 'var(--primary)';
btnLoop.style.color = 'var(--bg-card)';
btnLoop.title = "Zapętlenie: cała kolejka (kliknij, aby zapętlić jeden utwór)";
loopBadge.style.display = 'flex';
loopBadge.innerHTML = '<i data-lucide="repeat"></i> Zapętlenie kolejki';
} else {
btnLoopPlaylist.classList.remove('active');
btnLoopPlaylist.style.background = '';
btnLoopPlaylist.style.color = '';
btnLoop.innerHTML = '<i data-lucide="repeat"></i>';
btnLoop.classList.remove('active');
btnLoop.style.background = '';
btnLoop.style.color = '';
btnLoop.title = "Zapętlenie: wyłączone (kliknij, aby zapętlić kolejkę)";
loopBadge.style.display = 'none';
}
if (window.lucide) {
lucide.createIcons();
}
}
@@ -700,35 +707,21 @@ async function stopPlayback() {
}
}
// Toggle Loop State
// Toggle Loop State (Cycle: Off -> Playlist -> Single -> Off)
async function toggleLoop() {
if (!currentStatus) return;
const nextState = !currentStatus.loop_single;
try {
const res = await fetch('/api/loop', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ loop: nextState })
});
if (!res.ok) throw new Error('Loop failed');
showToast(nextState ? 'Zapętlanie utworu włączone' : 'Zapętlanie utworu wyłączone', 'info');
const res = await fetch('/api/loop_cycle', { method: 'POST' });
if (!res.ok) throw new Error('Loop cycle failed');
const data = await res.json();
if (data.mode === 'playlist') showToast('Zapętlanie kolejki włączone', 'info');
else if (data.mode === 'single') showToast('Zapętlanie utworu włączone', 'info');
else showToast('Zapętlanie wyłączone', 'info');
} catch (err) {
showToast('Błąd ustawiania pętli', 'error');
}
}
// Toggle Playlist Loop State
async function toggleLoopPlaylist() {
try {
const res = await fetch('/api/loop_playlist', { method: 'POST' });
const data = await res.json();
if (!res.ok) throw new Error(data.detail || 'Błąd zapętlania');
showToast(data.loop_playlist ? 'Włączono zapętlanie całej kolejki (playlisty)!' : 'Wyłączono zapętlanie kolejki.', 'info');
} catch (err) {
showToast('Nie udało się zmienić trybu zapętlania', 'error');
}
}
// Set Volume
async function setVolume(vol) {
try {