From bfc0675f5a095ec86a4add552edcdbaaa04dc345 Mon Sep 17 00:00:00 2001 From: Ultradesu Date: Tue, 17 Mar 2026 17:21:15 +0000 Subject: [PATCH] Improve web UI --- furumi-server/src/web/player.html | 55 ++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/furumi-server/src/web/player.html b/furumi-server/src/web/player.html index b61931e..513a7bb 100644 --- a/furumi-server/src/web/player.html +++ b/furumi-server/src/web/player.html @@ -238,14 +238,15 @@ body { .queue-item .qi-info { flex: 1; overflow: hidden; } .queue-item .qi-title { font-size: 0.875rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .queue-item .qi-artist { font-size: 0.75rem; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } -.queue-item .qi-dur { font-size: 0.72rem; color: var(--text-muted); flex-shrink: 0; } -.queue-item .qi-remove { - opacity: 0; font-size: 0.8rem; color: var(--text-muted); - background: none; border: none; cursor: pointer; padding: 2px 5px; - border-radius: 4px; transition: all 0.15s; +.queue-item .qi-dur { font-size: 0.75rem; color: var(--text-muted); margin-left: auto; margin-right: 0.5rem; } +.qi-remove, .qi-locate { + background: none; border: none; font-size: 0.9rem; + color: var(--text-muted); cursor: pointer; padding: 0.3rem; + border-radius: 4px; transition: all 0.2s; opacity: 0; } -.queue-item:hover .qi-remove { opacity: 1; } -.queue-item .qi-remove:hover { color: var(--danger); } +.queue-item:hover .qi-remove, .queue-item:hover .qi-locate { opacity: 1; } +.qi-remove:hover { background: rgba(248,113,113,0.15); color: var(--danger); } +.qi-locate:hover { background: rgba(124,106,247,0.15); color: var(--primary); } .queue-item.dragging { opacity: 0.5; background: var(--bg-active); } .queue-item.drag-over { border-top: 2px solid var(--accent); margin-top: -2px; } @@ -772,7 +773,7 @@ async function loadMeta(track) { if (res.ok) { const meta = await res.json(); metaCache[track.path] = meta; - track.meta = meta; + if (queue[idx]) { queue[idx].meta = meta; } updateNowPlaying(track); renderQueue(); } @@ -840,6 +841,7 @@ function renderQueue() {
${esc(artist)}
${dur} + `; div.addEventListener('click', () => playIndex(origIdx)); @@ -878,22 +880,45 @@ function scrollQueueToActive() { } function removeFromQueue(origIdx, ev) { - ev.stopPropagation(); + if (ev) ev.stopPropagation(); + const isPlaying = origIdx === queueIndex; + + if (isPlaying) { + queueIndex = -1; + audio.pause(); + audio.src = ''; + updateNowPlaying(); + } else if (queueIndex > origIdx) { + queueIndex--; + } + queue.splice(origIdx, 1); - if (queueIndex === origIdx) { queueIndex = -1; audio.pause(); audio.src = ''; } - else if (queueIndex > origIdx) queueIndex--; if (shuffle) { const sidx = shuffleOrder.indexOf(origIdx); if (sidx !== -1) shuffleOrder.splice(sidx, 1); for (let i = 0; i < shuffleOrder.length; i++) { - if (shuffleOrder[i] > origIdx) shuffleOrder[i]--; + if (shuffleOrder[i] > origIdx) shuffleOrder[i]--; } } renderQueue(); } +function locateTrack(idx, ev) { + if (ev) ev.stopPropagation(); + const track = queue[idx]; + if (!track) return; + const parts = track.path.split('/'); + parts.pop(); // remove filename + const folder = parts.join('/'); + navigate(folder); + if (window.innerWidth <= 768) { + const sidebar = document.getElementById('sidebar'); + if (!sidebar.classList.contains('open')) toggleSidebar(); + } +} + function moveQueueItem(fromPos, toPos) { if (fromPos === toPos) return; @@ -1061,6 +1086,12 @@ const trackPath = urlParams.get('t'); if (trackPath) { const parts = trackPath.split('/'); const name = parts[parts.length - 1]; + + // Navigate to folder + const folderParts = [...parts]; + folderParts.pop(); // remove name + navigate(folderParts.join('/')); + addToQueue(trackPath, name, true); }