feat: all-songs view as separate page, iTunes album detail page

- 'Alle X Songs' button now navigates to a dedicated page instead of expanding inline
- Partial/not-downloaded albums now open an iTunes album detail page with track list,
  preview buttons and download option
- Added page-artist-all-songs and page-itunes-album-detail to index.html
- Replaced _expandArtistAllSongs with loadArtistAllSongs + loadItunesAlbumDetail

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Sonnet 4.6 committed 2026-04-26 19:23:16 +02:00
1 parent 72f6087043
commit 976e80f86d
2 files changed
+63 -12

No files matched your search

+38 -12
View File
@@ -38,8 +38,10 @@ export function navigate(page, data=null) {
if(page==='albums' && !document.getElementById('albums-grid').children.length) loadAlbums();
if(page==='starred') loadStarred();
if(page==='random') loadRandom();
if(page==='artist-detail' && data) loadArtistDetail(data);
if(page==='album-detail' && data) loadAlbumDetail(data);
if(page==='artist-detail' && data) loadArtistDetail(data);
if(page==='artist-all-songs' && data) loadArtistAllSongs(data);
if(page==='album-detail' && data) loadAlbumDetail(data);
if(page==='itunes-album-detail'&& data) loadItunesAlbumDetail(data);
if(page==='new-releases') loadNewReleases();
if(page==='playlists') loadPlaylists();
if(page==='playlist-detail' && data) loadPlaylistDetail(data);
@@ -319,7 +321,7 @@ export async function loadArtistDetail(artist) {
const btn = document.createElement('button');
btn.className = 'btn-outline'; btn.style.cssText = 'font-size:12px;padding:7px 14px;margin-bottom:16px;margin-top:4px';
btn.textContent = `Alle ${total} Songs in Library`;
btn.onclick = () => _expandArtistAllSongs(btn, ndAlbums, artist);
btn.onclick = () => navigate('artist-all-songs', { albums: ndAlbums, artist });
tsEl.appendChild(btn);
}
}
@@ -391,7 +393,7 @@ function _renderArtistAlbums(el, ndAlbums, iAlbums, artist) {
const art = itunes?.artworkUrl100?.replace('100x100','300x300') || coverUrl(nd.coverArt, 300);
const c = makeCard(nd.name, `${have} / ${total} Tracks`, art, '💿');
c.querySelector('.play-btn').onclick = (e) => { e.stopPropagation(); quickPlayAlbum(nd); };
c.onclick = () => navigate('album-detail', { ...nd, _fromArtist: artist });
c.onclick = () => itunes ? navigate('itunes-album-detail', itunes) : navigate('album-detail', { ...nd, _fromArtist: artist });
const artEl = c.querySelector('.card-art');
const badge = document.createElement('div');
badge.className = 'album-partial-badge'; badge.textContent = `${have}/${total}`;
@@ -412,7 +414,7 @@ function _renderArtistAlbums(el, ndAlbums, iAlbums, artist) {
notDl.forEach(ia => {
const art = ia.artworkUrl100?.replace('100x100','300x300');
const c = makeCard(ia.collectionName, ia.releaseDate?.slice(0,4)||'', art, '💿');
c.onclick = () => loadItunesAlbum(ia);
c.onclick = () => navigate('itunes-album-detail', ia);
const artEl = c.querySelector('.card-art');
const btn = document.createElement('button');
btn.className = 'card-dl-btn'; btn.title = 'Album laden';
@@ -430,11 +432,13 @@ function _renderArtistAlbums(el, ndAlbums, iAlbums, artist) {
}
}
async function _expandArtistAllSongs(btn, albums, artist) {
btn.disabled = true; btn.textContent = 'Lädt…';
export async function loadArtistAllSongs({ albums, artist }) {
document.getElementById('artist-songs-title').textContent = `Alle Songs · ${artist.name}`;
document.getElementById('artist-songs-back-btn').onclick = () => _navGoBack();
const el = document.getElementById('artist-songs-list');
el.innerHTML = '<div class="spinner"></div>';
const results = await Promise.allSettled(albums.map(a => api('getAlbum', `&id=${a.id}`)));
const container = document.createElement('div'); container.style.marginBottom = '16px';
btn.replaceWith(container);
el.innerHTML = '';
const allSongs = results
.filter(r => r.status === 'fulfilled')
.flatMap(r => { const alb = r.value?.album; return (alb?.song || []).map(s => ({ ...s, _alb: alb })); })
@@ -448,8 +452,9 @@ async function _expandArtistAllSongs(btn, albums, artist) {
if(s._alb?.id !== curId) {
curId = s._alb?.id || '';
const h = document.createElement('div');
h.style.cssText = 'font-size:12px;font-weight:700;color:var(--text2);padding:8px 0 2px;border-top:1px solid var(--border);margin-top:4px';
h.textContent = s._alb?.name || ''; container.appendChild(h);
h.style.cssText = 'font-size:12px;font-weight:700;color:var(--text2);padding:12px 0 4px;border-top:1px solid var(--border);margin-top:4px';
h.textContent = s._alb?.name || '';
el.appendChild(h);
}
const cv = coverUrl(s.coverArt, 60);
const row = document.createElement('div'); row.className = 'topsong-item';
@@ -459,10 +464,31 @@ async function _expandArtistAllSongs(btn, albums, artist) {
<div class="topsong-plays">${s.playCount?s.playCount.toLocaleString():''}</div>`;
row.onclick = () => playQueue(allSongs, i);
row.addEventListener('contextmenu', e => { e.preventDefault(); showCtxMenu(e, s, allSongs, i); });
container.appendChild(row);
el.appendChild(row);
});
}
export async function loadItunesAlbumDetail(album) {
document.getElementById('itunes-album-back-btn').onclick = () => _navGoBack();
document.getElementById('itunes-album-detail-name').textContent = album.collectionName || '—';
document.getElementById('itunes-album-detail-artist').textContent = album.artistName || '';
const cw = document.getElementById('itunes-album-cover-wrap');
const art = (album.artworkUrl100 || '').replace('100x100bb','600x600bb').replace('100x100','600x600');
cw.innerHTML = art ? `<img src="${art}" onerror="this.parentNode.innerHTML='<div class=\\'no-art\\'>💿</div>'">` : '<div class="no-art">💿</div>';
const dlBtn = document.getElementById('itunes-album-dl-btn');
dlBtn.onclick = () => openDlModal({ artistName: album.artistName, trackName: album.collectionName, collectionName: album.collectionName, artworkUrl100: album.artworkUrl100||'', isAlbum: true, itunesData: album, collectionId: album.collectionId });
const sl = document.getElementById('itunes-album-songs');
sl.innerHTML = '<div class="spinner"></div>';
try {
const tracks = await itunesLookupAlbum(album.collectionId);
const year = album.releaseDate ? new Date(album.releaseDate).getFullYear() : '';
document.getElementById('itunes-album-detail-stats').textContent = `${tracks.length} Titel${year ? ' · ' + year : ''}`;
sl.innerHTML = '';
if(!tracks.length) { sl.innerHTML = '<div style="padding:16px;color:var(--text3)">Keine Tracks gefunden</div>'; return; }
tracks.forEach((t, i) => sl.appendChild(makeGlobalTrackItem(t, i, tracks)));
} catch(e) { sl.innerHTML = `<p style="color:var(--danger)">${e.message}</p>`; }
}
// ─── ALBUM DETAIL ───
export async function loadAlbumDetail(album) {
document.getElementById('album-back-btn').onclick = () =>