From 5ff20fbfec21adc298c9edc9f12492580de9f3e2 Mon Sep 17 00:00:00 2001 From: Antti Kettunen Date: Fri, 1 May 2026 12:51:51 +0300 Subject: [PATCH] Polish Spotify source selection - Show Spotify with a lock icon when it is not currently selectable. - Keep the explanation in the hover title instead of cluttering the dropdown label. - Redirect users to the Spotify settings section when they try to pick a locked source. --- webui/static/settings.js | 53 ++++++++++++++++++++++++++++++++++ webui/static/shared-helpers.js | 5 +++- 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/webui/static/settings.js b/webui/static/settings.js index 5c84b53b..c034298f 100644 --- a/webui/static/settings.js +++ b/webui/static/settings.js @@ -55,6 +55,49 @@ function syncMetadataSourceSelection(source) { if (!select || !source) return; const option = select.querySelector(`option[value="${source}"]`); if (option) select.value = source; + select.dataset.lastValidSource = source; +} + +function focusSpotifySettingsSection() { + const card = document.querySelector('#settings-page .stg-service[data-service="spotify"]'); + if (!card) return; + + const header = card.querySelector('.stg-service-header'); + if (!card.classList.contains('expanded') && header) { + toggleStgService(header); + } + + card.scrollIntoView({ behavior: 'smooth', block: 'center' }); + + const firstControl = card.querySelector('input, button'); + if (firstControl) { + firstControl.focus({ preventScroll: true }); + } + + showToast('Spotify must be authenticated before it can be selected as the primary metadata source.', 'warning'); +} + +function handleMetadataSourceChange(event) { + const select = event.target; + if (!select || select.id !== 'metadata-fallback-source') return; + + const selectedSource = select.value; + if (selectedSource !== 'spotify') { + select.dataset.lastValidSource = selectedSource; + return; + } + + const spotifySessionActive = _lastServiceStatus?.spotify?.authenticated === true; + if (spotifySessionActive) { + select.dataset.lastValidSource = selectedSource; + return; + } + + const fallbackSource = select.dataset.lastValidSource || _lastServiceStatus?.spotify?.source || 'deezer'; + if (fallbackSource && fallbackSource !== 'spotify') { + select.value = fallbackSource; + } + focusSpotifySettingsSection(); } function initializeSettings() { @@ -83,6 +126,11 @@ function initializeSettings() { }); } + const metadataSourceSelect = document.getElementById('metadata-fallback-source'); + if (metadataSourceSelect) { + metadataSourceSelect.addEventListener('change', handleMetadataSourceChange); + } + // Server toggle buttons const plexToggle = document.getElementById('plex-toggle'); if (plexToggle) { @@ -115,6 +163,9 @@ function initializeSettings() { } syncSpotifySettingsAuthState(_lastServiceStatus?.spotify || null); syncMetadataSourceSelection(_lastServiceStatus?.spotify?.source); + if (metadataSourceSelect) { + metadataSourceSelect.dataset.lastValidSource = metadataSourceSelect.value; + } } function resetFileOrganizationTemplates() { @@ -315,6 +366,8 @@ async function applyServiceStatusGradients() { } function syncSpotifySettingsAuthState(statusData) { + if (!statusData) return; + const card = document.querySelector('#settings-page .stg-service[data-service="spotify"]'); if (!card) return; diff --git a/webui/static/shared-helpers.js b/webui/static/shared-helpers.js index 359fbd21..2262b40f 100644 --- a/webui/static/shared-helpers.js +++ b/webui/static/shared-helpers.js @@ -3199,8 +3199,11 @@ function syncSpotifyMetadataSourceAvailability(statusData) { if (!spotifyOption) return; const spotifyAvailable = statusData?.authenticated === true; - spotifyOption.disabled = !spotifyAvailable; spotifyOption.dataset.unavailable = spotifyAvailable ? 'false' : 'true'; + spotifyOption.textContent = spotifyAvailable ? 'Spotify' : '🔒 Spotify'; + spotifyOption.title = spotifyAvailable + ? 'Spotify' + : 'Spotify authentication is required before this source can be selected.'; } function getMetadataSourceLabel(source) {