feat: dynamic source labels and enhanced connection testing

- Display "Apple Music" instead of "Spotify" in UI when iTunes is active source
- Enhanced connection test messages to indicate Spotify config/auth status
- Fixed similar artists requiring Spotify re-scan when Spotify becomes available
- Fixed hero slider buttons failing for iTunes-only artists
- Updated activity feed items to show correct source name dynamically
This commit is contained in:
Broque Thomas 2026-01-25 00:29:33 -08:00
parent 4cbb3c952b
commit 59848acaf3
3 changed files with 47 additions and 9 deletions

View file

@ -1506,10 +1506,23 @@ def run_service_test(service, test_config):
# 3. Run the test with the temporary config # 3. Run the test with the temporary config
if service == "spotify": if service == "spotify":
temp_client = SpotifyClient() temp_client = SpotifyClient()
# Check if Spotify credentials are configured
spotify_config = config_manager.get('spotify', {})
spotify_configured = bool(spotify_config.get('client_id') and spotify_config.get('client_secret'))
if temp_client.is_authenticated(): if temp_client.is_authenticated():
# Determine which source is active
if temp_client.is_spotify_authenticated():
return True, "Spotify connection successful!" return True, "Spotify connection successful!"
else: else:
return False, "Spotify authentication failed. Check credentials and complete OAuth flow in browser if prompted." # Using iTunes fallback
if spotify_configured:
return True, "Apple Music connection successful! (Spotify configured but not authenticated)"
else:
return True, "Apple Music connection successful! (Spotify not configured)"
else:
return False, "Music service authentication failed. Check credentials and complete OAuth flow in browser if prompted."
elif service == "tidal": elif service == "tidal":
temp_client = TidalClient() temp_client = TidalClient()
if temp_client.is_authenticated(): if temp_client.is_authenticated():
@ -1926,9 +1939,14 @@ def get_status():
# Actually validate authentication (makes API call, but cached for 2 min) # Actually validate authentication (makes API call, but cached for 2 min)
spotify_status = spotify_client.is_authenticated() spotify_status = spotify_client.is_authenticated()
spotify_response_time = (time.time() - spotify_start) * 1000 spotify_response_time = (time.time() - spotify_start) * 1000
# Determine active music source (spotify or itunes)
music_source = 'spotify' if spotify_client.is_spotify_authenticated() else 'itunes'
_status_cache['spotify'] = { _status_cache['spotify'] = {
'connected': spotify_status, 'connected': spotify_status,
'response_time': round(spotify_response_time, 1) 'response_time': round(spotify_response_time, 1),
'source': music_source
} }
_status_cache_timestamps['spotify'] = current_time _status_cache_timestamps['spotify'] = current_time
# else: use cached value # else: use cached value
@ -2365,7 +2383,7 @@ def test_connection_endpoint():
# Add activity for connection test # Add activity for connection test
if success: if success:
add_activity_item("", "Connection Test", f"{service.title()} connection successful", "Now") add_activity_item("", "Connection Test", message, "Now")
else: else:
add_activity_item("", "Connection Test", f"{service.title()} connection failed", "Now") add_activity_item("", "Connection Test", f"{service.title()} connection failed", "Now")
@ -2411,7 +2429,7 @@ def test_dashboard_connection_endpoint():
# Add activity for dashboard connection test (different from settings test) # Add activity for dashboard connection test (different from settings test)
if success: if success:
add_activity_item("🎛️", "Dashboard Test", f"{service.title()} service verified", "Now") add_activity_item("🎛️", "Dashboard Test", message, "Now")
else: else:
add_activity_item("⚠️", "Dashboard Test", f"{service.title()} service check failed", "Now") add_activity_item("⚠️", "Dashboard Test", f"{service.title()} service check failed", "Now")

View file

@ -139,7 +139,7 @@
<h4 class="status-title">Service Status</h4> <h4 class="status-title">Service Status</h4>
<div class="status-indicator" id="spotify-indicator"> <div class="status-indicator" id="spotify-indicator">
<span class="status-dot disconnected"></span> <span class="status-dot disconnected"></span>
<span class="status-name">Spotify</span> <span class="status-name" id="music-source-name">Spotify</span>
</div> </div>
<div class="status-indicator" id="media-server-indicator"> <div class="status-indicator" id="media-server-indicator">
<span class="status-dot disconnected"></span> <span class="status-dot disconnected"></span>
@ -175,7 +175,7 @@
<div class="service-status-grid"> <div class="service-status-grid">
<div class="service-card" id="spotify-service-card"> <div class="service-card" id="spotify-service-card">
<div class="service-card-header"> <div class="service-card-header">
<span class="service-card-title">Spotify</span> <span class="service-card-title" id="music-source-title">Spotify</span>
<span class="service-card-indicator disconnected" <span class="service-card-indicator disconnected"
id="spotify-status-indicator">●</span> id="spotify-status-indicator">●</span>
</div> </div>

View file

@ -2164,7 +2164,8 @@ async function testConnection(service) {
const result = await response.json(); const result = await response.json();
if (result.success) { if (result.success) {
showToast(`${service} connection successful`, 'success'); // Use backend's message which contains dynamic source name (Spotify or Apple Music)
showToast(result.message || `${service} connection successful`, 'success');
// Load music libraries after successful connection // Load music libraries after successful connection
if (service === 'plex') { if (service === 'plex') {
@ -2197,7 +2198,8 @@ async function testDashboardConnection(service) {
const result = await response.json(); const result = await response.json();
if (result.success) { if (result.success) {
showToast(`${service} service verified`, 'success'); // Use backend's message which contains dynamic source name (Spotify or Apple Music)
showToast(result.message || `${service} service verified`, 'success');
} else { } else {
showToast(`${service} service check failed: ${result.error}`, 'error'); showToast(`${service} service check failed: ${result.error}`, 'error');
} }
@ -23214,6 +23216,15 @@ function updateServiceStatus(service, statusData) {
statusText.className = 'service-card-status-text disconnected'; statusText.className = 'service-card-status-text disconnected';
} }
} }
// Update music source title (Spotify or Apple Music) based on active source
if (service === 'spotify' && statusData.source) {
const musicSourceTitleElement = document.getElementById('music-source-title');
if (musicSourceTitleElement) {
const sourceName = statusData.source === 'itunes' ? 'Apple Music' : 'Spotify';
musicSourceTitleElement.textContent = sourceName;
}
}
} }
function updateSidebarServiceStatus(service, statusData) { function updateSidebarServiceStatus(service, statusData) {
@ -23238,6 +23249,15 @@ function updateSidebarServiceStatus(service, statusData) {
mediaServerNameElement.textContent = serverName; mediaServerNameElement.textContent = serverName;
} }
} }
// Update music source name (Spotify or Apple Music) based on active source
if (service === 'spotify' && statusData.source) {
const musicSourceNameElement = document.getElementById('music-source-name');
if (musicSourceNameElement) {
const sourceName = statusData.source === 'itunes' ? 'Apple Music' : 'Spotify';
musicSourceNameElement.textContent = sourceName;
}
}
} }
} }