diff --git a/core/audiodb_worker.py b/core/audiodb_worker.py index ae8de9af..c1074559 100644 --- a/core/audiodb_worker.py +++ b/core/audiodb_worker.py @@ -96,10 +96,13 @@ class AudioDBWorker: is_actually_running = self.running and (self.thread is not None and self.thread.is_alive()) + is_idle = is_actually_running and not self.paused and self.stats['pending'] == 0 and self.current_item is None + return { 'enabled': True, 'running': is_actually_running and not self.paused, 'paused': self.paused, + 'idle': is_idle, 'current_item': self.current_item, 'stats': self.stats.copy(), 'progress': progress diff --git a/core/deezer_worker.py b/core/deezer_worker.py index d02fc4b7..488da00c 100644 --- a/core/deezer_worker.py +++ b/core/deezer_worker.py @@ -96,10 +96,13 @@ class DeezerWorker: is_actually_running = self.running and (self.thread is not None and self.thread.is_alive()) + is_idle = is_actually_running and not self.paused and self.stats['pending'] == 0 and self.current_item is None + return { 'enabled': True, 'running': is_actually_running and not self.paused, 'paused': self.paused, + 'idle': is_idle, 'current_item': self.current_item, 'stats': self.stats.copy(), 'progress': progress diff --git a/core/musicbrainz_worker.py b/core/musicbrainz_worker.py index fcb3e1cf..683d4740 100644 --- a/core/musicbrainz_worker.py +++ b/core/musicbrainz_worker.py @@ -92,10 +92,13 @@ class MusicBrainzWorker: # Check if thread is actually alive (in case it crashed) is_actually_running = self.running and (self.thread is not None and self.thread.is_alive()) + is_idle = is_actually_running and not self.paused and self.stats['pending'] == 0 and self.current_item is None + return { 'enabled': True, 'running': is_actually_running and not self.paused, 'paused': self.paused, + 'idle': is_idle, 'current_item': self.current_item, 'stats': self.stats.copy(), 'progress': progress diff --git a/webui/static/script.js b/webui/static/script.js index 43ac560c..6977733f 100644 --- a/webui/static/script.js +++ b/webui/static/script.js @@ -35141,8 +35141,10 @@ async function updateMusicBrainzStatus() { if (!button) return; // Update button state classes - button.classList.remove('active', 'paused'); - if (data.running && !data.paused) { + button.classList.remove('active', 'paused', 'complete'); + if (data.idle) { + button.classList.add('complete'); + } else if (data.running && !data.paused) { button.classList.add('active'); } else if (data.paused) { button.classList.add('paused'); @@ -35154,7 +35156,9 @@ async function updateMusicBrainzStatus() { const tooltipProgress = document.getElementById('mb-tooltip-progress'); if (tooltipStatus) { - if (data.running && !data.paused) { + if (data.idle) { + tooltipStatus.textContent = 'Complete'; + } else if (data.running && !data.paused) { tooltipStatus.textContent = 'Running'; } else if (data.paused) { tooltipStatus.textContent = 'Paused'; @@ -35164,7 +35168,9 @@ async function updateMusicBrainzStatus() { } if (tooltipCurrent) { - if (data.current_item && data.current_item.name) { + if (data.idle) { + tooltipCurrent.textContent = 'All items processed'; + } else if (data.current_item && data.current_item.name) { const type = data.current_item.type || 'item'; const name = data.current_item.name; tooltipCurrent.textContent = `${type.charAt(0).toUpperCase() + type.slice(1)}: "${name}"`; @@ -35280,8 +35286,10 @@ async function updateAudioDBStatus() { if (!button) return; // Update button state classes - button.classList.remove('active', 'paused'); - if (data.running && !data.paused) { + button.classList.remove('active', 'paused', 'complete'); + if (data.idle) { + button.classList.add('complete'); + } else if (data.running && !data.paused) { button.classList.add('active'); } else if (data.paused) { button.classList.add('paused'); @@ -35293,7 +35301,9 @@ async function updateAudioDBStatus() { const tooltipProgress = document.getElementById('audiodb-tooltip-progress'); if (tooltipStatus) { - if (data.running && !data.paused) { + if (data.idle) { + tooltipStatus.textContent = 'Complete'; + } else if (data.running && !data.paused) { tooltipStatus.textContent = 'Running'; } else if (data.paused) { tooltipStatus.textContent = 'Paused'; @@ -35303,7 +35313,9 @@ async function updateAudioDBStatus() { } if (tooltipCurrent) { - if (data.current_item && data.current_item.name) { + if (data.idle) { + tooltipCurrent.textContent = 'All items processed'; + } else if (data.current_item && data.current_item.name) { const type = data.current_item.type || 'item'; const name = data.current_item.name; tooltipCurrent.textContent = `${type.charAt(0).toUpperCase() + type.slice(1)}: "${name}"`; @@ -35406,8 +35418,10 @@ async function updateDeezerStatus() { if (!button) return; // Update button state classes - button.classList.remove('active', 'paused'); - if (data.running && !data.paused) { + button.classList.remove('active', 'paused', 'complete'); + if (data.idle) { + button.classList.add('complete'); + } else if (data.running && !data.paused) { button.classList.add('active'); } else if (data.paused) { button.classList.add('paused'); @@ -35419,7 +35433,9 @@ async function updateDeezerStatus() { const tooltipProgress = document.getElementById('deezer-tooltip-progress'); if (tooltipStatus) { - if (data.running && !data.paused) { + if (data.idle) { + tooltipStatus.textContent = 'Complete'; + } else if (data.running && !data.paused) { tooltipStatus.textContent = 'Running'; } else if (data.paused) { tooltipStatus.textContent = 'Paused'; @@ -35428,8 +35444,12 @@ async function updateDeezerStatus() { } } - if (tooltipCurrent && data.current_item) { - tooltipCurrent.textContent = `Now: ${data.current_item.name}`; + if (tooltipCurrent) { + if (data.idle) { + tooltipCurrent.textContent = 'All items processed'; + } else if (data.current_item && data.current_item.name) { + tooltipCurrent.textContent = `Now: ${data.current_item.name}`; + } } if (data.progress && tooltipProgress) { diff --git a/webui/static/style.css b/webui/static/style.css index 89cfb5d1..6318b4d3 100644 --- a/webui/static/style.css +++ b/webui/static/style.css @@ -21896,6 +21896,27 @@ body { filter: drop-shadow(0 0 8px rgba(186, 85, 211, 0.6)); } +/* Complete/Idle State */ +.musicbrainz-button.complete { + background: linear-gradient(135deg, + rgba(76, 175, 80, 0.15) 0%, + rgba(56, 142, 60, 0.20) 100%); + border-color: rgba(76, 175, 80, 0.35); + box-shadow: + 0 4px 16px rgba(76, 175, 80, 0.2), + 0 2px 8px rgba(0, 0, 0, 0.15), + inset 0 1px 0 rgba(255, 255, 255, 0.08); +} + +.musicbrainz-button.complete .mb-logo { + opacity: 0.85; + filter: drop-shadow(0 0 6px rgba(76, 175, 80, 0.5)); +} + +.musicbrainz-button.complete .mb-spinner { + opacity: 0; +} + /* Paused State */ .musicbrainz-button.paused { background: linear-gradient(135deg, @@ -22137,6 +22158,27 @@ body { filter: drop-shadow(0 0 8px rgba(0, 188, 212, 0.6)); } +/* Complete/Idle State */ +.audiodb-button.complete { + background: linear-gradient(135deg, + rgba(76, 175, 80, 0.15) 0%, + rgba(56, 142, 60, 0.20) 100%); + border-color: rgba(76, 175, 80, 0.35); + box-shadow: + 0 4px 16px rgba(76, 175, 80, 0.2), + 0 2px 8px rgba(0, 0, 0, 0.15), + inset 0 1px 0 rgba(255, 255, 255, 0.08); +} + +.audiodb-button.complete .audiodb-logo { + opacity: 0.85; + filter: drop-shadow(0 0 6px rgba(76, 175, 80, 0.5)); +} + +.audiodb-button.complete .audiodb-spinner { + opacity: 0; +} + /* Paused State */ .audiodb-button.paused { background: linear-gradient(135deg, @@ -22361,6 +22403,27 @@ body { filter: drop-shadow(0 0 8px rgba(162, 56, 255, 0.6)); } +/* Complete/Idle State */ +.deezer-button.complete { + background: linear-gradient(135deg, + rgba(76, 175, 80, 0.15) 0%, + rgba(56, 142, 60, 0.20) 100%); + border-color: rgba(76, 175, 80, 0.35); + box-shadow: + 0 4px 16px rgba(76, 175, 80, 0.2), + 0 2px 8px rgba(0, 0, 0, 0.15), + inset 0 1px 0 rgba(255, 255, 255, 0.08); +} + +.deezer-button.complete .deezer-logo { + opacity: 0.85; + filter: drop-shadow(0 0 6px rgba(76, 175, 80, 0.5)); +} + +.deezer-button.complete .deezer-spinner { + opacity: 0; +} + /* Paused State */ .deezer-button.paused { background: linear-gradient(135deg,