diff --git a/index.html b/index.html index ce0ac89..633d243 100644 --- a/index.html +++ b/index.html @@ -3297,13 +3297,15 @@

Albums

diff --git a/js/db.js b/js/db.js index 122155b..1924e49 100644 --- a/js/db.js +++ b/js/db.js @@ -585,6 +585,7 @@ export class MusicDatabase { // TRIGGER SYNC this._dispatchPlaylistSync('create', playlist); + window.dispatchEvent(new CustomEvent('playlist-tracks-changed')); return playlist; } @@ -657,6 +658,7 @@ export class MusicDatabase { // TRIGGER SYNC (but for deleting) this._dispatchPlaylistSync('delete', { id: playlistId }); + window.dispatchEvent(new CustomEvent('playlist-tracks-changed')); } async getPlaylist(playlistId) { diff --git a/js/ui.js b/js/ui.js index e363cc8..15a6017 100644 --- a/js/ui.js +++ b/js/ui.js @@ -3953,11 +3953,13 @@ export class UIRenderer { if (inLibrarySection) inLibrarySection.style.display = 'none'; if (inLibraryContainer) { inLibraryContainer.innerHTML = ''; - inLibraryContainer.style.display = 'none'; + inLibraryContainer.hidden = true; } - // Reset chevron state + // Reset chevron and toggle state const chevronEl = document.getElementById('in-library-chevron'); if (chevronEl) chevronEl.style.transform = 'rotate(0deg)'; + const toggleBtn = document.getElementById('in-library-toggle'); + if (toggleBtn) toggleBtn.setAttribute('aria-expanded', 'false'); try { const artist = await this.api.getArtist(artistId, provider); @@ -4199,12 +4201,16 @@ export class UIRenderer { const isTrackByArtist = (track) => { if (track.artists && Array.isArray(track.artists)) { return track.artists.some( - (a) => a && a.name && a.name.toLowerCase() === artistNameLower + (a) => a && ((artist.id && a.id === artist.id) || (a.name && a.name.toLowerCase() === artistNameLower)) ); } if (track.artist) { - const artistStr = typeof track.artist === 'string' ? track.artist : track.artist.name; - if (artistStr && artistStr.toLowerCase() === artistNameLower) return true; + if (typeof track.artist === 'object') { + if (artist.id && track.artist.id === artist.id) return true; + if (track.artist.name && track.artist.name.toLowerCase() === artistNameLower) return true; + } else if (typeof track.artist === 'string') { + if (track.artist.toLowerCase() === artistNameLower) return true; + } } return false; }; @@ -4285,18 +4291,27 @@ export class UIRenderer { const sourceSpan = document.createElement('span'); sourceSpan.className = 'library-source'; + const labelSpan = document.createElement('span'); + labelSpan.className = 'library-source-label'; + labelSpan.textContent = '· Source:\u00a0'; + + const linkSpan = document.createElement('span'); + linkSpan.className = 'library-source-link'; + + sourceSpan.style.cursor = 'pointer'; + sourceSpan.appendChild(labelSpan); + sourceSpan.appendChild(linkSpan); + if (sources.length === 1) { const srcLabel = sources[0].label.length > 15 ? sources[0].label.slice(0, 15) + '…' : sources[0].label; - sourceSpan.innerHTML = `· Source: ${srcLabel}`; - sourceSpan.style.cursor = 'pointer'; + linkSpan.textContent = srcLabel; sourceSpan.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); navigate(sources[0].href); }); } else { - sourceSpan.innerHTML = `· Source: Multiple Playlists`; - sourceSpan.style.cursor = 'pointer'; + linkSpan.textContent = 'Multiple Playlists'; sourceSpan.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); @@ -4306,11 +4321,16 @@ export class UIRenderer { const cancelBtn = document.getElementById('goto-playlist-cancel'); const overlay = modal.querySelector('.modal-overlay'); - list.innerHTML = sources.map((s) => - `` - ).join(''); + list.innerHTML = ''; + sources.forEach((s) => { + const option = document.createElement('div'); + option.className = 'modal-option'; + option.dataset.href = s.href; + const span = document.createElement('span'); + span.textContent = s.label; + option.appendChild(span); + list.appendChild(option); + }); const closeModal = () => { modal.classList.remove('active'); @@ -4357,7 +4377,7 @@ export class UIRenderer { // Initial load refreshInLibrary().then(() => { - inLibraryContainer.style.display = 'none'; + inLibraryContainer.hidden = true; }); // Setup chevron toggle (once) @@ -4365,8 +4385,9 @@ export class UIRenderer { const chevron = document.getElementById('in-library-chevron'); if (toggle) { toggle.onclick = () => { - const isOpen = inLibraryContainer.style.display !== 'none'; - inLibraryContainer.style.display = isOpen ? 'none' : ''; + const isOpen = !inLibraryContainer.hidden; + inLibraryContainer.hidden = isOpen; + toggle.setAttribute('aria-expanded', String(!isOpen)); if (chevron) { chevron.style.transform = isOpen ? 'rotate(0deg)' : 'rotate(90deg)'; } @@ -4379,15 +4400,17 @@ export class UIRenderer { clearTimeout(refreshTimeout); refreshTimeout = setTimeout(() => refreshInLibrary(), 300); }; - window.addEventListener('favorites-changed', debouncedRefresh); - window.addEventListener('playlist-tracks-changed', debouncedRefresh); - // Cleanup listeners when navigating away + // Cleanup previous listeners before attaching new ones const cleanupOnNav = () => { window.removeEventListener('favorites-changed', debouncedRefresh); window.removeEventListener('playlist-tracks-changed', debouncedRefresh); window.removeEventListener('popstate', cleanupOnNav); }; + cleanupOnNav(); + + window.addEventListener('favorites-changed', debouncedRefresh); + window.addEventListener('playlist-tracks-changed', debouncedRefresh); window.addEventListener('popstate', cleanupOnNav, { once: true }); } diff --git a/styles.css b/styles.css index 71a5579..1740d4f 100644 --- a/styles.css +++ b/styles.css @@ -1994,6 +1994,10 @@ input[type='search']::-webkit-search-cancel-button { gap: 2px var(--spacing-xl); } +#artist-detail-in-library[hidden] { + display: none; +} + .library-source { color: var(--muted-foreground); font-size: inherit; @@ -2365,8 +2369,8 @@ input[type='search']::-webkit-search-cancel-button { align-items: center; gap: 1rem; flex-wrap: wrap; - overflow-wrap: break-word; - word-break: break-word; + overflow-wrap: anywhere; + word-break: normal; min-width: 0; }