Clarify hybrid source album behavior

Add dynamic level badges to the hybrid source order settings. The first enabled source shows Album-level only when it supports album-bundle downloads; every other source shows Track-level to make fallback behavior visible.

Update the helper copy and badge styling so users can understand why putting Soulseek, Torrent, or Usenet first changes album-download behavior.
This commit is contained in:
Broque Thomas 2026-05-23 15:15:28 -07:00
parent 6c226613bf
commit 94129d3099
3 changed files with 27 additions and 0 deletions

View file

@ -4372,6 +4372,7 @@
<div id="hybrid-settings-container" style="display: none;">
<div class="setting-help-text">
Drag to reorder source priority. Enable sources you want to use. Downloads try each enabled source in order.
The first source can use album-level downloads when supported; later sources stay track-level fallback.
</div>
<div class="hybrid-source-list" id="hybrid-source-list">
<!-- Populated by JS -->

View file

@ -600,6 +600,7 @@ const HYBRID_SOURCES = [
{ id: 'torrent', name: 'Torrent', icon: null, emoji: '🧲' },
{ id: 'usenet', name: 'Usenet', icon: null, emoji: '📰' },
];
const ALBUM_LEVEL_HYBRID_SOURCES = new Set(['soulseek', 'torrent', 'usenet']);
let _hybridSourceOrder = ['soulseek', 'youtube'];
let _hybridSourceEnabled = { soulseek: true, youtube: true, tidal: false, qobuz: false, hifi: false, deezer_dl: false, amazon: false, lidarr: false, soundcloud: false, torrent: false, usenet: false };
@ -625,6 +626,13 @@ function buildHybridSourceList() {
const enabled = _hybridSourceEnabled[srcId] !== false;
const isInOrder = _hybridSourceOrder.includes(srcId);
const priorityNum = isInOrder && enabled ? _hybridSourceOrder.indexOf(srcId) + 1 : '';
const canOwnAlbum = enabled && priorityNum === 1 && ALBUM_LEVEL_HYBRID_SOURCES.has(srcId);
const sourceLevel = canOwnAlbum ? 'Album-level' : 'Track-level';
const sourceLevelClass = canOwnAlbum ? 'album' : 'track';
const sourceLevelTitle = canOwnAlbum
? 'This first source can download a whole album release before per-track fallback.'
: 'This source runs as per-track fallback in the current hybrid order.';
const sourceLevelBadge = `<span class="hybrid-source-badge hybrid-source-badge-${sourceLevelClass}" title="${sourceLevelTitle}">${sourceLevel}</span>`;
const item = document.createElement('div');
item.className = `hybrid-source-item${enabled ? '' : ' disabled'}`;
@ -641,6 +649,7 @@ function buildHybridSourceList() {
: `<span class="hybrid-source-icon emoji-icon">${src.emoji}</span>`
}
<span class="hybrid-source-name">${src.name}</span>
${sourceLevelBadge}
<span class="hybrid-source-priority">${priorityNum}</span>
<label class="hybrid-source-toggle">
<input type="checkbox" ${enabled ? 'checked' : ''} onchange="toggleHybridSource('${srcId}', this.checked)">

View file

@ -52933,6 +52933,23 @@ tr.tag-diff-same {
color: rgba(255, 255, 255, 0.85);
font-weight: 500;
}
.hybrid-source-badge {
flex-shrink: 0;
font-size: 0.68em;
line-height: 1;
font-weight: 700;
letter-spacing: 0.01em;
padding: 4px 7px;
border-radius: 6px;
border: 1px solid rgba(125, 211, 252, 0.24);
background: rgba(125, 211, 252, 0.1);
color: #7dd3fc;
}
.hybrid-source-badge-track {
border-color: rgba(255, 255, 255, 0.12);
background: rgba(255, 255, 255, 0.05);
color: rgba(255, 255, 255, 0.48);
}
.hybrid-source-priority {
font-size: 0.75em;
color: rgba(255, 255, 255, 0.3);