Add Qobuz credentials to Settings Connections tab (#218)
Qobuz login was only available on the Downloads tab when Qobuz was selected as download source. But Qobuz credentials are also needed for the enrichment worker which runs independently. Users saw "Connect Qobuz in Settings" on the dashboard but couldn't find it. Adds a Qobuz section to Settings → Connections (same pattern as Tidal's existing Connections section). checkQobuzAuthStatus() now syncs both the Connections and Downloads tab sections. Login from either tab updates both. No backend changes — same API endpoints.
This commit is contained in:
parent
7133595e0d
commit
ab8e44dafd
4 changed files with 106 additions and 5 deletions
|
|
@ -19071,6 +19071,15 @@ def get_version_info():
|
|||
"title": "What's New in SoulSync",
|
||||
"subtitle": f"Version {SOULSYNC_VERSION} — Latest Changes",
|
||||
"sections": [
|
||||
{
|
||||
"title": "🔧 Add Qobuz to Connections Tab (#218)",
|
||||
"description": "Qobuz credentials now available on the Connections tab for metadata enrichment",
|
||||
"features": [
|
||||
"• New Qobuz section on Settings → Connections tab for enrichment auth",
|
||||
"• Users can connect Qobuz for metadata enrichment regardless of download source",
|
||||
"• Auth status syncs between Connections and Downloads tabs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "🔧 Fix Enrichment Widget Showing 'Running' When Rate Limited",
|
||||
"description": "Enrichment tooltip now shows Rate Limited or Daily Limit Reached instead of stuck on Running",
|
||||
|
|
|
|||
|
|
@ -3632,6 +3632,38 @@
|
|||
</div>
|
||||
|
||||
|
||||
<!-- Qobuz Metadata/Enrichment Auth -->
|
||||
<div class="api-service-frame">
|
||||
<h4 class="service-title qobuz-title">Qobuz (Metadata & Enrichment)</h4>
|
||||
<div id="qobuz-connection-logged-in" style="display: none; margin-bottom: 8px;">
|
||||
<span id="qobuz-connection-user-info" class="setting-help-text" style="color: #4caf50;"></span>
|
||||
<button class="auth-button" onclick="logoutQobuz()" style="margin-left: 8px;">
|
||||
Disconnect
|
||||
</button>
|
||||
</div>
|
||||
<div id="qobuz-connection-form">
|
||||
<div class="form-group">
|
||||
<label>Email:</label>
|
||||
<input type="email" id="qobuz-connection-email" class="form-input"
|
||||
placeholder="Qobuz email" autocomplete="email">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Password:</label>
|
||||
<input type="password" id="qobuz-connection-password" class="form-input"
|
||||
placeholder="Qobuz password" autocomplete="current-password">
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<button class="auth-button" id="qobuz-connection-login-btn" onclick="loginQobuzFromConnections()">
|
||||
Connect Qobuz
|
||||
</button>
|
||||
<span id="qobuz-connection-status" class="setting-help-text" style="margin-left: 8px;"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-help-text" style="margin-top: 6px;">
|
||||
Connects Qobuz for metadata enrichment (ISRC, labels, copyright). Also used for downloads if Qobuz is your download source.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ListenBrainz Settings -->
|
||||
<div class="api-service-frame">
|
||||
<h4 class="service-title listenbrainz-title">ListenBrainz</h4>
|
||||
|
|
|
|||
|
|
@ -3403,6 +3403,7 @@ function closeHelperSearch() {
|
|||
const WHATS_NEW = {
|
||||
'2.1': [
|
||||
// Newest features first
|
||||
{ title: 'Qobuz on Connections Tab', desc: 'Qobuz credentials now on Settings → Connections for metadata enrichment without needing it as download source' },
|
||||
{ title: 'Fix Enrichment Status Widget', desc: 'Enrichment tooltip now shows Rate Limited or Daily Limit instead of stuck on Running' },
|
||||
{ title: 'Cache Maintenance', desc: 'Cache evictor now cleans junk entities, orphaned searches, and stale MusicBrainz nulls' },
|
||||
{ title: 'Fix Wishlist Download Selection', desc: 'Download Selection now only downloads checked tracks instead of the entire category' },
|
||||
|
|
|
|||
|
|
@ -7602,24 +7602,83 @@ async function checkQobuzAuthStatus() {
|
|||
try {
|
||||
const resp = await fetch('/api/qobuz/auth/status');
|
||||
const data = await resp.json();
|
||||
|
||||
// Update downloads tab section
|
||||
const formEl = document.getElementById('qobuz-auth-form');
|
||||
const loggedInEl = document.getElementById('qobuz-auth-logged-in');
|
||||
const userInfoEl = document.getElementById('qobuz-auth-user-info');
|
||||
|
||||
// Update connections tab section
|
||||
const connFormEl = document.getElementById('qobuz-connection-form');
|
||||
const connLoggedInEl = document.getElementById('qobuz-connection-logged-in');
|
||||
const connUserInfoEl = document.getElementById('qobuz-connection-user-info');
|
||||
|
||||
if (data.authenticated) {
|
||||
const user = data.user || {};
|
||||
userInfoEl.textContent = `Connected: ${user.display_name || 'Qobuz User'} (${user.subscription || 'Active'})`;
|
||||
loggedInEl.style.display = 'flex';
|
||||
formEl.style.display = 'none';
|
||||
const label = `Connected: ${user.display_name || 'Qobuz User'} (${user.subscription || 'Active'})`;
|
||||
|
||||
if (userInfoEl) { userInfoEl.textContent = label; }
|
||||
if (loggedInEl) loggedInEl.style.display = 'flex';
|
||||
if (formEl) formEl.style.display = 'none';
|
||||
|
||||
if (connUserInfoEl) { connUserInfoEl.textContent = label; }
|
||||
if (connLoggedInEl) connLoggedInEl.style.display = 'flex';
|
||||
if (connFormEl) connFormEl.style.display = 'none';
|
||||
} else {
|
||||
loggedInEl.style.display = 'none';
|
||||
formEl.style.display = 'block';
|
||||
if (loggedInEl) loggedInEl.style.display = 'none';
|
||||
if (formEl) formEl.style.display = 'block';
|
||||
|
||||
if (connLoggedInEl) connLoggedInEl.style.display = 'none';
|
||||
if (connFormEl) connFormEl.style.display = 'block';
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Qobuz auth status check failed:', e);
|
||||
}
|
||||
}
|
||||
|
||||
async function loginQobuzFromConnections() {
|
||||
const btn = document.getElementById('qobuz-connection-login-btn');
|
||||
const statusEl = document.getElementById('qobuz-connection-status');
|
||||
const email = document.getElementById('qobuz-connection-email').value.trim();
|
||||
const password = document.getElementById('qobuz-connection-password').value;
|
||||
|
||||
if (!email || !password) {
|
||||
showToast('Please enter your Qobuz email and password', 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
btn.disabled = true;
|
||||
btn.textContent = 'Connecting...';
|
||||
statusEl.textContent = '';
|
||||
|
||||
try {
|
||||
const resp = await fetch('/api/qobuz/auth/login', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ email, password }),
|
||||
});
|
||||
const data = await resp.json();
|
||||
|
||||
if (data.success) {
|
||||
showToast('Qobuz connected successfully!', 'success');
|
||||
document.getElementById('qobuz-connection-password').value = '';
|
||||
checkQobuzAuthStatus();
|
||||
} else {
|
||||
statusEl.textContent = data.error || 'Login failed';
|
||||
statusEl.style.color = '#ff5555';
|
||||
showToast(data.error || 'Qobuz login failed', 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Qobuz login error:', error);
|
||||
statusEl.textContent = 'Connection error';
|
||||
statusEl.style.color = '#ff5555';
|
||||
showToast('Failed to connect to Qobuz', 'error');
|
||||
} finally {
|
||||
btn.disabled = false;
|
||||
btn.textContent = 'Connect Qobuz';
|
||||
}
|
||||
}
|
||||
|
||||
async function loginQobuz() {
|
||||
const btn = document.getElementById('qobuz-login-btn');
|
||||
const statusEl = document.getElementById('qobuz-auth-status');
|
||||
|
|
|
|||
Loading…
Reference in a new issue