Auto-Sync sidebar: brand logo on each source-group header

The sidebar source-group headers (Spotify / Tidal / Qobuz / Deezer /
YouTube / Last.fm Radio / ListenBrainz / iTunes Link / SoulSync
Discovery / Spotify Link) only showed the source name in caps —
the dashboard equalizer + connections panels both render the
actual brand logo, so the sidebar reading as text-only felt
disconnected.

Added a small (18px) circular brand-logo chip to the left of
each source-group title, sourced from the same URLs the
dashboard equalizer avatars use. Dark glass backdrop + accent
ring + drop-shadow on the logo so the chip stays legible
against either light or dark marks; brightness(0) invert(1)
applied to Tidal / Qobuz / iTunes-Link so their dark-foreground
marks render as white silhouettes against the disc (same
recipe the equalizer overrides use). Last.fm's square avatar
PNG clips to a circle via object-fit: cover.

Sources without a publicly available logo (Beatport, file
imports) fall through to no-chip — the <img onerror> swap
hides the broken image so the header still renders cleanly.
This commit is contained in:
Broque Thomas 2026-05-27 20:23:12 -07:00
parent e296fbfadd
commit b19c1ae8cc
2 changed files with 85 additions and 2 deletions

View file

@ -161,6 +161,35 @@ function autoSyncSourceLabel(source) {
return labels[source] || source || 'Other';
}
// Per-source logo URLs for the sidebar source-group headers and
// anywhere else a small branded chip helps disambiguate the source.
// Same URLs the dashboard equalizer / header-action orbs reference
// so the visual language stays consistent. Sources without a
// readily available logo (``beatport``, ``file``) fall through to
// no-image; the source-icon element drops to display:none via
// the ``<img onerror>`` swap so the header renders cleanly without
// a broken-image placeholder.
const _AUTO_SYNC_SOURCE_LOGOS = {
spotify: 'https://storage.googleapis.com/pr-newsroom-wp/1/2023/05/Spotify_Primary_Logo_RGB_Green.png',
spotify_public: 'https://storage.googleapis.com/pr-newsroom-wp/1/2023/05/Spotify_Primary_Logo_RGB_Green.png',
tidal: 'https://www.svgrepo.com/show/519734/tidal.svg',
youtube: 'https://www.svgrepo.com/show/13671/youtube.svg',
deezer: 'https://cdn.brandfetch.io/idEUKgCNtu/theme/dark/symbol.svg?c=1bxid64Mup7aczewSAYMX&t=1758260798610',
qobuz: 'https://www.svgrepo.com/show/504778/qobuz.svg',
itunes_link: 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/df/ITunes_logo.svg/960px-ITunes_logo.svg.png',
lastfm: 'https://www.last.fm/static/images/lastfm_avatar_twitter.52a5d69a85ac.png',
listenbrainz: 'https://listenbrainz.org/static/img/listenbrainz-logo-no-text.svg',
soulsync_discovery: '/static/favicon.png',
};
function autoSyncSourceIconHtml(source) {
const src = _AUTO_SYNC_SOURCE_LOGOS[source];
if (!src) return '';
return `<img class="auto-sync-source-icon" data-svc="${_escAttr(source)}"
src="${src}" alt="" aria-hidden="true"
onerror="this.style.display='none'">`;
}
function autoSyncCanSchedulePlaylist(playlist) {
if (!playlist) return false;
const src = playlist.source || '';
@ -407,7 +436,10 @@ function renderAutoSyncSchedulePanel(playlists, playlistSchedules) {
const sidebarHtml = sourceKeys.length ? sourceKeys.map(source => `
<div class="auto-sync-source-group">
<div class="auto-sync-source-group-head">
<span class="auto-sync-source-title">${_esc(autoSyncSourceLabel(source))}</span>
<span class="auto-sync-source-title">
${autoSyncSourceIconHtml(source)}
<span class="auto-sync-source-title-label">${_esc(autoSyncSourceLabel(source))}</span>
</span>
<button type="button" class="auto-sync-source-bulk-btn"
onclick="event.stopPropagation(); openAutoSyncBulkMenu(event, '${_escAttr(source)}')"
title="Schedule all ${_escAttr(autoSyncSourceLabel(source))} playlists at the same interval">
@ -517,7 +549,10 @@ function renderAutoSyncWeeklyPanel(playlists, playlistSchedules) {
const sidebarHtml = sourceKeys.length ? sourceKeys.map(source => `
<div class="auto-sync-source-group">
<div class="auto-sync-source-group-head">
<span class="auto-sync-source-title">${_esc(autoSyncSourceLabel(source))}</span>
<span class="auto-sync-source-title">
${autoSyncSourceIconHtml(source)}
<span class="auto-sync-source-title-label">${_esc(autoSyncSourceLabel(source))}</span>
</span>
</div>
${grouped[source].map(p => {
const weekly = weeklySchedules[p.id];

View file

@ -63544,6 +63544,54 @@ body.reduce-effects .dash-card::after {
font-weight: 800;
letter-spacing: 0.12em;
text-transform: uppercase;
display: inline-flex;
align-items: center;
gap: 8px;
}
.auto-sync-source-title-label {
/* Wrap the label text so the inline-flex container doesn't
collapse line-height when the logo isn't loaded yet. */
display: inline-block;
line-height: 1;
}
/* Source-group logo chip matches the dashboard equalizer
avatar treatment: dark glass disc, accent-tinted ring, logo
sized at 70% with a brand-colored drop-shadow. Dark-foreground
marks (tidal / qobuz / amazon) invert to white silhouette so
they read against the disc, same as the equalizer overrides. */
.auto-sync-source-icon {
width: 18px;
height: 18px;
border-radius: 50%;
background:
radial-gradient(circle at 30% 25%,
rgba(255, 255, 255, 0.08),
rgba(0, 0, 0, 0.35) 70%);
border: 1px solid rgba(255, 255, 255, 0.1);
object-fit: contain;
padding: 2px;
flex: 0 0 auto;
filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.5));
}
/* Last.fm's source icon is a square avatar PNG clip it to a
circle so the chip reads as a uniform disc just like the
equalizer avatar does. */
.auto-sync-source-icon[data-svc="lastfm"] {
padding: 0;
object-fit: cover;
}
/* Dark-foreground marks: invert to white silhouette so the logo
reads against the dark glass disc. Matches the equalizer
``brightness(0) invert(1)`` recipe for Tidal / Qobuz / Discogs
/ Amazon. */
.auto-sync-source-icon[data-svc="tidal"],
.auto-sync-source-icon[data-svc="qobuz"],
.auto-sync-source-icon[data-svc="itunes_link"] {
filter: brightness(0) invert(1) drop-shadow(0 1px 1px rgba(0, 0, 0, 0.5));
}