Gate Discogs primary source by token
- Show Discogs with a lock icon until a personal access token is present. - Prevent selecting locked Discogs and steer users to the Discogs settings section. - Keep metadata-source availability and selection state synced as the token changes.
This commit is contained in:
parent
5ff20fbfec
commit
4e40bce3e9
3 changed files with 106 additions and 25 deletions
|
|
@ -476,6 +476,12 @@ function handleServiceStatusUpdate(data) {
|
|||
if (typeof syncSpotifySettingsAuthState === 'function') {
|
||||
syncSpotifySettingsAuthState(data?.spotify || null);
|
||||
}
|
||||
if (typeof syncPrimaryMetadataSourceAvailability === 'function') {
|
||||
syncPrimaryMetadataSourceAvailability(data?.spotify || null);
|
||||
}
|
||||
if (typeof sanitizeMetadataSourceSelection === 'function') {
|
||||
sanitizeMetadataSourceSelection({ quiet: true });
|
||||
}
|
||||
|
||||
// Same logic as fetchAndUpdateServiceStatus response handler
|
||||
updateServiceStatus('spotify', data.spotify);
|
||||
|
|
|
|||
|
|
@ -58,8 +58,25 @@ function syncMetadataSourceSelection(source) {
|
|||
select.dataset.lastValidSource = source;
|
||||
}
|
||||
|
||||
function focusSpotifySettingsSection() {
|
||||
const card = document.querySelector('#settings-page .stg-service[data-service="spotify"]');
|
||||
function _isMetadataSourceSelectable(source) {
|
||||
if (source === 'spotify') {
|
||||
return _lastServiceStatus?.spotify?.authenticated === true;
|
||||
}
|
||||
if (source === 'discogs') {
|
||||
const token = document.getElementById('discogs-token');
|
||||
return !!token?.value?.trim();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function _metadataSourceFallback(source) {
|
||||
if (source === 'spotify') return 'deezer';
|
||||
if (source === 'discogs') return 'itunes';
|
||||
return 'itunes';
|
||||
}
|
||||
|
||||
function focusServiceSettingsSection(service, message) {
|
||||
const card = document.querySelector(`#settings-page .stg-service[data-service="${service}"]`);
|
||||
if (!card) return;
|
||||
|
||||
const header = card.querySelector('.stg-service-header');
|
||||
|
|
@ -74,7 +91,39 @@ function focusSpotifySettingsSection() {
|
|||
firstControl.focus({ preventScroll: true });
|
||||
}
|
||||
|
||||
showToast('Spotify must be authenticated before it can be selected as the primary metadata source.', 'warning');
|
||||
if (message) {
|
||||
showToast(message, 'warning');
|
||||
}
|
||||
}
|
||||
|
||||
function sanitizeMetadataSourceSelection({ quiet = true } = {}) {
|
||||
const select = document.getElementById('metadata-fallback-source');
|
||||
if (!select) return false;
|
||||
|
||||
const selectedSource = select.value || 'itunes';
|
||||
if (_isMetadataSourceSelectable(selectedSource)) {
|
||||
select.dataset.lastValidSource = selectedSource;
|
||||
return false;
|
||||
}
|
||||
|
||||
const lastValid = select.dataset.lastValidSource;
|
||||
const fallbackSource = lastValid && lastValid !== selectedSource && _isMetadataSourceSelectable(lastValid)
|
||||
? lastValid
|
||||
: _metadataSourceFallback(selectedSource);
|
||||
|
||||
if (fallbackSource && fallbackSource !== selectedSource) {
|
||||
select.value = fallbackSource;
|
||||
}
|
||||
select.dataset.lastValidSource = fallbackSource;
|
||||
|
||||
if (!quiet) {
|
||||
const message = selectedSource === 'discogs'
|
||||
? 'Discogs requires a personal access token before it can be selected as the primary metadata source.'
|
||||
: 'Spotify must be authenticated before it can be selected as the primary metadata source.';
|
||||
focusServiceSettingsSection(selectedSource, message);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleMetadataSourceChange(event) {
|
||||
|
|
@ -82,22 +131,12 @@ function handleMetadataSourceChange(event) {
|
|||
if (!select || select.id !== 'metadata-fallback-source') return;
|
||||
|
||||
const selectedSource = select.value;
|
||||
if (selectedSource !== 'spotify') {
|
||||
if (_isMetadataSourceSelectable(selectedSource)) {
|
||||
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();
|
||||
sanitizeMetadataSourceSelection({ quiet: false });
|
||||
}
|
||||
|
||||
function initializeSettings() {
|
||||
|
|
@ -130,6 +169,15 @@ function initializeSettings() {
|
|||
if (metadataSourceSelect) {
|
||||
metadataSourceSelect.addEventListener('change', handleMetadataSourceChange);
|
||||
}
|
||||
const discogsTokenInput = document.getElementById('discogs-token');
|
||||
if (discogsTokenInput) {
|
||||
discogsTokenInput.addEventListener('input', () => {
|
||||
if (typeof syncPrimaryMetadataSourceAvailability === 'function') {
|
||||
syncPrimaryMetadataSourceAvailability(_lastServiceStatus?.spotify || null);
|
||||
}
|
||||
sanitizeMetadataSourceSelection({ quiet: true });
|
||||
});
|
||||
}
|
||||
|
||||
// Server toggle buttons
|
||||
const plexToggle = document.getElementById('plex-toggle');
|
||||
|
|
@ -158,11 +206,12 @@ function initializeSettings() {
|
|||
// Test connection buttons
|
||||
// Test button event listeners removed - they use onclick attributes in HTML to avoid double firing
|
||||
|
||||
if (typeof syncSpotifyMetadataSourceAvailability === 'function') {
|
||||
syncSpotifyMetadataSourceAvailability(_lastServiceStatus?.spotify || null);
|
||||
if (typeof syncPrimaryMetadataSourceAvailability === 'function') {
|
||||
syncPrimaryMetadataSourceAvailability(_lastServiceStatus?.spotify || null);
|
||||
}
|
||||
syncSpotifySettingsAuthState(_lastServiceStatus?.spotify || null);
|
||||
syncMetadataSourceSelection(_lastServiceStatus?.spotify?.source);
|
||||
sanitizeMetadataSourceSelection({ quiet: true });
|
||||
if (metadataSourceSelect) {
|
||||
metadataSourceSelect.dataset.lastValidSource = metadataSourceSelect.value;
|
||||
}
|
||||
|
|
@ -2491,6 +2540,8 @@ async function saveSettings(quiet = false) {
|
|||
}
|
||||
|
||||
const metadataSourceSelect = document.getElementById('metadata-fallback-source');
|
||||
const discogsTokenInput = document.getElementById('discogs-token');
|
||||
const discogsTokenPresent = !!discogsTokenInput?.value?.trim();
|
||||
let metadataSource = metadataSourceSelect?.value || 'itunes';
|
||||
const spotifySessionActive = _lastServiceStatus?.spotify?.authenticated === true;
|
||||
if (metadataSource === 'spotify' && !spotifySessionActive) {
|
||||
|
|
@ -2499,6 +2550,12 @@ async function saveSettings(quiet = false) {
|
|||
if (!quiet) {
|
||||
showToast('Spotify is disconnected, so Deezer is used as the primary metadata source.', 'warning');
|
||||
}
|
||||
} else if (metadataSource === 'discogs' && !discogsTokenPresent) {
|
||||
metadataSource = 'itunes';
|
||||
if (metadataSourceSelect) metadataSourceSelect.value = metadataSource;
|
||||
if (!quiet) {
|
||||
showToast('Discogs requires a personal access token before it can be selected as the primary metadata source.', 'warning');
|
||||
}
|
||||
}
|
||||
|
||||
const settings = {
|
||||
|
|
|
|||
|
|
@ -3148,6 +3148,12 @@ async function fetchAndUpdateServiceStatus() {
|
|||
if (typeof syncSpotifySettingsAuthState === 'function') {
|
||||
syncSpotifySettingsAuthState(data?.spotify || null);
|
||||
}
|
||||
if (typeof syncPrimaryMetadataSourceAvailability === 'function') {
|
||||
syncPrimaryMetadataSourceAvailability(data?.spotify || null);
|
||||
}
|
||||
if (typeof sanitizeMetadataSourceSelection === 'function') {
|
||||
sanitizeMetadataSourceSelection({ quiet: true });
|
||||
}
|
||||
|
||||
// Update service status indicators and text (dashboard)
|
||||
updateServiceStatus('spotify', data.spotify);
|
||||
|
|
@ -3190,20 +3196,32 @@ async function fetchAndUpdateServiceStatus() {
|
|||
}
|
||||
}
|
||||
|
||||
function syncSpotifyMetadataSourceAvailability(statusData) {
|
||||
function syncPrimaryMetadataSourceAvailability(statusData) {
|
||||
const select = document.getElementById('metadata-fallback-source');
|
||||
if (!select) return;
|
||||
if (!statusData) return;
|
||||
|
||||
const spotifyOption = select.querySelector('option[value="spotify"]');
|
||||
if (!spotifyOption) return;
|
||||
const discogsOption = select.querySelector('option[value="discogs"]');
|
||||
|
||||
const spotifyAvailable = statusData?.authenticated === true;
|
||||
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.';
|
||||
if (spotifyOption) {
|
||||
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.';
|
||||
}
|
||||
|
||||
if (discogsOption) {
|
||||
const discogsToken = document.getElementById('discogs-token');
|
||||
const discogsAvailable = !!discogsToken?.value?.trim();
|
||||
discogsOption.dataset.unavailable = discogsAvailable ? 'false' : 'true';
|
||||
discogsOption.textContent = discogsAvailable ? 'Discogs' : '🔒 Discogs';
|
||||
discogsOption.title = discogsAvailable
|
||||
? 'Discogs'
|
||||
: 'Discogs personal access token is required before this source can be selected.';
|
||||
}
|
||||
}
|
||||
|
||||
function getMetadataSourceLabel(source) {
|
||||
|
|
@ -3304,7 +3322,7 @@ function updateServiceStatus(service, statusData) {
|
|||
disconnectBtn.style.display = spotifySessionActive ? '' : 'none';
|
||||
}
|
||||
|
||||
syncSpotifyMetadataSourceAvailability(statusData);
|
||||
syncPrimaryMetadataSourceAvailability(statusData);
|
||||
}
|
||||
|
||||
// Update download source title on dashboard card
|
||||
|
|
|
|||
Loading…
Reference in a new issue