diff --git a/index.html b/index.html index 762a33a..34a8275 100644 --- a/index.html +++ b/index.html @@ -310,6 +310,10 @@

EPs and Singles

+
diff --git a/js/api.js b/js/api.js index a3cc3e8..707c841 100644 --- a/js/api.js +++ b/js/api.js @@ -575,6 +575,27 @@ export class LosslessAPI { + async getSimilarArtists(artistId) { + const cached = await this.cache.get('similar_artists', artistId); + if (cached) return cached; + + try { + const response = await this.fetchWithRetry(`/artist/similar/?id=${artistId}`, { type: 'api' }); + const data = await response.json(); + + // Handle various response structures + const items = data.artists || data.items || data.data || (Array.isArray(data) ? data : []); + + const result = items.map(artist => this.prepareArtist(artist)); + + await this.cache.set('similar_artists', artistId, result); + return result; + } catch (e) { + console.warn('Failed to fetch similar artists:', e); + return []; + } + } + normalizeTrackResponse(apiResponse) { if (!apiResponse || typeof apiResponse !== 'object') { return apiResponse; diff --git a/js/ui.js b/js/ui.js index 0c8a107..b74a023 100644 --- a/js/ui.js +++ b/js/ui.js @@ -938,6 +938,22 @@ async showFullscreenCover(track, nextTrack, lyricsManager, audioPlayer) { renderSection(`More albums from ${album.artist.name}`, artistData.albums); renderSection(`EPs and Singles from ${album.artist.name}`, artistData.eps); + // Similar Artists + this.api.getSimilarArtists(album.artist.id).then(similar => { + if (similar && similar.length > 0) { + const section = document.createElement('section'); + section.className = 'content-section album-more-section'; + section.style.marginTop = '3rem'; + section.innerHTML = ` +

Fans Also Like

+
+ ${similar.map(a => this.createArtistCardHTML(a)).join('')} +
+ `; + document.getElementById('page-album').appendChild(section); + } + }).catch(e => console.warn('Failed to load similar artists:', e)); + } catch (err) { console.warn('Failed to load "More from artist":', err); document.querySelectorAll('.album-more-section').forEach(el => el.remove()); @@ -1099,6 +1115,8 @@ async showFullscreenCover(track, nextTrack, lyricsManager, audioPlayer) { const albumsContainer = document.getElementById('artist-detail-albums'); const epsContainer = document.getElementById('artist-detail-eps'); const epsSection = document.getElementById('artist-section-eps'); + const similarContainer = document.getElementById('artist-detail-similar'); + const similarSection = document.getElementById('artist-section-similar'); const dlBtn = document.getElementById('download-discography-btn'); if (dlBtn) dlBtn.innerHTML = `${SVG_DOWNLOAD}Download Discography`; @@ -1110,10 +1128,26 @@ async showFullscreenCover(track, nextTrack, lyricsManager, audioPlayer) { albumsContainer.innerHTML = this.createSkeletonCards(6, false); if (epsContainer) epsContainer.innerHTML = this.createSkeletonCards(6, false); if (epsSection) epsSection.style.display = 'none'; + if (similarContainer) similarContainer.innerHTML = this.createSkeletonCards(6, true); + if (similarSection) similarSection.style.display = 'block'; try { const artist = await this.api.getArtist(artistId); + // Similar Artists + if (similarContainer && similarSection) { + this.api.getSimilarArtists(artistId).then(similar => { + if (similar && similar.length > 0) { + similarContainer.innerHTML = similar.map(a => this.createArtistCardHTML(a)).join(''); + similarSection.style.display = 'block'; + } else { + similarSection.style.display = 'none'; + } + }).catch(() => { + similarSection.style.display = 'none'; + }); + } + imageEl.src = this.api.getArtistPictureUrl(artist.picture, '750'); imageEl.style.backgroundColor = ''; nameEl.textContent = artist.name;