import { formatTime, createPlaceholder, trackDataStore } from './utils.js'; import { recentActivityManager } from './storage.js'; export class UIRenderer { constructor(api) { this.api = api; } createTrackItemHTML(track, index, showCover = false) { const playIconSmall = ''; const trackNumberHTML = `
Album • ${album.artist?.name ?? ''}
`; } createArtistCardHTML(artist) { return `Artist
`; } renderListWithTracks(container, tracks, showCover) { container.innerHTML = tracks.map((track, i) => this.createTrackItemHTML(track, i, showCover) ).join(''); tracks.forEach(track => { const element = container.querySelector(`[data-track-id="${track.id}"]`); if (element) trackDataStore.set(element, track); }); } showPage(pageId) { document.querySelectorAll('.page').forEach(page => { page.classList.toggle('active', page.id === `page-${pageId}`); }); document.querySelectorAll('.sidebar-nav a').forEach(link => { link.classList.toggle('active', link.hash === `#${pageId}`); }); document.querySelector('.main-content').scrollTop = 0; if (pageId === 'settings') { this.renderApiSettings(); } } renderHomePage() { this.showPage('home'); const recents = recentActivityManager.getRecents(); document.getElementById('home-recent-albums').innerHTML = recents.albums.length ? recents.albums.map(album => this.createAlbumCardHTML(album)).join('') : createPlaceholder("You haven't viewed any albums yet."); document.getElementById('home-recent-artists').innerHTML = recents.artists.length ? recents.artists.map(artist => this.createArtistCardHTML(artist)).join('') : createPlaceholder("You haven't viewed any artists yet."); } async renderSearchPage(query) { this.showPage('search'); document.getElementById('search-results-title').textContent = `Search Results for "${query}"`; const tracksContainer = document.getElementById('search-tracks-container'); const artistsContainer = document.getElementById('search-artists-container'); const albumsContainer = document.getElementById('search-albums-container'); tracksContainer.innerHTML = createPlaceholder('Searching...', true); artistsContainer.innerHTML = createPlaceholder('Searching...', true); albumsContainer.innerHTML = createPlaceholder('Searching...', true); try { const [tracksResult, artistsResult, albumsResult] = await Promise.all([ this.api.searchTracks(query), this.api.searchArtists(query), this.api.searchAlbums(query) ]); let finalTracks = tracksResult.items; let finalArtists = artistsResult.items; let finalAlbums = albumsResult.items; if (finalArtists.length === 0 && finalTracks.length > 0) { console.log('Using fallback: extracting artists from tracks'); const artistMap = new Map(); finalTracks.forEach(track => { if (track.artist && !artistMap.has(track.artist.id)) { artistMap.set(track.artist.id, track.artist); } if (track.artists) { track.artists.forEach(artist => { if (!artistMap.has(artist.id)) { artistMap.set(artist.id, artist); } }); } }); finalArtists = Array.from(artistMap.values()); } if (finalAlbums.length === 0 && finalTracks.length > 0) { console.log('Using fallback: extracting albums from tracks'); const albumMap = new Map(); finalTracks.forEach(track => { if (track.album && !albumMap.has(track.album.id)) { albumMap.set(track.album.id, track.album); } }); finalAlbums = Array.from(albumMap.values()); } if (finalTracks.length) { this.renderListWithTracks(tracksContainer, finalTracks, false); } else { tracksContainer.innerHTML = createPlaceholder('No tracks found.'); } artistsContainer.innerHTML = finalArtists.length ? finalArtists.map(artist => this.createArtistCardHTML(artist)).join('') : createPlaceholder('No artists found.'); albumsContainer.innerHTML = finalAlbums.length ? finalAlbums.map(album => this.createAlbumCardHTML(album)).join('') : createPlaceholder('No albums found.'); } catch (error) { console.error("Search failed:", error); const errorMsg = createPlaceholder(`Error during search. ${error.message}`); tracksContainer.innerHTML = errorMsg; artistsContainer.innerHTML = errorMsg; albumsContainer.innerHTML = errorMsg; } } async renderAlbumPage(albumId) { this.showPage('album'); const tracklistContainer = document.getElementById('album-detail-tracklist'); tracklistContainer.innerHTML = createPlaceholder('Loading...', true); try { const { album, tracks } = await this.api.getAlbum(albumId); document.getElementById('album-detail-image').src = this.api.getCoverUrl(album.cover); document.getElementById('album-detail-title').textContent = album.title; document.getElementById('album-detail-meta').innerHTML = `By ${album.artist.name} • ${new Date(album.releaseDate).getFullYear()}`; tracklistContainer.innerHTML = `