diff --git a/core/genius_worker.py b/core/genius_worker.py index d4c6b73d..1ddf0494 100644 --- a/core/genius_worker.py +++ b/core/genius_worker.py @@ -111,6 +111,7 @@ class GeniusWorker: 'running': is_actually_running and not self.paused, 'paused': self.paused, 'idle': is_idle, + 'authenticated': bool(self.client and self.client.access_token), 'current_item': self.current_item, 'stats': self.stats.copy(), 'progress': progress diff --git a/core/lastfm_worker.py b/core/lastfm_worker.py index 17e17c11..0c398136 100644 --- a/core/lastfm_worker.py +++ b/core/lastfm_worker.py @@ -111,6 +111,7 @@ class LastFMWorker: 'running': is_actually_running and not self.paused, 'paused': self.paused, 'idle': is_idle, + 'authenticated': bool(self.client and self.client.api_key), 'current_item': self.current_item, 'stats': self.stats.copy(), 'progress': progress diff --git a/webui/static/script.js b/webui/static/script.js index 09ad0ff6..ce9c9d14 100644 --- a/webui/static/script.js +++ b/webui/static/script.js @@ -45104,13 +45104,17 @@ function updateLastFMEnrichmentStatusFromData(data) { const button = document.getElementById('lastfm-enrich-button'); if (!button) return; - button.classList.remove('active', 'paused', 'complete'); - if (data.idle) { + const notAuthenticated = data.authenticated === false; + + button.classList.remove('active', 'paused', 'complete', 'no-auth'); + if (data.paused) { + button.classList.add('paused'); + } else if (notAuthenticated) { + button.classList.add('no-auth'); + } else 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'); } const tooltipStatus = document.getElementById('lastfm-enrich-tooltip-status'); @@ -45118,14 +45122,19 @@ function updateLastFMEnrichmentStatusFromData(data) { const tooltipProgress = document.getElementById('lastfm-enrich-tooltip-progress'); if (tooltipStatus) { - if (data.idle) { tooltipStatus.textContent = 'Complete'; } - else if (data.running && !data.paused) { tooltipStatus.textContent = 'Running'; } - else if (data.paused) { tooltipStatus.textContent = 'Paused'; } + if (data.paused) { tooltipStatus.textContent = 'Paused'; } + else if (notAuthenticated) { tooltipStatus.textContent = 'Not Authenticated'; } + else if (data.idle) { tooltipStatus.textContent = 'Complete'; } + else if (data.running) { tooltipStatus.textContent = 'Running'; } else { tooltipStatus.textContent = 'Idle'; } } if (tooltipCurrent) { - if (data.idle) { + if (data.paused) { + tooltipCurrent.textContent = notAuthenticated ? 'Add Last.fm API key in Settings to enrich' : 'Click to resume'; + } else if (notAuthenticated) { + tooltipCurrent.textContent = 'Add Last.fm API key in Settings to enrich'; + } else if (data.idle) { tooltipCurrent.textContent = 'All items processed'; } else if (data.current_item && data.current_item.name) { tooltipCurrent.textContent = `Now: ${data.current_item.name}`; @@ -45133,27 +45142,31 @@ function updateLastFMEnrichmentStatusFromData(data) { } if (data.progress && tooltipProgress) { - const artists = data.progress.artists || {}; - const albums = data.progress.albums || {}; - const tracks = data.progress.tracks || {}; - - const currentType = data.current_item?.type; - let progressText = ''; - - const artistsComplete = artists.matched >= artists.total; - const albumsComplete = albums.matched >= albums.total; - - if (currentType === 'artist' || (!artistsComplete && !currentType)) { - progressText = `Artists: ${artists.matched || 0} / ${artists.total || 0} (${artists.percent || 0}%)`; - } else if (currentType === 'album' || (artistsComplete && !albumsComplete)) { - progressText = `Albums: ${albums.matched || 0} / ${albums.total || 0} (${albums.percent || 0}%)`; - } else if (currentType === 'track' || (artistsComplete && albumsComplete)) { - progressText = `Tracks: ${tracks.matched || 0} / ${tracks.total || 0} (${tracks.percent || 0}%)`; + if (notAuthenticated) { + tooltipProgress.textContent = `Pending: ${data.stats?.pending || 0} items`; } else { - progressText = `Artists: ${artists.matched || 0} / ${artists.total || 0} (${artists.percent || 0}%)`; - } + const artists = data.progress.artists || {}; + const albums = data.progress.albums || {}; + const tracks = data.progress.tracks || {}; - tooltipProgress.textContent = progressText; + const currentType = data.current_item?.type; + let progressText = ''; + + const artistsComplete = artists.matched >= artists.total; + const albumsComplete = albums.matched >= albums.total; + + if (currentType === 'artist' || (!artistsComplete && !currentType)) { + progressText = `Artists: ${artists.matched || 0} / ${artists.total || 0} (${artists.percent || 0}%)`; + } else if (currentType === 'album' || (artistsComplete && !albumsComplete)) { + progressText = `Albums: ${albums.matched || 0} / ${albums.total || 0} (${albums.percent || 0}%)`; + } else if (currentType === 'track' || (artistsComplete && albumsComplete)) { + progressText = `Tracks: ${tracks.matched || 0} / ${tracks.total || 0} (${tracks.percent || 0}%)`; + } else { + progressText = `Artists: ${artists.matched || 0} / ${artists.total || 0} (${artists.percent || 0}%)`; + } + + tooltipProgress.textContent = progressText; + } } } @@ -45218,13 +45231,17 @@ function updateGeniusEnrichmentStatusFromData(data) { const button = document.getElementById('genius-enrich-button'); if (!button) return; - button.classList.remove('active', 'paused', 'complete'); - if (data.idle) { + const notAuthenticated = data.authenticated === false; + + button.classList.remove('active', 'paused', 'complete', 'no-auth'); + if (data.paused) { + button.classList.add('paused'); + } else if (notAuthenticated) { + button.classList.add('no-auth'); + } else 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'); } const tooltipStatus = document.getElementById('genius-enrich-tooltip-status'); @@ -45232,14 +45249,19 @@ function updateGeniusEnrichmentStatusFromData(data) { const tooltipProgress = document.getElementById('genius-enrich-tooltip-progress'); if (tooltipStatus) { - if (data.idle) { tooltipStatus.textContent = 'Complete'; } - else if (data.running && !data.paused) { tooltipStatus.textContent = 'Running'; } - else if (data.paused) { tooltipStatus.textContent = 'Paused'; } + if (data.paused) { tooltipStatus.textContent = 'Paused'; } + else if (notAuthenticated) { tooltipStatus.textContent = 'Not Authenticated'; } + else if (data.idle) { tooltipStatus.textContent = 'Complete'; } + else if (data.running) { tooltipStatus.textContent = 'Running'; } else { tooltipStatus.textContent = 'Idle'; } } if (tooltipCurrent) { - if (data.idle) { + if (data.paused) { + tooltipCurrent.textContent = notAuthenticated ? 'Add Genius access token in Settings to enrich' : 'Click to resume'; + } else if (notAuthenticated) { + tooltipCurrent.textContent = 'Add Genius access token in Settings to enrich'; + } else if (data.idle) { tooltipCurrent.textContent = 'All items processed'; } else if (data.current_item && data.current_item.name) { tooltipCurrent.textContent = `Now: ${data.current_item.name}`; @@ -45247,21 +45269,25 @@ function updateGeniusEnrichmentStatusFromData(data) { } if (data.progress && tooltipProgress) { - const artists = data.progress.artists || {}; - const tracks = data.progress.tracks || {}; - - const currentType = data.current_item?.type; - let progressText = ''; - - const artistsComplete = artists.matched >= artists.total; - - if (currentType === 'artist' || (!artistsComplete && !currentType)) { - progressText = `Artists: ${artists.matched || 0} / ${artists.total || 0} (${artists.percent || 0}%)`; + if (notAuthenticated) { + tooltipProgress.textContent = `Pending: ${data.stats?.pending || 0} items`; } else { - progressText = `Tracks: ${tracks.matched || 0} / ${tracks.total || 0} (${tracks.percent || 0}%)`; - } + const artists = data.progress.artists || {}; + const tracks = data.progress.tracks || {}; - tooltipProgress.textContent = progressText; + const currentType = data.current_item?.type; + let progressText = ''; + + const artistsComplete = artists.matched >= artists.total; + + if (currentType === 'artist' || (!artistsComplete && !currentType)) { + progressText = `Artists: ${artists.matched || 0} / ${artists.total || 0} (${artists.percent || 0}%)`; + } else { + progressText = `Tracks: ${tracks.matched || 0} / ${tracks.total || 0} (${tracks.percent || 0}%)`; + } + + tooltipProgress.textContent = progressText; + } } } diff --git a/webui/static/style.css b/webui/static/style.css index a454d1cd..0591a9f8 100644 --- a/webui/static/style.css +++ b/webui/static/style.css @@ -27436,6 +27436,39 @@ body { color: #ffc107; } +.lastfm-enrich-button.no-auth { + background: linear-gradient(135deg, + rgba(120, 120, 120, 0.08) 0%, + rgba(80, 80, 80, 0.12) 100%); + border-color: rgba(120, 120, 120, 0.25); + box-shadow: + 0 4px 16px rgba(0, 0, 0, 0.15), + 0 2px 8px rgba(0, 0, 0, 0.1), + inset 0 1px 0 rgba(255, 255, 255, 0.04); + opacity: 0.5; + cursor: not-allowed; +} + +.lastfm-enrich-button.no-auth .lastfm-enrich-logo { + filter: grayscale(1) opacity(0.4); +} + +.lastfm-enrich-button.no-auth .lastfm-enrich-spinner { + display: none; +} + +.lastfm-enrich-button.no-auth:hover { + border-color: rgba(120, 120, 120, 0.35); + box-shadow: + 0 6px 20px rgba(0, 0, 0, 0.2), + 0 3px 12px rgba(0, 0, 0, 0.15); + opacity: 0.55; +} + +.lastfm-enrich-button.no-auth+.lastfm-enrich-tooltip #lastfm-enrich-tooltip-status { + color: rgba(120, 120, 120, 0.8); +} + .lastfm-enrich-tooltip-content::before { content: ''; position: absolute; @@ -27629,6 +27662,39 @@ body { color: #ffc107; } +.genius-enrich-button.no-auth { + background: linear-gradient(135deg, + rgba(120, 120, 120, 0.08) 0%, + rgba(80, 80, 80, 0.12) 100%); + border-color: rgba(120, 120, 120, 0.25); + box-shadow: + 0 4px 16px rgba(0, 0, 0, 0.15), + 0 2px 8px rgba(0, 0, 0, 0.1), + inset 0 1px 0 rgba(255, 255, 255, 0.04); + opacity: 0.5; + cursor: not-allowed; +} + +.genius-enrich-button.no-auth .genius-enrich-logo { + filter: grayscale(1) opacity(0.4); +} + +.genius-enrich-button.no-auth .genius-enrich-spinner { + display: none; +} + +.genius-enrich-button.no-auth:hover { + border-color: rgba(120, 120, 120, 0.35); + box-shadow: + 0 6px 20px rgba(0, 0, 0, 0.2), + 0 3px 12px rgba(0, 0, 0, 0.15); + opacity: 0.55; +} + +.genius-enrich-button.no-auth+.genius-enrich-tooltip #genius-enrich-tooltip-status { + color: rgba(120, 120, 120, 0.8); +} + .genius-enrich-tooltip-content::before { content: ''; position: absolute;