diff --git a/webui/index.html b/webui/index.html
index aa34bef0..bdef4cfa 100644
--- a/webui/index.html
+++ b/webui/index.html
@@ -8066,6 +8066,9 @@
+
@@ -8076,6 +8079,10 @@
+
diff --git a/webui/static/media-player.js b/webui/static/media-player.js
index bb3ccc8d..23072eab 100644
--- a/webui/static/media-player.js
+++ b/webui/static/media-player.js
@@ -61,6 +61,12 @@ function initializeMediaPlayer() {
if (miniPrevBtn) miniPrevBtn.addEventListener('click', (e) => { e.stopPropagation(); playPreviousInQueue(); });
if (miniNextBtn) miniNextBtn.addEventListener('click', (e) => { e.stopPropagation(); playNextInQueue(); });
+ // Mini shuffle / repeat — share the modal handlers (which now sync both UIs)
+ const miniShuffleBtn = document.getElementById('mini-shuffle-btn');
+ const miniRepeatBtn = document.getElementById('mini-repeat-btn');
+ if (miniShuffleBtn) miniShuffleBtn.addEventListener('click', (e) => { e.stopPropagation(); handleNpShuffle(); });
+ if (miniRepeatBtn) miniRepeatBtn.addEventListener('click', (e) => { e.stopPropagation(); handleNpRepeat(); });
+
// Restore a previously-saved queue (does not auto-play)
npRestoreQueue();
}
@@ -2064,15 +2070,32 @@ function updateNpMuteIcon() {
if (muteBtn) muteBtn.classList.toggle('muted', npMuted);
}
+// Reflect shuffle/repeat state on BOTH the modal and mini-player buttons.
+function syncShuffleRepeatUI() {
+ const npShuffle = document.getElementById('np-shuffle-btn');
+ const miniShuffle = document.getElementById('mini-shuffle-btn');
+ if (npShuffle) npShuffle.classList.toggle('active', npShuffleOn);
+ if (miniShuffle) miniShuffle.classList.toggle('active', npShuffleOn);
+
+ const repeatOn = npRepeatMode !== 'off';
+ const repeatOne = npRepeatMode === 'one';
+ const npRepeat = document.getElementById('np-repeat-btn');
+ const miniRepeat = document.getElementById('mini-repeat-btn');
+ if (npRepeat) npRepeat.classList.toggle('active', repeatOn);
+ if (miniRepeat) miniRepeat.classList.toggle('active', repeatOn);
+ const npBadge = document.getElementById('np-repeat-one-badge');
+ const miniBadge = document.getElementById('mini-repeat-one-badge');
+ if (npBadge) npBadge.classList.toggle('hidden', !repeatOne);
+ if (miniBadge) miniBadge.style.display = repeatOne ? '' : 'none';
+}
+
function handleNpShuffle() {
npShuffleOn = !npShuffleOn;
- const btn = document.getElementById('np-shuffle-btn');
- if (btn) btn.classList.toggle('active', npShuffleOn);
+ syncShuffleRepeatUI();
updateNpPrevNextButtons();
}
function handleNpRepeat() {
- const badge = document.getElementById('np-repeat-one-badge');
if (npRepeatMode === 'off') {
npRepeatMode = 'all';
if (audioPlayer) audioPlayer.loop = false;
@@ -2083,9 +2106,7 @@ function handleNpRepeat() {
npRepeatMode = 'off';
if (audioPlayer) audioPlayer.loop = false;
}
- const btn = document.getElementById('np-repeat-btn');
- if (btn) btn.classList.toggle('active', npRepeatMode !== 'off');
- if (badge) badge.classList.toggle('hidden', npRepeatMode !== 'one');
+ syncShuffleRepeatUI();
updateNpPrevNextButtons();
}
diff --git a/webui/static/style.css b/webui/static/style.css
index e5d7a6b3..7ee3be99 100644
--- a/webui/static/style.css
+++ b/webui/static/style.css
@@ -693,6 +693,48 @@ body {
cursor: not-allowed;
}
+/* Mini shuffle / repeat toggle buttons (parity with the modal). Smaller than
+ nav buttons; accent when active; repeat-one shows a tiny badge. */
+.mini-toggle-btn {
+ position: relative;
+ width: 22px;
+ height: 22px;
+ border-radius: 50%;
+ background: transparent;
+ border: none;
+ color: rgba(255, 255, 255, 0.38);
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: color 0.18s ease, background 0.18s ease;
+ padding: 0;
+ flex-shrink: 0;
+}
+.mini-toggle-btn:hover {
+ color: rgba(255, 255, 255, 0.85);
+ background: rgba(255, 255, 255, 0.08);
+}
+.mini-toggle-btn.active {
+ color: rgb(var(--accent-light-rgb));
+}
+.mini-repeat-one {
+ position: absolute;
+ bottom: -1px;
+ right: -1px;
+ font-size: 8px;
+ font-weight: 800;
+ line-height: 1;
+ background: rgb(var(--accent-light-rgb));
+ color: #06140b;
+ border-radius: 50%;
+ width: 10px;
+ height: 10px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
/* Controls cluster in the mini player */
.mini-player-controls {
display: flex;